Files
yunke/docs/superpowers/plans/2026-08-08-yunke-calllist-cell-click.md
T

6.5 KiB
Raw Blame History

CallList 列内可点(④,微信语音)Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans. Steps use checkbox (- [ ]).

Goal: CallList「微信语音」tab 的 客户信息/员工微信/员工信息 三类单元格可点,对齐云客(复用 Phase B 客户→1:1 chat + step 5 员工→账号级聊天窗 + drawer)。

Architecture: 纯前端,仅 CallList.vue。加 useRouter + chatChannel 映射 + viewCallCustomer/viewCallStaff 两个 handler + voice_call 模板 3 处单元格包 <el-button link>。WA语音/电话 tab 不动。

Tech Stack: Vue3+TS+Element Plus;门禁 vue-tsc -b。无后端、无路由、无新组件。

Spec: docs/superpowers/specs/2026-08-08-yunke-calllist-cell-click-design.md(已过审 + 已收窄至 voice_call)。


关键事实(plan 核实,codebase)

  • CallList.vue voice_call 模板块(<template v-if="callType === 'voice_call'">)现有 6 列:通话信息 / 客户信息 / 员工微信 / 员工信息 / 通话录音 / 通话时长。
    • 客户信息 单元格:<div>{{ cell(row, 'talkerNickName') || '--' }}</div> + 子行 call_number || cell(row,'talker')。
    • 员工微信 单元格:<div>{{ cell(row, 'userWeChatNickName') || '--' }}</div> + 子行 cell(row,'userWeChatAlias') || cell(row,'weChatId')。
    • 员工信息 单元格:<div>{{ row.user_id_name || '--' }}</div> + 子行 cell(row,'userPhone')。
  • cell(row, camelKey) 已存在(包装 readField)。openDrawer(row) 已存在。
  • PhoneCall(api/types.ts):channel(通话类型 voice_call/wa_voice_call/phone_call)、user_id/user_id_name、call_number、raw_json。
  • 路由 /chat/:channel/:ownerId/:talkerId?(name 'chat',talkerId 可选)—— account 级 /chat/wechat/{owner} 与 1:1 /chat/wechat/{owner}/{talker} 都可用(step 5/Phase B 已建)。
  • CALL_FIELD_LABELS(callFields.ts)含 weChatId、talker——可经 cell() 读。
  • 云客真机(2026-08-08):客户→detail/message/{owner}/{talker}、员工→wechat-window/1/{owner}、员工姓名→详情页。

文件清单

  • 改 yunkes/src/views/CallList.vue(仅 voice_call 模板 3 处 + script 加 router/handlers)。仅此一文件。

Task 1: CallList 微信语音 单元格可点

Files: Modify yunkes/src/views/CallList.vue(仅此一文件)。

  • Step 1: script 加 router + handlers

import { computed, onMounted, ref } from 'vue' 行附近加 useRouter:

import { useRouter } from 'vue-router'

const router = useRouter()(放 script 顶部状态区,如 const drawerOpen = ref(false) 之前)。

加 handlers(放 openDrawer 附近):

/** 客户昵称 → 该员工×客户 1:1 聊天(复用 Phase B 导航)。 */
function viewCallCustomer(row: PhoneCall): void {
  const owner = cell(row, 'weChatId')
  const talker = cell(row, 'talker')
  if (!owner || !talker) return
  router.push({
    name: 'chat',
    params: { channel: 'wechat', ownerId: String(owner), talkerId: String(talker) },
  })
}

/** 员工微信昵称 → 账号级聊天窗(复用 step 5 导航)。 */
function viewCallStaff(row: PhoneCall): void {
  const owner = cell(row, 'weChatId')
  if (!owner) return
  router.push({ name: 'chat', params: { channel: 'wechat', ownerId: String(owner) } })
}

本 plan 仅微信语音(voice_call→'wechat' 硬编码)。WA 映射 chatChannel()(voice_call→wechat, wa_voice_call→whatsapp)留待 WA tab 实现时再加(避免 noUnusedLocals 死代码)。PhoneCall 已在 import。

  • Step 2: voice_call 模板 3 处单元格包 link button

<template v-if="callType === 'voice_call'"> 内:

客户信息 列(约 line 170):

<el-button v-if="cell(row, 'talkerNickName')" link type="primary" size="small" class="yk-cell__main" @click.stop="viewCallCustomer(row)">{{ cell(row, 'talkerNickName') }}</el-button>
<span v-else class="yk-cell__main">--</span>

(替换原 <div>{{ cell(row, 'talkerNickName') || '--' }}</div>;子行 call_number || talker 不变。)

员工微信 列(约 line 177):

<el-button v-if="cell(row, 'userWeChatNickName')" link type="primary" size="small" class="yk-cell__main" @click.stop="viewCallStaff(row)">{{ cell(row, 'userWeChatNickName') }}</el-button>
<span v-else class="yk-cell__main">--</span>

(替换原 <div>{{ cell(row, 'userWeChatNickName') || '--' }}</div>;子行不变。)

员工信息 列(约 line 183):

<el-button v-if="row.user_id_name" link type="primary" size="small" class="yk-cell__main" @click.stop="openDrawer(row)">{{ row.user_id_name }}</el-button>
<span v-else class="yk-cell__main">--</span>

(替换原 <div>{{ row.user_id_name || '--' }}</div>;子行 userPhone 不变。)

@click.stop 阻止冒泡到 row-click(避免同时开 drawer)。class="yk-cell__main" 让按钮文字继承主文本样式(13px);可在 <style scoped> 加 .yk-cell__main { font-size: 13px; }(若需要;el-button link 默认字号可能略偏)。

  • Step 3: vue-tsc
cd /d/refactor/yunke/yunkes && npx vue-tsc -b

Expected: exit 0。

  • Step 4: 浏览器实测

启动后端(smoke.db)+前端。/calls → 微信语音 tab:

  • 点客户昵称 → /chat/wechat/{owner}/{talker}(侧栏+该会话+消息)。

  • 点员工微信昵称 → /chat/wechat/{owner}(账号级聊天窗+空态或会话列表)。

  • 点员工姓名 → drawer。

  • 行点击空白处 → drawer(row-click 不受影响)。

  • 缺字段格显 --(不可点);WA语音/电话 tab 不变。

  • Step 5: Commit

git add yunkes/src/views/CallList.vue
git commit -m "feat(calls): CallList 微信语音 客户/员工/姓名 单元格可点(复用聊天导航,对齐云客)"

End with blank line + Co-Authored-By: Claude <noreply@anthropic.com>。


验收(spec §6)

  • vue-tsc -b exit 0。
  • 浏览器(本地 smoke.db,无云客):微信语音 三单元格可点且跳转正确;缺字段 -- 不可点;WA语音/电话 不变;row-click→drawer 不变;network 仅 localhost。

风险

  • weChatId/talker 缺失:守卫已加(if (!owner || !talker) return),该格显 -- 不可点。
  • WA语音/电话:本 plan 不动;WA 待云客真机核实其 WA 语音列表后另做(小补丁,复用同 handler + chatChannel('wa_voice_call')→'whatsapp')。