功能(提醒):统一项目提醒中心与桌面通知链路
增加通用提醒状态、数据库迁移和定时同步,覆盖风险时效、文件回执、项目里程碑、访视窗口与协作申请。 新增网页端和桌面端提醒中心、真实投递诊断与固定隐私通知正文,并补齐登录来源聚合、测试和说明文档。
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { listGeneralNotifications, markGeneralNotificationRead } from "../api/notifications";
|
||||
import {
|
||||
listGeneralNotifications,
|
||||
markAllGeneralNotificationsRead,
|
||||
markGeneralNotificationRead,
|
||||
} from "../api/notifications";
|
||||
import { useStudyStore } from "../store/study";
|
||||
import type { GeneralNotificationFeed, GeneralNotificationItem } from "../types/notifications";
|
||||
|
||||
@@ -32,7 +36,7 @@ export const useProjectNotifications = () => {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const headerRemindersLoading = ref(false);
|
||||
const feed = ref<GeneralNotificationFeed>({ unread_count: 0, items: [] });
|
||||
const feed = ref<GeneralNotificationFeed>({ unread_count: 0, total_count: 0, items: [] });
|
||||
let requestId = 0;
|
||||
let pollTimer: number | undefined;
|
||||
|
||||
@@ -40,12 +44,12 @@ export const useProjectNotifications = () => {
|
||||
const studyId = study.currentStudy?.id;
|
||||
const currentRequest = ++requestId;
|
||||
if (!studyId || route.path.startsWith("/admin")) {
|
||||
feed.value = { unread_count: 0, items: [] };
|
||||
feed.value = { unread_count: 0, total_count: 0, items: [] };
|
||||
return;
|
||||
}
|
||||
headerRemindersLoading.value = true;
|
||||
try {
|
||||
const { data } = await listGeneralNotifications(studyId, 10);
|
||||
const { data } = await listGeneralNotifications(studyId, { limit: 10 });
|
||||
if (currentRequest === requestId && study.currentStudy?.id === studyId) feed.value = data;
|
||||
} catch {
|
||||
// 短时网络异常时保留当前内存中的提醒,避免角标在轮询失败时闪烁消失。
|
||||
@@ -67,6 +71,17 @@ export const useProjectNotifications = () => {
|
||||
const headerReminderBadgeValue = computed(() => headerReminderTotal.value > 99 ? "99+" : headerReminderTotal.value);
|
||||
|
||||
const handleReminderCommand = async (command: string) => {
|
||||
if (command === "notification:center") {
|
||||
await router.push("/project/notifications");
|
||||
return;
|
||||
}
|
||||
if (command === "notification:read-all") {
|
||||
const studyId = study.currentStudy?.id;
|
||||
if (!studyId || feed.value.unread_count <= 0) return;
|
||||
await markAllGeneralNotificationsRead(studyId);
|
||||
await loadHeaderReminders();
|
||||
return;
|
||||
}
|
||||
if (!command.startsWith("notification:")) return;
|
||||
const notificationId = command.slice("notification:".length);
|
||||
const item = feed.value.items.find((candidate) => candidate.id === notificationId);
|
||||
@@ -75,10 +90,15 @@ export const useProjectNotifications = () => {
|
||||
if (!item.read_at) {
|
||||
item.read_at = new Date().toISOString();
|
||||
feed.value.unread_count = Math.max(0, feed.value.unread_count - 1);
|
||||
await markGeneralNotificationRead(studyId, item.id).catch(() => {
|
||||
const response = await markGeneralNotificationRead(studyId, item.id).catch(() => {
|
||||
item.read_at = null;
|
||||
feed.value.unread_count += 1;
|
||||
return null;
|
||||
});
|
||||
if (response?.data.resolved_at) {
|
||||
feed.value.items = feed.value.items.filter((candidate) => candidate.id !== item.id);
|
||||
feed.value.total_count = Math.max(0, feed.value.total_count - 1);
|
||||
}
|
||||
}
|
||||
if (item.action_path?.startsWith("/")) await router.push(item.action_path);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user