feat: 全面公告系统 + 全系统 Bug 修复

全面公告系统:
- notifications 表新增置顶/强提醒/定时发布/过期/配图/链接字段
- 后端增强:7 个接口(列表/置顶/未读数/已读/发布/编辑/删除)
- 首页强提醒公告弹窗
- 通知中心:置顶标记、配图展示、链接跳转、管理员操作
- 管理员发布表单:标题+内容+链接+配图+置顶+强提醒+定时+过期

Bug 修复:
- 401 重试队列竞态导致请求永久挂起
- 多分类筛选条件被静默丢弃
- 网络错误导致群组选择丢失
- Numpad 输入 '.' 显示异常
- transaction store 错误时清空数据
- 首页/预算页 Promise.all 部分失败阻塞关键数据
- CSS prefers-reduced-motion 类名不匹配
- 通知 read-all 遗漏群组通知
- auth.ts 错误日志缺少 stack trace
- stats 页面 v-for key 使用 index
- add 页面重复调用 fetchCategories
This commit is contained in:
wangxiaogang
2026-06-06 22:02:28 +08:00
parent 83571de723
commit a35689cdda
20 changed files with 1058 additions and 202 deletions

View File

@@ -9,6 +9,12 @@ export interface Notification {
is_read: number
created_at: string
group_id?: number | null
is_pinned?: number
is_urgent?: number
publish_at?: string | null
expire_at?: string | null
image_url?: string
link_url?: string
}
/** 通知列表响应 */
@@ -19,11 +25,30 @@ export interface NotificationList {
pageSize: number
}
/** 发布公告参数 */
export interface PublishParams {
title: string
content?: string
type?: 'system' | 'group' | 'personal'
group_id?: number
is_pinned?: boolean
is_urgent?: boolean
publish_at?: string
expire_at?: string
image_url?: string
link_url?: string
}
/** 获取通知列表 */
export function getNotifications(params?: { type?: string; page?: number; pageSize?: number }) {
return request<NotificationList>({ url: '/notifications', data: params })
}
/** 获取置顶/强提醒公告 */
export function getPinnedNotifications() {
return request<Notification[]>({ url: '/notifications/pinned' })
}
/** 获取未读数量 */
export function getUnreadCount() {
return request<{ count: number }>({ url: '/notifications/unread-count' })
@@ -39,7 +64,17 @@ export function markAllRead() {
return request({ url: '/notifications/read-all', method: 'PUT' })
}
/** 发布系统公告(管理员) */
export function publishNotification(data: { title: string; content?: string }) {
return request({ url: '/notifications', method: 'POST', data })
/** 发布公告 */
export function publishNotification(data: PublishParams) {
return request<{ id: number }>({ url: '/notifications', method: 'POST', data })
}
/** 编辑公告 */
export function updateNotification(id: number, data: Partial<PublishParams>) {
return request({ url: `/notifications/${id}`, method: 'PUT', data })
}
/** 删除公告 */
export function deleteNotification(id: number) {
return request({ url: `/notifications/${id}`, method: 'DELETE' })
}