From 0cc940837125cd2968ef2c3d3d1596416541f4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Tue, 11 Aug 2026 14:58:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(staff):=20WA=E5=91=98=E5=B7=A5=20modal=20?= =?UTF-8?q?=E5=88=97=E5=AF=B9=E9=BD=90=E4=BA=91=E5=AE=A2(=E5=BA=8F?= =?UTF-8?q?=E5=8F=B7/=E5=91=98=E5=B7=A5=E4=BF=A1=E6=81=AF/=E5=91=98?= =?UTF-8?q?=E5=B7=A5WhatsApp/=E5=AE=A2=E6=88=B7WhatsApp/=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=97=B6=E9=97=B4/=E6=9C=80=E5=90=8E=E6=B2=9F=E9=80=9A)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude --- yunkes/src/views/StaffList.vue | 58 +++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/yunkes/src/views/StaffList.vue b/yunkes/src/views/StaffList.vue index 871bba0..b3f6e55 100644 --- a/yunkes/src/views/StaffList.vue +++ b/yunkes/src/views/StaffList.vue @@ -270,12 +270,37 @@ const detailCols = ref([]) const fmtTime = (_r: any, _c: any, v: any): string => typeof v === 'number' && v > 0 ? formatTime(v) : v ? String(v) : '--' -const baseCustomerCols = [ - { prop: 'friend_nickname', label: '客户', minWidth: 140 }, - { prop: 'phone', label: '客户号码', width: 130 }, - { prop: 'last_chat_time', label: '最后沟通', width: 150, formatter: fmtTime }, - { prop: 'add_time', label: '添加时间', width: 150, formatter: fmtTime }, -] +/** + * WA 员工 modal 列(对齐云客 WA 真机,6 列): + * 序号 / 员工信息 / 员工WhatsApp / 客户WhatsApp / 添加时间 / 最后沟通时间. + * 序号/员工信息/员工WhatsApp/客户WhatsApp 为注入字段(同 Phase B 微信 modal 模式), + * 由 fetcher 在每条 Customer 上合成;add_time/last_chat_time 为 Customer 本身字段。 + */ +function waModalCols(_row: Account): any[] { + return [ + { prop: '_serial', label: '序号', width: 70, align: 'center' }, + { prop: 'staff_info', label: '员工信息', minWidth: 140 }, + { prop: 'staff_wx', label: '员工WhatsApp', minWidth: 140 }, + { prop: 'friend_wx', label: '客户WhatsApp', minWidth: 160 }, + { prop: 'add_time', label: '添加时间', width: 150, formatter: fmtTime }, + { prop: 'last_chat_time', label: '最后沟通时间', width: 150, formatter: fmtTime }, + ] +} + +/** 为 WA modal 一页 Customer 合成注入字段(序号跨页连续 + 员工/客户显示字段)。 */ +function injectWaModalFields(rows: any[], page: number, pageSize: number, row: Account): any[] { + const startIdx = (page - 1) * pageSize + const staffInfo = joinFields(cellText(row, 'userName'), cellText(row, 'phone')) + // WA 员工可能无 alias,用 nickName+phone,兜底 account_id。 + const staffWx = joinFields(cellText(row, 'nickName'), cellText(row, 'phone'), row.account_id) + return rows.map((c, i) => ({ + ...c, + _serial: startIdx + i + 1, + staff_info: staffInfo, + staff_wx: staffWx, + friend_wx: joinFields(c.friend_nickname, c.friend_id), + })) +} function openAddedModal(row: Account) { // ⚠️ WA customer has no add_time (Task 2 confirmed: WA raw_json lacks @@ -284,9 +309,16 @@ function openAddedModal(row: Account) { // 用 owner_account_id(=account_id,始终存在)而非 user_id(可能 null 导致全表泄漏)。 // 标题如实写"客户列表"——非"添加人数",因 WA 无法按 add_time 精确筛新增。 detailTitle.value = `客户列表 · ${row.user_name ?? row.account_id}` - detailCols.value = baseCustomerCols - detailFetcher.value = (p, s) => - getCustomers({ owner_account_id: row.account_id, channel: row.channel, page: p, page_size: s }) + detailCols.value = waModalCols(row) + detailFetcher.value = async (p, s) => { + const res = await getCustomers({ + owner_account_id: row.account_id, + channel: row.channel, + page: p, + page_size: s, + }) + return { ...res, items: injectWaModalFields(res.items, p, s, row) } + } detailOpen.value = true } @@ -295,15 +327,17 @@ function openTalkedModal(row: Account) { // channels). 用 owner_account_id(始终存在)而非 user_id(可能 null)。 const since = Date.now() - 7 * 86400000 detailTitle.value = `沟通人数 · ${row.user_name ?? row.account_id}` - detailCols.value = baseCustomerCols - detailFetcher.value = (p, s) => - getCustomers({ + detailCols.value = waModalCols(row) + detailFetcher.value = async (p, s) => { + const res = await getCustomers({ owner_account_id: row.account_id, channel: row.channel, last_chat_since: since, page: p, page_size: s, }) + return { ...res, items: injectWaModalFields(res.items, p, s, row) } + } detailOpen.value = true }