diff --git a/src/components/CustomerRemoveDialog.vue b/src/components/CustomerRemoveDialog.vue new file mode 100644 index 0000000..26cfd50 --- /dev/null +++ b/src/components/CustomerRemoveDialog.vue @@ -0,0 +1,151 @@ + + + + + diff --git a/src/pages/customer/CustomerDetail.vue b/src/pages/customer/CustomerDetail.vue index b01609c..3f73329 100644 --- a/src/pages/customer/CustomerDetail.vue +++ b/src/pages/customer/CustomerDetail.vue @@ -105,52 +105,12 @@ > - -
-
删除后无法恢复,将同时清除以下关联数据:
-
    -
  • 登记事件记录及其附件,并撤销这些登记产生的积分
  • -
  • 客户积分账户、标签和客户附件
  • -
  • 解除该客户与其被邀请客户之间的邀请关系,被邀请客户不会被删除
  • -
  • 减少该客户原介绍人的邀请客户计数
  • -
  • 客户档案本身
  • -
-
- 请输入客户姓名 - - 以确认删除 -
- -
- - -
+ :customer="removeTarget" + :loading="isRemoving" + @confirm="removeConfirmedCustomer" + /> @@ -163,6 +123,7 @@ import CustomerAPI from "@/api/CustomerAPI"; import PointAPI from "@/api/PointAPI"; import TagAPI from "@/api/TagAPI"; import BodyAreaSelector from "@/components/BodyAreaSelector.vue"; +import CustomerRemoveDialog from "@/components/CustomerRemoveDialog.vue"; import CustomerProfileCard from "@/components/CustomerProfileCard.vue"; import PhotoScroller from "@/components/PhotoScroller.vue"; import TagSelector from "@/components/TagSelector.vue"; @@ -190,15 +151,12 @@ const userStore = useUserStore(); const isRemoving = ref(false); const removeDialogVisible = ref(false); const removeTarget = ref(); -const removeConfirmName = ref(""); const canReadStat = computed(() => userStore.hasPermissions(permissionCodes.stat.read)); const canReadPointAccount = computed(() => userStore.hasPermissions(permissionCodes.point.accountRead)); const canReadTag = computed(() => userStore.hasPermissions(corePermissionCodes.tag.read)); const canApplyTag = computed(() => userStore.hasPermissions(corePermissionCodes.tag.apply)); const canUpdateCustomer = computed(() => userStore.hasPermissions(permissionCodes.customer.update)); -const removeCustomerName = computed(() => removeTarget.value?.name || ""); -const canConfirmRemove = computed(() => !!removeCustomerName.value && removeConfirmName.value === removeCustomerName.value); // ---------- 资料 ---------- @@ -375,25 +333,21 @@ async function confirmRemoveCustomer(): Promise { } removeTarget.value = currentCustomer; - removeConfirmName.value = ""; removeDialogVisible.value = true; } function closeRemoveDialog(): void { removeDialogVisible.value = false; removeTarget.value = undefined; - removeConfirmName.value = ""; } -async function removeConfirmedCustomer(): Promise { - const customerId = removeTarget.value?.id; - if (!customerId || !canConfirmRemove.value || isRemoving.value) { +async function removeConfirmedCustomer(target: Customer): Promise { + const customerId = target.id; + if (!customerId || isRemoving.value) { return; } - removeDialogVisible.value = false; - removeTarget.value = undefined; - removeConfirmName.value = ""; + closeRemoveDialog(); await removeCustomer(customerId); } @@ -531,45 +485,6 @@ onUnmounted(() => navBarStore.clearRight()); } } -.remove-dialog { - - :deep(.t-dialog__footer) { - gap: 1rem; - } - - .content { - text-align: left; - - .warning { - color: #b42318; - font-weight: 700; - } - - .items { - gap: .5rem; - height: 9rem; - margin: .75rem 0 1rem; - display: flex; - overflow-y: auto; - line-height: 1.2; - padding-left: 1.25rem; - flex-direction: column; - } - - .name { - font-weight: 700; - } - - .confirm-input { - --td-input-vertical-padding: 10px; - - border: 1px solid var(--td-component-border); - margin-top: .5rem; - border-radius: .75rem; - } - } -} - :global(html.theme-dark) { .customer-detail { @@ -581,17 +496,6 @@ onUnmounted(() => navBarStore.clearRight()); color: #94a3b8; } - .remove-dialog { - - .warning { - color: #fda29b; - } - - .confirm-input { - background: rgba(15, 23, 42, .72); - border-color: rgba(148, 163, 184, .16); - } - } } } diff --git a/src/pages/customer/CustomerList.vue b/src/pages/customer/CustomerList.vue index c7b7c22..9d3c31e 100644 --- a/src/pages/customer/CustomerList.vue +++ b/src/pages/customer/CustomerList.vue @@ -38,20 +38,34 @@ @scrolltolower="fetch" > + - + + +
@@ -60,6 +74,12 @@ v-model:visible="tagSelectorVisible" @change="handleTagFilterChanged" /> +
@@ -69,6 +89,7 @@ import { Message } from "@/utils/message"; import { Time, Toolkit, WebToolkit } from "timi-web"; import { type Page, type PageResult, useUserStore } from "timi-web-api"; import CustomerAPI from "@/api/CustomerAPI"; +import CustomerRemoveDialog from "@/components/CustomerRemoveDialog.vue"; import TagSelector from "@/components/TagSelector.vue"; import { useCurrentStoreStore } from "@/store/currentStoreStore"; import { useNavBarStore } from "@/store/navBarStore"; @@ -87,9 +108,14 @@ const currentStoreStore = useCurrentStoreStore(); const navBarStore = useNavBarStore(); const isRefreshing = ref(false); const isExporting = ref(false); +const isRemoving = ref(false); +const removeDialogVisible = ref(false); +const removeTarget = ref(); +const removingCustomerId = ref(""); const isGlobalManager = computed(() => userStore.hasRoles(gaoRoleCodes.globalManager)); const canReadTag = computed(() => userStore.hasPermissions(corePermissionCodes.tag.read)); const canCreateCustomer = computed(() => userStore.hasPermissions(permissionCodes.customer.create)); +const canDeleteCustomer = computed(() => userStore.hasPermissions(permissionCodes.customer.delete)); const canExportCustomer = computed(() => userStore.hasPermissions(permissionCodes.customer.export)); const canShowActionMenu = computed(() => canCreateCustomer.value || canExportCustomer.value); @@ -217,6 +243,44 @@ async function toCreate(): Promise { }); } +async function toDetail(customer: Customer): Promise { + if (!customer.id) { + return; + } + await router.push(`/management/customers/${customer.id}`); +} + +// ---------- 删除客户 ---------- + +function openRemoveDialog(customer: Customer): void { + if (!customer.id || isRemoving.value) { + return; + } + removeTarget.value = customer; + removeDialogVisible.value = true; +} + +async function removeCustomer(customer: Customer): Promise { + const customerId = customer.id; + if (!customerId || isRemoving.value) { + return; + } + + isRemoving.value = true; + removingCustomerId.value = customerId; + removeDialogVisible.value = false; + removeTarget.value = undefined; + try { + await CustomerAPI.remove(customerId); + pageResult.list = pageResult.list.filter(item => item.id !== customerId); + pageResult.total = Math.max(0, pageResult.total - 1); + Message.success("客户已删除"); + } finally { + isRemoving.value = false; + removingCustomerId.value = ""; + } +} + // ---------- 导出 ---------- async function doExport(): Promise { @@ -282,11 +346,10 @@ async function doExport(): Promise { .list-wrapper { padding: 1rem 0; - .items { - - .item { - padding: 10px; - } + .delete { + height: 100%; + padding: 0 1rem; + border-radius: 0; } }