完善uniapp

This commit is contained in:
2026-07-16 00:35:50 +08:00
parent 61a937f7a3
commit 834c088aa2
29 changed files with 4444 additions and 305 deletions
+48 -101
View File
@@ -1,138 +1,85 @@
import { generateId } from '@/api/request.js'
const STORAGE_KEY = 'app_notes'
function readLocal() {
return uni.getStorageSync(STORAGE_KEY) || []
}
function writeLocal(list) {
uni.setStorageSync(STORAGE_KEY, list)
}
function seedIfEmpty() {
const list = readLocal()
if (list.length) return list
const now = Date.now()
const seeded = [
{
id: generateId(),
title: '欢迎使用记事本',
content: '在这里记录灵感、待办或任何想法。支持置顶、搜索与编辑,后续可一键接入云端同步。',
pinned: true,
createdAt: now - 86400000,
updatedAt: now - 3600000
},
{
id: generateId(),
title: '项目会议要点',
content: '1. 确认 Q3 目标\n2. 排期评审\n3. 接口联调时间',
pinned: false,
createdAt: now - 172800000,
updatedAt: now - 7200000
}
]
writeLocal(seeded)
return seeded
}
function sortNotes(list) {
return [...list].sort((a, b) => {
if (a.pinned !== b.pinned) return a.pinned ? -1 : 1
return (b.updatedAt || 0) - (a.updatedAt || 0)
})
}
import { request } from '@/api/request.js'
/**
* 获取笔记列表
* @param {{ keyword?: string }} params
* @returns {Promise<{ list: Array, total: number }>}
*/
export async function fetchNotes(params = {}) {
// TODO: return request({ url: '/api/notes', data: params })
let list = seedIfEmpty()
const keyword = (params.keyword || '').trim().toLowerCase()
if (keyword) {
list = list.filter(
item =>
item.title.toLowerCase().includes(keyword) ||
item.content.toLowerCase().includes(keyword)
)
}
list = sortNotes(list)
return { list, total: list.length }
const data = await request({
url: '/app/notebook/list',
data: {
keyword: params.keyword || ''
}
})
const list = (data.list || []).map(item => ({
...item,
pinned: !!item.pinned,
createdAt: item.created_at ? new Date(item.created_at.replace(' ', 'T')).getTime() : 0,
updatedAt: item.updated_at ? new Date(item.updated_at.replace(' ', 'T')).getTime() : 0
}))
return { list, total: data.total || 0 }
}
/**
* 获取单条笔记
* @param {string} id
*/
export async function getNote(id) {
// TODO: return request({ url: `/api/notes/${id}` })
const list = readLocal()
return list.find(item => item.id === id) || null
const data = await request({ url: `/app/notebook/${id}` })
if (!data) return null
return {
...data,
pinned: !!data.pinned,
createdAt: data.created_at ? new Date(data.created_at.replace(' ', 'T')).getTime() : 0,
updatedAt: data.updated_at ? new Date(data.updated_at.replace(' ', 'T')).getTime() : 0
}
}
/**
* 创建笔记
* @param {{ title: string, content: string, pinned?: boolean }} data
*/
export async function createNote(data) {
// TODO: return request({ url: '/api/notes', method: 'POST', data })
const now = Date.now()
const note = {
id: generateId(),
title: (data.title || '').trim() || '无标题',
content: (data.content || '').trim(),
pinned: !!data.pinned,
createdAt: now,
updatedAt: now
}
const list = readLocal()
list.unshift(note)
writeLocal(list)
return note
const res = await request({
url: '/app/notebook',
method: 'POST',
data: {
title: data.title || '',
content: data.content || '',
pinned: !!data.pinned
}
})
return res
}
/**
* 更新笔记
* @param {string} id
* @param {{ title?: string, content?: string, pinned?: boolean }} data
*/
export async function updateNote(id, data) {
// TODO: return request({ url: `/api/notes/${id}`, method: 'PUT', data })
const list = readLocal()
const index = list.findIndex(item => item.id === id)
if (index === -1) throw new Error('笔记不存在')
const note = {
...list[index],
...data,
title: data.title !== undefined ? (data.title.trim() || '无标题') : list[index].title,
content: data.content !== undefined ? data.content.trim() : list[index].content,
updatedAt: Date.now()
}
list[index] = note
writeLocal(list)
return note
const res = await request({
url: `/app/notebook/${id}`,
method: 'PUT',
data: {
title: data.title || '',
content: data.content || '',
pinned: data.pinned
}
})
return res
}
/**
* 删除笔记
* @param {string} id
*/
export async function deleteNote(id) {
// TODO: return request({ url: `/api/notes/${id}`, method: 'DELETE' })
const list = readLocal().filter(item => item.id !== id)
writeLocal(list)
await request({ url: `/app/notebook/${id}`, method: 'DELETE' })
return true
}
/**
* 切换置顶
* @param {string} id
*/
export async function toggleNotePin(id) {
const note = await getNote(id)
if (!note) throw new Error('笔记不存在')
return updateNote(id, { pinned: !note.pinned })
const res = await request({
url: `/app/notebook/${id}/togglePin`,
method: 'POST'
})
return res
}
+76 -149
View File
@@ -1,15 +1,4 @@
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)
import { request } from '@/api/request.js'
export const REMIND_CHANNEL_OPTIONS = [
{ value: 'sms', label: '短信' },
@@ -30,181 +19,112 @@ export const REMIND_MINUTES_OPTIONS = [
{ 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
let remindChannels = item.remindChannels || item.remind_channels || []
if (!Array.isArray(remindChannels)) {
remindChannels = item.remindMinutes > 0 ? ['app'] : []
remindChannels = []
}
remindChannels = remindChannels.map(ch => ch === 'SITE_MSG' ? 'app' : ch.toLowerCase())
const datetime = item.schedule_time
? new Date(item.schedule_time.replace(' ', 'T')).getTime()
: item.datetime || 0
const createdAt = item.created_at
? new Date(item.created_at.replace(' ', 'T')).getTime()
: item.createdAt || datetime
const updatedAt = item.updated_at
? new Date(item.updated_at.replace(' ', 'T')).getTime()
: item.updatedAt || datetime
return {
...item,
id: item.id,
title,
content,
remindChannels,
remindMinutes: item.remindMinutes ?? 15
remindMinutes: item.advance_minutes ?? item.remindMinutes ?? 15,
completed: item.is_finished ?? item.completed ?? false,
datetime,
createdAt,
updatedAt
}
}
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 }
const data = await request({
url: '/app/schedule/list',
data: {
page: params.page || 1,
pageSize: params.pageSize || 50,
keyword: params.keyword || '',
status: params.status || ''
}
})
const list = (data.list || []).map(normalizeSchedule)
return { list, total: data.total || 0 }
}
/**
* 获取单条日程
*/
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
const data = await request({ url: `/app/schedule/${id}` })
return data ? normalizeSchedule(data) : 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 channels = (data.remindChannels || []).map(ch => {
if (ch === 'app') return 'SITE_MSG'
return ch.toUpperCase()
})
const list = readLocal()
list.push(schedule)
writeLocal(list)
return schedule
const res = await request({
url: '/app/schedule',
method: 'POST',
data: {
content: data.content,
schedule_time: formatDateTime(data.datetime),
remind_channels: channels,
advance_minutes: data.remindMinutes ?? 15
}
})
return res
}
/**
* 更新日程
*/
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()
const channels = (data.remindChannels || []).map(ch => {
if (ch === 'app') return 'SITE_MSG'
return ch.toUpperCase()
})
await request({
url: `/app/schedule/${id}`,
method: 'PUT',
data: {
content: data.content,
schedule_time: formatDateTime(data.datetime),
remind_channels: channels,
advance_minutes: data.remindMinutes ?? 15
}
})
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)
await request({ url: `/app/schedule/${id}`, method: 'DELETE' })
return true
}
@@ -212,13 +132,20 @@ export async function deleteSchedule(id) {
* 切换完成状态
*/
export async function toggleScheduleComplete(id) {
const item = await getSchedule(id)
if (!item) throw new Error('日程不存在')
return updateSchedule(id, { completed: !item.completed })
const res = await request({
url: `/app/schedule/${id}/toggle`,
method: 'POST'
})
return {
...res,
completed: res?.is_finished ?? false
}
}
export function getPriorityMeta(value) {
return PRIORITY[value] || PRIORITY.medium
function formatDateTime(timestamp) {
const d = new Date(timestamp)
const pad = n => String(n).padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
}
export function getRemindChannelLabel(value) {