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:
@@ -50,19 +50,19 @@ export const useGroupStore = defineStore('group', () => {
|
||||
loading.value = true
|
||||
try {
|
||||
groups.value = await api.getGroups()
|
||||
|
||||
// 仅在成功获取后验证 currentGroupId 是否仍有效
|
||||
if (currentGroupId.value !== null) {
|
||||
const stillValid = groups.value.some(g => g.id === currentGroupId.value)
|
||||
if (!stillValid) {
|
||||
switchToPersonal()
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
groups.value = []
|
||||
// 网络失败时保留上次数据,不丢失群组选择
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
// 验证 currentGroupId 是否仍有效(群组可能已被解散或退出)
|
||||
if (currentGroupId.value !== null) {
|
||||
const stillValid = groups.value.some(g => g.id === currentGroupId.value)
|
||||
if (!stillValid) {
|
||||
switchToPersonal()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 创建群组 */
|
||||
|
||||
@@ -1,24 +1,34 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import * as api from '@/api/notification'
|
||||
import type { Notification } from '@/api/notification'
|
||||
|
||||
export const useNotificationStore = defineStore('notification', () => {
|
||||
const unreadCount = ref(0)
|
||||
const urgentNotifications = ref<Notification[]>([])
|
||||
|
||||
async function fetchUnreadCount() {
|
||||
const data = await api.getUnreadCount()
|
||||
unreadCount.value = data.count
|
||||
}
|
||||
|
||||
/** 获取未读的强提醒公告(首页弹窗用) */
|
||||
async function fetchUrgentNotifications() {
|
||||
urgentNotifications.value = await api.getPinnedNotifications()
|
||||
}
|
||||
|
||||
async function markRead(id: number) {
|
||||
await api.markRead(id)
|
||||
if (unreadCount.value > 0) unreadCount.value--
|
||||
// 从强提醒列表中移除
|
||||
urgentNotifications.value = urgentNotifications.value.filter(n => n.id !== id)
|
||||
}
|
||||
|
||||
async function markAllRead() {
|
||||
await api.markAllRead()
|
||||
unreadCount.value = 0
|
||||
urgentNotifications.value = []
|
||||
}
|
||||
|
||||
return { unreadCount, fetchUnreadCount, markRead, markAllRead }
|
||||
return { unreadCount, urgentNotifications, fetchUnreadCount, fetchUrgentNotifications, markRead, markAllRead }
|
||||
})
|
||||
|
||||
@@ -21,8 +21,7 @@ export const useTransactionStore = defineStore('transaction', () => {
|
||||
total.value = data.total
|
||||
return data
|
||||
} catch (err) {
|
||||
transactions.value = []
|
||||
total.value = 0
|
||||
// 不清空数据,保留上次成功的状态,避免并发请求失败时丢失已有数据
|
||||
throw err
|
||||
} finally {
|
||||
loading.value = false
|
||||
|
||||
Reference in New Issue
Block a user