Przeglądaj źródła

docs: 建议诊断下拉限制 实现计划

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
张田田 1 tydzień temu
rodzic
commit
1c11dbb331

+ 307 - 0
docs/superpowers/plans/2026-06-18-建议诊断下拉限制.md

@@ -0,0 +1,307 @@
+# 建议诊断(suggestDiag)下拉限制为后端返回值 实现计划
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** 把适宜技术 tab 的「建议诊断」从「搜全库多选」改成「只能从后端返回的候选里多选,默认第一个,空则展示空」。
+
+**Architecture:** 新增 `suggestDiagAll`(候选,对象数组)与 `suggestDiag`(已选,code 数组)分离;autocomplete 数据源改为 `suggestDiagAll`(不再搜全库);`searchWesternDisease` 全库搜索代码保留不动。
+
+**Tech Stack:** Vue 2.6 + Element UI 2.15(el-tag / el-autocomplete)。**无单元测试框架**,验证靠 `npm run build` 编译 + 浏览器手动测试。
+
+---
+
+## 前置说明(执行前确认)
+
+- 后端 `techData.suggestDiag` 现状是 **code 字符串**(逗号分隔)。本计划在赋值时做**规范化**:对象 → 取 `{westcode, westname}`;纯 code → `{westcode, westname: 已有 name 映射或 code}`。
+- 若希望候选显示**诊断名称**(而非 code),需后端 `suggestDiag` 返回对象数组带 `westname`;否则降级显示 code。**执行前请与后端确认返回格式**。
+
+## File Structure
+
+- 修改:`src/views/diagnosis/Prescribing.vue`(单文件,6 处改动)
+  - `data`(`:1343`):新增 `suggestDiagAll`
+  - `assignRecipe3`(`:2556`):候选规范化 + 默认第一个 + 预填充 name 映射
+  - `queryWesternDisease`(`:2969`):候选过滤,不再搜全库
+  - `onWesternDiseaseVisible`(`:2936`):移除全库搜索/滚动加载
+  - `_setDataToStorage`(`:1577`)/ `_showDataFromStorage`(`:1651`):缓存/恢复 `suggestDiagAll`
+- **不变**:`searchWesternDisease` / `loadMoreWesternDisease`(保留代码不删)、el-tag / `removeWesternDisease`、提交逻辑(`:2132`)
+
+---
+
+### Task 1: 新增 `suggestDiagAll` data 字段
+
+**Files:**
+- Modify: `src/views/diagnosis/Prescribing.vue:1343`
+
+- [ ] **Step 1: 在 `suggestDiag` 后新增 `suggestDiagAll`**
+
+找到(`:1343`):
+```js
+      suggestDiag: [], // 建议诊断(用户可编辑,多选)
+```
+改为:
+```js
+      suggestDiag: [], // 建议诊断(已选,多选,提交用)
+      suggestDiagAll: [], // 建议诊断候选(后端返回的全部,对象数组 {westcode, westname})
+```
+
+- [ ] **Step 2: Commit**
+
+```bash
+git add src/views/diagnosis/Prescribing.vue
+git commit -m "feat: 新增 suggestDiagAll 候选字段" -m "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>"
+```
+
+---
+
+### Task 2: 赋值逻辑——候选规范化 + 默认第一个 + 预填充 name
+
+**Files:**
+- Modify: `src/views/diagnosis/Prescribing.vue:2554-2559`
+
+- [ ] **Step 1: 改写 suggestDiag 赋值块**
+
+找到(`:2554-2559`):
+```js
+        // 建议诊断(多选,从接口返回)
+        if (techData.suggestDiag) {
+          this.suggestDiag = typeof techData.suggestDiag === 'string'
+            ? techData.suggestDiag.split(',').filter(Boolean)
+            : Array.isArray(techData.suggestDiag) ? techData.suggestDiag : [];
+        }
+```
+改为:
+```js
+        // 建议诊断候选(后端返回的全部)→ 规范化成对象数组,并预填充 name 映射
+        const rawSuggest = techData.suggestDiag;
+        const rawArr = typeof rawSuggest === 'string'
+          ? rawSuggest.split(',').filter(Boolean)
+          : Array.isArray(rawSuggest) ? rawSuggest : [];
+        // 规范化:对象 → {westcode, westname};纯 code → {westcode, westname: 已有映射或 code}
+        this.suggestDiagAll = rawArr.map(it => {
+          if (it && typeof it === 'object') {
+            const code = it.westcode || it.code;
+            return { westcode: code, westname: it.westname || it.name || code };
+          }
+          return { westcode: it, westname: this.westernDiseaseNameMap[it] || it };
+        });
+        // 预填充 name 映射,供 el-tag / autocomplete 显示
+        this.suggestDiagAll.forEach(it => {
+          if (it.westcode) this.westernDiseaseNameMap[it.westcode] = it.westname;
+        });
+        // 已选默认第一个
+        this.suggestDiag = this.suggestDiagAll.length ? [this.suggestDiagAll[0].westcode] : [];
+```
+
+- [ ] **Step 2: Commit**
+
+```bash
+git add src/views/diagnosis/Prescribing.vue
+git commit -m "feat: suggestDiag 赋值改为候选规范化+默认第一个" -m "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>"
+```
+
+---
+
+### Task 3: `queryWesternDisease` 改为只返回候选(不搜全库)
+
+**Files:**
+- Modify: `src/views/diagnosis/Prescribing.vue:2969-2981`
+
+- [ ] **Step 1: 改写 queryWesternDisease**
+
+找到(`:2969-2981`):
+```js
+    async queryWesternDisease(queryString, cb) {
+      await this.searchWesternDisease(queryString);
+      if (this.westernDiseaseOptions.length > 0) {
+        const selectedCodes = Array.isArray(this.suggestDiag) ? this.suggestDiag : [];
+        const options = this.westernDiseaseOptions.map(item => ({
+          ...item,
+          _disabled: selectedCodes.includes(item.westcode),
+        }));
+        cb(options);
+      } else {
+        cb([{ westname: "暂无数据", _disabled: true }]);
+      }
+    },
+```
+改为:
+```js
+    // 候选来源为后端 suggestDiagAll,不再调 searchWesternDisease 搜全库
+    queryWesternDisease(queryString, cb) {
+      const selectedCodes = Array.isArray(this.suggestDiag) ? this.suggestDiag : [];
+      const kw = (queryString || '').trim();
+      const options = (Array.isArray(this.suggestDiagAll) ? this.suggestDiagAll : [])
+        .filter(it => !kw || (it.westname || it.westcode || '').includes(kw))
+        .map(it => ({
+          ...it,
+          _disabled: selectedCodes.includes(it.westcode),
+        }));
+      cb(options.length ? options : [{ westname: "暂无数据", _disabled: true }]);
+    },
+```
+
+- [ ] **Step 2: Commit**
+
+```bash
+git add src/views/diagnosis/Prescribing.vue
+git commit -m "feat: queryWesternDisease 改为只返回候选 suggestDiagAll" -m "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>"
+```
+
+---
+
+### Task 4: `onWesternDiseaseVisible` 移除全库搜索与滚动加载
+
+**Files:**
+- Modify: `src/views/diagnosis/Prescribing.vue:2936-2968`
+
+- [ ] **Step 1: 简化 onWesternDiseaseVisible**
+
+候选已在 `suggestDiagAll`,打开下拉时不再搜全库,也不再滚动加载更多。找到(`:2936-2968`):
+```js
+    onWesternDiseaseVisible(show) {
+      if (!show) {
+        const wrap = document.querySelector(
+          ".western-disease-input-wrapper .el-scrollbar__wrap",
+        );
+        if (wrap && this._wdScroll) {
+          wrap.removeEventListener("scroll", this._wdScroll);
+        }
+        return;
+      }
+      // 首次打开且无数据时加载初始列表
+      if (this.westernDiseaseOptions.length === 0) {
+        this.searchWesternDisease("");
+      }
+      this.$nextTick(() => {
+        const wrap = document.querySelector(
+          ".western-disease-input-wrapper .el-scrollbar__wrap",
+        );
+        if (wrap) {
+          wrap.addEventListener(
+            "scroll",
+            (this._wdScroll = () => {
+              if (
+                wrap.scrollTop + wrap.clientHeight >=
+                wrap.scrollHeight - 10
+              ) {
+                this.loadMoreWesternDisease();
+              }
+            }),
+          );
+        }
+      });
+    },
+```
+改为:
+```js
+    // 候选来源为后端 suggestDiagAll,打开下拉不再搜全库、不再滚动加载
+    // searchWesternDisease / loadMoreWesternDisease 代码保留不删,仅此处不再调用
+    onWesternDiseaseVisible(show) {
+      if (!show) {
+        const wrap = document.querySelector(
+          ".western-disease-input-wrapper .el-scrollbar__wrap",
+        );
+        if (wrap && this._wdScroll) {
+          wrap.removeEventListener("scroll", this._wdScroll);
+        }
+      }
+    },
+```
+
+- [ ] **Step 2: Commit**
+
+```bash
+git add src/views/diagnosis/Prescribing.vue
+git commit -m "feat: onWesternDiseaseVisible 不再搜全库/滚动加载" -m "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>"
+```
+
+---
+
+### Task 5: 缓存/恢复 `suggestDiagAll`
+
+**Files:**
+- Modify: `src/views/diagnosis/Prescribing.vue:1577`(缓存)、`:1651`(恢复)
+
+- [ ] **Step 1: 缓存时带上 suggestDiagAll**
+
+找到(`:1577`,在 `_setDataToStorage` 的 `obj` 里):
+```js
+        suggestDiag: this.suggestDiag,
+```
+改为:
+```js
+        suggestDiag: this.suggestDiag,
+        suggestDiagAll: this.suggestDiagAll,
+```
+
+- [ ] **Step 2: 恢复时还原 suggestDiagAll**
+
+找到(`:1651`,在 `_showDataFromStorage` 里):
+```js
+      this.suggestDiag = Array.isArray(storageData.suggestDiag) ? storageData.suggestDiag : [];
+```
+改为:
+```js
+      this.suggestDiag = Array.isArray(storageData.suggestDiag) ? storageData.suggestDiag : [];
+      this.suggestDiagAll = Array.isArray(storageData.suggestDiagAll) ? storageData.suggestDiagAll : [];
+```
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add src/views/diagnosis/Prescribing.vue
+git commit -m "feat: 缓存/恢复 suggestDiagAll 候选" -m "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>"
+```
+
+---
+
+### Task 6: 编译验证 + 浏览器手动测试
+
+**Files:** 无(验证)
+
+- [ ] **Step 1: 编译检查**
+
+Run: `npm run build`
+Expected: 编译通过,无报错。
+
+- [ ] **Step 2: 启动开发服务器**
+
+Run: `npm run serve`
+Expected: 服务正常启动。
+
+- [ ] **Step 3: 浏览器手动验证**
+
+进入适宜技术 tab(有后端返回建议诊断的患者),验证:
+
+1. **候选非空(多个)**:建议诊断默认显示 **1 个 tag**(候选第一个);点开 autocomplete 下拉,只显示 `suggestDiagAll` 里的候选(不能搜到全库其他诊断);选中一个 → 新增 tag;已选的项在下拉里置灰。
+2. **候选只有 1 个**:默认显示它,下拉只有它。
+3. **候选为空**:展示空(无 tag),下拉显示「暂无数据」。
+4. **删除已选 tag**:tag 消失,该项重新可在下拉选。
+5. **切 tab 再切回**:已选和候选都还在(缓存恢复生效)。
+
+- [ ] **Step 4: 若 name 显示为 code**
+
+若候选/tag 显示的是 code 而非诊断名称,说明后端 `suggestDiag` 未返回 `westname`。与后端确认返回对象数组 `{westcode, westname}`,或接受降级显示 code。
+
+- [ ] **Step 5: 全部通过后**
+
+无需额外 commit(本任务只验证)。
+
+---
+
+## Self-Review(计划作者已完成)
+
+**1. Spec 覆盖:**
+- §4.1 数据结构(suggestDiagAll + suggestDiag)→ Task 1 + Task 2 ✓
+- §4.3 改动点 1(data)→ Task 1 ✓
+- §4.3 改动点 2(赋值,默认第一个)→ Task 2 ✓
+- §4.3 改动点 3(queryWesternDisease 不搜全库)→ Task 3 ✓
+- §4.3 改动点 4(onWesternDiseaseSelect)→ 来源已由 Task 3 限定,天然满足,无需改 ✓
+- §4.3 改动点 5(el-tag/removeWesternDisease 不变)→ 不动 ✓
+- §4.3 改动点 6(提交不变)→ 不动 ✓
+- §4.3 改动点 7 + §5(缓存/恢复 suggestDiagAll)→ Task 5 ✓
+- §4.4 不变项(searchWesternDisease 保留)→ Task 3/4 不删,仅不调用 ✓
+
+**2. 占位符扫描:** 无 TBD/TODO;每步都有完整代码 ✓
+
+**3. 类型一致性:** `suggestDiagAll` 全程为对象数组 `{westcode, westname}`;`suggestDiag` 全程为 code 数组;字段名一致 ✓