243 lines
6.7 KiB
JavaScript
243 lines
6.7 KiB
JavaScript
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 || '无内容'
|
|
}
|