feat(agent): 坐席端左栏会话状态 Tab 顺序调整 + 默认显示待处理 (#134)

**改动**
- `src/frontend-agent/src/components/conversation/ConversationList.vue`
  - `filterTags` 数组顺序倒置:`[全部, 待处理, 进行中, 已完成]` → `[待处理, 进行中, 已完成, 全部]`
  - `activeFilter` 初始值 `'all'` → `'pending'`(坐席日常首选入口)
- `docs/07-项目管理/任务说明书/任务说明书-134-坐席端左栏会话状态Tab顺序调整+默认显示待处理.md`(新增)

**未改**
- 不动 store(`myConversations` / `colleagueConversations` / `historyConversations` 划分准确)
- 不动 `applyFilters` 逻辑(status 映射正确:pending→queued、active→serving/ai_handling、done→resolved)
- 不动 ConversationItem.vue / 样式 / backend API
- 不重命名 `activeFilter` 的 key(保持 `'pending' | 'active' | 'done' | 'all'` 后向兼容)

**部署**
- 构建:`npm run build` 6.20s 通过,新 main chunk `index-BK_U7e10.js`(旧 `index-BDGZ_gcJ.js`),Workspace chunk 唯一 `D44-5RYv.js`
- 打包:`packages/frontend-agent-dist-0803-133.tar.gz` 576,913B(25 个文件,0 累积污染)
- jumpserver-V2 全程免登录(cache 19.7h 内有效)
- 备份链:`/opt/wecom-it-desk/frontend-agent/dist.bak.0803_pre133`

**验证**
- 服务端(curl 绕用户/CDN 缓存):HTTP 200 + main JS hash 变更 + Workspace=1 + 备份存在 
- 浏览器无痕模式:用户 2026-08-03 17:48 确认"显示已更新"(默认激活"待处理" + Tab 顺序倒置)
- v1.2 原型与实际页面 Tab 顺序一致 

**任务编号修正**
- 起草时用了 #133,但该编号已被当日另一任务 `voice_asr.py POST /asr auth 加固` 占用
- 沿用 #132 后下一个空号 → 实际为 **#134**
This commit is contained in:
Simon
2026-08-03 17:49:42 +08:00
parent a20606f328
commit 566bb46cd4
2 changed files with 189 additions and 5 deletions
@@ -0,0 +1,185 @@
# 任务说明书:坐席端左栏会话状态 Tab 顺序调整 + 默认显示待处理
> **版本**: v1.0 | **日期**: 2026-08-03
---
## 📋 基本信息
| 项目 | 内容 |
|------|------|
| **任务名称** | 坐席端左栏会话状态 Tab 顺序调整 + 默认显示待处理 |
| **任务ID** | #134#133 已被 voice_asr-auth 加固占用,沿用 #132 后下一个空号) |
| **优先级** | 🟢 P3 |
| **类型** | 功能开发(UI 微调) |
| **状态** | ✅ 已完成 |
| **负责人** | 宋献 |
| **创建日期** | 2026-08-03 |
| **计划完成日期** | 2026-08-03 |
| **前置任务** | #132(坐席端待办事项移至右栏底部 — 已完成) |
---
## 📥 输入项来源
### 产品需求
| 来源文档 | 相关章节 | 说明 |
|----------|----------|------|
| 原型 v1.2(本文) | 左栏会话 Tab 行 | 「全部」Tab 移至「已完成」之后;默认进入页面激活「待处理」 |
| 用户口头要求 | 2026-08-03 17:14 | "全部"频次最低放末尾;待处理是坐席日常首选 |
### 原型设计
| 来源文档 | 页面 | 说明 |
|----------|------|------|
| `docs/01-产品文档/04-坐席工作台/原型-REQ-坐席-000-坐席工作台-v1.2.html` | 坐席工作台 左栏 | v1.1 → v1.2:Tab 顺序调整 + 默认激活「待处理」 |
| `docs/01-产品文档/04-坐席工作台/v1.2-验收截图/` | 4 张 tab 状态截图 | 用户确认无问题(2026-08-03 17:34 |
### 需了解的现有代码(历史现状)
| 模块/文件 | 说明 | 需了解的内容 |
|-----------|------|-------------|
| `src/frontend-agent/src/components/conversation/ConversationList.vue` | 左栏会话列表 | line 108-113 `filterTags` 数组顺序为 `[全部, 待处理, 进行中, 已完成]`line 126 `activeFilter = ref<string>('all')` 默认激活"全部"line 150-163 `applyFilters` 根据 `activeFilter` 过滤;status 映射:pending→queued、active→serving/ai_handling、done→resolved |
| `src/frontend-agent/src/stores/conversation.ts` | 会话 Pinia Store | line 315 `myConversations` 合并 queued + serving+is_mine + pending_close+is_mine + collaborator+servingline 333 `colleagueConversations` 合并 serving+!is_mine+!collaborator + ai_handlingline 349 `historyConversations` 仅 resolved90 天内) |
---
## 📤 输出成果要求
### 交付物清单
| # | 交付物 | 类型 | 说明 |
|---|--------|------|------|
| 1 | `src/frontend-agent/src/components/conversation/ConversationList.vue` | 代码 | `filterTags` 顺序倒置;`activeFilter` 初始值改为 `'pending'` |
| 2 | 坐席端构建产物 | 构建 | `npm run build` 通过 |
| 3 | 浏览器端到端验证 | 测试 | 默认进入页面显示「待处理」激活、左侧仅展示 pending 会话;切换其他 tab 正常 |
### 代码要求
- 最小改动原则(仅 2 处变更,不重构)
- 保持 `activeFilter` 的 key 名不变(`'pending' \| 'active' \| 'done' \| 'all'`),仅改数组顺序和初值
- `applyFilters` 逻辑不动(已按 status 准确映射)
- 不动 store、不动 ConversationItem.vue、不动样式
- 不加数量徽章 / 空状态(v1.2 原型里有,但需要新加 4 个 computed 算实时数量;本任务范围仅"顺序+默认",数量徽章作后续独立任务)
---
## 🔧 验证方式
### 功能验证
| 验证项 | 验证方法 | 预期结果 |
|--------|----------|----------|
| Tab 顺序 | 浏览器访问坐席工作台 | 从左到右依次:`待处理 → 进行中 → 已完成 → 全部` |
| 默认激活态 | 刷新坐席工作台 | "待处理" Tab 高亮(蓝色背景 + 蓝色文字) |
| 默认列表 | 刷新坐席工作台 | 左侧仅展示 status=queued(待接单)的会话("我的会话"区,其他两区因 store 自然为空) |
| Tab 切换 | 点击"进行中" | 切换为蓝色高亮,左侧展示 status=serving/ai_handling 的会话 |
| Tab 切换 | 点击"已完成" | 切换为蓝色高亮,左侧展示 status=resolved 的会话(来自 historyConversations,跨区渲染) |
| Tab 切换 | 点击"全部" | 切换为蓝色高亮,左侧展示所有 3 个区(my + colleague + history |
| 搜索过滤 | 在搜索框输入关键词 | 关键词过滤仍生效,与 tab 过滤为 AND 关系 |
### 兼容性验证
| 验证项 | 验证方法 | 预期结果 |
|--------|----------|----------|
| 搜索 + tab 联动 | 输入关键词后切换 tab | 关键词过滤在所有 tab 下均生效 |
| 无会话态 | 数据库清空会话,刷新页面 | 「待处理」Tab 激活,左侧显示 `el-empty description="暂无会话"` 占位 |
| 我的会话 vs 同事会话区分 | 切换"全部" tab | 同事会话(赵敏/周芳/吴明)的"接手"按钮仍正常弹出 |
| 接手 + 关闭会话流 | 在同事会话点击"接手",接单后该会话进入"我的"区 | 接单成功后该会话归入 myConversations"全部" tab 下可见 |
### 与 v1.2 原型一致性验证
| 验证项 | 验证方法 | 预期结果 |
|--------|----------|----------|
| Tab 顺序对照 | 部署后浏览器对比 `原型-REQ-坐席-000-坐席工作台-v1.2.html` | 实际页 Tab 顺序与原型一致 |
| 默认激活对照 | 部署后浏览器对比原型默认视图 | 默认进入页面 = "待处理"激活 |
---
## ✅ 完成标准
### 验收条件
- [x] 代码已修改(`ConversationList.vue` 共 2 处:`filterTags` 顺序倒置 + `activeFilter` 初值 `'all'``'pending'`
- [x] 坐席端 `npm run build` 通过(6.20s,新 main chunk `index-BK_U7e10.js`Workspace chunk 唯一 `D44-5RYv.js`
- [x] 部署到生产(`rm -rf dist` → build → 打包 576,913B → jumpserver-V2 上传 → sudo 替换 → restart nginx
- [x] 生产服务验证:HTTP 200 + 主 chunk hash 由 `index-BDGZ_gcJ.js``index-BK_U7e10.js` + Workspace JS 数 = 1(无累积污染)+ 备份链 `dist.bak.0803_pre133` 保留
- [x] 浏览器端到端验证(用户无痕模式确认 2026-08-03 17:48"无痕模式显示已更新")
- [x] v1.2 原型与实际页面 Tab 顺序一致(`原型-REQ-坐席-000-坐席工作台-v1.2.html` 与生产渲染一致)
- [x] git commit(见下方"📞 变更记录"
---
## 📊 工作分解
### 子任务
| 子任务 | 负责人 | 预估工时 | 状态 |
|--------|--------|----------|------|
| 修改 `ConversationList.vue``filterTags` 顺序 + `activeFilter` 初值) | 宋献 | 0.1h | ✅ 已完成 |
| 坐席端 `npm run build` | 宋献 | 0.1h | ✅ 已完成(6.20s,无累积,Workspace chunk 唯一) |
| 打包 + jumpserver-V2 部署 + 清理旧 dist/chunk | 宋献 | 0.3h | ✅ 已完成(jumpserver cache 19.7h 内有效,全程免登录;server 验证 HTTP 200 |
| 浏览器端到端验证(用户确认默认待处理视图) | 宋献 | 0.1h | ✅ 已完成(用户 17:48 无痕模式确认"显示已更新" |
| git commit | 宋献 | 0.1h | ✅ 已完成 |
**总预估**0.7h(短平快,原型已确认)
---
## 📞 依赖与阻塞
### 前置依赖
| 依赖任务 | 依赖说明 | 状态 |
|----------|----------|------|
| #132 坐席端待办移至右栏底部 | 当前 `ConversationList.vue` 已是"干净"版本(已移除 TodoPanel | ✅ 已完成 |
### 阻塞因素
| 阻塞项 | 影响范围 | 解决方案 |
|--------|----------|----------|
| 无 | - | - |
---
## 📈 变更记录
| 日期 | 变更内容 | 变更人 | 说明 |
|------|----------|--------|------|
| 2026-08-03 | 创建任务 | 宋献 | 初始版本;承接 v1.2 原型调整(用户 17:14 触发,17:34 用户确认原型图,17:36 用户指令"写任务说明书,然后落地代码") |
| | | | |
---
## 📎 调整需求说明
### 需求概述
将坐席端左栏会话窗口的状态 Tab 顺序调整为 **`待处理 → 进行中 → 已完成 → 全部`**"全部"频次最低放末尾),并把默认激活项从「全部」改为 **「待处理」**(坐席日常工作的最高频入口)。
### 改动点(精确 2 处)
1. **`filterTags` 数组顺序**`ConversationList.vue` line 108-113):
```typescript
// 改前:[全部, 待处理, 进行中, 已完成]
const filterTags: FilterTag[] = [
{ key: 'all', label: '全部' },
{ key: 'pending', label: '待处理' },
{ key: 'active', label: '进行中' },
{ key: 'done', label: '已完成' },
]
// 改后:[待处理, 进行中, 已完成, 全部]
const filterTags: FilterTag[] = [
{ key: 'pending', label: '待处理' },
{ key: 'active', label: '进行中' },
{ key: 'done', label: '已完成' },
{ key: 'all', label: '全部' },
]
```
2. **`activeFilter` 初始值**`ConversationList.vue` line 126):
```typescript
// 改前:
const activeFilter = ref<string>('all')
// 改后:
const activeFilter = ref<string>('pending')
```
### 不做的事(明确范围)
- 不改 store 数据分区(`myConversations` / `colleagueConversations` / `historyConversations` 划分逻辑准确)
- 不改 `applyFilters` 函数逻辑(status 映射已正确:pending→queued、active→serving/ai_handling、done→resolved
- 不动 ConversationItem.vue / 不动样式 / 不动 backend API
- **不在本任务加 Tab 数量徽章 + 空状态文案**(v1.2 原型里有该设计,但需要 store 新增 4 个 computed 计算实时数量;作后续独立任务 #134 候选)
- 不动 `activeFilter` 的 key 名(保持 `'pending' \| 'active' \| 'done' \| 'all'` 与 `applyFilters` switch 兼容;改名为 `'in-progress'` 等需配合多处同步调整,超出本任务范围)
### 为什么是「最小改动」
用户需求 = "Tab 顺序 + 默认激活" 两件事。代码现状已经按 status 准确分桶,store 划分合理,applyFilters 正确 — 唯一缺的就是"两处默认值",故 2 处 Edit 即可完成,避免引入回归风险。
@@ -106,12 +106,11 @@ interface FilterTag {
}
const filterTags: FilterTag[] = [
{ key: 'all', label: '全部' },
{ key: 'pending', label: '待处理' },
{ key: 'active', label: '进行中' },
{ key: 'done', label: '已完成' },
]
{ key: 'all', label: '全部' },
] // ⚠️ #133 v1.2:「全部」移至末位
// ============================================================================
// 状态
// ============================================================================
@@ -122,8 +121,8 @@ const conversationStore = useConversationStore()
/** 搜索关键词 */
const searchKeyword = ref('')
/** 当前筛选标签 */
const activeFilter = ref<string>('all')
/** 当前筛选标签#133 v1.2:默认进入"待处理" */
const activeFilter = ref<string>('pending')
// ============================================================================
// 计算属性