feat(平台): 补齐服务端持久化和AI拆解契约

This commit is contained in:
Script Generator
2026-06-25 15:21:32 +08:00
parent 5723356d08
commit 5adc7759ad
73 changed files with 5599 additions and 368 deletions

View File

@@ -3,8 +3,7 @@ import { create } from 'zustand';
import type { OvertimeRecord } from '@/lib/overtime';
import type { DictItem } from '@/lib/requirement';
import { calcDuration } from '@/lib/overtime';
const STORAGE_KEY = 'ftb_overtime_v1';
import { loadServerData, saveServerData } from '@/lib/server-data';
const PRESET_REASONS: DictItem[] = [
{ id: 'reason-1', name: '需求变更', createdAt: '2024-01-01' },
@@ -20,19 +19,13 @@ const PRESET_REASONS: DictItem[] = [
{ id: 'reason-11', name: '返工修改', createdAt: '2024-01-01' },
];
const MOCK_RECORDS: OvertimeRecord[] = [
{ id: 'ot-1', projectId: 'p1', versionId: 'v2', person: '张三', startTime: '2024-12-10T19:00', endTime: '2024-12-10T22:30', duration: 3.5, reasonId: 'reason-3', createdAt: '2024-12-10' },
{ id: 'ot-2', projectId: 'p2', versionId: 'v5', person: '李四', startTime: '2024-12-11T18:30', endTime: '2024-12-11T21:00', duration: 2.5, reasonId: 'reason-1', createdAt: '2024-12-11' },
{ id: 'ot-3', projectId: 'p1', versionId: 'v2', person: '王五', startTime: '2024-12-12T19:00', endTime: '2024-12-12T23:00', duration: 4, reasonId: 'reason-4', createdAt: '2024-12-12' },
{ id: 'ot-4', projectId: 'p3', person: '张三', startTime: '2024-12-13T18:00', endTime: '2024-12-13T20:30', duration: 2.5, reasonId: 'reason-7', createdAt: '2024-12-13' },
{ id: 'ot-5', projectId: 'p2', versionId: 'v5', person: '赵六', startTime: '2024-12-14T19:30', endTime: '2024-12-15T01:00', duration: 5.5, reasonId: 'reason-5', remark: '线上紧急事故', createdAt: '2024-12-14' },
];
const MOCK_RECORDS: OvertimeRecord[] = [];
interface OvertimeState {
records: OvertimeRecord[];
reasons: DictItem[];
loading: boolean;
fetchRecords: () => void;
fetchRecords: () => Promise<void>;
createRecord: (data: Omit<OvertimeRecord, 'id' | 'duration' | 'createdAt'>) => void;
updateRecord: (id: string, data: Partial<OvertimeRecord>) => void;
deleteRecord: (id: string) => void;
@@ -41,14 +34,13 @@ interface OvertimeState {
deleteReason: (id: string) => void;
}
function saveLocal(data: { records: OvertimeRecord[]; reasons: DictItem[] }) {
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); } catch {}
function saveStored(data: { records: OvertimeRecord[]; reasons: DictItem[] }) {
saveServerData('overtime', data).catch(() => {});
}
function loadLocal(): { records: OvertimeRecord[]; reasons: DictItem[] } | null {
async function loadStored(): Promise<{ records: OvertimeRecord[]; reasons: DictItem[] } | null> {
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (raw) return JSON.parse(raw);
return await loadServerData<{ records: OvertimeRecord[]; reasons: DictItem[] }>('overtime');
} catch {}
return null;
}
@@ -58,8 +50,8 @@ export const useOvertimeStore = create<OvertimeState>((set, get) => ({
reasons: PRESET_REASONS,
loading: false,
fetchRecords: () => {
const cached = loadLocal();
fetchRecords: async () => {
const cached = await loadStored();
if (cached) set({ records: cached.records, reasons: cached.reasons });
},
@@ -73,7 +65,7 @@ export const useOvertimeStore = create<OvertimeState>((set, get) => ({
};
const records = [...get().records, record];
set({ records });
saveLocal({ records, reasons: get().reasons });
saveStored({ records, reasons: get().reasons });
},
updateRecord: (id, data) => {
@@ -86,31 +78,31 @@ export const useOvertimeStore = create<OvertimeState>((set, get) => ({
return updated;
});
set({ records });
saveLocal({ records, reasons: get().reasons });
saveStored({ records, reasons: get().reasons });
},
deleteRecord: (id) => {
const records = get().records.filter((r) => r.id !== id);
set({ records });
saveLocal({ records, reasons: get().reasons });
saveStored({ records, reasons: get().reasons });
},
addReason: (name) => {
const item: DictItem = { id: `reason-${Date.now()}`, name, createdAt: new Date().toISOString().slice(0, 10) };
const reasons = [...get().reasons, item];
set({ reasons });
saveLocal({ records: get().records, reasons });
saveStored({ records: get().records, reasons });
},
updateReason: (id, name) => {
const reasons = get().reasons.map((r) => r.id === id ? { ...r, name } : r);
set({ reasons });
saveLocal({ records: get().records, reasons });
saveStored({ records: get().records, reasons });
},
deleteReason: (id) => {
const reasons = get().reasons.filter((r) => r.id !== id);
set({ reasons });
saveLocal({ records: get().records, reasons });
saveStored({ records: get().records, reasons });
},
}));