# PRD 需求文档 — 问题排查助手易用性优化（在线/离线模式）

> **适用范围**：本文档仅针对「问题排查助手」模块的在线模式与离线模式用户体验优化。
> 版本：1.0 ｜ 日期：2026-08-12 ｜ 分支：troubleshoot-ai-assistant

---

## 1. 需求背景

### 1.1 现状

问题排查助手已实现在线模式（AI 分析）和离线模式（知识库匹配）双模式运行。代码已部署到 5.60 服务器，知识库 357 条记录。

当前问题排查助手的使用场景：

| 场景 | 用户 | 模式 | 使用频率 |
|------|------|------|---------|
| 内部研发/运维 | 有外网访问 | 在线（AI 分析） | 日常 |
| 客户现场实施 | 内网无外网 | 离线（知识库匹配） | 项目交付/故障时 |
| 客户现场技术人员 | 内网/外网 | 两种模式 | 日常维护 |

### 1.2 目标用户画像

本优化的核心目标用户是**现场技术人员和客户**：

- **技术水平**：熟悉基本操作，但不熟悉 Linux 命令和系统架构
- **使用场景**：现场遇到问题 → 打开问题排查助手 → 输入描述 → 获取排查步骤
- **核心诉求**：简单、快速、解决问题
- **痛点**：等待时间长、找不到入口、结果看不懂

### 1.3 问题清单

通过代码审查发现以下问题，按严重程度排列：

| 编号 | 问题 | 影响 | 涉及范围 |
|------|------|------|---------|
| P1-1 | 离线模式无全文搜索，用户只能按产品浏览 | 离线模式核心功能缺失，现场人员无法快速定位问题 | 前端OfflineIndex + 后端API |
| P1-2 | 在线SSE流式响应是"伪流式"：先收完整响应再慢放 | 用户等待20-50秒才看到结果，完全失去流式意义 | 后端ai_service + routes/troubleshoot |
| P2-1 | 离线模式FAQsPanel使用v-html直接渲染用户提交内容，存在XSS风险 | 安全性风险，恶意用户可注入脚本 | 前端FAQsPanel组件 |
| P2-2 | 模型选择前端可选但后端非流式接口不传model参数 | 用户选了模型但实际不生效，功能Bug | 后端routes/troubleshoot |
| P3-1 | 离线模式切换产品需重新请求API，无本地缓存 | 用户体验差，每次切换都等待加载 | 前端FAQsPanel + OfflineIndex |
| P3-2 | SSE连接无断线重连，网络波动直接判定失败 | 长时间分析中断后无法恢复，已收内容丢失 | 前端sse.ts + OnlineIndex |
| P3-3 | 缓存key不包含model参数 | 切换模型后返回旧缓存，用户看不到差异 | 后端routes/troubleshoot |
| P4-1 | Prompt每次重复发送skill_text（5000字符固定内容） | 浪费token/API费用 | 后端ai_service |
| P4-2 | 离线模式文档不能在线预览（只能下载） | 现场人员查看文档不便 | 后端routes + 前端 |
| P4-3 | "357条记录"在前端硬编码 | 知识库数量变化时前端显示不准确 | 前端OnlineIndex |

---

## 2. 优化目标

### 2.1 总体目标

让现场技术人员和客户能够**简单、快速、有效**地使用问题排查助手解决问题。

### 2.2 具体目标

| 维度 | 当前 | 目标 |
|------|------|------|
| 离线模式搜索 | 仅产品树浏览 | 全文搜索 + 产品树浏览 |
| 在线流式响应 | 等待20-50s才看到结果 | 实时逐字推送，<3s看到首帧 |
| 安全性 | XSS风险 | 安全渲染 |
| 模型选择 | 部分生效 | 完全生效 |
| 离线加载 | 每次请求API | 本地缓存5分钟 |
| 网络稳定性 | 断连即失败 | 自动重连3次 |
| 缓存准确性 | 切换模型返回旧缓存 | 按模型区分缓存 |

---

## 3. 需求详述

### 3.1 P1-1：离线模式全文搜索（核心功能）

#### 3.1.1 需求描述

当前离线模式只能通过产品树浏览 FAQ，**没有搜索框**。现场技术人员遇到问题时，往往不知道问题属于哪个产品类别，无法通过产品树定位。

需要在离线模式顶部增加**全局搜索框**，支持全文搜索知识库。

#### 3.1.2 交互流程

```
用户打开离线模式 → 看到搜索框（顶部） + 产品树（左侧）
用户输入关键词 → 实时搜索（或点击搜索按钮） → 展示匹配结果列表
搜索结果点击 → 查看详情（同在线模式的记录详情弹窗）
```

#### 3.1.3 界面要求

**搜索框**：
- 位置：离线模式页面顶部（产品树上方）
- 样式：宽输入框 + 搜索按钮，与在线模式搜索风格一致
- 占位提示："搜索历史问题案例..."

**搜索结果**：
- 列表形式：标题 + 匹配度 + 项目名 + 关键词摘要
- 每项可点击展开查看详情
- 无结果时显示友好提示

**搜索源**：调用后端 `/api/troubleshoot` 或 `/api/search` 接口（TF-IDF 搜索，无需联网）

#### 3.1.4 验收标准

- [ ] 搜索框在离线模式页面顶部可见
- [ ] 输入关键词后能返回知识库匹配结果
- [ ] 匹配结果按相似度排序
- [ ] 无结果时显示"未找到相关案例"提示
- [ ] 搜索结果可点击查看详情
- [ ] 搜索不影响产品树浏览功能

---

### 3.2 P1-2：流式响应实时推送（在线模式）

#### 3.2.1 需求描述

当前在线模式的 SSE 流式接口是"伪流式"：后端 `analyze_stream()` 先完整接收 Claude API 的流式响应（20-50秒），然后做安全过滤，最后按30字符+10ms延迟"回放"模拟打字效果。用户实际上**等待了完整API调用时间才看到结果**，完全失去流式接口的意义。

需要改为**边收边推**：每收到一个 API chunk，实时进行安全过滤并立即推送到前端。

#### 3.2.2 技术方案

**当前流程**：
```
用户提问 → API调用(20-50s) → 收集全部响应 → 安全过滤 → 分块回放(额外几秒)
                                                                    ↑ 用户看到第一帧
```

**优化后流程**：
```
用户提问 → API调用开始 → 逐chunk接收 → 逐chunk安全过滤 → 立即推送
                           ↑ 用户<3s看到第一帧
```

#### 3.2.3 实现要点

- `call_claude_api_stream()` 保持流式返回不变
- 安全过滤改为逐 chunk 处理（而非等完整响应）
- 安全过滤依赖完整上下文的规则（如危险命令匹配单行）可逐行处理
- 敏感信息过滤（IP、密码等）也可逐行处理
- 缓存策略改为：完整响应收完后再统一缓存

#### 3.2.4 验收标准

- [ ] 用户点击"帮我排查"后 <3秒 看到首帧内容
- [ ] 流式内容实时显示，无需等待全部生成
- [ ] 安全过滤仍然生效（危险命令行被替换）
- [ ] 敏感信息仍被过滤（IP/密码掩码）
- [ ] 完整响应仍存入缓存
- [ ] 降级路径（API失败→模拟响应）正常工作

---

### 3.3 P2-1：FAQsPanel 安全渲染修复

#### 3.3.1 需求描述

`FAQsPanel.vue:89` 使用 `v-html="faq.solution.replace(/\n/g, '<br>')"` 直接渲染用户提交的内容，存在 XSS 风险。而且 `replace(/\n/g, '<br>')` 不是真正的 Markdown 渲染，**列表、代码块、链接全都不支持**，显示效果差。

#### 3.3.2 技术方案

- 将 `v-html` 改为使用 `renderMarkdown()` 函数（复用在线模式已有的 Markdown 渲染函数）
- 确保渲染函数对内容进行转义处理
- 或者使用 `DOMPurify` 库对 HTML 内容进行消毒后再渲染

#### 3.3.3 验收标准

- [ ] FAQ 详情使用 Markdown 渲染（支持标题、列表、代码块、链接）
- [ ] XSS 注入脚本不会被执行
- [ ] 原有 FAQ 内容显示正常，无格式丢失

---

### 3.4 P2-2：模型选择参数对齐

#### 3.4.1 需求描述

前端在线模式提供 `glm-4-flash` / `glm-5.1` / `glm-4-plus` 三种模型选择，并通过 SSE 端点 `analyze_stream` 传递 `model` 参数。但后端 `/api/analyze`（非流式接口）**不接收 model 参数**，固定使用 `config.get('default_model', 'glm-5.1')`。此外缓存 key 也不包含 model，切换模型后仍返回旧缓存。

#### 3.4.2 技术方案

- `/api/analyze` 接口增加 `model` 参数接收
- 缓存 key 增加 `model` 字段
- 前端降级路径 `fallbackToNormalRequest()` 传递 model 参数
- 非 SSE 的 `call_claude_api()` 也支持 model 参数传递

#### 3.4.3 验收标准

- [ ] 非流式接口 `/api/analyze` 支持 model 参数
- [ ] 切换模型后缓存返回对应模型的结果
- [ ] 前端降级路径（SSE失败时）正确传递模型参数

---

### 3.5 P3-1：离线模式本地缓存

#### 3.5.1 需求描述

离线模式切换产品时，每次都要重新请求 API 获取 FAQ 列表。在离线模式下，知识库数据在服务启动后不会变化，重复请求浪费带宽和时间。

在前端使用 `localStorage` 或 `IndexedDB` 缓存 FAQ 列表，设置 5 分钟过期时间。

#### 3.5.2 验收标准

- [ ] 首次加载产品 FAQ 后写入本地缓存
- [ ] 5分钟内再次切换同一产品，不请求API，使用缓存
- [ ] 超过5分钟自动刷新
- [ ] 缓存不影响数据正确性

---

### 3.6 P3-2：SSE 断线重连

#### 3.6.1 需求描述

当前 SSE 连接断开后直接判定失败，触发降级路径。但 AI 分析过程可能在服务端仍在进行，断连后已收到的内容丢失，用户需要重新点击"帮我排查"。

需要实现 SSE 自动重连机制（带递增退避），并保留已收到的内容。

#### 3.6.2 技术方案

- `sse.ts` 的 `createSSE()` 增加重试逻辑
- 重试策略：1s → 2s → 4s → 8s → 最多 3 次
- 重连后前端已收到的内容保留，不重置
- 后端需要保证重连请求不会重复触发分析（幂等性由后端实现，本次不做）

#### 3.6.3 验收标准

- [ ] SSE 断连后自动尝试重连（最多3次）
- [ ] 重连成功后续内容继续追加到已有内容
- [ ] 已显示的内容不会丢失或重复
- [ ] 3次重试失败后判定为最终失败，显示错误提示
- [ ] 用户手动取消时不会自动重连

---

### 3.7 P3-3：缓存 key 增加 model 参数

#### 3.7.1 需求描述

当前缓存 key 为 `(project_name, system_type, apk_product, query)`，不包含 `model`。切换模型后返回旧模型缓存结果，用户看不到差异。

#### 3.7.2 技术方案

- `cache_manager.py` 的 `get()` / `set()` 方法增加 `model` 参数
- 缓存文件名或 key 拼接 model 字段
- 后端路由层传递 model 参数到缓存方法

#### 3.7.3 验收标准

- [ ] 同一 query 不同 model 返回各自的缓存
- [ ] 旧缓存（无 model 字段）兼容处理，不清除

---

## 4. 非功能需求

### 4.1 性能

| 优化项 | 当前 | 目标 |
|--------|------|------|
| 离线全文搜索响应 | 无此功能 | <3秒 |
| 在线流式首帧时间 | 20-50秒 | <3秒 |
| 离线模式切换产品 | 网络请求（0.5-2秒） | 本地缓存（<10ms） |
| SSE断线恢复 | 失败 | 自动重连（<15秒恢复） |

### 4.2 兼容性

- 所有优化向下兼容，不破坏现有功能
- 浏览器兼容：Chrome / Firefox / Edge 最新两个大版本
- 移动端兼容：768px 和 375px 断点

### 4.3 安全性

- 修复 XSS 漏洞（FAQsPanel v-html）
- 不引入新的安全风险
- 敏感信息过滤继续有效

---

## 5. 验收标准总表

| 编号 | 验收项 | 类型 | 优先级 |
|------|--------|------|--------|
| A1 | 离线模式全文搜索可用 | 功能 | P1 |
| A2 | 离线搜索结果按相似度排序 | 功能 | P1 |
| A3 | 在线流式首帧<3秒 | 性能 | P1 |
| A4 | 流式实时安全过滤生效 | 安全 | P1 |
| A5 | FAQ详情Markdown渲染正确 | 功能 | P2 |
| A6 | XSS注入测试通过 | 安全 | P2 |
| A7 | 非流式接口支持model参数 | 功能 | P2 |
| A8 | 切换模型缓存不同 | 功能 | P3 |
| A9 | 离线模式缓存5分钟 | 功能 | P3 |
| A10 | SSE断线自动重连3次 | 可用性 | P3 |
| A11 | 所有现有测试全绿 | 质量 | P1 |

---

## 6. 约束与隔离

### 6.1 不改的范围

| 模块 | 理由 |
|------|------|
| `search_engine.py` 公开接口 | 单元测试依赖（46用例） |
| `safety_filter.py` 公开接口 | 单元测试依赖（41用例） |
| `cache_manager.py` 公开接口 | 单元测试依赖（19用例） |
| `service_monitor/` 全部文件 | 服务监测模块隔离红线 |
| `service_manage/` 全部文件 | 服务管理模块隔离红线 |

### 6.2 依赖

| 依赖 | 用途 | 是否新增 |
|------|------|---------|
| Element Plus | 前端UI组件库 | 已有 |
| ECharts | 图表（非本次使用） | 已有 |
| DOMPurify（可选） | HTML消毒 | 可选新增 |
| 无新增Python依赖 | — | 否 |

---

## 7. 文档记录

- 本文档：`Docs/需求文档/问题处理助手/PRD_需求文档_易用性优化.md`
- 执行计划：`Docs/需求文档/问题处理助手/PRD_计划执行_易用性优化.md`
- 关联 HANDOFF：`HANDOFF.md`