From 675704e4daf9528e604b6969c714f8fc82ce0b03 Mon Sep 17 00:00:00 2001 From: xiaomai Date: Tue, 14 Oct 2025 10:43:23 +0800 Subject: [PATCH] feat(item): add delete functionality This commit introduces the ability to delete items. A new `ItemDeleteModal` component provides a confirmation step before removal. - Adds a 'Delete' option to the action menu in the items table. - Refactors the `useItems` composable to ensure reactivity with `useLocalStorage` by creating new array references on add/remove operations. - Renames `AddModal` to `EditModal` to better align with its future role in both adding and editing items. --- app/components/item/DeleteModal.vue | 53 +++++++++++++++++++ .../item/{AddModal.vue => EditModal.vue} | 0 app/composables/items.ts | 37 +++++++------ app/layouts/default.vue | 2 +- app/pages/index.vue | 47 +++++++++++----- 5 files changed, 109 insertions(+), 30 deletions(-) create mode 100644 app/components/item/DeleteModal.vue rename app/components/item/{AddModal.vue => EditModal.vue} (100%) diff --git a/app/components/item/DeleteModal.vue b/app/components/item/DeleteModal.vue new file mode 100644 index 0000000..5fcd2fc --- /dev/null +++ b/app/components/item/DeleteModal.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/app/components/item/AddModal.vue b/app/components/item/EditModal.vue similarity index 100% rename from app/components/item/AddModal.vue rename to app/components/item/EditModal.vue diff --git a/app/composables/items.ts b/app/composables/items.ts index d39c68b..e822d9f 100644 --- a/app/composables/items.ts +++ b/app/composables/items.ts @@ -1,6 +1,5 @@ import { useLocalStorage, createSharedComposable } from "@vueuse/core"; -// 类型定义 export type Item = { id: number; name: string; @@ -12,9 +11,10 @@ export type Item = { }; const _useItems = () => { - const items = useLocalStorage("item-database", [], { + const stored = useLocalStorage("item-database", [], { serializer: { read: (v) => { + if (!v) return []; const parsed = JSON.parse(v); return parsed.map((item: any) => ({ ...item, @@ -26,34 +26,37 @@ const _useItems = () => { }, }); + // 直接使用 stored(Ref)。模板会自动解包,其他逻辑也简单。 + const items = stored; // Ref + + // 统计项使用 items.value const stats = { - totalItems: computed(() => items.value.length), + totalItems: computed(() => (items.value ?? []).length), addedThisMonth: computed(() => { const now = new Date(); const thisMonth = now.getMonth(); const thisYear = now.getFullYear(); - - let count = 0; - for (const item of items.value) { - const date = item.createdAt; - if (date.getMonth() === thisMonth && date.getFullYear() === thisYear) { - count++; - } - } - return count; + 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 + () => (items.value?.[items.value.length - 1]?.id ?? 0) + 1 ), }; const isNameAvailable = (name: string) => - !items.value.some((item) => item.name === name); + !(items.value ?? []).some((item) => item.name === name); - const addItem = (item: Item) => items.value.push(item); + const addItem = (item: Item) => { + items.value = [...(items.value ?? []), item]; // <-- 替换数组引用 + }; - const removeItem = (id: number) => - (items.value = items.value.filter((i) => i.id !== id)); + const removeItem = (id: number) => { + items.value = (items.value ?? []).filter((i) => i.id !== id); // <-- 替换数组引用 + }; return { items, stats, isNameAvailable, addItem, removeItem }; }; diff --git a/app/layouts/default.vue b/app/layouts/default.vue index 5366a0a..3ab660b 100644 --- a/app/layouts/default.vue +++ b/app/layouts/default.vue @@ -36,7 +36,7 @@ const items = computed(() => [ { label: "物品管理", to: "/", - icon: "marketeq:home-alt-3", + icon: "marketeq:box", }, { label: "导出配置", diff --git a/app/pages/index.vue b/app/pages/index.vue index 9190023..260538f 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -1,10 +1,10 @@ + + @@ -104,15 +109,23 @@