import { generateId } from '@/api/request.js' import { startOfDay, endOfDay } from '@/utils/date.js' const STORAGE_KEY = 'app_schedules' const PRIORITY = { low: { value: 'low', label: '低', color: '#909399' }, medium: { value: 'medium', label: '中', color: '#3c9cff' }, high: { value: 'high', label: '高', color: '#f56c6c' } } export const PRIORITY_OPTIONS = Object.values(PRIORITY) export const REMIND_CHANNEL_OPTIONS = [ { value: 'sms', label: '短信' }, { value: 'email', label: '邮件' }, { value: 'bark', label: 'Bark推送' }, { value: 'site', label: '站内信' }, { value: 'app', label: 'APP' } ] export const REMIND_MINUTES_OPTIONS = [ { label: '不提前', value: 0 }, { label: '提前 5 分钟', value: 5 }, { label: '提前 10 分钟', value: 10 }, { label: '提前 15 分钟', value: 15 }, { label: '提前 30 分钟', value: 30 }, { label: '提前 1 小时', value: 60 }, { label: '提前 2 小时', value: 120 }, { label: '提前 1 天', value: 1440 } ] function readLocal() { const list = uni.getStorageSync(STORAGE_KEY) || [] return list.map(normalizeSchedule) } function writeLocal(list) { uni.setStorageSync(STORAGE_KEY, list) } export function normalizeSchedule(item) { const content = (item.content || item.title || '').trim() const title = (item.title || content.split('\n')[0] || '无标题').trim().slice(0, 60) let remindChannels = item.remindChannels if (!Array.isArray(remindChannels)) { remindChannels = item.remindMinutes > 0 ? ['app'] : [] } return { ...item, title, content, remindChannels, remindMinutes: item.remindMinutes ?? 15 } } function buildTitle(content) { const line = (content || '').split('\n')[0].trim() return line.slice(0, 60) || '无标题' } function seedIfEmpty() { const raw = uni.getStorageSync(STORAGE_KEY) if (raw && raw.length) return raw.map(normalizeSchedule) const now = Date.now() const today = new Date() const seeded = [ { id: generateId(), content: '团队周会\n汇报本周进度,讨论下周计划', datetime: new Date(today.getFullYear(), today.getMonth(), today.getDate(), 10, 0).getTime(), remindChannels: ['app', 'site'], remindMinutes: 15, priority: 'high', completed: false, createdAt: now - 86400000, updatedAt: now - 86400000 }, { id: generateId(), content: '提交月报\n整理本月数据并发送给主管', datetime: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1, 18, 0).getTime(), remindChannels: ['email', 'site'], remindMinutes: 30, priority: 'medium', completed: false, createdAt: now - 43200000, updatedAt: now - 43200000 }, { id: generateId(), content: '健身打卡\n有氧运动 30 分钟', datetime: new Date(today.getFullYear(), today.getMonth(), today.getDate() - 1, 19, 30).getTime(), remindChannels: ['bark', 'app'], remindMinutes: 10, priority: 'low', completed: true, createdAt: now - 259200000, updatedAt: now - 86400000 } ].map(normalizeSchedule) writeLocal(seeded) return seeded } function sortSchedules(list) { return [...list].sort((a, b) => { if (a.completed !== b.completed) return a.completed ? 1 : -1 return (a.datetime || 0) - (b.datetime || 0) }) } /** * 获取日程列表 */ export async function fetchSchedules(params = {}) { // TODO: return request({ url: '/api/schedules', data: params }) let list = seedIfEmpty() const keyword = (params.keyword || '').trim().toLowerCase() const status = params.status || 'all' if (keyword) { list = list.filter(item => { const text = `${item.title} ${item.content}`.toLowerCase() return text.includes(keyword) }) } if (status === 'pending') list = list.filter(item => !item.completed) if (status === 'done') list = list.filter(item => item.completed) if (params.date) { const dayStart = startOfDay(params.date).getTime() const dayEnd = endOfDay(params.date).getTime() list = list.filter(item => item.datetime >= dayStart && item.datetime <= dayEnd) } list = sortSchedules(list) return { list, total: list.length } } /** * 获取单条日程 */ export async function getSchedule(id) { // TODO: return request({ url: `/api/schedules/${id}` }) const list = readLocal() const item = list.find(entry => entry.id === id) return item ? normalizeSchedule(item) : null } /** * 创建日程 * @param {{ content: string, datetime: number, remindChannels?: string[], remindMinutes?: number }} data */ export async function createSchedule(data) { // TODO: return request({ url: '/api/schedules', method: 'POST', data }) const now = Date.now() const content = (data.content || '').trim() const schedule = normalizeSchedule({ id: generateId(), title: buildTitle(content), content, datetime: data.datetime, remindChannels: data.remindChannels || [], remindMinutes: data.remindMinutes ?? 15, priority: data.priority || 'medium', completed: false, createdAt: now, updatedAt: now }) const list = readLocal() list.push(schedule) writeLocal(list) return schedule } /** * 更新日程 */ export async function updateSchedule(id, data) { // TODO: return request({ url: `/api/schedules/${id}`, method: 'PUT', data }) const list = readLocal() const index = list.findIndex(item => item.id === id) if (index === -1) throw new Error('日程不存在') const prev = list[index] const content = data.content !== undefined ? data.content.trim() : prev.content const schedule = normalizeSchedule({ ...prev, ...data, title: data.content !== undefined ? buildTitle(content) : prev.title, content, updatedAt: Date.now() }) list[index] = schedule writeLocal(list) return schedule } /** * 删除日程 */ export async function deleteSchedule(id) { // TODO: return request({ url: `/api/schedules/${id}`, method: 'DELETE' }) const list = readLocal().filter(item => item.id !== id) writeLocal(list) return true } /** * 切换完成状态 */ export async function toggleScheduleComplete(id) { const item = await getSchedule(id) if (!item) throw new Error('日程不存在') return updateSchedule(id, { completed: !item.completed }) } export function getPriorityMeta(value) { return PRIORITY[value] || PRIORITY.medium } export function getRemindChannelLabel(value) { return REMIND_CHANNEL_OPTIONS.find(item => item.value === value)?.label || value } export function getRemindChannelLabels(channels = []) { if (!channels.length) return '未设置' return channels.map(getRemindChannelLabel).join('、') } export function getRemindMinutesLabel(minutes) { const item = REMIND_MINUTES_OPTIONS.find(option => option.value === minutes) return item?.label || (minutes ? `提前 ${minutes} 分钟` : '不提前') } export function getScheduleSummary(item) { const text = (item?.content || item?.title || '').trim() const line = text.split('\n')[0] return line || '无内容' }