44e77dcb0e
**重构前**(旧编号 02-11): - docs/02-产品需求/ → 00 产品规划/PRD - docs/03-技术架构/ → 01-05 子目录散落 - docs/04-原型设计/ → 01-02 产品设计(HTML 原型) - docs/05-原型设计/ → screens/ - docs/06-测试素材/ → 02-E2E / 03-功能 / 04-版本测试 - docs/07-项目管理/ → 任务说明书/日报/计划 - docs/08-安全审计/ → 审计报告 - docs/09-堡垒运维/ → toolbox / deploy - docs/10-项目管理/ → 任务说明书(重复) - docs/11-历史归档/ → deploy-nas-archived **重构后**(新编号 00-07,语义化): - docs/00-产品开发流程与文档管理规范.md - docs/00-版本迭代总览.md - docs/01-产品文档/ (PRD/原型/认证/会话/AI 服务/坐席/集成) - docs/02-技术文档/ (技术方案/架构图/重构记录/前端改造/实现配置) - docs/03-测试文档/ (E2E/功能用例/版本报告/缺陷单) - docs/04-运维文档/ (部署运维/运维指南) - docs/05-运营文档/ (品牌推广/用户手册) - docs/06-安全审计/ (审计报告) - docs/07-项目管理/ (任务说明书/日报/计划/看板) **净收益**: - 目录编号与产品文档管理规范对齐(按文档阶段 01-07 编号) - 消除 02-产品需求 与 10-项目管理 的编号重叠 - 子目录按文档类型分组(如 01-产品文档/00-产品规划、01-产品文档/01-认证与登录) - 把运维/安全/项目管理从 0X 散落改为 04/06/07 合计 494 文件 + 78495 行 / - 14076 行
451 lines
16 KiB
Markdown
451 lines
16 KiB
Markdown
# 技术方案 — 管理后台 v1.2 IA 重构整体
|
||
|
||
> **版本**: v1.2 | **日期**: 2026-07-28
|
||
> **作者**: 宋献 · 主理人齐活林(Qi) · 高见远(Gao)
|
||
> **关联 PRD**: `docs/01-产品文档/08-集成生态/PRD-REQ-集成-002-管理后台-v1.2.md`
|
||
> **关联原型**: `docs/01-产品文档/08-集成生态/原型-REQ-集成-000-管理后台-v1.0.html`
|
||
> **任务说明书**: `docs/07-项目管理/任务说明书/任务说明书-REQ-集成-002-IA重构整体.md`
|
||
> **状态**: ✅ 已实施(生产环境上线 2026-07-28)
|
||
|
||
---
|
||
|
||
## 1. 目标
|
||
|
||
把管理后台从 v1.0 的「4 组按优先级」导航重构为 v1.1 的「5 组按用户场景」结构,覆盖完整 27 项功能域(v1.0 漏列 12 项),并通过单一真源 menu.config.ts 消除「Sidebar 与 router 双重维护脱节」的历史包袱。
|
||
|
||
本次重构由 6 个阶段组成:
|
||
|
||
| 阶段 | 内容 | 优先级 | 状态 |
|
||
|------|------|--------|------|
|
||
| P0 | 三 bug 修复(router 重复 / sidebar 漏权限矩阵 / locked-menu-item 可点) | P0 | ✅ 已上线 |
|
||
| P1 | 单一真源 menu.config.ts 重构(5 组 27 项 + 子标签 + 角色过滤) | P1 | ✅ 已上线 |
|
||
| P1-b | Dashboard 嵌入会话监控 widget(双视图:Dashboard 概览 + /monitor 详情) | P1 | ✅ 已上线 |
|
||
| P2-a | `/quick-rules-audit` 顶级路由补全 | P2 | ✅ 已上线 |
|
||
| P2-c | `/quick-rules/template` 路由 child 补全(复用 QuickReplies.vue) | P2 | ✅ 已上线 |
|
||
| v1.2 | 分配模式 Tab 收编到坐席管理 | P2 | 🟡 待实施 |
|
||
|
||
---
|
||
|
||
## 2. 整体架构
|
||
|
||
### 2.1 5 组导航结构(v1.1 替代 v1.0 4 组)
|
||
|
||
```
|
||
🟦 运营中心(7 项 · 实时作战 + 实时监控)
|
||
运营总览 / 会话监控 / 坐席管理 / 角色管理 / 权限矩阵 / OTP 管理 / 功能开关
|
||
|
||
🟪 数据与监控(4 项 · 离线分析 + AI 指标)
|
||
会话审计 / 坐席绩效 / 满意度评价 / 自动化指标
|
||
|
||
🟥 安全审计(5 项 · 合规追溯 + 系统安全)
|
||
配置变更历史 / 运行期日志 / 安全审计日志 / 终端安全 / 快速回复审计日志
|
||
|
||
🟩 系统与集成(4 项 · 底层能力配置)
|
||
系统集成 / 欢迎与引导 / 自动化场景 / 规则版本
|
||
|
||
🟪 知识与 AI(7 项 · 配置规则 + 知识沉淀 + 智能建议)
|
||
快速回复规则 / 排查流程图 / 代答排除 / 知识迭代 / RAGFlow / 拓扑预览 / 知识库建议
|
||
```
|
||
|
||
### 2.2 单一真源架构
|
||
|
||
```
|
||
menu.config.ts(单一真源)
|
||
├─ groups[] // 5 个分组(顺序、图标、颜色)
|
||
├─ items[] // 27 项业务菜单
|
||
├─ quickRulesSubTabs[] // 快速回复规则页 5 子 tab
|
||
├─ lockedItems[] // 3 个 P2 折叠区占位
|
||
└─ rolesFilter // 按角色过滤的字段
|
||
|
||
↓ 派生
|
||
|
||
Sidebar.vue // v-for 渲染,零硬编码
|
||
router/index.ts // 从 menuConfig 派生路由(meta.menuKey 反查)
|
||
```
|
||
|
||
**收益**:新增菜单仅改 menu.ts,自动出现在 Sidebar + router + 角色过滤三处。
|
||
|
||
---
|
||
|
||
## 3. P0 三 bug 修复
|
||
|
||
### 3.1 router 重复注册
|
||
|
||
**症状**:`router/index.ts` L87 + L201 重复注册 `path: 'knowledge'`,后注册 Placeholder 覆盖 Knowledge.vue,导致真页面成死代码。
|
||
|
||
**修复**(`router/index.ts`):
|
||
```diff
|
||
{
|
||
path: 'knowledge',
|
||
name: 'Knowledge',
|
||
component: () => import('@/views/Knowledge.vue'),
|
||
},
|
||
+ {
|
||
+ path: 'knowledge-mgmt', // 占位路由改名避免冲突
|
||
+ name: 'KnowledgeMgmt',
|
||
+ component: () => import('@/views/Placeholder.vue'),
|
||
+ meta: { title: '知识库管理', priority: 'P2', locked: true },
|
||
+ }
|
||
```
|
||
|
||
### 3.2 Sidebar 漏权限矩阵
|
||
|
||
**症状**:`/permissions-matrix` 路由已注册但 Sidebar 完全没显示(菜单与路由双重维护脱节典型案例)。
|
||
|
||
**修复**(P1 阶段由 menu.config.ts 自动修复,菜单项已在 menu.ts 声明)。
|
||
|
||
### 3.3 locked-menu-item 可点击
|
||
|
||
**症状**:`.locked-menu-item { pointer-events: auto !important }` 让"开发中"灰化菜单仍可点击,误导用户。
|
||
|
||
**修复**(`Sidebar.vue` 或 `global.css`):
|
||
```css
|
||
.locked-menu-item {
|
||
pointer-events: none;
|
||
cursor: not-allowed;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. P1 单一真源重构
|
||
|
||
### 4.1 menu.config.ts 数据结构(232 行)
|
||
|
||
```ts
|
||
export const menuConfig = {
|
||
groups: [
|
||
{ key: 'operation', label: '运营中心', icon: 'Operation', color: '#3b82f6', order: 1 },
|
||
{ key: 'monitor', label: '数据与监控', icon: 'Monitor', color: '#8b5cf6', order: 2 },
|
||
{ key: 'security', label: '安全审计', icon: 'Security', color: '#ef4444', order: 3 },
|
||
{ key: 'system', label: '系统与集成', icon: 'System', color: '#10b981', order: 4 },
|
||
{ key: 'ai', label: '知识与 AI', icon: 'AI', color: '#ec4899', order: 5 },
|
||
],
|
||
items: [
|
||
// 27 项业务菜单,每项包含 path/title/icon/groupKey/roles/badge
|
||
],
|
||
quickRulesSubTabs: [
|
||
{ key: 'greeting', label: '打招呼' },
|
||
{ key: 'contacts', label: '联系人' },
|
||
{ key: 'routing', label: '路由关键词' },
|
||
{ key: 'targets', label: '路由目标' },
|
||
{ key: 'template', label: '模板', badge: 'v5 收编' },
|
||
],
|
||
lockedItems: [
|
||
{ key: 'themes', label: '主题模板', stage: '阶段二' },
|
||
{ key: 'dashboard-board', label: '数据看板', stage: '阶段四' },
|
||
{ key: 'knowledge-mgmt', label: '知识库管理', stage: '阶段四' },
|
||
],
|
||
rolesFilter: ['admin', 'super_admin'],
|
||
}
|
||
```
|
||
|
||
### 4.2 Sidebar.vue 重构(282 → 222 行)
|
||
|
||
```vue
|
||
<template>
|
||
<el-menu :default-active="activeRoute">
|
||
<template v-for="group in menuConfig.groups" :key="group.key">
|
||
<el-sub-menu :index="group.key">
|
||
<template #title>
|
||
<el-icon><component :is="group.icon" /></el-icon>
|
||
<span>{{ group.label }}</span>
|
||
</template>
|
||
<template v-for="item in itemsOfGroup(group.key)" :key="item.path">
|
||
<el-menu-item :index="item.path" :disabled="isLocked(item)">
|
||
<el-icon><component :is="item.icon" /></el-icon>
|
||
<span>{{ item.title }}</span>
|
||
<el-badge v-if="item.badge" :value="item.badge" class="menu-badge" />
|
||
</el-menu-item>
|
||
</template>
|
||
</el-sub-menu>
|
||
</template>
|
||
<!-- 折叠区占位 -->
|
||
<el-sub-menu v-for="locked in lockedItems" :key="locked.key" class="locked-menu-item">
|
||
...
|
||
</el-sub-menu>
|
||
</el-menu>
|
||
</template>
|
||
```
|
||
|
||
### 4.3 图标替换诚实记录
|
||
|
||
| 原计划 | 实际使用 | 原因 |
|
||
|--------|---------|------|
|
||
| `Shield`(终端安全) | `Warning` | 与原 sidebar 一致 |
|
||
| `Bulb`(知识库建议) | `Sunny` | element-plus/icons-vue@2.3.0 不存在 Bulb |
|
||
|
||
---
|
||
|
||
## 5. P1-b Dashboard 嵌入会话监控 widget
|
||
|
||
### 5.1 双视图设计(Datadog/Grafana 同款)
|
||
|
||
```
|
||
Dashboard 概览(/admin/dashboard)
|
||
├─ 第一行 4 张核心 KPI(在线坐席/今日会话/平均响应/AI 命中率)
|
||
├─ 第二行 3 张副卡(进行中/等待中/异常告警)
|
||
├─ 🆕 实时会话 Top 5 widget
|
||
├─ 待处理事项
|
||
└─ 系统健康
|
||
|
||
会话监控详情(/admin/monitor)
|
||
└─ 完整会话表格 + 详情
|
||
```
|
||
|
||
### 5.2 Dashboard.vue 单文件实现
|
||
|
||
```vue
|
||
<template>
|
||
<!-- 原有 KPI + 待处理 + 系统健康 -->
|
||
|
||
<!-- 🆕 实时会话监控 widget -->
|
||
<div class="monitor-widget">
|
||
<div class="widget-header">
|
||
<h3>实时会话监控</h3>
|
||
<el-button text @click="$router.push('/admin/monitor')">
|
||
查看全部 →
|
||
</el-button>
|
||
</div>
|
||
|
||
<div class="monitor-stats">
|
||
<StatCard label="进行中" :value="monitorStats.in_progress" color="green" />
|
||
<StatCard label="等待中" :value="monitorStats.queued" color="yellow" />
|
||
<StatCard label="今日已结" :value="monitorStats.resolved_today" color="blue" />
|
||
<StatCard label="异常告警" :value="monitorStats.alerts" color="red" />
|
||
</div>
|
||
|
||
<el-table :data="monitorSessions.slice(0, 6)" stripe>
|
||
<el-table-column prop="session_id" label="会话 ID" />
|
||
<el-table-column prop="employee_name" label="员工" />
|
||
<el-table-column prop="agent_name" label="坐席" />
|
||
<el-table-column label="持续时长">
|
||
<template #default="{ row }">{{ formatDuration(row.started_at) }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="状态">
|
||
<template #default="{ row }">
|
||
<el-tag :type="getSessionStatusTag(row.status)">
|
||
{{ getSessionStatusText(row.status) }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { getMonitorSessions } from '@/api/admin'
|
||
import type { MonitorSession, MonitorStats } from '@/types'
|
||
|
||
const monitorStats = reactive<MonitorStats>({
|
||
in_progress: 0, queued: 0, resolved_today: 0, alerts: 0,
|
||
})
|
||
const monitorSessions = ref<MonitorSession[]>([])
|
||
|
||
onMounted(async () => {
|
||
try {
|
||
const res = await getMonitorSessions()
|
||
Object.assign(monitorStats, res.stats)
|
||
monitorSessions.value = res.items
|
||
} catch (err) {
|
||
// Demo 兜底(与 Monitor.vue 一致)
|
||
monitorStats.in_progress = 5
|
||
monitorStats.queued = 0
|
||
monitorStats.resolved_today = 42
|
||
monitorStats.alerts = 1
|
||
monitorSessions.value = [...]
|
||
}
|
||
})
|
||
|
||
// 复用 formatDuration / getSessionStatusTag / getSessionStatusText
|
||
</script>
|
||
```
|
||
|
||
### 5.3 API 设计
|
||
|
||
```ts
|
||
// api/admin.ts
|
||
export async function getMonitorSessions(params?: { limit?: number }) {
|
||
return request<MonitorSessionsData>({
|
||
url: '/admin/monitor/sessions',
|
||
method: 'get',
|
||
params,
|
||
})
|
||
}
|
||
|
||
export interface MonitorStats {
|
||
in_progress: number
|
||
queued: number
|
||
resolved_today: number
|
||
alerts: number
|
||
}
|
||
|
||
export interface MonitorSession {
|
||
session_id: string
|
||
employee_name: string
|
||
agent_name: string
|
||
status: 'pending' | 'active' | 'resolved' | 'abandoned'
|
||
started_at: string
|
||
}
|
||
|
||
export interface MonitorSessionsData {
|
||
stats: MonitorStats
|
||
items: MonitorSession[]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. P2-a `/quick-rules-audit` 顶级路由补全
|
||
|
||
### 6.1 修复内容(`router/index.ts`)
|
||
|
||
```ts
|
||
{
|
||
// 快速回复审计日志(v1.1 从快速回复规则组移至安全审计组)
|
||
path: 'quick-rules-audit',
|
||
name: 'QuickRulesAuditLog',
|
||
component: () => import('@/views/quick-rules/audit.vue'),
|
||
meta: { title: '快速回复审计日志', requiresAuth: true },
|
||
},
|
||
```
|
||
|
||
**复用现有 `views/quick-rules/audit.vue`**,name 与嵌套 `QuickRulesAudit` 区分避免冲突。
|
||
|
||
---
|
||
|
||
## 7. P2-c `/quick-rules/template` 路由 child 补全
|
||
|
||
### 7.1 修复内容(`router/index.ts` L219-225)
|
||
|
||
```ts
|
||
{
|
||
// 快速回复模板(v5 收编:菜单已配于 menu.ts L197;复用旧 QuickReplies.vue 组件)
|
||
path: 'quick-rules/template',
|
||
name: 'QuickRulesTemplate',
|
||
component: () => import('@/views/QuickReplies.vue'),
|
||
meta: { title: '快速回复模板', requiresAuth: true },
|
||
},
|
||
```
|
||
|
||
**复用现有 `views/QuickReplies.vue`**(独立页面组件,用全局 `quickReplyStore` Pinia 单例,无父级 route props 依赖,安全作 route component)。
|
||
|
||
---
|
||
|
||
## 8. v1.2 分配模式 Tab 收编(待实施)
|
||
|
||
### 8.1 路由改造
|
||
|
||
```diff
|
||
- {
|
||
- path: 'assignment-mode',
|
||
- name: 'AssignmentMode',
|
||
- component: () => import('@/views/AssignmentMode.vue'),
|
||
- meta: { title: '消息分配模式', priority: 'P1' },
|
||
- },
|
||
```
|
||
|
||
### 8.2 Agents.vue 双 Tab 改造
|
||
|
||
```vue
|
||
<el-tabs v-model="activeTab" class="agents-tabs">
|
||
<el-tab-pane label="坐席列表" name="agents-list">
|
||
<!-- 原 toolbar + AgentTable + 三个 dialog -->
|
||
</el-tab-pane>
|
||
<el-tab-pane label="分配策略" name="agents-assignment">
|
||
<div class="page-desc">
|
||
当前坐席 {{ agentStore.agents.length }} 人...
|
||
</div>
|
||
<div class="mode-card" v-for="mode in modes" :key="mode.id">
|
||
<!-- 复用 AssignmentMode.vue 的 mode-card -->
|
||
</div>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
```
|
||
|
||
### 8.3 旧页面保留
|
||
|
||
`views/AssignmentMode.vue` 保留但停用(不删除),方便阶段二/三分配策略膨胀时回滚为独立页。
|
||
|
||
### 8.4 后端零改动
|
||
|
||
仍走 `system_configs.assignment_mode` + `GET/PUT /api/admin/assignment-mode`。
|
||
|
||
---
|
||
|
||
## 9. 关键技术决策
|
||
|
||
| # | 决策 | 理由 |
|
||
|---|------|------|
|
||
| 1 | **单一真源 menu.config.ts** | 消除「Sidebar 与 router 双重维护脱节」;新增菜单仅改 1 文件 |
|
||
| 2 | **5 组按用户场景分组**(v1.1) | v1.0 按优先级分组不符合实际运营场景;安全审计类功能分散 |
|
||
| 3 | **快速回复审计移出知识与 AI 组** | 审计类功能属安全合规范畴,不应混杂在业务规则配置组 |
|
||
| 4 | **终端安全移入安全审计组** | 终端安全是合规管控(联软/火绒),与底层引擎集成性质不同 |
|
||
| 5 | **快速回复模板作为 tab 收编** | 与快速回复规则同属「快速回复」业务的不同维度 |
|
||
| 6 | **Dashboard widget + /monitor 双视图** | 用户进 Dashboard 即见实时状态,无需跳转(Datadog/Grafana 同款) |
|
||
| 7 | **P2 路由补全复用既有组件** | audit.vue 与 QuickReplies.vue 已有完整实现,避免重复 |
|
||
| 8 | **v1.2 分配模式 Tab 收编可逆** | 旧 AssignmentMode.vue 保留文件 + 回滚步骤文档化 |
|
||
|
||
---
|
||
|
||
## 10. 风险与回滚
|
||
|
||
| 风险 | 概率 | 影响 | 缓解 |
|
||
|------|------|------|------|
|
||
| menu.config.ts 数据错误导致菜单错位 | 低 | 用户困惑 | 双重核对(sidebar 渲染 + 路由可达) |
|
||
| 子标签 / 角色过滤边界 | 低 | 普通管理员看到超管菜单 | menuConfig.rolesFilter 字段校验 |
|
||
| Tab 切换时数据二次请求 | 低 | 网络浪费 | watch(activeTab) 懒加载或一次性加载 |
|
||
| 旧页面成僵尸代码 | 低 | 维护混淆 | 注释中写明"vX.Y 起停用,仅供回滚" |
|
||
| 阶段二/三分配模式复杂化需拆回 | 中 | 需重构 | 已记录回滚步骤,30 分钟内可逆 |
|
||
|
||
**回滚预案**:
|
||
- 服务器 `/tmp/dist-template-deploy.zip` + `/tmp/dist-widget.zip`(最近 2 个 dist 包,保留 7 天)
|
||
- 各版本 dist md5 在 memory 记录中可查(af00cf1c→a0c93a6c→6e8933dd→6f261495)
|
||
|
||
---
|
||
|
||
## 11. 验证清单(端到端三层验证)
|
||
|
||
### 11.1 代码层
|
||
|
||
- [x] 工程师 IS_PASS: YES(单文件最小变更)
|
||
- [x] 主理人 Grep 核对:行号 / 函数名 / 引用一致
|
||
- [x] QA 工程师六维回归 PASS(路由 entry / 组件独立 / name 唯一 / menu 对齐 / 无回归 / build 成功)
|
||
|
||
### 11.2 Build 层
|
||
|
||
- [x] `npm run build` 成功(9.57s, 2409 modules transformed, 51 chunks)
|
||
- [x] dist 总大小 3.32 MB / 89 文件
|
||
- [x] 主 chunk index-Dnr-1RNY.js (1173 KB)
|
||
|
||
### 11.3 部署层
|
||
|
||
- [x] 主机 dist md5 ↔ 服务器挂载目录 md5 一致
|
||
- [x] `curl http://localhost/itadmin/` HTTP 200
|
||
- [x] 关键路由抽查:dashboard / monitor / quick-rules / quick-rules-audit / quick-rules/template / permissions-matrix 全部 200
|
||
- [x] nginx bind mount 源路径:`/opt/wecom-it-desk/frontend-admin/dist/`(**带 dist 后缀**)
|
||
|
||
### 11.4 浏览器层
|
||
|
||
- [ ] 用户登录后 1-click 视觉确认(agent-browser 自动化 / 人工)
|
||
- 关键页面:Dashboard 会话监控 widget / 5 组导航 / 快速回复模板 tab
|
||
|
||
---
|
||
|
||
## 12. 变更日志
|
||
|
||
| 版本 | 日期 | 变更 | 变更人 | 影响范围 |
|
||
|------|------|------|--------|---------|
|
||
| v1.0 | 2026-07-28 12:00 | 初版(仅覆盖分配模式 Tab 收编) | 宋献 | §8 |
|
||
| v1.1 | 2026-07-28 13:00 | 扩展为 IA 重构整体(P0+P1+P2) | 宋献 | §1-§7, §9-§11 |
|
||
| v1.2 | 2026-07-28 16:30 | 三件套对齐,标记「分配模式 Tab 收编」为待实施 | 宋献 | §8 标记 🟡 待实施 |
|
||
|
||
---
|
||
|
||
## 13. 关联文档
|
||
|
||
- **PRD v1.2**:`docs/01-产品文档/08-集成生态/PRD-REQ-集成-002-管理后台-v1.2.md`
|
||
- **任务说明书 v1.2**:`docs/07-项目管理/任务说明书/任务说明书-REQ-集成-002-IA重构整体.md`
|
||
- **原型 HTML**:`docs/01-产品文档/08-集成生态/原型-REQ-集成-000-管理后台-v1.0.html`(v1.1 已同步更新)
|
||
- **整改记录**:`docs/04-运维文档/部署运维/00-文档规范化整改记录.md`(新增整改 #6 - IA 重构三件套补齐)
|
||
- **memory 日志**:`D:\资料\03-项目开发\wecom_it_smart_desk\.workbuddy\memory\2026-07-28.md`(IA 重构全过程记录) |