'use client'; import { create } from 'zustand'; import type { Bug, BugStatus } from '@/lib/bug'; import { canBugTransition, generateBugNo } from '@/lib/bug'; const STORAGE_KEY = 'ftb_bugs_v1'; function saveLocal(items: Bug[]) { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(items)); } catch {} } function loadLocal(): Bug[] | null { try { const raw = localStorage.getItem(STORAGE_KEY); if (raw) return JSON.parse(raw); } catch {} return null; } interface BugState { bugs: Bug[]; fetchBugs: () => void; createBug: (data: Omit) => Bug; updateBug: (id: string, data: Partial) => void; deleteBug: (id: string) => void; changeStatus: (id: string, to: BugStatus, extra?: { resolution?: string }) => { ok: boolean; message?: string }; getByTestCase: (caseId: string) => Bug[]; getByVersion: (versionId: string) => Bug[]; getByAssignee: (assigneeId: string) => Bug[]; } export const useBugStore = create((set, get) => ({ bugs: [], fetchBugs: () => { const cached = loadLocal(); if (cached) set({ bugs: cached }); }, createBug: (data) => { const list = get().bugs; const now = new Date().toISOString(); const bug: Bug = { ...data, id: `bug-${Date.now()}`, bugNo: generateBugNo(list), status: 'open', createdAt: now, updatedAt: now, }; const updated = [...list, bug]; set({ bugs: updated }); saveLocal(updated); return bug; }, updateBug: (id, data) => { const updated = get().bugs.map((b) => b.id === id ? { ...b, ...data, updatedAt: new Date().toISOString() } : b, ); set({ bugs: updated }); saveLocal(updated); }, deleteBug: (id) => { const updated = get().bugs.filter((b) => b.id !== id); set({ bugs: updated }); saveLocal(updated); }, changeStatus: (id, to, extra) => { const bug = get().bugs.find((b) => b.id === id); if (!bug) return { ok: false, message: 'Bug不存在' }; if (!canBugTransition(bug.status, to)) { return { ok: false, message: `不允许从「${bug.status}」流转到「${to}」` }; } const today = new Date().toISOString().slice(0, 10); const patch: Partial = { status: to }; if (to === 'fixed') patch.resolvedAt = today; if (to === 'closed') patch.closedAt = today; if (extra?.resolution) patch.resolution = extra.resolution; get().updateBug(id, patch); return { ok: true }; }, getByTestCase: (caseId) => { return get().bugs.filter((b) => b.testCaseId === caseId); }, getByVersion: (versionId) => { return get().bugs.filter((b) => b.versionId === versionId); }, getByAssignee: (assigneeId) => { return get().bugs.filter((b) => b.assigneeId === assigneeId); }, }));