diff --git a/yunkes/src/views/StaffList.vue b/yunkes/src/views/StaffList.vue index 6b459ad..90df382 100644 --- a/yunkes/src/views/StaffList.vue +++ b/yunkes/src/views/StaffList.vue @@ -335,16 +335,44 @@ const METRIC_TITLES: Record = { last_reply: '员工最后回复数', no_reply: '未回复客户数', } -// 对齐云客 spec §6:所有 modal 显示「客户微信」;仅「有效沟通数」modal 额外显示发送/接收数。 -// 序号需改 YkStaffDetailModal(spec §1 不改组件,略);员工信息/员工微信由 modal 标题承载,行内冗余故略。 -function commModalColsFor(metric: ChatMetric): any[] { - const cols: any[] = [{ prop: 'friend_name', label: '客户微信', minWidth: 180 }] +/** 拼接非空字段(过滤 '--'),全缺则 '--'。用于 modal 里员工信息/员工微信 单行显示。 */ +function joinFields(...vals: (string | undefined | null)[]): string { + const parts = vals.map((v) => (v == null ? '' : String(v).trim())).filter((v) => v && v !== '--') + return parts.length ? parts.join(' ') : '--' +} + +/** modal 客户微信 → 该员工×客户聊天(带 StaffList 当前日期窗)。缺失 owner/talker 静默 no-op。 */ +function openCustomerChat(row: Account, customer: StaffChatCustomer): void { + if (!row.account_id || !customer.talker_id) return + router.push({ + name: 'chat', + params: { channel: 'wechat', ownerId: row.account_id, talkerId: customer.talker_id }, + query: { start: String(statsStart.value), end: String(statsEnd.value) }, + }) +} + +// 对齐云客(2026-08-08 真机):序号 / 客户微信(可点→聊天) / [仅有效沟通:发送·接收] / 员工信息 / 员工微信。 +// 序号/员工信息/员工微信 靠 fetcher 注入字段实现,不改 YkStaffDetailModal(其 cols 仍 prop 驱动)。 +function commModalColsFor(metric: ChatMetric, row: Account): any[] { + const cols: any[] = [ + { prop: '_serial', label: '序号', width: 70, align: 'center' }, + { + prop: 'customer_wx', + label: '客户微信', + minWidth: 180, + onClick: (c: any) => openCustomerChat(row, c), + }, + ] if (metric === 'effective') { cols.push( { prop: 'send_count', label: '发送消息数', width: 110, align: 'center' }, { prop: 'receive_count', label: '接收消息数', width: 110, align: 'center' }, ) } + cols.push( + { prop: 'staff_info', label: '员工信息', minWidth: 140 }, + { prop: 'staff_wx', label: '员工微信', minWidth: 160 }, + ) return cols } /** 按 metric 过滤客户明细(口径见 spec §4;last_is_send 为 null 时既非最后回复也非未回复)。 */ @@ -366,7 +394,7 @@ function metricFilter(c: StaffChatCustomer, m: ChatMetric): boolean { /** 微信员工 5 数字 → 明细 modal(数据源:本地 staff-chat-stats,按 metric 过滤 + 合成分页)。 */ function openWechatCommModal(row: Account, metric: ChatMetric): void { detailTitle.value = `${METRIC_TITLES[metric]} · ${row.user_name ?? row.account_id}` - detailCols.value = commModalColsFor(metric) + detailCols.value = commModalColsFor(metric, row) detailFetcher.value = async (page: number, page_size: number): Promise> => { // 复用已缓存的 stats;点击早于列表加载完成则按需补拉。 let stats = staffStats.value[row.account_id] @@ -386,12 +414,16 @@ function openWechatCommModal(row: Account, metric: ChatMetric): void { } const filtered = stats.customers.filter((c) => metricFilter(c, metric)) const startIdx = (page - 1) * page_size - return { - items: filtered.slice(startIdx, startIdx + page_size), - total: filtered.length, - page, - page_size, - } + const staffInfo = joinFields(cellText(row, 'userName'), cellText(row, 'phone')) + const staffWx = joinFields(cellText(row, 'nickName'), row.account_id) + const items = filtered.slice(startIdx, startIdx + page_size).map((c, i) => ({ + ...c, + _serial: startIdx + i + 1, + customer_wx: joinFields(c.friend_name, c.talker_id), + staff_info: staffInfo, + staff_wx: staffWx, + })) + return { items, total: filtered.length, page, page_size } } detailOpen.value = true }