'use client'; import { create } from 'zustand'; import type { Requirement, RequirementStatus, Effort, DictItem, SourceType, SourceTarget } from '@/lib/requirement'; import type { Priority } from '@/lib/derive'; import { loadServerData, saveServerData, SERVER_DATA_CACHE_MS } from '@/lib/server-data'; interface RequirementState { requirements: Requirement[]; sourceTargets: SourceTarget[]; types: DictItem[]; platforms: DictItem[]; loading: boolean; loaded: boolean; fetchRequirements: (options?: { force?: boolean }) => Promise; createRequirement: (data: Omit) => void; updateRequirement: (id: string, data: Partial) => void; deleteRequirement: (id: string) => void; addSourceTarget: (name: string, sourceType: SourceType) => void; updateSourceTarget: (id: string, name: string) => void; deleteSourceTarget: (id: string) => void; addType: (name: string) => void; updateType: (id: string, name: string) => void; deleteType: (id: string) => void; addPlatform: (name: string) => void; updatePlatform: (id: string, name: string) => void; deletePlatform: (id: string) => void; } // --- Preset dictionaries --- const PRESET_SOURCE_TARGETS: SourceTarget[] = []; const PRESET_TYPES: DictItem[] = [ { id: 'type-1', name: '新功能', createdAt: '2024-01-01' }, { id: 'type-2', name: 'BUG修复', createdAt: '2024-01-01' }, { id: 'type-3', name: '数据需求/埋点需求', createdAt: '2024-01-01' }, { id: 'type-4', name: '优化需求', createdAt: '2024-01-01' }, { id: 'type-5', name: '模块重构', createdAt: '2024-01-01' }, { id: 'type-6', name: '缺陷修复', createdAt: '2024-01-01' }, { id: 'type-7', name: '功能优化', createdAt: '2024-01-01' }, { id: 'type-8', name: '插单/紧急需求', createdAt: '2024-01-01' }, ]; const PRESET_PLATFORMS: DictItem[] = [ { id: 'platform-1', name: 'Web', createdAt: '2024-01-01' }, { id: 'platform-2', name: 'App(iOS)', createdAt: '2024-01-01' }, { id: 'platform-3', name: 'App(Android)', createdAt: '2024-01-01' }, { id: 'platform-4', name: '小程序', createdAt: '2024-01-01' }, { id: 'platform-5', name: 'H5', createdAt: '2024-01-01' }, ]; // --- Mock requirements --- const MOCK_REQUIREMENTS: Requirement[] = []; let lastRequirementsFetchAt = 0; // --- Server persistence helpers --- function saveStored(state: { requirements: Requirement[]; sourceTargets: SourceTarget[]; types: DictItem[]; platforms: DictItem[] }) { saveServerData('requirements', state).catch(() => {}); } async function loadStored(): Promise<{ requirements: Requirement[]; sourceTargets: SourceTarget[]; types: DictItem[]; platforms: DictItem[] } | null> { try { return await loadServerData<{ requirements: Requirement[]; sourceTargets: SourceTarget[]; types: DictItem[]; platforms: DictItem[] }>('requirements'); } catch {} return null; } // --- Store --- export const useRequirementStore = create((set, get) => { return { requirements: MOCK_REQUIREMENTS, sourceTargets: PRESET_SOURCE_TARGETS, types: PRESET_TYPES, platforms: PRESET_PLATFORMS, loading: false, loaded: false, fetchRequirements: async (options) => { if (!options?.force && get().loaded && Date.now() - lastRequirementsFetchAt < SERVER_DATA_CACHE_MS) return; const cached = await loadStored(); if (!options?.force && get().loaded && Date.now() - lastRequirementsFetchAt < SERVER_DATA_CACHE_MS) return; lastRequirementsFetchAt = Date.now(); if (cached) { set({ requirements: cached.requirements, sourceTargets: cached.sourceTargets, types: cached.types, platforms: cached.platforms, loaded: true }); } else { set({ loaded: true }); } }, createRequirement: (data) => { const { requirements, sourceTargets, types, platforms } = get(); const code = `REQ-${String(requirements.length + 1).padStart(3, '0')}`; const newReq: Requirement = { ...data, status: data.status ?? 'pending_review', id: `req-${Date.now()}`, code, createdAt: new Date().toISOString(), }; const updated = [...requirements, newReq]; set({ requirements: updated, loaded: true }); saveStored({ requirements: updated, sourceTargets, types, platforms }); }, updateRequirement: (id, data) => { const { requirements, sourceTargets, types, platforms } = get(); const updated = requirements.map((r) => (r.id === id ? { ...r, ...data } : r)); set({ requirements: updated, loaded: true }); saveStored({ requirements: updated, sourceTargets, types, platforms }); }, deleteRequirement: (id) => { const { requirements, sourceTargets, types, platforms } = get(); const updated = requirements.filter((r) => r.id !== id); set({ requirements: updated, loaded: true }); saveStored({ requirements: updated, sourceTargets, types, platforms }); }, // --- SourceTarget dict --- addSourceTarget: (name, sourceType) => { const { requirements, sourceTargets, types, platforms } = get(); const item: SourceTarget = { id: `st-${Date.now()}`, name, sourceType, createdAt: new Date().toISOString().slice(0, 10) }; const updated = [...sourceTargets, item]; set({ sourceTargets: updated, loaded: true }); saveStored({ requirements, sourceTargets: updated, types, platforms }); }, updateSourceTarget: (id, name) => { const { requirements, sourceTargets, types, platforms } = get(); const updated = sourceTargets.map((s) => (s.id === id ? { ...s, name } : s)); set({ sourceTargets: updated, loaded: true }); saveStored({ requirements, sourceTargets: updated, types, platforms }); }, deleteSourceTarget: (id) => { const { requirements, sourceTargets, types, platforms } = get(); const updated = sourceTargets.filter((s) => s.id !== id); set({ sourceTargets: updated, loaded: true }); saveStored({ requirements, sourceTargets: updated, types, platforms }); }, // --- Type dict --- addType: (name) => { const { requirements, sourceTargets, types, platforms } = get(); const item: DictItem = { id: `type-${Date.now()}`, name, createdAt: new Date().toISOString().slice(0, 10) }; const updated = [...types, item]; set({ types: updated, loaded: true }); saveStored({ requirements, sourceTargets, types: updated, platforms }); }, updateType: (id, name) => { const { requirements, sourceTargets, types, platforms } = get(); const updated = types.map((t) => (t.id === id ? { ...t, name } : t)); set({ types: updated, loaded: true }); saveStored({ requirements, sourceTargets, types: updated, platforms }); }, deleteType: (id) => { const { requirements, sourceTargets, types, platforms } = get(); const updated = types.filter((t) => t.id !== id); set({ types: updated, loaded: true }); saveStored({ requirements, sourceTargets, types: updated, platforms }); }, // --- Platform dict --- addPlatform: (name) => { const { requirements, sourceTargets, types, platforms } = get(); const item: DictItem = { id: `platform-${Date.now()}`, name, createdAt: new Date().toISOString().slice(0, 10) }; const updated = [...platforms, item]; set({ platforms: updated, loaded: true }); saveStored({ requirements, sourceTargets, types, platforms: updated }); }, updatePlatform: (id, name) => { const { requirements, sourceTargets, types, platforms } = get(); const updated = platforms.map((p) => (p.id === id ? { ...p, name } : p)); set({ platforms: updated, loaded: true }); saveStored({ requirements, sourceTargets, types, platforms: updated }); }, deletePlatform: (id) => { const { requirements, sourceTargets, types, platforms } = get(); const updated = platforms.filter((p) => p.id !== id); set({ platforms: updated, loaded: true }); saveStored({ requirements, sourceTargets, types, platforms: updated }); }, }; });