feat(staffchat): 入口改造(StaffList/CustomerList微信行切新页)+useStaffProfile缓存+StatsPane固定列/金额格式+vitest依赖化
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,11 +4,12 @@
|
||||
根元素必须保持单 div——父组件 StaffChat 靠 attrs fallthrough 挂
|
||||
sc-root__pane 列宽。 -->
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { computed, ref, toRef, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { getAccounts, getStaffStatsCounts, getStaffStatsDetail } from '@/api'
|
||||
import { getStaffStatsCounts, getStaffStatsDetail } from '@/api'
|
||||
import type { StaffStatsKind } from '@/api'
|
||||
import type { Account, StaffStatsCounts } from '@/api/types'
|
||||
import type { StaffStatsCounts } from '@/api/types'
|
||||
import { useStaffProfile } from '@/composables/useStaffProfile'
|
||||
import {
|
||||
callDirectionLabel,
|
||||
formatCallDuration,
|
||||
@@ -74,6 +75,8 @@ interface Col {
|
||||
label: string
|
||||
/** link=客户/群点击跳聊天;staff=员工微信(资料卡);缺省按 prop 特判文本。 */
|
||||
kind?: 'link' | 'staff'
|
||||
/** 操作列固定右侧(对齐云客,防横向滚动时被挤出视口)。 */
|
||||
fixed?: 'right'
|
||||
}
|
||||
|
||||
const KIND_COLS: Partial<Record<KindKey, Col[]>> = {
|
||||
@@ -94,7 +97,7 @@ const KIND_COLS: Partial<Record<KindKey, Col[]>> = {
|
||||
{ prop: 'staff', label: '员工微信', kind: 'staff' },
|
||||
{ prop: 'amount', label: '金额' },
|
||||
{ prop: 'time', label: '发生时间' },
|
||||
{ prop: '_action', label: '操作' },
|
||||
{ prop: '_action', label: '操作', fixed: 'right' },
|
||||
],
|
||||
del_customers: [
|
||||
{ prop: 'nickname', label: '客户微信', kind: 'link' },
|
||||
@@ -137,18 +140,10 @@ function windowParams(): { start?: number; end?: number } {
|
||||
}
|
||||
|
||||
// ---- 员工微信列数据: 后端明细行无 staff 字段——数据本就是该员工的统计,
|
||||
// 用资料卡信息渲染(nickname/avatar,与 StaffChat 同款 getAccounts 手法) ----
|
||||
// 用资料卡信息渲染(nickname/avatar;useStaffProfile 与 StaffChat 资料卡
|
||||
// 共享模块级缓存,全 app 一份请求) ----
|
||||
|
||||
const profile = ref<Account | null>(null)
|
||||
|
||||
async function loadProfile(): Promise<void> {
|
||||
try {
|
||||
const res = await getAccounts({ channel: 'wechat', page: 1, page_size: 100 })
|
||||
profile.value = res.items.find(a => a.account_id === props.ownerId) ?? null
|
||||
} catch {
|
||||
profile.value = null // 后端未起: 员工列退化为 ownerId 兜底
|
||||
}
|
||||
}
|
||||
const { profile } = useStaffProfile(toRef(props, 'ownerId'))
|
||||
|
||||
const staffName = computed(() => profile.value?.nickname || props.ownerId)
|
||||
|
||||
@@ -231,7 +226,6 @@ watch(
|
||||
() => props.ownerId,
|
||||
() => {
|
||||
dateRange.value = defaultRange()
|
||||
void loadProfile()
|
||||
void loadCounts()
|
||||
void loadDetail()
|
||||
},
|
||||
@@ -431,7 +425,8 @@ function playRecord(row: StatsRow): void {
|
||||
v-for="col in activeCols"
|
||||
:key="col.prop"
|
||||
:label="col.label"
|
||||
:min-width="col.kind === 'link' || col.kind === 'staff' ? 150 : col.prop === '_action' ? 110 : 110"
|
||||
:fixed="col.fixed"
|
||||
:min-width="col.kind === 'link' || col.kind === 'staff' ? 150 : 110"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<!-- link 列: 客户/群 → 跳本员工聊天窗 -->
|
||||
@@ -473,7 +468,9 @@ function playRecord(row: StatsRow): void {
|
||||
|
||||
<!-- 时间/金额/操作列特判,其余纯文本 -->
|
||||
<template v-else-if="col.prop === 'time'">{{ formatTime(row.time) }}</template>
|
||||
<template v-else-if="col.prop === 'amount'">{{ row.amount ?? '—' }}</template>
|
||||
<template v-else-if="col.prop === 'amount'">{{
|
||||
row.amount != null ? '¥' + row.amount.toFixed(2) : '—'
|
||||
}}</template>
|
||||
<template v-else-if="col.prop === '_action'">
|
||||
<el-button link type="primary" size="small" @click="goChat(row, true)">
|
||||
查看聊天记录
|
||||
|
||||
Reference in New Issue
Block a user