# 建议诊断(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 数组;字段名一致 ✓
