- 移除所有 Vue 组件和 README 中的 emoji (按钮文字、标题、功能列表) - 将 src 下所有英文注释改为中文, 保留专业名词 (RRULE, EXDATE, ICS 等) - 涉及文件: date.js, event-factory.js, ical-io.js, organize.js, recur.js, split.js, weekday.js, useCalendar.js, EventDetail.vue, App.vue, DropZone.vue, EventList.vue, HeaderBar.vue, README.md
49 lines
1.2 KiB
JavaScript
49 lines
1.2 KiB
JavaScript
/**
|
|
* 重复网格展开 - 移植自 ical_editor.py 的 occurrence 生成逻辑。
|
|
* occurrence 按需从 exdates 计算, 不存储在模型上。
|
|
*/
|
|
import { toISODate, toDate, addDays } from './date.js'
|
|
|
|
/** 重复事件的间隔天数。 */
|
|
export function intervalDays(ev) {
|
|
if (!ev.rrule) return 0
|
|
const { freq, interval } = ev.rrule
|
|
const step = interval || 1
|
|
return freq === 'WEEKLY' ? 7 * step : step
|
|
}
|
|
|
|
const MAX_OCCURRENCES = 500
|
|
|
|
/**
|
|
* 将重复事件展开为 occurrence 网格。
|
|
* 返回 [{ date: 'YYYY-MM-DD', skipped: boolean }]。
|
|
*/
|
|
export function expandOccurrences(ev) {
|
|
// 非重复事件: 单个 occurrence
|
|
if (!ev.rrule) {
|
|
return [{ date: ev.dtstartDate, skipped: false }]
|
|
}
|
|
|
|
const step = intervalDays(ev)
|
|
if (step <= 0) {
|
|
return [{ date: ev.dtstartDate, skipped: false }]
|
|
}
|
|
|
|
const until = ev.rrule.untilDate
|
|
? toDate(ev.rrule.untilDate)
|
|
: new Date(toDate(ev.dtstartDate).getTime() + 365 * 24 * 3600 * 1000)
|
|
|
|
const exdateSet = new Set(ev.exdates || [])
|
|
const occs = []
|
|
let cur = ev.dtstartDate
|
|
let count = 0
|
|
|
|
while (cur <= toISODate(until) && count < MAX_OCCURRENCES) {
|
|
occs.push({ date: cur, skipped: exdateSet.has(cur) })
|
|
cur = addDays(cur, step)
|
|
count++
|
|
}
|
|
|
|
return occs
|
|
}
|