Files
deerflow-code/frontend-web/src/core/notifications/api.ts
T
吉鑫升andClaude Opus 4.8 5ecf28e60c feat(y-log/knowledge): 日志前缀改 CM助手-全量 + 入库 nodeName 按标题去时间戳保持一致
1. Y-Log 上报 optDetail 前缀 B1-CM助手 → CM助手-全量(全量替换 44 个前端文件 + 文档)
2. 知识库入库 nodeName 改为只取 md5(标题).md(去掉时间戳),同一篇 md 每次入库一致,避免重复记录

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 15:46:51 +08:00

82 lines
3.0 KiB
TypeScript

import { apiFetch } from "@/core/api";
import { getBackendBaseURL } from "@/core/config";
import { OptType, writeYLog } from "@/core/log/y-log";
import type {
NotificationItem,
NotificationListResponse,
NotificationUnreadCountResponse,
} from "./types";
async function parseDetail(res: Response, fallback: string): Promise<Error> {
const data = (await res.json().catch(() => ({}))) as { detail?: unknown };
const detail = typeof data.detail === "string" && data.detail ? data.detail : null;
return new Error(detail ?? `${fallback} (HTTP ${res.status})`);
}
export async function listNotifications(
options: { unreadOnly?: boolean; limit?: number } = {},
): Promise<NotificationItem[]> {
const params = new URLSearchParams();
if (options.unreadOnly) params.set("unread_only", "true");
if (options.limit) params.set("limit", String(options.limit));
const query = params.toString();
const url = `${getBackendBaseURL()}/api/notifications${query ? `?${query}` : ""}`;
const res = await apiFetch(url);
if (!res.ok) throw await parseDetail(res, "Failed to list notifications");
const data = (await res.json()) as NotificationListResponse;
writeYLog({
optType: OptType.search,
optDetail: "CM助手-全量-通知-查询通知列表",
url,
reqParam: options,
returnParam: { count: data.items.length },
});
return data.items;
}
export async function getUnreadCount(): Promise<number> {
const res = await apiFetch(`${getBackendBaseURL()}/api/notifications/unread_count`);
if (!res.ok) throw await parseDetail(res, "Failed to load unread count");
const data = (await res.json()) as NotificationUnreadCountResponse;
return data.unread;
}
export async function markNotificationRead(id: string): Promise<void> {
const url = `${getBackendBaseURL()}/api/notifications/${encodeURIComponent(id)}/read`;
const res = await apiFetch(url, { method: "POST" });
if (!res.ok) throw await parseDetail(res, "Failed to mark notification read");
writeYLog({
optType: OptType.edit,
optDetail: "CM助手-全量-通知-标记已读",
url,
reqParam: { id },
});
}
export async function markAllNotificationsRead(): Promise<number> {
const url = `${getBackendBaseURL()}/api/notifications/read_all`;
const res = await apiFetch(url, { method: "POST" });
if (!res.ok) throw await parseDetail(res, "Failed to mark all read");
const data = (await res.json()) as { updated: number };
writeYLog({
optType: OptType.edit,
optDetail: "CM助手-全量-通知-全部标记已读",
url,
returnParam: data,
});
return data.updated;
}
export async function deleteNotification(id: string): Promise<void> {
const url = `${getBackendBaseURL()}/api/notifications/${encodeURIComponent(id)}`;
const res = await apiFetch(url, { method: "DELETE" });
if (!res.ok) throw await parseDetail(res, "Failed to delete notification");
writeYLog({
optType: OptType.delete,
optDetail: "CM助手-全量-通知-删除通知",
url,
reqParam: { id },
});
}