This commit is contained in:
Your Name
2026-07-15 09:07:05 +08:00
parent f6688a740d
commit 796441b407
4 changed files with 398 additions and 161 deletions
+80 -5
View File
@@ -39,8 +39,16 @@
<div class="grid grid-cols-4 gap-4 mb-4">
<el-card shadow="hover">
<div class="text-gray-500 text-sm mb-1">总客户数</div>
<div class="text-gray-500 text-sm mb-1">总客户数去重</div>
<div class="text-2xl font-bold text-primary">{{ stats.total }}</div>
<el-tooltip
content="企微管理后台「全部客户」按客户×添加人关系计数:同一客户被 N 名员工添加计 N 条。与企微对账请看此数字。"
placement="bottom"
>
<div class="text-xs text-gray-400 mt-1 cursor-help">
跟进关系数企微口径{{ stats.relation_total }}
</div>
</el-tooltip>
</el-card>
<el-card shadow="hover" class="today-arrival-card cursor-pointer" @click="openArrivalDrawer">
<div class="flex items-center justify-between mb-1">
@@ -52,6 +60,9 @@
<div class="flex items-end gap-2">
<div class="text-2xl font-bold text-success leading-none">{{ stats.today }}</div>
<div class="text-xs text-gray-400 pb-1"></div>
<div v-if="arrival.returning > 0" class="text-xs text-warning pb-1">
含老客户 {{ arrival.returning }}
</div>
</div>
<!-- 24 小时分布迷你柱高度相对今日峰值等比 -->
<div class="hourly-bars mt-2" :title="hourlyTooltip">
@@ -114,6 +125,24 @@
@change="onAddTimeRangeChange"
/>
</el-form-item>
<el-form-item>
<template #label>
<el-tooltip
content="首次添加:客户第一次加入企业的时间在所选范围内。任意添加(企微口径):范围内发生过添加动作即算,含老客户被重加/被其他员工添加,与企微后台时间筛选一致。"
placement="top"
>
<span class="cursor-help">时间口径</span>
</el-tooltip>
</template>
<el-select
v-model="queryParams.add_time_mode"
class="!w-[180px]"
@change="onAddTimeModeChange"
>
<el-option label="首次添加" value="first" />
<el-option label="任意添加(企微口径)" value="any" />
</el-select>
</el-form-item>
<el-form-item label="标签">
<el-select
v-model="queryParams.tag_ids"
@@ -158,7 +187,23 @@
<div class="flex items-center gap-2">
<el-avatar :size="40" :src="row.avatar" />
<div>
<div class="font-medium">{{ row.name }}</div>
<div class="font-medium flex items-center gap-1">
<span>{{ row.name }}</span>
<el-tooltip
v-if="row.readd_flag"
content="这个人以前加过企业:被删除后重新添加,或已是企业客户又被其他员工添加"
placement="top"
>
<el-tag size="small" type="warning" effect="plain">以前加过</el-tag>
</el-tooltip>
<el-tooltip
v-if="row.is_deleted"
content="该客户已被删除/流失(企微中已不是企业客户),仅在「任意添加」口径下展示"
placement="top"
>
<el-tag size="small" type="danger" effect="plain">已删除</el-tag>
</el-tooltip>
</div>
<div class="text-xs text-gray-400">{{ row.external_userid }}</div>
</div>
</div>
@@ -278,6 +323,9 @@
<div class="flex items-center gap-3">
<span class="text-base font-semibold">今日进入明细</span>
<el-tag type="success" effect="plain"> {{ arrivalList.total }} </el-tag>
<el-tag v-if="arrival.returning > 0" type="warning" effect="plain">
老客户 {{ arrival.returning }}
</el-tag>
</div>
<el-button link type="primary" :loading="arrivalListLoading" @click="loadArrival(true)">
<template #icon><Refresh /></template>
@@ -331,8 +379,17 @@
{{ (row.customer_name || '?').slice(0, 1) }}
</el-avatar>
<div class="flex-1 min-w-0">
<div class="text-sm font-medium truncate">
{{ row.customer_name || row.external_userid || '(未知客户)' }}
<div class="text-sm font-medium truncate flex items-center gap-1">
<span class="truncate">
{{ row.customer_name || row.external_userid || '(未知客户)' }}
</span>
<el-tooltip
v-if="row.is_old_customer"
content="老客户回流:今天之前就加过企业(删除后重加,或已是其他员工的客户)"
placement="top"
>
<el-tag size="small" type="warning" effect="plain">老客户</el-tag>
</el-tooltip>
</div>
<div class="text-xs text-gray-500 mt-0.5">
<span>接待{{ row.admin_name || row.user_id || '—' }}</span>
@@ -469,6 +526,9 @@
</el-descriptions-item>
<el-descriptions-item label="类型">
{{ currentCustomer.type === 1 ? '微信用户' : '企业微信用户' }}
<el-tag v-if="currentCustomer.readd_flag" size="small" type="warning" effect="plain" class="ml-1">
以前加过
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="企业名称" :span="2">
{{ currentCustomer.corp_name || '—' }}
@@ -544,6 +604,7 @@ const currentCustomer = ref<any>(null)
const stats = reactive({
total: 0,
relation_total: 0,
today: 0,
today_follow_staff: 0,
lastSync: '',
@@ -575,12 +636,14 @@ const queryParams = reactive<{
tag_ids: string[]
add_time_start: string
add_time_end: string
add_time_mode: 'first' | 'any'
}>({
name: '',
follow_user: '',
tag_ids: [],
add_time_start: '',
add_time_end: ''
add_time_end: '',
add_time_mode: 'first'
})
/** 与列表「添加时间」列口径一致(库内 external_first_add_time / create_time */
@@ -597,6 +660,13 @@ function onAddTimeRangeChange(val: [string, string] | null) {
resetPage()
}
/** 口径切换只在已选时间范围时才需要重查 */
function onAddTimeModeChange() {
if (queryParams.add_time_start || queryParams.add_time_end) {
resetPage()
}
}
// ── 标签维度(筛选下拉 + 抽屉面板共用同一份数据) ──────────────────────────
interface TagItem {
tag_id: string
@@ -689,6 +759,7 @@ function filterByTag(tagId: string) {
interface ArrivalStats {
total: number
recent_time: number
returning: number
hourly: number[]
by_state: { state: string; count: number }[]
}
@@ -702,11 +773,13 @@ interface ArrivalItem {
customer_avatar: string
state: string
welcome_code: number
is_old_customer: number
}
const arrival = reactive<ArrivalStats>({
total: 0,
recent_time: 0,
returning: 0,
hourly: new Array(24).fill(0),
by_state: []
})
@@ -740,6 +813,7 @@ async function loadArrival(refreshList = false) {
if (res) {
arrival.total = Number(res.total ?? 0)
arrival.recent_time = Number(res.recent_time ?? 0)
arrival.returning = Number(res.returning ?? 0)
arrival.hourly = Array.isArray(res.hourly) && res.hourly.length === 24
? res.hourly.map((n: any) => Number(n) || 0)
: new Array(24).fill(0)
@@ -829,6 +903,7 @@ function handleReset() {
queryParams.tag_ids = []
queryParams.add_time_start = ''
queryParams.add_time_end = ''
queryParams.add_time_mode = 'first'
addTimeRange.value = null
resetParams()
}