refactor(data): 收口关系表运行时数据源
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled

- 移除已迁移业务 AppData 运行时 fallback,改走领域 API 和关系表快读
- 补齐需求产品负责人、版本计划任务 JSON 和成员 username 回填迁移
- 统一治理字典入口,并补充 AI provider、数据源契约和领域服务测试

Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
2026-07-09 14:59:49 +08:00
parent 1e6fb0c7aa
commit 2e595c7e72
98 changed files with 2938 additions and 1441 deletions

View File

@@ -12,10 +12,9 @@ import {
updateBugStatusByVersionId,
} from '@/lib/domain-api';
import { scheduleSaveWithOptimisticRollback } from '@/lib/optimistic-persistence';
import { loadServerData, saveServerData, SERVER_DATA_CACHE_MS } from '@/lib/server-data';
import { SERVER_DATA_CACHE_MS } from '@/lib/server-data';
import type { WorkActivity } from '@/lib/work-activity';
import {
makeBugCreatedActivity,
makeBugStatusActivity,
makeBugTransferredActivity,
} from '@/lib/work-activity-factory';
@@ -23,13 +22,6 @@ import { useWorkActivityStore } from './useWorkActivityStore';
let lastBugsFetchAt = 0;
async function loadStored(): Promise<Bug[] | null> {
try {
return await loadServerData<Bug[]>('bugs');
} catch {}
return null;
}
function makeLog(action: BugLog['action'], operator: string, from?: string, to?: string, remark?: string): BugLog {
return { id: `log-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`, action, fromValue: from, toValue: to, operator, remark, createdAt: new Date().toISOString() };
}
@@ -53,13 +45,18 @@ export const useBugStore = create<BugState>((set, get) => ({
loaded: false,
fetchBugs: async (options) => {
if (!options?.force && get().loaded && Date.now() - lastBugsFetchAt < SERVER_DATA_CACHE_MS) return;
if (!options?.versionId && !options?.force && get().loaded && Date.now() - lastBugsFetchAt < SERVER_DATA_CACHE_MS) return;
const cached = options?.versionId
? await listBugsByVersionId(options.versionId).catch(loadStored)
: await loadStored();
if (!options?.force && get().loaded && Date.now() - lastBugsFetchAt < SERVER_DATA_CACHE_MS) return;
? await listBugsByVersionId(options.versionId).catch(() => [])
: get().bugs;
if (!options?.versionId && !options?.force && get().loaded && Date.now() - lastBugsFetchAt < SERVER_DATA_CACHE_MS) return;
lastBugsFetchAt = Date.now();
set({ bugs: cached ?? [], loaded: true });
set({
bugs: options?.versionId
? mergeBugsForVersion(get().bugs, options.versionId, cached ?? [])
: cached ?? [],
loaded: true,
});
},
createBug: (data, operator) => {
@@ -79,17 +76,12 @@ export const useBugStore = create<BugState>((set, get) => ({
set({ bugs: updated, loaded: true });
scheduleSaveWithOptimisticRollback({
save: async () => {
try {
const result = await createBugByVersionId(bug.versionId, bug);
set({
bugs: get().bugs.map((item) => (item.id === bug.id ? { ...bug, ...result.item, logs: bug.logs } : item)),
loaded: true,
});
appendDomainActivities(result.activities);
} catch {
await saveBugsFallback(updated);
useWorkActivityStore.getState().addActivity(makeBugCreatedActivity(bug, operator));
}
const result = await createBugByVersionId(bug.versionId, bug);
set({
bugs: get().bugs.map((item) => (item.id === bug.id ? { ...bug, ...result.item, logs: bug.logs } : item)),
loaded: true,
});
appendDomainActivities(result.activities);
},
expected: updated,
getCurrent: () => get().bugs,
@@ -106,14 +98,10 @@ export const useBugStore = create<BugState>((set, get) => ({
set({ bugs: updated, loaded: true });
scheduleSaveWithOptimisticRollback({
save: async () => {
try {
const versionId = previous.find((bug) => bug.id === id)?.versionId;
if (!versionId) throw new Error('missing versionId');
const result = await updateBugByVersionId(versionId, id, data);
appendDomainActivities(result.activities);
} catch {
await saveBugsFallback(updated);
}
const versionId = previous.find((bug) => bug.id === id)?.versionId;
if (!versionId) throw new Error('missing versionId');
const result = await updateBugByVersionId(versionId, id, data);
appendDomainActivities(result.activities);
},
expected: updated,
getCurrent: () => get().bugs,
@@ -127,13 +115,9 @@ export const useBugStore = create<BugState>((set, get) => ({
set({ bugs: updated, loaded: true });
scheduleSaveWithOptimisticRollback({
save: async () => {
try {
const versionId = previous.find((bug) => bug.id === id)?.versionId;
if (!versionId) throw new Error('missing versionId');
await deleteBugByVersionId(versionId, id);
} catch {
await saveBugsFallback(updated);
}
const versionId = previous.find((bug) => bug.id === id)?.versionId;
if (!versionId) throw new Error('missing versionId');
await deleteBugByVersionId(versionId, id);
},
expected: updated,
getCurrent: () => get().bugs,
@@ -157,17 +141,12 @@ export const useBugStore = create<BugState>((set, get) => ({
const activity = makeBugStatusActivity(bug, bug.status, to, operator);
scheduleSaveWithOptimisticRollback({
save: async () => {
try {
const result = await updateBugStatusByVersionId(bug.versionId, id, to, {
operator,
resolution: extra?.resolution,
});
appendDomainActivities(result.activities);
if (result.activities.length === 0 && activity) useWorkActivityStore.getState().addActivity(activity);
} catch {
await saveBugsFallback(updated);
if (activity) useWorkActivityStore.getState().addActivity(activity);
}
const result = await updateBugStatusByVersionId(bug.versionId, id, to, {
operator,
resolution: extra?.resolution,
});
appendDomainActivities(result.activities);
if (result.activities.length === 0 && activity) useWorkActivityStore.getState().addActivity(activity);
},
expected: updated,
getCurrent: () => get().bugs,
@@ -189,14 +168,9 @@ export const useBugStore = create<BugState>((set, get) => ({
set({ bugs: updated, loaded: true });
scheduleSaveWithOptimisticRollback({
save: async () => {
try {
const result = await transferBugByVersionId(bug.versionId, id, newAssigneeId, operator);
appendDomainActivities(result.activities);
if (result.activities.length === 0) useWorkActivityStore.getState().addActivity(activity);
} catch {
await saveBugsFallback(updated);
useWorkActivityStore.getState().addActivity(activity);
}
const result = await transferBugByVersionId(bug.versionId, id, newAssigneeId, operator);
appendDomainActivities(result.activities);
if (result.activities.length === 0) useWorkActivityStore.getState().addActivity(activity);
},
expected: updated,
getCurrent: () => get().bugs,
@@ -218,8 +192,11 @@ export const useBugStore = create<BugState>((set, get) => ({
},
}));
async function saveBugsFallback(bugs: Bug[]) {
await saveServerData('bugs', bugs);
function mergeBugsForVersion(current: Bug[], versionId: string, scopedBugs: Bug[]) {
return [
...current.filter((bug) => bug.versionId !== versionId),
...scopedBugs,
];
}
function appendDomainActivities(activities: WorkActivity[]) {