149 lines
4.5 KiB
TypeScript
149 lines
4.5 KiB
TypeScript
export type AccountLanguage = "zh-CN" | "en-US";
|
|
export type AccountAnswerDepth = "concise" | "balanced" | "deep";
|
|
export type AccountEvidenceDisplay = "summary" | "inline" | "full";
|
|
export type AccountNotificationKey = "pendingConfirmation" | "executionWriteback" | "releaseGate" | "failureAlert";
|
|
export type AccountSettingsSaveScope = "local" | "account";
|
|
|
|
export interface AccountProfileSettings {
|
|
displayName: string;
|
|
roleTitle: string;
|
|
email: string;
|
|
defaultLanguage: AccountLanguage;
|
|
}
|
|
|
|
export interface AccountAiPreferenceSettings {
|
|
answerDepth: AccountAnswerDepth;
|
|
evidenceDisplay: AccountEvidenceDisplay;
|
|
}
|
|
|
|
export interface AccountNotificationPreference {
|
|
enabled: boolean;
|
|
desktop: boolean;
|
|
emailDigest: boolean;
|
|
}
|
|
|
|
export type AccountNotificationSettings = Record<AccountNotificationKey, AccountNotificationPreference>;
|
|
|
|
export interface AccountSettings {
|
|
profile: AccountProfileSettings;
|
|
aiPreferences: AccountAiPreferenceSettings;
|
|
notifications: AccountNotificationSettings;
|
|
saveScope: AccountSettingsSaveScope;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface AccountSettingsSeed {
|
|
displayName?: string | null;
|
|
roleTitle?: string | null;
|
|
email?: string | null;
|
|
}
|
|
|
|
const STORAGE_KEY = "pmflow:account-settings:v1";
|
|
|
|
export const accountNotificationLabels: Record<AccountNotificationKey, { title: string; detail: string }> = {
|
|
pendingConfirmation: {
|
|
title: "待确认",
|
|
detail: "AI 生成草案、变更项或写入前确认需要你拍板时提醒。",
|
|
},
|
|
executionWriteback: {
|
|
title: "执行回写",
|
|
detail: "Agent、IDE 或集成系统回传开发进度、分支、PR 与测试结果时提醒。",
|
|
},
|
|
releaseGate: {
|
|
title: "发布门禁",
|
|
detail: "发布校验、合规检查、验收项阻塞或通过时提醒。",
|
|
},
|
|
failureAlert: {
|
|
title: "失败提醒",
|
|
detail: "AI 调用、同步任务、执行回写或外部集成失败时提醒。",
|
|
},
|
|
};
|
|
|
|
export const accountNotificationKeys: AccountNotificationKey[] = [
|
|
"pendingConfirmation",
|
|
"executionWriteback",
|
|
"releaseGate",
|
|
"failureAlert",
|
|
];
|
|
|
|
export function createDefaultAccountSettings(seed: AccountSettingsSeed = {}): AccountSettings {
|
|
return {
|
|
profile: {
|
|
displayName: seed.displayName?.trim() || "张子墨",
|
|
roleTitle: seed.roleTitle?.trim() || "产品负责人",
|
|
email: seed.email?.trim() || "",
|
|
defaultLanguage: "zh-CN",
|
|
},
|
|
aiPreferences: {
|
|
answerDepth: "balanced",
|
|
evidenceDisplay: "inline",
|
|
},
|
|
notifications: {
|
|
pendingConfirmation: { enabled: true, desktop: true, emailDigest: false },
|
|
executionWriteback: { enabled: true, desktop: true, emailDigest: false },
|
|
releaseGate: { enabled: true, desktop: true, emailDigest: true },
|
|
failureAlert: { enabled: true, desktop: true, emailDigest: true },
|
|
},
|
|
saveScope: "local",
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
}
|
|
|
|
function isBrowserStorageAvailable(): boolean {
|
|
return typeof window !== "undefined" && typeof window.localStorage !== "undefined";
|
|
}
|
|
|
|
function readStoredAccountSettings(): Partial<AccountSettings> | null {
|
|
if (!isBrowserStorageAvailable()) return null;
|
|
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
if (!raw) return null;
|
|
try {
|
|
const parsed = JSON.parse(raw) as Partial<AccountSettings>;
|
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function persistAccountSettings(settings: AccountSettings): void {
|
|
if (!isBrowserStorageAvailable()) {
|
|
throw new Error("当前环境不支持本机暂存");
|
|
}
|
|
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
|
|
}
|
|
|
|
function mergeAccountSettings(base: AccountSettings, stored: Partial<AccountSettings> | null): AccountSettings {
|
|
if (!stored) return base;
|
|
return {
|
|
...base,
|
|
...stored,
|
|
profile: {
|
|
...base.profile,
|
|
...stored.profile,
|
|
},
|
|
aiPreferences: {
|
|
...base.aiPreferences,
|
|
...stored.aiPreferences,
|
|
},
|
|
notifications: {
|
|
...base.notifications,
|
|
...stored.notifications,
|
|
},
|
|
};
|
|
}
|
|
|
|
export async function getAccountSettings(seed?: AccountSettingsSeed): Promise<AccountSettings> {
|
|
const defaults = createDefaultAccountSettings(seed);
|
|
return mergeAccountSettings(defaults, readStoredAccountSettings());
|
|
}
|
|
|
|
export async function updateAccountSettings(nextSettings: AccountSettings): Promise<AccountSettings> {
|
|
const persisted = {
|
|
...nextSettings,
|
|
saveScope: "local" as const,
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
persistAccountSettings(persisted);
|
|
return persisted;
|
|
}
|