import { useLocalStorage, createSharedComposable } from "@vueuse/core"; export type Item = { id: number; name: string; imageUrl?: string | null; description?: string | null; tags?: string[] | null; createdAt: Date; updatedAt: Date; }; const _useItems = () => { const stored = useLocalStorage("item-database", [], { serializer: { read: (v) => { if (!v) return []; const parsed = JSON.parse(v); return parsed.map((item: any) => ({ ...item, createdAt: new Date(item.createdAt), updatedAt: new Date(item.updatedAt), })); }, write: (v) => JSON.stringify(v), }, }); // 直接使用 stored(Ref)。模板会自动解包,其他逻辑也简单。 const items = stored; // Ref // 统计项使用 items.value const stats = { totalItems: computed(() => (items.value ?? []).length), addedThisMonth: computed(() => { const now = new Date(); const thisMonth = now.getMonth(); const thisYear = now.getFullYear(); return (items.value ?? []).filter( (item) => item.createdAt.getMonth() === thisMonth && item.createdAt.getFullYear() === thisYear ).length; }), latestId: computed( () => (items.value?.[items.value.length - 1]?.id ?? 0) + 1 ), }; const isNameAvailable = (name: string) => !(items.value ?? []).some((item) => item.name === name); const addItem = (item: Item) => { items.value = [...(items.value ?? []), item]; // <-- 替换数组引用 }; const removeItem = (id: number) => { items.value = (items.value ?? []).filter((i) => i.id !== id); // <-- 替换数组引用 }; return { items, stats, isNameAvailable, addItem, removeItem }; }; export const useItemsStore = createSharedComposable(_useItems);