# AI 诊断(兽医、机构)— 前端技术方案 > 依据:`AI诊断(兽医、机构)功能需求.md`、`AI诊断(兽医、机构)技术方案.md`(**v1.5**);实现文件 `ruoyi-ui/src/views/diseaseTreatment/onlineConsult/ai/index.vue`;布局参考同目录在线接诊(左右分栏 IM)。 --- ## 1. 页面与路由 | 项 | 说明 | | --- | --- | | **Vue 路径** | `ruoyi-ui/src/views/diseaseTreatment/onlineConsult/ai/index.vue` | | **组件名** | 以若依菜单 `component` 配置为准 | | **菜单配置(示例)** | 组件路径:`diseaseTreatment/onlineConsult/ai/index` | | **权限前缀** | `diseaseTreatment:aiOnlineConsult:list`、`query`、`add`(发送走大模型直连 + 落库,**未使用** `send` 按钮权限) | **准入**:列表/新建/历史消息仅需登录与 `diseaseTreatment:aiOnlineConsult:*` 权限;后端**不校验**是否绑定兽医/机构医疗资源。 --- ## 2. 接口分工(双通道) 本期前端采用 **会话管理走后端、对话框问答走大模型网关** 的混合方案。 | 能力 | 调用方式 | 说明 | | --- | --- | --- | | 会话列表 | 若依 `request` → `GET /diseaseTreatment/onlineConsult/ai/session/list` | 含 `disclaimer` | | 新建会话 | `POST .../session` | 返回 `id`/`sessionId`、`disclaimer` | | 历史消息 | `GET .../session/{id}/messages` | 打开会话、上拉加载更早 | | **提问与 AI 回复** | **`streamChatMessage`**(`utils/llmStreamChat.js`)→ `{VUE_APP_LLM_BASE_URL}/v1/chat/completions` | 对话框问答,支持 SSE 流式;失败可回退非流式 | | **会话落库** | `POST .../session/{id}/message` | Body:`msgType`、`content`、`aiReplyContent`、`realSessionId?`、`aiCategory?`;大模型返回后落库,**不**再调后端 AI 网关 | | 媒体上传 | `POST /common/upload` | 先上传再随提问送 LLM | > **与后端技术方案**:后端 **§4.4** 同时支持全后端 `ConsultAiGateway` 通道与前端 `aiReplyContent` 落库通道。当前页面采用后者。 > **大模型上下文**:`session.llmSessionId` / `realSessionId` 存网关返回的 `session_id`,与后端会话主键 `activeSessionId` 分离;落库时通过 `realSessionId` 写入 `biz_consult_session.real_session_id`。 --- ## 3. API 模块(若依) | 项 | 说明 | | --- | --- | | **文件** | `ruoyi-ui/src/api/diseaseTreatment/aiOnlineConsult.js` | | **Base** | `/diseaseTreatment/onlineConsult/ai` | | 方法 | HTTP | 页面是否使用 | | --- | --- | --- | | `listAiConsultSessions` | GET `/session/list` | ✓ | | `createAiConsultSession` | POST `/session` | ✓ | | `listAiConsultMessages` | GET `/session/{sessionId}/messages` | ✓ | | `sendAiConsultMessage` | POST `/session/{sessionId}/message`(timeout 65s,`repeatSubmit: false`);Body 含 `msgType`、`content`、`aiReplyContent`、`realSessionId?`、`aiCategory?` | ✓(落库) | **列表 Query(小驼峰)**:`pageNum`(默认 1)、`pageSize`(默认 100)、`contentKeyword`、`searchMode`(仅点击搜索为 `true`)。 **消息 Query**:`beforeId`、`pageSize`(默认 50)。 --- ## 4. 大模型对话(对话框) | 项 | 说明 | | --- | --- | | **环境变量** | `VUE_APP_LLM_BASE_URL`(开发常为 `/llm-dev-proxy`,由 `vue.config.js` 转发)、`VUE_APP_LLM_API_KEY` | | **请求** | `POST {llmBase}/v1/chat/completions` | | **鉴权(直连上游)** | `Authorization: Bearer {VUE_APP_LLM_API_KEY}` | | **鉴权(经 8010 转发)** | **`Authorization: Bearer {getToken()}`**(若依登录 Token,与 `request.js` 一致);**不能**仅用 `VUE_APP_LLM_API_KEY` | | **超时** | 120000 ms | | **Body** | `model`、`messages[]`、`stream: true`(优先流式)、`user`;可选 `session_id`(`llmSessionId`) | | **流式解析** | `utils/sseParse.js`、`utils/llmResponseParse.js`(提取 `session_id`、增量 `content`) | | **后端转发(可选)** | `VUE_APP_LLM_BASE_URL` → `http://localhost:8010`;`KbOpenAiProxyController` 须登录,详见 `doc/大模型/大模型网关转发接口说明.md` §3、§6 | **模型选项(前端常量)** | value | 说明 | | --- | --- | | `auto` | 自动选择 | | `yak-disease` | 疫病诊疗助手 | | `yak-general` | 通用助手 | | `yak-feeding` | 饲喂决策助手 | **`messages` 构建**:将当前会话 `messages` 转为 OpenAI 风格;`senderRole === 1` → `user`,`senderRole === 3` → `assistant`;`msgType === 2` 图片转为 `image_url`。 --- ## 5. 页面结构 1. **筛选区**:会话内容关键字;**搜索**(须非空,`searchMode=true`)、**重置**(默认近 3 个月)、**新增会话**。 2. **免责声明**:`disclaimer` 自列表/新建响应写入,工具栏下 `el-alert` **常驻展示**。 3. **左侧历史会话**:`sessionTitle`、摘要、`lastMessageTime`(格式 **M月D日**);**本期不改前端**:隐藏会话后端已提供 `POST .../session/{id}/hide`(§4.5),页面未接按钮/API 封装。 4. **右侧对话区**:标题为当前会话标题;消息按日分组;用户气泡在右(绿)、AI 在左(蓝)。 5. **输入区**:文本、图片/视频/语音上传、模型选择、发送;等待时展示「AI 正在思考…」动效。 --- ## 6. 业务规则(前端) | 规则 | 实现 | | --- | --- | | 默认列表 | 不传 `searchMode`;近 3 个月有消息的会话 | | 搜索 | `contentKeyword` 非空 + `searchMode=true`;空关键字提示「请输入会话内容后再搜索」 | | 会话主键 | `resolveSessionId(s)`:`id` 优先,否则 `sessionId` | | 消息角色 | `senderRole`:`1` 提问人(右)、`3` AI(左) | | 消息类型 | `msgType`:`1` 文本、`2` 图片、`3` 视频、`4` 语音 | | 发送流程 | 先本地展示提问 → `streamChatMessage` 调 LLM → 本地展示 AI 回复 → `sendAiConsultMessage`(`aiReplyContent`、`realSessionId`、`aiCategory`)落库并合并服务端消息 ID | | 思考中 | `sending` 且最后一条为 `senderRole === 1` 时显示占位气泡 | | 上拉历史 | `scrollTop < 40` 时用 `beforeId` 加载更早 50 条 | | 轮询 | 选中会话后 **2s** 仅 `refreshSessionListQuiet`(**不**轮询消息,避免覆盖仅存在本地的 LLM 对话) | | 媒体限制 | 图 jpg/jpeg/png/gif ≤10MB;视频 mp4/mov ≤50MB;语音 mp3/m4a/wav ≤10MB;文件名不含英文逗号 | | 本地消息 ID | 前缀 `m_`(`genLocalId`),与服务端数字 ID 区分 | **数据持久化说明**:大模型返回后调用 `POST .../message` 并传 `aiReplyContent`、可选 `realSessionId`(大模型 `session_id`)、`aiCategory`(提问分类);服务端仅落库、不调 `ConsultAiGateway`;响应 `data.realSessionId` 可与本地 `llmSessionId` 对齐。落库失败时界面仍保留本地气泡并提示「保存会话失败」。 --- ## 7. 与在线接诊(兽医)差异 | 项 | AI 诊断 | 在线接诊(兽医) | | --- | --- | --- | | 列表标题 | `sessionTitle` | `askerName` | | 筛选 | 仅 `contentKeyword` | 问诊人 + 会话内容 | | 新建会话 | 有 | 无 | | 对话对象 | AI(`senderRole=3`) | 问诊人 / 兽医(1/2) | | 发送接口 | 大模型 `chat/completions` | `POST .../vet/session/{id}/message` | | 消息轮询 | 仅刷新会话列表 | 消息 + 列表 | --- ## 8. 国际化 | 项 | 说明 | | --- | --- | | **语言包** | `diseaseTreatment.aiOnlineConsult`(`lang/zh/diseaseTreatment.js`、`lang/bo/diseaseTreatment.js`) | | **Mixin** | `diseaseTreatmentLocaleMixin`,页面 `dtNs = 'aiOnlineConsult'`,`dtT` / `dtCommon` | --- ## 9. 文件清单 | 路径 | 说明 | | --- | --- | | `src/views/diseaseTreatment/onlineConsult/ai/index.vue` | 主页面(IM + LLM 流式发送 + 落库) | | `src/api/diseaseTreatment/aiOnlineConsult.js` | 若依会话/消息 API | | `src/utils/llmStreamChat.js`、`sseParse.js`、`llmResponseParse.js` | 大模型流式与响应解析 | | `src/mixins/diseaseTreatmentLocaleMixin.js` | 文案 | | `src/lang/zh/diseaseTreatment.js` | 中文 `aiOnlineConsult` | | `src/lang/bo/diseaseTreatment.js` | 藏文 `aiOnlineConsult` | | `.env.development` / `.env.production` | `VUE_APP_LLM_*` | | `vue.config.js` | 开发环境 `LLM_PROXY_TARGET` → `/llm-dev-proxy` | --- ## 10. 联调说明 1. 登录账号须具备 AI 诊断菜单与接口权限;**不要求**在「畜牧医疗资源管理」绑定兽医/机构资源。 2. 配置 `VUE_APP_LLM_BASE_URL`、`VUE_APP_LLM_API_KEY` 后重启 `npm run dev`。 3. 新建会话后左侧应出现「新会话」;发送后 Network 应先后出现 **`/v1/chat/completions`** 与 **`/session/.../message`**(`aiReplyContent` 落库)。 4. 与在线接诊数据隔离:`consult_type=2` 会话不出现在接诊列表。 5. **切换全后端 AI**:将 `sendViaLlm` 改为调用 `sendAiConsultMessage`,合并 `res.data.userMessage` / `aiMessage`,并恢复消息轮询或 STOMP(见后端 **§5.1**)。 --- ## 11. 修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初稿:混合架构(会话后端 + 对话 LLM 直连);对齐 `onlineConsult/ai/index.vue` 实现 | | 1.1 | 落库通道:`sendAiConsultMessage` + `aiReplyContent`;`realSessionId`、`aiCategory`;LLM SSE 流式 |