Files
Agent-System/web/src/data/storage.ts
T

198 lines
6.9 KiB
TypeScript

import { ProjectSession, ChatMessage, DeliverableItem } from '../types/workbench';
import { RoleDefinition } from '../types/rbac';
import { UserProfile } from '../types/docgov';
const STORAGE_PREFIX = 'smdf_agent_workbench_';
export const STORAGE_KEYS = {
SESSIONS: `${STORAGE_PREFIX}sessions`,
ACTIVE_SESSION: `${STORAGE_PREFIX}active_session`,
MESSAGES: `${STORAGE_PREFIX}messages`,
DELIVERABLES: `${STORAGE_PREFIX}deliverables`,
DOC_CACHE: `${STORAGE_PREFIX}doc_cache`,
ROLES: `${STORAGE_PREFIX}roles`,
USERS: `${STORAGE_PREFIX}users`,
};
/**
* 默认预设项目会话
*/
export const DEFAULT_SESSIONS: ProjectSession[] = [
{
sessionId: 'sess-001',
projectId: 1,
title: '4K超高清荧光内窥镜系统',
deviceType: '硬管荧光腹腔内窥镜',
stage: 'V0.5',
stageLabel: 'V0.5 方案成型与法规对齐',
messageCount: 3,
updatedAt: '14:20',
},
{
sessionId: 'sess-002',
projectId: 2,
title: '便携式掌上无线超声诊断仪',
deviceType: '便携式超声探头',
stage: 'V0.1',
stageLabel: 'V0.1 需求摸底与产品定义',
messageCount: 2,
updatedAt: '昨天',
},
];
/**
* 默认预设消息流(按 sessionId 严格隔离)
*/
export const DEFAULT_MESSAGES: ChatMessage[] = [
// sess-001 专属对话 (4K超高清荧光内窥镜)
{
id: 'm-001-0',
sessionId: 'sess-001',
role: 'system',
content: '水木东方协同参谋小队已就位,当前项目进入【V0.5 方案成型与法规对齐】阶段。',
timestamp: '14:00',
},
{
id: 'm-001-1',
sessionId: 'sess-001',
role: 'assistant',
authorName: '水木东方协同参谋',
intentTag: '🎯 推进立项阶段',
content:
'张工您好!参谋小队已依据法规知识库完成《4K超高清荧光内窥镜系统立项与可行性报告》初稿编制。右侧已就绪块状结构化视图,您可以直接审阅或下达修改指令。',
timestamp: '14:02',
phaseEvents: [
{ step: '1', icon: '👥', label: '组装小队', status: 'completed' },
{ step: '2', icon: '📚', label: '检索法规', status: 'completed' },
{ step: '3', icon: '⚙️', label: '执行编制', status: 'completed' },
{ step: '4', icon: '🛡️', label: '门禁把关', status: 'completed' },
],
recommendedCases: [
{
docId: 'SMDF-MD-2025-09',
taskKey: 'feasibility_reg',
artifactTitle: '4K硬管内窥镜摄像系统注册申报经验',
sectionTitle: '电气安全与高频电刀抗扰度评价',
similarityScore: 0.89,
keyRegulations: ['GB 9706.1-2020', 'IEC 60601-1-2'],
summarySnippet:
'在型式检验中,腹腔内窥镜主机需特别注意电刀高频耦合对荧光信噪比的干扰,建议在前端光电接收处增加硬件陷波滤波。',
},
],
},
// sess-002 专属对话 (便携式掌上无线超声诊断仪)
{
id: 'm-002-0',
sessionId: 'sess-002',
role: 'system',
content: '水木东方协同参谋小队已就位,当前项目进入【V0.1 需求摸底与产品定义】阶段。',
timestamp: '09:30',
},
{
id: 'm-002-1',
sessionId: 'sess-002',
role: 'assistant',
authorName: '水木东方协同参谋',
intentTag: '💡 掌超项目摸底',
content:
'张工,便携式掌上无线超声诊断仪立项需求摸底已启动!\n\n小队已针对其换能器阵元数 (128阵元)、无线 Wi-Fi 6 低延迟图传以及 GB 9706.237-2020 超声声输出安全标准进行技术基线梳理。您可以直接提出需求调整或测算指令。',
timestamp: '09:35',
phaseEvents: [
{ step: '1', icon: '🔍', label: '超声盲区探测', status: 'completed' },
{ step: '2', icon: '📋', label: '声功率标准初筛', status: 'completed' },
],
},
];
// ----------------------------------------------------------------------------------
// 安全的 localStorage 存取包装器
// ----------------------------------------------------------------------------------
function safeGetItem<T>(key: string, fallback: T): T {
if (typeof window === 'undefined' || !window.localStorage) return fallback;
try {
const item = window.localStorage.getItem(key);
if (!item) return fallback;
return JSON.parse(item) as T;
} catch (e) {
console.warn(`[storage] Failed to parse localStorage item: ${key}`, e);
return fallback;
}
}
function safeSetItem<T>(key: string, val: T): void {
if (typeof window === 'undefined' || !window.localStorage) return;
try {
window.localStorage.setItem(key, JSON.stringify(val));
} catch (e) {
console.warn(`[storage] Failed to set localStorage item: ${key}`, e);
}
}
export function loadSessions(): ProjectSession[] {
return safeGetItem<ProjectSession[]>(STORAGE_KEYS.SESSIONS, DEFAULT_SESSIONS);
}
export function saveSessions(sessions: ProjectSession[]): void {
safeSetItem(STORAGE_KEYS.SESSIONS, sessions);
}
export function loadActiveSessionId(fallback = 'sess-001'): string {
if (typeof window === 'undefined' || !window.localStorage) return fallback;
return window.localStorage.getItem(STORAGE_KEYS.ACTIVE_SESSION) || fallback;
}
export function saveActiveSessionId(sessionId: string): void {
if (typeof window === 'undefined' || !window.localStorage) return;
window.localStorage.setItem(STORAGE_KEYS.ACTIVE_SESSION, sessionId);
}
export function loadMessages(): ChatMessage[] {
return safeGetItem<ChatMessage[]>(STORAGE_KEYS.MESSAGES, DEFAULT_MESSAGES);
}
export function saveMessages(messages: ChatMessage[]): void {
safeSetItem(STORAGE_KEYS.MESSAGES, messages);
}
export function loadDeliverables(fallback: DeliverableItem[]): DeliverableItem[] {
return safeGetItem<DeliverableItem[]>(STORAGE_KEYS.DELIVERABLES, fallback);
}
export function saveDeliverables(deliverables: DeliverableItem[]): void {
safeSetItem(STORAGE_KEYS.DELIVERABLES, deliverables);
}
export function loadDocCache(): Record<string, string> {
return safeGetItem<Record<string, string>>(STORAGE_KEYS.DOC_CACHE, {});
}
export function saveDocCache(cache: Record<string, string>): void {
safeSetItem(STORAGE_KEYS.DOC_CACHE, cache);
}
export function loadRoles(fallback: RoleDefinition[]): RoleDefinition[] {
return safeGetItem<RoleDefinition[]>(STORAGE_KEYS.ROLES, fallback);
}
export function saveRoles(roles: RoleDefinition[]): void {
safeSetItem(STORAGE_KEYS.ROLES, roles);
}
export function loadUsers(fallback: UserProfile[]): UserProfile[] {
return safeGetItem<UserProfile[]>(STORAGE_KEYS.USERS, fallback);
}
export function saveUsers(users: UserProfile[]): void {
safeSetItem(STORAGE_KEYS.USERS, users);
}
/**
* resetWorkbenchStorage: 清空工作台缓存,恢复系统默认体验状态
*/
export function resetWorkbenchStorage(): void {
if (typeof window === 'undefined' || !window.localStorage) return;
Object.values(STORAGE_KEYS).forEach((k) => window.localStorage.removeItem(k));
}