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

129 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`:
```typescript
import { useRouter } from 'vue-router'
```
`const router = useRouter()`(放 script 顶部状态区,如 `const drawerOpen = ref(false)` 之前)。
加 handlers(放 `openDrawer` 附近):
```typescript
/** 客户昵称 → 该员工×客户 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):
```vue
<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):
```vue
<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):
```vue
<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**
```bash
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**
```bash
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'`)。