This commit is contained in:
Timi
2026-08-13 17:36:59 +08:00
parent 37d7972cf9
commit 6ebd83edbc
11 changed files with 975 additions and 27 deletions
+64 -1
View File
@@ -23,6 +23,12 @@
<t-cell title="录入用户" :note="Text.display(customer.creatorUser?.nick || customer.creatorUser?.name)" />
<t-cell title="录入时间" :note="Time.toPassedDateTime(customer.createdAt)" />
</t-cell-group>
<customer-tag-card
v-if="customer && canReadTag"
:editable="canApplyTag"
:tag-list="customerTagList"
@edit="openTagSelector"
/>
<t-cell-group v-if="customer" theme="card">
<t-cell v-if="canReadStat" title="客户数据图表" arrow @click="toCustomerDataCharts">
<template #left-icon>
@@ -121,6 +127,11 @@
v-model:visible="selectorVisible"
@change="handleInviteeSelected"
/>
<tag-selector
v-model="selectedTagIdList"
v-model:visible="tagSelectorVisible"
@change="handleTagSelected"
/>
<t-popup v-model="scanPopupVisible" placement="bottom">
<div class="scan-popup bg-white">
<div class="header">
@@ -159,15 +170,19 @@ import { DialogPlugin, Toast } from "tdesign-mobile-vue";
import { Text, Time, useUserStore } from "timi-web";
import CustomerAPI from "@/api/CustomerAPI";
import PointAPI from "@/api/PointAPI";
import TagAPI from "@/api/TagAPI";
import BodyAreaSelector from "@/components/BodyAreaSelector.vue";
import CodeScanner from "@/components/CodeScanner.vue";
import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
import CustomerSelector from "@/components/CustomerSelector.vue";
import TagSelector from "@/components/TagSelector.vue";
import CustomerTagCard from "@/pages/customer/component/CustomerTagCard.vue";
import { useSettingStore } from "@/store/settingStore";
import type { BodyAreaValue, Customer } from "@/types/Customer";
import type { PointAccount } from "@/types/Point";
import type { Tag } from "@/types/Tag";
import { getCustomerPhotoURL, normalizeBodyAreaValue } from "@/utils/customer";
import { permissionCodes } from "@/utils/permission";
import { corePermissionCodes, permissionCodes } from "@/utils/permission";
import { LunarCalendar } from "@/utils/LunarCalendar";
defineOptions({
@@ -183,6 +198,8 @@ const isRemoving = ref(false);
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));
// ---------- 资料 ----------
@@ -226,6 +243,8 @@ async function loadCustomer(): Promise<void> {
const id = String(route.params.id || "");
if (!id) {
customer.value = undefined;
customerTagList.value = [];
selectedTagIdList.value = [];
invitees.value = [];
showSolarBirthdate.value = false;
return;
@@ -235,15 +254,59 @@ async function loadCustomer(): Promise<void> {
showSolarBirthdate.value = false;
customer.value = await CustomerAPI.detail(id);
await loadPointAccount();
await loadCustomerTags();
await loadInvitees();
} catch (err) {
customer.value = undefined;
customerTagList.value = [];
selectedTagIdList.value = [];
invitees.value = [];
console.warn("客户详情加载失败", err);
Toast.warning("客户详情加载失败");
}
}
// ---------- 客户标签 ----------
const customerTagList = ref<Tag[]>([]);
const selectedTagIdList = ref<string[]>([]);
const tagSelectorVisible = ref(false);
async function loadCustomerTags(): Promise<void> {
const customerId = customer.value?.id;
if (!customerId || !canReadTag.value) {
customerTagList.value = [];
selectedTagIdList.value = [];
return;
}
customerTagList.value = await TagAPI.listByBizType("GAO_CUSTOMER", customerId);
selectedTagIdList.value = customerTagList.value.map(item => item.id || "").filter(Boolean);
}
function openTagSelector(): void {
if (!canApplyTag.value) {
return;
}
selectedTagIdList.value = customerTagList.value.map(item => item.id || "").filter(Boolean);
tagSelectorVisible.value = true;
}
async function handleTagSelected(tagList: Tag[]): Promise<void> {
const customerId = customer.value?.id;
if (!customerId) {
return;
}
await TagAPI.apply({
bizType: "GAO_CUSTOMER",
bizId: customerId,
tagIdList: tagList.map(item => item.id || "").filter(Boolean)
});
customerTagList.value = tagList;
selectedTagIdList.value = tagList.map(item => item.id || "").filter(Boolean);
Toast.success("客户标签已保存");
}
// ---------- 邀请来源和邀请列表 ----------
let latestDecodedText = "";
const invitees = ref<Customer[]>([]);