Explorar el Código

非药物目录

张田田 hace 3 semanas
padre
commit
3744e798f9

+ 1 - 1
.env.production

@@ -1,6 +1,6 @@
 NODE_ENV = 'production'
 BASE_URL = './'
-VUE_APP_BASE_API = '/'
+VUE_APP_BASE_API = '/kd'
 #appid
 
 VUE_APP_CODE_IMG='http://101.133.232.97:8063/'

+ 79 - 81
package-lock.json

@@ -1702,6 +1702,63 @@
           "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
           "dev": true
         },
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true,
+          "optional": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "loader-utils": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
+          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
         "ssri": {
           "version": "8.0.1",
           "resolved": "https://registry.npmmirror.com/ssri/download/ssri-8.0.1.tgz",
@@ -1710,6 +1767,28 @@
           "requires": {
             "minipass": "^3.1.1"
           }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        },
+        "vue-loader-v16": {
+          "version": "npm:vue-loader@16.8.3",
+          "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
+          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "chalk": "^4.1.0",
+            "hash-sum": "^2.0.0",
+            "loader-utils": "^2.0.0"
+          }
         }
       }
     },
@@ -11065,87 +11144,6 @@
         }
       }
     },
-    "vue-loader-v16": {
-      "version": "npm:vue-loader@16.8.3",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
-      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "chalk": "^4.1.0",
-        "hash-sum": "^2.0.0",
-        "loader-utils": "^2.0.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-          "dev": true,
-          "optional": true
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "loader-utils": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
-          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        }
-      }
-    },
     "vue-print-nb": {
       "version": "1.7.4",
       "resolved": "https://registry.npmmirror.com/vue-print-nb/download/vue-print-nb-1.7.4.tgz",

+ 110 - 0
public/data/classify.json

@@ -0,0 +1,110 @@
+{
+    "classify": [
+        {
+            "label": "艾灸疗法",
+            "value": "1"
+        },
+        {
+            "label": "非艾·疗法",
+            "value": "2"
+        },
+        {
+            "label": "拔罐疗法",
+            "value": "3"
+        },
+        {
+            "label": "拔罐疗法",
+            "value": "4"
+        },
+        {
+            "label": "敷熨熏浴",
+            "value": "5"
+        },
+        {
+            "label": "推拿疗法",
+            "value": "6"
+        },
+        {
+            "label": "耳穴疗法",
+            "value": "7"
+        },
+        {
+            "label": "刮痧疗法",
+            "value": "8"
+        },
+        {
+            "label": "物理疗法",
+            "value": "9"
+        },
+        {
+            "label": "中医肛肠",
+            "value": "10"
+        },
+        {
+            "label": "中医微创",
+            "value": "11"
+        },
+        {
+            "label": "其他疗法",
+            "value": "12"
+        }
+    ],
+    "detailCumulative": [
+        {
+            "label": "穴位",
+            "value": "1"
+        },
+        {
+            "label": "部位",
+            "value": "2"
+        },
+        {
+            "label": "耳穴",
+            "value": "3"
+        },
+        {
+            "label": "经络",
+            "value": "4"
+        },
+        {
+            "label": "其他详情",
+            "value": "5"
+        }
+    ],
+    "detailDefault": [
+        {
+            "label": "穴位",
+            "value": "1"
+        },
+        {
+            "label": "部位",
+            "value": "2"
+        },
+        {
+            "label": "耳穴",
+            "value": "3"
+        },
+        {
+            "label": "经络",
+            "value": "4"
+        },
+        {
+            "label": "其他详情",
+            "value": "5"
+        },
+        {
+            "label": "无详情",
+            "value": "6"
+        }
+    ],
+    "singleNumber": [
+        {
+            "label": "默认1",
+            "value": "0"
+        },
+        {
+            "label": "详情累计/计数系数",
+            "value": "1"
+        }
+    ]
+}

+ 1 - 1
src/api/business.js

@@ -465,4 +465,4 @@ export function getDepartTreeData(data) {
         method: 'post',
         data
     })
-}
+}

+ 126 - 0
src/api/nonDrug.js

@@ -0,0 +1,126 @@
+import request from '@/utils/request.js'
+import {analysisAgency, analysisDelivery} from '@/model/transition';
+// 获取非药物目录列表
+export function getNondrugList(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/nondrugCataloguelistPain?page=' + data.page + '&limit=' + data.limit,
+        method: 'post',
+        data
+    })
+};
+// 新增非药物目录
+export function addNondrugCatalog(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/addNondrugCatalog',
+        method: 'post',
+        data
+    })
+};
+// 修改非药物目录
+export function updateNondrugCatalog(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/updateNondrugCatalog',
+        method: 'post',
+        data
+    })
+};
+// 非药物治疗目录详情列表
+export function getCatalogDetailsList(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/catalogDetailsList?pageNum=' + data.pageNum + '&pageSize=' + data.pageSize,
+        method: 'post',
+        data
+    })
+};
+// 获取机构非药物目录列表
+export function getOrgNondrugList(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/listNondrugItem?page=' + data.page + '&limit=' + data.limit,
+        method: 'post',
+        data
+    })
+};
+// 新增机构非药物项目
+export function addNondrugItem(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/addNondrugItem',
+        method: 'post',
+        data
+    })
+};
+// 修改机构非药物项目
+export function updateNondrugItem(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/updateNondrugItem',
+        method: 'post',
+        data
+    })
+};
+// 机构非药物项目名称模糊查询
+export function materialQuery(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/materialQuery',
+        method: 'post',
+        data
+    })
+};
+// 批量删除机构非药物项目
+export function batchDeleteNondrugItem(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/batchDeleteNondrugItem?ids=' + data.ids,
+        method: 'post'
+    })
+};
+// 非药物治疗映射管理列表
+export function getNondrugMapList(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/mappingList?pageNum=' + data.pageNum + '&pageSize=' + data.pageSize,
+        method: 'post',
+        data
+    })
+};
+// 非药物自动映射
+export function autoMapNondrug(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/autoMapNondrug?basisNondrugcatalogueId=' + data.basisNondrugcatalogueId,
+        method: 'post'
+    })
+};
+// 非药物清除映射关系
+export function clearMapNondrug(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/clearNondrugMapping?basisNondrugcatalogueId=' + data.basisNondrugcatalogueId,
+        method: 'post'
+    })
+};
+// 导入非药物类目
+export function importNondrug(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/importnodrug?appid=' + (data.appid || '') + '&deptId=' + (data.deptId || '') + '&institutionCode=' + (data.institutionCode || '') + '&institutionName=' + (data.institutionName || ''),
+        method: 'post',
+        data: data.formData
+    })
+};
+// 非药物手动映射
+export function manualMapping(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/manualMapping',
+        method: 'post',
+        data
+    })
+};
+// 导出非药物类目
+export function exportNondrug(data) {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/export?basisNondrugcatalogueId=' + data.basisNondrugcatalogueId,
+        method: 'Post',
+    })
+};
+// 下载非药物导入模版
+export function downloadNondrugTemplate() {
+    return request({
+        url: '/basis/stitutionsnondrugMgr/exportTemplate',
+        method: 'post',
+    })
+};
+

+ 18 - 0
src/components/Header.vue

@@ -246,6 +246,24 @@ export default {
         //     type: "page",
         // })
 
+        // 在"药品目录管理"菜单后插入"非药物目录管理"
+        res.Data.forEach(item => {
+          const drugListIdx = item.list.findIndex(m => m.jump === '/index/druglist');
+          if (drugListIdx !== -1) {
+            const drugListItem = item.list[drugListIdx];
+            const parentIdx = drugListItem.id.split('-')[0];
+            const newId = parentIdx + '-' + (item.list.length + 1);
+            const nondrugItem = {
+              id: newId,
+              jump: "/index/nondruglist",
+              name: "nondruglist",
+              title: "非药物目录管理",
+              type: "page",
+            };
+            item.list.splice(drugListIdx + 1, 0, nondrugItem);
+          }
+        });
+
         this.navlist = res.Data;
         this.navlist.forEach((item, index) => {
           item.list.forEach(item1 => {

+ 17 - 0
src/router/business.js

@@ -54,6 +54,14 @@ export default [{
         title: '药品目录管理',
         pftitle: '业务管理'
     }
+}, {
+    path: 'nondruglist',
+    name: 'nondruglist',
+    component: () => import('@/views/business/NonDrugList.vue'),
+    meta: {
+        title: '非药物目录管理',
+        pftitle: '业务管理'
+    }
 }, {
     path: 'drugmap',
     name: 'drugmap',
@@ -71,6 +79,15 @@ export default [{
         pftitle: '业务管理',
         keeplive: true
     }
+}, {
+    path: 'nondrugmaplist',
+    name: 'nondrugmaplist',
+    component: () => import('@/views/business/NonDrugMapList.vue'),
+    meta: {
+        title: '非药物目录管理',
+        pftitle: '业务管理',
+        keeplive: true
+    }
 }, {
     path: 'pharmacy',
     name: 'pharmacy',

+ 2 - 2
src/views/Home.vue

@@ -52,7 +52,7 @@ export default {
       code: "",
 
       checked: false,
-      src: process.env.VUE_APP_BASE_API + "captchaImage"
+      src: process.env.VUE_APP_BASE_API + "/captchaImage"
     };
   },
   created() {
@@ -67,7 +67,7 @@ export default {
     async getCodeimg() {
       let res = await getCodeimg();
       let time = new Date().getTime();
-      this.src = process.env.VUE_APP_BASE_API + "captchaImage?time=" + time;
+      this.src = process.env.VUE_APP_BASE_API + "/captchaImage?time=" + time;
     },
     async login() {
       localStorage.removeItem("token");

+ 1636 - 0
src/views/business/NonDrugList.vue

@@ -0,0 +1,1636 @@
+<template>
+  <div class="druglist">
+    <!-- 顶部筛选 -->
+    <div class="screening">
+      <div class="screening-title flex-vertical-center-l">
+        <img src="~@/assets/filters.png" alt />
+      </div>
+      <div class="screening-form flex-vertical-center-l flex-wrap">
+        <div class="screening-item flex-vertical-center-l">
+          <span>医共体名称:</span>
+          <div class="input">
+            <el-select
+              size="mini"
+              placeholder="请选择"
+              v-model="searchData.ygtid"
+              @change="onSearchYgtChange"
+            >
+              <el-option
+                :label="item.name"
+                :value="item.pid"
+                v-for="(item, index) in doctorBodyList"
+                :key="index"
+              ></el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="screening-item flex-vertical-center-l">
+          <span>医疗机构名称:</span>
+          <div class="input">
+            <el-select
+              size="mini"
+              placeholder="请选择"
+              clearable
+              v-model="searchData.stitutionsId"
+              @change="onSearchInstitutionChange"
+            >
+              <el-option
+                :label="item.label"
+                :value="item.value"
+                v-for="(item, index) in institutionList"
+                :key="index"
+              ></el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="screening-item flex-vertical-center-l">
+          <span>科室名称:</span>
+          <div class="input">
+            <el-select
+              size="mini"
+              placeholder="请选择"
+              clearable
+              v-model="searchData.departmentidSelsource"
+            >
+              <el-option
+                :label="item.label"
+                :value="item.value"
+                v-for="(item, index) in departList"
+                :key="index"
+              ></el-option>
+            </el-select>
+          </div>
+        </div>
+
+        <el-button type="primary" size="mini" @click="search()">搜索</el-button>
+        <el-button type="warning" size="mini" @click="clearFilter()"
+          >清空</el-button
+        >
+
+        <el-button type="primary" size="mini" @click="openEditDialog()"
+          >新增</el-button
+        >
+      </div>
+    </div>
+
+    <!-- 底部表格数据 -->
+    <div class="table">
+      <div class="today-table">
+        <div class="table-container">
+          <el-table
+            :data="tableData"
+            stripe
+            style="width: 100%"
+            border
+            height="100%"
+            cell-class-name="cell-max-height"
+          >
+            <el-table-column
+              prop="id"
+              label="序号"
+              width="50"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="name"
+              width="200"
+              label="非药物目录名称"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="ygtName"
+              width="200"
+              label="医共体"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="stitutionsName"
+              width="200"
+              label="医疗机构"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="departmentName"
+              label="科室"
+              align="center"
+            ></el-table-column>
+            <el-table-column
+              prop="describe"
+              label="非药物目录描述"
+              align="center"
+              show-overflow-tooltip
+            ></el-table-column>
+            <el-table-column label="操作" align="center" width="300">
+              <div class="flex-center operation" slot-scope="scope">
+                <div class="flex-center" @click="openEditDialog(scope.row)">
+                  修改
+                </div>
+                <div
+                  class="flex-center bg-yellow"
+                  @click="openMapPage(scope.row)"
+                >
+                  映射管理
+                </div>
+                <div class="flex-center" @click="openEditProject(scope.row)">
+                  编辑项目
+                </div>
+                <div class="flex-center bg-yellow">
+                  导入
+                  <input
+                    type="file"
+                    accept=".xlsx,.xls"
+                    runat="server"
+                    @change="uploadXSL($event, scope.row)"
+                  />
+                </div>
+                <div
+                  class="flex-center bg-yellow"
+                  @click="exportData(scope.row)"
+                >
+                  导出
+                </div>
+                <div
+                  class="flex-center bg-green"
+                  @click="downloadTemplate(scope.row)"
+                >
+                  模版下载
+                </div>
+              </div>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div class="flex-vertical-center-r today-page">
+          <el-pagination
+            background
+            layout=" prev, pager, next, jumper, total"
+            :total="total"
+            :page-size="limit"
+            @current-change="sizeC($event)"
+          ></el-pagination>
+        </div>
+      </div>
+    </div>
+
+    <popup
+      distanceTop="5vh"
+      :showDialog="showEditDialog"
+      :loading="editLoading"
+      @cancle="
+        showEditDialog = false;
+        editLoading = false;
+      "
+      @confim="submitEditData()"
+      :title="editData.pid ? '修改非药物目录' : '新增非药物目录'"
+    >
+      <div class="flex-center" slot="body">
+        <div class="form">
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">非药物目录名称:</div>
+            <div class="input">
+              <el-input
+                v-model="editData.name"
+                placeholder="请输入非药物目录名称"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">医共体:</div>
+            <div class="input">
+              <el-select
+                style="width: 100%"
+                placeholder="请选择医共体"
+                v-model="editData.ygtid"
+                @change="onEditYgtChange"
+              >
+                <el-option
+                  :label="item.name"
+                  :value="item.pid"
+                  v-for="(item, index) in doctorBodyList"
+                  :key="index"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>&nbsp;</span>
+            <div class="name">医疗机构:</div>
+            <div class="input">
+              <el-select
+                style="width: 100%"
+                placeholder="请选择医疗机构"
+                clearable
+                v-model="editData.stitutionsId"
+                @change="onEditInstitutionChangeSingle"
+              >
+                <el-option
+                  :label="item.label"
+                  :value="item.value"
+                  v-for="(item, index) in editInstitutionList"
+                  :key="index"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>&nbsp;</span>
+            <div class="name">科室:</div>
+            <div class="input">
+              <el-select
+                style="width: 100%"
+                placeholder="请选择科室"
+                clearable
+                multiple
+                v-model="editData.departmentidSelsource"
+              >
+                <el-option
+                  :label="item.label"
+                  :value="item.value"
+                  v-for="(item, index) in editDepartList"
+                  :key="index"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="form-item flex-plane-center-l">
+            <span>&nbsp;</span>
+            <div class="name">非药物目录描述:</div>
+            <div class="input">
+              <el-input
+                type="textarea"
+                v-model="editData.describe"
+                placeholder="请输入描述"
+              ></el-input>
+            </div>
+          </div>
+        </div>
+      </div>
+    </popup>
+
+    <!-- 编辑项目弹窗 -->
+    <el-dialog
+      :visible.sync="showProjectDialog"
+      :title="projectDialogTitle"
+      width="100%"
+      :close-on-click-modal="false"
+      top="0"
+      custom-class="project-full-dialog"
+      :fullscreen="true"
+    >
+      <div class="project-dialog">
+        <div class="project-toolbar">
+          <el-button type="primary" size="mini" @click="openItemDialog()"
+            >新增</el-button
+          >
+        </div>
+        <el-table
+          :data="projectListData"
+          stripe
+          border
+          height="calc(100vh - 180px)"
+          size="mini"
+        >
+          <el-table-column
+            type="index"
+            label="序号"
+            width="50"
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="itemCode"
+            label="编码"
+            width="100"
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="itemName"
+            label="项目名称"
+            width="120"
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="connotation"
+            label="项目内涵"
+            width="120"
+            align="center"
+            show-overflow-tooltip
+          ></el-table-column>
+          <el-table-column
+            prop="excludedContent"
+            label="除外内容"
+            width="120"
+            align="center"
+            show-overflow-tooltip
+          ></el-table-column>
+          <el-table-column
+            prop="pricingUnit"
+            label="计价单位"
+            width="80"
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="price"
+            label="价格"
+            width="80"
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="remark"
+            label="备注"
+            width="120"
+            align="center"
+            show-overflow-tooltip
+          ></el-table-column>
+          <el-table-column
+            prop="limitPayScope"
+            label="限定支付范围"
+            width="140"
+            align="center"
+            show-overflow-tooltip
+          ></el-table-column>
+          <el-table-column label="详情默认值" width="100" align="center">
+            <template slot-scope="scope">
+              {{
+                getOptionLabel(detailDefaultOptions, scope.row.detailDefault)
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column label="详情是否必填" width="110" align="center">
+            <template slot-scope="scope">
+              {{ scope.row.detailIsnull === "1" ? "是" : "否" }}
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop="singleNumber"
+            label="单次数量"
+            width="120"
+            align="center"
+          >
+            <template slot-scope="scope">
+              {{
+                getOptionLabel(singleQuantityOptions, scope.row.singleNumber)
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column label="详情累计项" width="100" align="center">
+            <template slot-scope="scope">
+              {{ getDetailCumulativeLabel(scope.row.detailCumulative) }}
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop="countCoefficient"
+            label="计数系数"
+            width="80"
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="minTreatmentDuration"
+            label="最少治疗时长(分钟)"
+            width="120"
+            align="center"
+          ></el-table-column>
+          <el-table-column label="分类" width="80" align="center">
+            <template slot-scope="scope">
+              {{ getOptionLabel(categoryOptions, scope.row.classify) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="100">
+            <template slot-scope="scope">
+              <span class="op-text op-blue" @click="openItemDialog(scope.row)"
+                >修改</span
+              >
+              <span
+                class="op-text op-orange"
+                @click="deleteProjectItem(scope.row)"
+                >删除</span
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+        <div class="flex-vertical-center-r today-page" style="margin-top: 10px">
+          <el-pagination
+            background
+            layout="prev, pager, next, jumper, total"
+            :total="projectTotal"
+            :page-size="projectLimit"
+            @current-change="projectPageChange($event)"
+          ></el-pagination>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 项目新增/修改弹窗 -->
+    <popup
+      distanceTop="10vh"
+      :showDialog="showItemDialog"
+      :loading="false"
+      @cancle="showItemDialog = false"
+      @confim="submitItemData()"
+      :title="itemEditData.pid ? '修改项目' : '新增项目'"
+      width="50%"
+    >
+      <div class="flex-center" slot="body">
+        <div class="form" style="width: 100%">
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">编码:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.itemCode"
+                placeholder="请输入编码"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">项目名称:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.itemName"
+                placeholder="请输入项目名称"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>&nbsp;</span>
+            <div class="name">项目内涵:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.connotation"
+                placeholder="请输入项目内涵"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>&nbsp;</span>
+            <div class="name">除外内容:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.excludedContent"
+                placeholder="请输入除外内容"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">计价单位:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.pricingUnit"
+                placeholder="请输入计价单位"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">价格:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.price"
+                placeholder="请输入价格"
+                type="number"
+                @input="itemEditData.price = itemEditData.price.replace(/[^0-9.]/g, '')"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>&nbsp;</span>
+            <div class="name">备注:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.remark"
+                placeholder="请输入备注"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>&nbsp;</span>
+            <div class="name">限定支付范围:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.limitPayScope"
+                placeholder="请输入限定支付范围"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">详情默认值:</div>
+            <div class="input">
+              <el-select
+                style="width: 100%"
+                v-model="itemEditData.detailDefault"
+                placeholder="请选择"
+              >
+                <el-option
+                  v-for="item in detailDefaultOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">详情是否必填:</div>
+            <div class="input">
+              <el-select
+                style="width: 100%"
+                v-model="itemEditData.detailIsnull"
+                placeholder="请选择"
+              >
+                <el-option
+                  v-for="item in detailRequiredOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">单次数量:</div>
+            <div class="input">
+              <el-select
+                style="width: 100%"
+                v-model="itemEditData.singleNumber"
+                placeholder="请选择"
+              >
+                <el-option
+                  v-for="item in singleQuantityOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>&nbsp;</span>
+            <div class="name">详情累计项:</div>
+            <div class="input">
+              <el-select
+                style="width: 100%"
+                v-model="itemEditData.detailCumulative"
+                placeholder="请选择"
+                multiple
+              >
+                <el-option
+                  v-for="item in detailCumulativeOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>&nbsp;</span>
+            <div class="name">计数系数:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.countCoefficient"
+                placeholder="请输入计数系数"
+                type="number"
+                @input="itemEditData.countCoefficient = itemEditData.countCoefficient.replace(/[^0-9]/g, '')"
+              ></el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">最少治疗时长:</div>
+            <div class="input">
+              <el-input
+                v-model="itemEditData.minTreatmentDuration"
+                placeholder="请输入最少治疗时长"
+                type="number"
+                @input="itemEditData.minTreatmentDuration = itemEditData.minTreatmentDuration.replace(/[^0-9]/g, '')"
+              >
+                <template slot="append">分钟</template>
+              </el-input>
+            </div>
+          </div>
+          <div class="form-item flex flex-col-center">
+            <span>*</span>
+            <div class="name">分类:</div>
+            <div class="input">
+              <el-select
+                style="width: 100%"
+                v-model="itemEditData.classify"
+                placeholder="请选择"
+              >
+                <el-option
+                  v-for="item in categoryOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+        </div>
+      </div>
+    </popup>
+  </div>
+</template>
+<script>
+import popup from "@/components/Propup.vue";
+import {
+  getNondrugList,
+  addNondrugCatalog,
+  updateNondrugCatalog,
+  getCatalogDetailsList,
+  addNondrugItem,
+  updateNondrugItem,
+  batchDeleteNondrugItem,
+  importNondrug,
+  exportNondrug,
+  downloadNondrugTemplate,
+} from "@/api/nonDrug.js";
+
+import { mapState, mapGetters, mapActions, mapMutations } from "vuex";
+import {
+  getDoctorBodySelect,
+  getMedSelect,
+  getDepartSelect,
+} from "@/api/system.js";
+import { errLog } from "vxe-pc-ui";
+
+let cache = new Map();
+export default {
+  components: {
+    popup,
+  },
+  data() {
+    return {
+      searchData: {
+        ygtid: "",
+        stitutionsId: "",
+        departmentidSelsource: "",
+      },
+      // 搜索区域下拉列表
+      institutionList: [],
+      departList: [],
+
+      tableData: [],
+      page: 1,
+      limit: 10,
+      total: 0,
+
+      // 编辑表单
+      showEditDialog: false,
+      editLoading: false,
+      editData: {
+        ygtid: "",
+        stitutionsId: "",
+        departmentidSelsource: [],
+        name: "",
+        describe: "",
+      },
+      // 编辑区域下拉列表
+      editInstitutionList: [],
+      editDepartList: [],
+
+      pid: "",
+      nowPid: "",
+
+      // 医共体
+      doctorBodyList: [],
+
+      // 编辑项目弹窗
+      showProjectDialog: false,
+      projectDialogTitle: "",
+      currentProjectPid: "",
+      currentProjectRow: null,
+      projectListData: [],
+      projectPage: 1,
+      projectLimit: 10,
+      projectTotal: 0,
+
+      // 项目新增/修改
+      showItemDialog: false,
+      itemEditData: {},
+
+      // 下拉选项(从 data/classify.json 加载)
+      detailDefaultOptions: [],
+      detailRequiredOptions: [
+        { label: "是", value: "1" },
+        { label: "否", value: "0" },
+      ],
+      singleQuantityOptions: [],
+      detailCumulativeOptions: [],
+      categoryOptions: [],
+    };
+  },
+  async created() {
+    this.getCascaderA();
+    await this.loadClassifyOptions();
+    await this.getList();
+    this.nowPid = this.getuserinfo.organizationid;
+  },
+  destroyed() {
+    cache.clear();
+  },
+  methods: {
+    // ===== 加载下拉选项 =====
+    async loadClassifyOptions() {
+      try {
+        const res = await fetch(`${window.BASE_URL}data/classify.json`);
+        const data = await res.json();
+        this.categoryOptions = data.classify || [];
+        this.detailDefaultOptions = data.detailDefault || [];
+        this.detailCumulativeOptions = data.detailCumulative || [];
+        this.singleQuantityOptions = data.singleNumber || [];
+      } catch (e) {
+        console.error("加载分类选项失败", e);
+      }
+    },
+    // ===== 搜索区域联动 =====
+    async onSearchYgtChange(ygtid) {
+      this.searchData.stitutionsId = "";
+      this.searchData.departmentidSelsource = "";
+      this.institutionList = [];
+      this.departList = [];
+      if (ygtid) await this.loadInstitutionList(ygtid, "search");
+    },
+    async onSearchInstitutionChange(institutionId) {
+      this.searchData.departmentidSelsource = "";
+      this.departList = [];
+      if (institutionId) await this.loadDepartList(institutionId, "search");
+    },
+
+    // ===== 编辑区域联动 =====
+    async onEditYgtChange(ygtid) {
+      this.editData.stitutionsId = "";
+      this.editData.departmentidSelsource = [];
+      this.editInstitutionList = [];
+      this.editDepartList = [];
+      if (ygtid) await this.loadInstitutionList(ygtid, "edit");
+    },
+    async onEditInstitutionChangeSingle(institutionId) {
+      this.editData.departmentidSelsource = [];
+      this.editDepartList = [];
+      if (institutionId) await this.loadDepartList(institutionId, "edit");
+    },
+
+    // ===== 通用数据加载 =====
+    async loadInstitutionList(organizationId, type) {
+      const key = "inst_" + organizationId;
+      let nodes = cache.has(key)
+        ? cache.get(key)
+        : await getMedSelect({ organizationId })
+            .then((res) =>
+              res && +res.ResultCode === 0
+                ? res.Data.map((item) => ({
+                    label: item.name,
+                    value: item.pid,
+                  }))
+                : [],
+            )
+            .catch(() => []);
+      cache.set(key, nodes);
+      if (type === "search") this.institutionList = nodes;
+      else this.editInstitutionList = nodes;
+      return nodes;
+    },
+    async loadDepartList(institutionId, type) {
+      const nodes = await this.getDepartNodes(institutionId);
+      if (type === "search") this.departList = nodes;
+      else this.editDepartList = nodes;
+      return nodes;
+    },
+    async getDepartNodes(institutionId) {
+      const key = "dept_" + institutionId;
+      if (cache.has(key)) return cache.get(key);
+      const nodes = await getDepartSelect({ institutionId })
+        .then((res) =>
+          res && +res.ResultCode === 0
+            ? res.Data.map((item) => ({ label: item.name, value: item.pid }))
+            : [],
+        )
+        .catch(() => []);
+      cache.set(key, nodes);
+      return nodes;
+    },
+
+    // ===== 获取医共体 =====
+    async getCascaderA() {
+      const res = await getDoctorBodySelect();
+      if (res && +res.ResultCode === 0) {
+        this.doctorBodyList = res.Data;
+      }
+    },
+
+    // ===== 映射管理跳转 =====
+    openMapPage(row) {
+      this.$router.push({
+        path: `/index/nondrugmaplist?pid=${row.pid}&ygtid=${row.ygtid ||
+          ""}&ygtName=${encodeURIComponent(
+          row.ygtName || "",
+        )}&stitutionsId=${row.stitutionsId ||
+          ""}&departmentidSelsource=${row.departmentidSelsource || ""}`,
+      });
+    },
+
+    // ===== 新增/编辑弹窗 =====
+    async openEditDialog(row = {}) {
+      this.editInstitutionList = [];
+      this.editDepartList = [];
+      this.editData = {
+        pid: row.pid,
+        describe: row.describe || "",
+        name: row.name || "",
+        ygtid: row.ygtid || this.searchData.ygtid,
+        stitutionsId: "",
+        departmentidSelsource: [],
+      };
+      this.editLoading = true;
+      this.showEditDialog = true;
+
+      if (this.editData.ygtid) {
+        await this.loadInstitutionList(this.editData.ygtid, "edit");
+
+        if (row.stitutionsId) {
+          // 加载科室
+          const nodes = await this.getDepartNodes(row.stitutionsId);
+          this.editDepartList = nodes;
+
+          // 用 $set 确保响应式更新,一次性设置避免中间态
+          this.$set(this.editData, "stitutionsId", row.stitutionsId);
+          this.$set(
+            this.editData,
+            "departmentidSelsource",
+            row.departmentidSelsource
+              ? row.departmentidSelsource.split(",").filter(Boolean)
+              : [],
+          );
+        }
+      }
+      this.editLoading = false;
+    },
+
+    // ===== 提交编辑 =====
+    async submitEditData() {
+      if (!this.editData.name || !this.editData.name.trim()) {
+        return this.$message.warning("请输入非药物目录名称");
+      }
+      if (!this.editData.ygtid) {
+        return this.$message.warning("请选择医共体");
+      }
+
+      // 校验唯一性:同一医共体/机构下,任一科室不可重复
+      {
+        const editDeptIds = Array.isArray(this.editData.departmentidSelsource)
+          ? this.editData.departmentidSelsource
+          : (this.editData.departmentidSelsource || "")
+              .split(",")
+              .filter(Boolean);
+        if (editDeptIds.length > 0 && this.editData.stitutionsId) {
+          const checkRes = await getNondrugList({
+            page: 1,
+            limit: 9999,
+            ygtid: this.editData.ygtid,
+          });
+          if (checkRes.ResultCode == 0) {
+            const items = (checkRes.Data.Items || []).filter(
+              (item) => item.pid !== this.editData.pid,
+            );
+            // 找出同一机构下的记录,逐个科室检查是否已存在
+            const matchedItems = items.filter(
+              (item) =>
+                (item.stitutionsId || "") === this.editData.stitutionsId &&
+                (item.departmentidSelsource || ""),
+            );
+            // 收集已存在的科室ID -> 名称映射
+            const existDeptMap = {};
+            matchedItems.forEach((item) => {
+              const ids = (item.departmentidSelsource || "")
+                .split(",")
+                .filter(Boolean);
+              ids.forEach((id) => {
+                if (!existDeptMap[id]) {
+                  existDeptMap[id] =
+                    item.departmentName || item.stitutionsName || "";
+                }
+              });
+            });
+            const conflictIds = editDeptIds.filter((id) => existDeptMap[id]);
+            if (conflictIds.length > 0) {
+              // 用 editDepartList 查出冲突科室名称
+              const conflictNames = conflictIds
+                .map((id) => {
+                  const dept = this.editDepartList.find(
+                    (d) => d.value === id,
+                  );
+                  return dept ? dept.label : id;
+                })
+                .join("、");
+              const ygtName =
+                this.doctorBodyList.find(
+                  (i) => i.pid === this.editData.ygtid,
+                )?.name || "";
+              const instName =
+                this.editInstitutionList.find(
+                  (i) => i.value === this.editData.stitutionsId,
+                )?.label || "";
+              return this.$message.warning(
+                `${ygtName}-${instName}-${conflictNames}的非药物目录已存在`,
+              );
+            }
+          }
+        }
+      }
+
+      const ygtItem = this.doctorBodyList.find(
+        (item) => item.pid === this.editData.ygtid,
+      );
+      // 构造 医共体 / 机构 / 科室 树
+      const instItem = this.editInstitutionList.find(
+        (item) => item.value === this.editData.stitutionsId,
+      );
+
+      // 多选科室:数组转逗号分隔字符串
+      const deptIds = Array.isArray(this.editData.departmentidSelsource)
+        ? this.editData.departmentidSelsource
+        : (this.editData.departmentidSelsource || "").split(",").filter(Boolean);
+      const deptIdsStr = deptIds.join(",");
+      const deptNamesStr = deptIds
+        .map((id) => {
+          const dept = this.editDepartList.find((d) => d.value === id);
+          return dept ? dept.label : "";
+        })
+        .filter(Boolean)
+        .join(",");
+
+      const params = {
+        pid: this.editData.pid || undefined,
+        name: this.editData.name,
+        describe: this.editData.describe,
+        ygtid: this.editData.ygtid,
+        ygtName: ygtItem ? ygtItem.name : "",
+        stitutionsId: this.editData.stitutionsId,
+        stitutionsName: instItem ? instItem.label : "",
+        departmentidSelsource: deptIdsStr,
+        departmentName: deptNamesStr,
+      };
+
+      params.groupInfo = [
+        {
+          pid: this.editData.ygtid,
+          name: ygtItem ? ygtItem.name : "",
+          children: params.stitutionsId
+            ? [
+                {
+                  pid: params.stitutionsId,
+                  name: instItem ? instItem.label : "",
+                  children: deptIds.length
+                    ? deptIds.map((id) => {
+                        const dept = this.editDepartList.find((d) => d.value === id);
+                        return {
+                          pid: id,
+                          name: dept ? dept.label : "",
+                          children: [],
+                        };
+                      })
+                    : [],
+                },
+              ]
+            : [],
+        },
+      ];
+      params.groupInfo = JSON.stringify(params.groupInfo);
+
+      const res = await (params.pid
+        ? updateNondrugCatalog(params)
+        : addNondrugCatalog(params));
+      if (res.ResultCode == 0) {
+        this.$message.success(params.pid ? "操作成功" : "添加成功");
+        this.showEditDialog = false;
+        await this.getList();
+      }
+    },
+
+    // ===== 列表相关 =====
+    sizeC(e) {
+      this.page = e;
+      this.getList();
+    },
+    search() {
+      this.page = 1;
+      this.getList();
+    },
+    clearFilter() {
+      this.searchData = {
+        ygtid: "",
+        stitutionsId: "",
+        departmentidSelsource: "",
+      };
+      this.institutionList = [];
+      this.departList = [];
+      this.getList();
+    },
+    async getList() {
+      let params = {
+        page: this.page,
+        limit: this.limit,
+        ygtid: this.searchData.ygtid,
+        stitutionsId: this.searchData.stitutionsId,
+        departmentidSelsource: this.searchData.departmentidSelsource,
+      };
+      let res = await getNondrugList(params);
+      if (res.ResultCode == 0) {
+        const items = res.Data.Items;
+        this.total = res.Data.TotalRecordCount;
+        items.forEach((item, index) => {
+          item.id = (this.page - 1) * this.limit + index + 1;
+        });
+        this.tableData = items;
+      }
+    },
+
+    // ===== 编辑项目 =====
+    openEditProject(row) {
+      this.currentProjectRow = row;
+      this.currentProjectPid = row.pid;
+      this.projectDialogTitle = (row.name || "") + "非药物目录";
+      this.projectPage = 1;
+      this.showProjectDialog = true;
+      this.getProjectList();
+    },
+
+    // ===== 编辑项目列表 =====
+    projectPageChange(e) {
+      this.projectPage = e;
+      this.getProjectList();
+    },
+    async getProjectList() {
+      const row = this.currentProjectRow || {};
+      const params = {
+        // page: this.projectPage,
+        // limit: this.projectLimit,
+        pageNum: this.projectPage,
+        pageSize: this.projectLimit,
+        appId: row.ygtid || "",
+        deptId: row.departmentidSelsource || "",
+        institutionCode: row.stitutionsId || "",
+      };
+      try {
+        const res = await getCatalogDetailsList(params);
+        if (res.ResultCode == 0) {
+          this.projectListData = res?.Data?.list || [];
+          this.projectTotal = res?.Data?.total || 0;
+        } else {
+          this.$message.error(res.ResultInfo || "获取列表失败");
+        }
+      } catch (e) {
+        this.$message.error(e.message || "获取列表失败");
+      }
+    },
+
+    // ===== 项目新增/修改 =====
+    openItemDialog(row) {
+      if (row && row.pid) {
+        this.itemEditData = { ...row };
+        if (
+          this.itemEditData.detailCumulative &&
+          typeof this.itemEditData.detailCumulative === "string"
+        ) {
+          this.itemEditData.detailCumulative = this.itemEditData.detailCumulative
+            .split(/[,、]/)
+            .filter(Boolean)
+            .map((v) => String(v));
+        } else if (Array.isArray(this.itemEditData.detailCumulative)) {
+          this.itemEditData.detailCumulative = this.itemEditData.detailCumulative.map((v) =>
+            String(v),
+          );
+        }
+        if (!Array.isArray(this.itemEditData.detailCumulative)) {
+          this.itemEditData.detailCumulative = [];
+        }
+      } else {
+        this.itemEditData = {
+          itemCode: "",
+          itemName: "",
+          connotation: "",
+          excludedContent: "",
+          pricingUnit: "",
+          price: "",
+          remark: "",
+          limitPayScope: "",
+          detailDefault: "",
+          detailIsnull: "",
+          singleNumber: "",
+          detailCumulative: [],
+          countCoefficient: "",
+          minTreatmentDuration: "",
+          classify: "",
+        };
+      }
+      this.showItemDialog = true;
+    },
+    async submitItemData() {
+      const d = this.itemEditData;
+      if (!d.itemCode || !d.itemCode.trim())
+        return this.$message.error("请输入编码");
+      if (!d.itemName || !d.itemName.trim())
+        return this.$message.error("请输入项目名称");
+      // 新增时校验编码和项目名称不能重复
+      if (!d.pid) {
+        const duplicateCode = this.projectListData.find(
+          (item) => item.itemCode === d.itemCode.trim(),
+        );
+        if (duplicateCode) {
+          return this.$message.error("编码已存在,请勿重复添加");
+        }
+        const duplicateName = this.projectListData.find(
+          (item) => item.itemName === d.itemName.trim(),
+        );
+        if (duplicateName) {
+          return this.$message.error("项目名称已存在,请勿重复添加");
+        }
+      }
+      if (!d.pricingUnit || !d.pricingUnit.trim())
+        return this.$message.error("请输入计价单位");
+      if (d.price === "" || d.price === null || d.price === undefined)
+        return this.$message.error("请输入价格");
+      if (Number(d.price) < 0)
+        return this.$message.error("价格不能为负数");
+      if (d.countCoefficient !== "" && d.countCoefficient !== null && d.countCoefficient !== undefined) {
+        if (!/^\d+$/.test(String(d.countCoefficient)) || Number(d.countCoefficient) <= 0)
+          return this.$message.error("计数系数必须为正整数");
+      }
+      if (!d.detailDefault) return this.$message.error("请选择详情默认值");
+      if (!d.detailIsnull && d.detailIsnull !== 0)
+        return this.$message.error("请选择详情是否必填");
+      if (!d.singleNumber) return this.$message.error("请选择单次数量");
+      if (!d.minTreatmentDuration)
+        return this.$message.error("请输入最少治疗时长");
+      if (!/^\d+$/.test(String(d.minTreatmentDuration)) || Number(d.minTreatmentDuration) <= 0)
+        return this.$message.error("最少治疗时长必须为正整数");
+      if (!d.classify) return this.$message.error("请选择分类");
+      try {
+        const params = { ...this.itemEditData };
+        if (Array.isArray(params.detailCumulative)) {
+          params.detailCumulative = params.detailCumulative.join(",");
+        }
+        const row = this.currentProjectRow || {};
+        params.appId = row.ygtid || "";
+        params.institutionCode = row.stitutionsId || "";
+        params.deptId = row.departmentidSelsource || "";
+        const res = await (params.pid
+          ? updateNondrugItem(params)
+          : addNondrugItem(params));
+        if (res.ResultCode == 0) {
+          this.$message.success(params.pid ? "修改成功" : "新增成功");
+          this.showItemDialog = false;
+          this.getProjectList();
+        } else {
+          this.$message.error(res.ResultInfo || "操作失败");
+        }
+      } catch (e) {
+        this.$message.error(e.message || "操作失败");
+      }
+    },
+
+    // ===== 项目删除 =====
+    deleteProjectItem(row) {
+      this.$confirm("确认删除该条目吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(async () => {
+          try {
+            const res = await batchDeleteNondrugItem({ ids: row.pid });
+            if (res.ResultCode == 0) {
+              this.$message.success("删除成功");
+              this.getProjectList();
+            } else {
+              this.$message.error(res.ResultInfo || "删除失败");
+            }
+          } catch (e) {
+            this.$message.error(e.message || "删除失败");
+          }
+        })
+        .catch(() => {});
+    },
+
+    // ===== 标签映射 =====
+    getOptionLabel(options, value) {
+      if ((value === "" || value === null || value === undefined) && value !== 0) return "-";
+      const sv = String(value);
+      const item = options.find((o) => String(o.value) === sv);
+      return item ? item.label : value;
+    },
+    getDetailCumulativeLabel(val) {
+      if (!val) return "-";
+      const arr = String(val).split(/[,、]/).filter(Boolean);
+      return arr
+        .map((v) => this.getOptionLabel(this.detailCumulativeOptions, v))
+        .join(",");
+    },
+
+    // ===== 模版下载 =====
+    async downloadTemplate(row) {
+      const loading = this.$loading({
+        lock: true,
+        text: "正在下载,请稍后",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      try {
+        const res = await downloadNondrugTemplate();
+        if (res && res.ResultCode == 0) {
+          let path = process.env.VUE_APP_UPLOAD + "file/" + res.ResultInfo;
+          const a = document.createElement("a");
+          a.setAttribute("download", "");
+          a.setAttribute("href", path);
+          a.click();
+          a.remove();
+          this.$message({
+            type: "success",
+            message: "下载成功",
+            showClose: true,
+          });
+        } else {
+          this.$message.error(res.ResultInfo || "下载失败");
+        }
+      } catch (e) {
+        this.$message.error(e.message || "下载失败");
+      } finally {
+        loading.close();
+      }
+    },
+
+    // ===== 导出 =====
+    async exportData(row) {
+      let params = {
+        basisNondrugcatalogueId: row.pid,
+      };
+      const loading = this.$loading({
+        lock: true,
+        text: "正在导出,请稍后",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      let res = await exportNondrug(params).catch(() => {
+        loading.close();
+      });
+      if (res && res.ResultCode == 0) {
+        let path = process.env.VUE_APP_UPLOAD + "file/" + res.ResultInfo;
+        const a = document.createElement("a");
+        a.setAttribute("download", "");
+        a.setAttribute("href", path);
+        a.click();
+        a.remove();
+        this.$message({
+          type: "success",
+          message: "导出成功",
+          showClose: true,
+        });
+        loading.close();
+      }
+    },
+
+    // ===== 导入 =====
+    uploadXSL(e, row) {
+      const file = e.target.files[0];
+      if (!file) return;
+      let formData = new FormData();
+      formData.append("file", file);
+      importNondrug({
+        appid: row.ygtid || "",
+        deptId: row.departmentidSelsource || "",
+        institutionCode: row.stitutionsId || "",
+        institutionName: row.stitutionsName || "",
+        formData,
+      })
+        .then((res) => {
+          if (res.ResultCode == 0) {
+            this.$message({
+              message: "导入成功",
+              type: "success",
+              showClose: true,
+            });
+            this.getList();
+          } else {
+            this.$message({
+              message: res.ResultInfo || "导入失败",
+              type: "error",
+              showClose: true,
+            });
+          }
+        })
+        .catch(() => {
+          // this.$message({ message: "导入失败", type: "error", showClose: true });
+        });
+      e.target.value = "";
+    },
+  },
+  computed: {
+    ...mapGetters(["getuserinfo"]),
+  },
+};
+</script>
+<style lang="scss" scoped>
+@import "../../style/common.scss";
+@import "../../style/base.scss";
+
+.bg-yellow {
+  background: #ffae45;
+  position: relative;
+  width: 56px;
+  height: 28px;
+
+  border-radius: 4px;
+  cursor: pointer;
+  font-size: 14px;
+  font-family: PingFang SC;
+  font-weight: 400;
+  color: #ffffff;
+  margin-left: 10px;
+  margin-right: 10px;
+
+  input {
+    width: 74px;
+    height: 36px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    opacity: 0;
+  }
+}
+
+.table {
+  padding: 10px 10px;
+  background: #ffffff;
+  border-radius: 5px;
+  margin-top: 10px;
+  height: 70vh;
+
+  .table-container {
+    height: 90%;
+  }
+
+  .today-table {
+    height: 100%;
+
+    .operation {
+      display: flex;
+      align-items: center;
+      justify-content: space-around;
+      flex-wrap: wrap;
+      div {
+        width: 60px;
+        height: 24px;
+        background: #5386f6;
+        border-radius: 2px;
+        font-size: 14px;
+        font-family: PingFang SC;
+        font-weight: 400;
+        color: #ffffff;
+        cursor: pointer;
+        margin: 5px 0;
+      }
+
+      .bg-yellow {
+        width: 80px;
+        height: 24px;
+        background: #ffae45;
+      }
+
+      .bg-red {
+        width: 80px;
+        height: 24px;
+        background: red;
+      }
+
+      .bg-green {
+        width: 80px;
+        height: 24px;
+        background: #67c23a;
+      }
+    }
+  }
+}
+
+.table-body::v-deep .el-table .cell {
+  text-align: center;
+}
+
+.el-table::v-deep {
+  .cell-max-height div {
+    max-height: 240px;
+    overflow-y: auto;
+  }
+}
+</style>
+
+<style lang="scss" scoped>
+@media screen and (min-width: 1681px) and (max-width: 1920px) {
+  .table {
+    height: 81vh;
+
+    .table-container {
+      height: 94%;
+    }
+  }
+
+  .today-table::v-deep .el-table td {
+    padding: 18px 0;
+  }
+
+  .today-table::v-deep .el-table th {
+    padding: 18px 0;
+  }
+}
+
+@media screen and (min-width: 1601px) and (max-width: 1680px) {
+  .table {
+    height: 80vh;
+
+    .table-container {
+      height: 94%;
+    }
+  }
+
+  .today-table::v-deep .el-table td {
+    padding: 18px 0;
+  }
+
+  .today-table::v-deep .el-table th {
+    padding: 18px 0;
+  }
+}
+
+@media screen and (min-width: 1361px) and (max-width: 1600px) {
+  .table {
+    height: 72vh;
+
+    .table-container {
+      height: 90%;
+    }
+  }
+
+  .today-table::v-deep .el-table td {
+    padding: 5px 0;
+  }
+
+  .today-table::v-deep .el-table th {
+    padding: 5px 0;
+  }
+}
+
+@media screen and(min-width:1281px) and (max-width: 1360px) {
+  .table {
+    height: 72vh;
+
+    .table-container {
+      height: 90%;
+    }
+  }
+
+  .today-table::v-deep .el-table td {
+    padding: 5px 0;
+  }
+
+  .today-table::v-deep .el-table th {
+    padding: 5px 0;
+  }
+}
+
+.form {
+  width: 50%;
+
+  .form-item {
+    margin-bottom: 10px;
+
+    span {
+      color: red;
+      width: 10px;
+      text-align: center;
+      flex-shrink: 0;
+    }
+
+    .name {
+      width: 150px;
+      white-space: nowrap;
+      flex-shrink: 0;
+    }
+
+    .input {
+      flex: 1;
+    }
+  }
+}
+
+.link-text {
+  color: #5386f6;
+  cursor: pointer;
+  text-decoration: underline;
+}
+
+.op-text {
+  cursor: pointer;
+  margin: 0 5px;
+  font-size: 14px;
+}
+.op-blue {
+  color: #5386f6;
+}
+.op-orange {
+  color: #ffae45;
+}
+
+.project-dialog {
+  .project-toolbar {
+    margin-bottom: 10px;
+  }
+}
+
+.group-form {
+  width: 100%;
+  padding: 0 20px;
+  box-sizing: border-box;
+
+  .group-form-item {
+    margin-bottom: 10px;
+
+    span {
+      color: red;
+    }
+
+    .name {
+      width: 90px;
+      text-align: right;
+      margin-right: 8px;
+    }
+
+    .input {
+      flex: 1;
+    }
+  }
+
+  .cond-label {
+    color: #333;
+    font-size: 14px;
+    white-space: nowrap;
+  }
+
+  .unit-label {
+    font-size: 14px;
+    color: #333;
+    white-space: nowrap;
+  }
+
+  .group-count {
+    position: absolute;
+    right: 8px;
+    top: 50%;
+    transform: translateY(-50%);
+    color: #ff4949;
+    font-size: 14px;
+    font-weight: bold;
+  }
+}
+
+.group-notice {
+  color: #e6a23c;
+  font-size: 13px;
+  margin-top: 10px;
+  padding-left: 30px;
+}
+
+.group-btns {
+  margin-top: 15px;
+
+  .group-btn-delete {
+    width: 108px;
+    height: 40px;
+    background: #ff4949;
+    border-radius: 3px;
+    font-size: 16px;
+    color: #fff;
+    cursor: pointer;
+    margin-left: auto;
+    margin-right: 30px;
+  }
+}
+</style>
+
+<style lang="scss">
+.project-full-dialog {
+  margin: 0 !important;
+  .el-dialog__header {
+    text-align: center;
+  }
+  .el-dialog__body {
+    padding: 10px 15px;
+  }
+}
+</style>

+ 572 - 0
src/views/business/NonDrugMapList.vue

@@ -0,0 +1,572 @@
+<template>
+  <div class="druglist">
+    <!-- 顶部筛选 -->
+    <div class="screening">
+      <div class="screening-title flex-vertical-center-l">
+        <img src="~@/assets/filters.png" alt />
+      </div>
+      <div class="screening-form flex-vertical-center-l flex-wrap">
+        <div class="screening-item flex-vertical-center-l">
+          <span>映射状态:</span>
+          <div class="input">
+            <el-select
+              size="mini"
+              placeholder="全部"
+              v-model="searchData.isMapping"
+              clearable
+            >
+              <el-option :value="0" label="未映射"></el-option>
+              <el-option :value="1" label="已映射"></el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="screening-item flex-vertical-center-l">
+          <span>平台非药物疗法:</span>
+          <div class="input">
+            <el-input
+              size="mini"
+              placeholder="请输入二级分类名称"
+              v-model="searchData.secondName"
+              @keydown.enter.native="search()"
+              clearable
+            ></el-input>
+          </div>
+        </div>
+
+        <el-button type="primary" size="mini" @click="search()">搜索</el-button>
+        <el-button type="warning" size="mini" @click="clearFilter()"
+          >清空</el-button
+        >
+        <div style="width: 60px;"></div>
+        <el-button type="warning" size="mini" @click="$router.back()"
+          >返回</el-button
+        >
+        <el-button type="primary" size="mini" @click="autoMap"
+          >自动映射</el-button
+        >
+        <el-button type="danger" size="mini" @click="clearMap"
+          >清空映射</el-button
+        >
+      </div>
+    </div>
+
+    <!-- 底部表格数据 -->
+    <div class="table">
+      <div class="today-table">
+        <div class="table-container">
+          <el-table
+            :data="tableData"
+            v-loading="loading"
+            stripe
+            style="width: 100%"
+            border
+            height="100%"
+            :header-cell-style="headerCellStyle"
+          >
+            <el-table-column
+              type="index"
+              label="序号"
+              width="60"
+              align="center"
+              :index="indexMethod"
+            ></el-table-column>
+            <el-table-column label="平台非药物疗法">
+              <el-table-column
+                label="一级分类"
+                prop="firstLevel"
+                align="center"
+              >
+                <template slot-scope="scope">
+                  <span
+                    :style="{
+                      color: String(scope.row.isMapping) !== '1' ? 'red' : '',
+                    }"
+                    >{{ scope.row.firstLevel || "-" }}</span
+                  >
+                </template>
+              </el-table-column>
+              <el-table-column
+                label="二级分类"
+                prop="secondLevel"
+                align="center"
+              >
+                <template slot-scope="scope">
+                  <span
+                    :style="{
+                      color: String(scope.row.isMapping) !== '1' ? 'red' : '',
+                    }"
+                    >{{ scope.row.secondLevel || "-" }}</span
+                  >
+                </template>
+              </el-table-column>
+            </el-table-column>
+            <el-table-column label="第三方非药物疗法">
+              <el-table-column label="项目名称" align="center">
+                <template slot-scope="scope">
+                  <el-select
+                    v-if="activeEditIndex === scope.$index"
+                    size="mini"
+                    :loading="editData[scope.$index].loading"
+                    :placeholder="editData[scope.$index].placeholder"
+                    filterable
+                    remote
+                    :remote-method="matSearchRemoteMethod"
+                    v-model="editData[scope.$index].matDrugId"
+                    @change="onSelectChange(scope.$index, $event)"
+                    @focus="focusEditRow(scope.$index)"
+                    @visible-change="onVisibleChange(scope.$index, $event)"
+                  >
+                    <el-option
+                      v-for="option in editData[scope.$index].options"
+                      :key="option.value"
+                      :label="option.label"
+                      :value="option.value"
+                    />
+                  </el-select>
+                  <div
+                    v-else
+                    class="clickable-name"
+                    @click="activateEdit(scope.$index)"
+                  >
+                    {{
+                      editData[scope.$index]
+                        ? editData[scope.$index].displayName || "-"
+                        : "-"
+                    }}
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="编码" width="150" align="center">
+                <template slot-scope="scope">
+                  <div>{{ scope.row.itemCode || "-" }}</div>
+                </template>
+              </el-table-column>
+              <el-table-column label="计价单位" width="100" align="center">
+                <template slot-scope="scope">
+                  <div>{{ scope.row.pricingUnit || "-" }}</div>
+                </template>
+              </el-table-column>
+              <el-table-column label="价格" width="100" align="center">
+                <template slot-scope="scope">
+                  <div>{{ scope.row.price || "-" }}</div>
+                </template>
+              </el-table-column>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div class="flex-vertical-center-r today-page">
+          <div></div>
+          <el-pagination
+            background
+            layout=" prev, pager, next, jumper, total"
+            :total="total"
+            :page-size="limit"
+            @current-change="sizeC($event)"
+          ></el-pagination>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import popup from "@/components/Propup.vue";
+import {
+  getNondrugMapList,
+  autoMapNondrug,
+  clearMapNondrug,
+  materialQuery,
+  manualMapping,
+} from "@/api/nonDrug.js";
+import { mapGetters } from "vuex";
+
+export default {
+  components: {
+    popup,
+  },
+  data() {
+    return {
+      searchData: {
+        pid: "",
+        appId: "",
+        deptId: "",
+        institutionCode: "",
+        isMapping: "",
+        secondName: "",
+      },
+      loading: false,
+      tableData: [],
+      page: 1,
+      limit: 10,
+      total: 0,
+
+      editIndex: -1,
+      activeEditIndex: -1,
+      editData: [],
+      editOriginalMatDrugId: "",
+      changeHandled: false,
+    };
+  },
+  activated() {
+    this.load();
+  },
+  methods: {
+    async load() {
+      this.activeEditIndex = -1;
+      this.searchData = {
+        pid: this.$route.query.pid || "",
+        appId: this.$route.query.ygtid || "",
+        deptId: this.$route.query.departmentidSelsource || "",
+        institutionCode: this.$route.query.stitutionsId || "",
+        isMapping: "",
+        secondName: "",
+      };
+      this.page = 1;
+      await this.getList();
+    },
+    sizeC(e) {
+      this.page = e;
+      this.getList();
+    },
+    search() {
+      this.page = 1;
+      this.getList();
+    },
+    async clearFilter() {
+      this.searchData = {
+        pid: this.$route.query.pid || "",
+        appId: this.$route.query.ygtid || "",
+        deptId: this.$route.query.departmentidSelsource || "",
+        institutionCode: this.$route.query.stitutionsId || "",
+        isMapping: "",
+        secondName: "",
+      };
+      this.page = 1;
+      this.getList();
+    },
+    async getList() {
+      this.loading = true;
+      try {
+        const {
+          appId,
+          deptId,
+          institutionCode,
+          isMapping,
+          secondName,
+        } = this.searchData;
+        let params = {
+          appId,
+          deptId,
+          institutionCode,
+          isMapping,
+          secondName,
+          pageNum: this.page,
+          pageSize: this.limit,
+        };
+        let res = await getNondrugMapList(params);
+        if (res.ResultCode == 0) {
+          const data = res.Data || {};
+          this.tableData = data.Items || [];
+          this.total = data.TotalRecordCount || 0;
+        } else throw { message: res.ResultInfo };
+        this.initEditData();
+      } catch (e) {
+        this.$message.error(e.message);
+      }
+      this.loading = false;
+    },
+    initEditData() {
+      this.editData = this.tableData.map((item) => {
+        const isMapped = String(item.isMapping) === "1";
+        const displayName = isMapped ? item.itemName || "-" : "-";
+        return {
+          id: item.id,
+          matDrugId: isMapped ? item.id : "",
+          matDrugName: item.itemName || "",
+          matDrugDw: item.pricingUnit || "",
+          displayName,
+          loading: false,
+          placeholder: displayName !== "-" ? displayName : "请输入项目名称搜索",
+          options: isMapped
+            ? [{ value: item.id, label: item.itemName, dw: item.pricingUnit }]
+            : [],
+        };
+      });
+    },
+    focusEditRow(index) {
+      this.editIndex = index;
+      const item = this.editData[index];
+      let name = "";
+      if (item.matDrugName) {
+        try {
+          name = item.matDrugName.match(/[\u4E00-\u9FFF]+/g)[0];
+        } catch (e) {
+          name = "";
+        }
+      }
+      this.matSearchRemoteMethod(name || " ", index);
+    },
+    activateEdit(index) {
+      this.activeEditIndex = index;
+      this.editOriginalMatDrugId = this.editData[index].matDrugId;
+      this.changeHandled = false;
+    },
+    async onSelectChange(index, value) {
+      this.changeHandled = true;
+      this.updateEditRow(index, value);
+      await this.doManualMapping(index);
+      this.activeEditIndex = -1;
+    },
+    onVisibleChange(index, visible) {
+      if (visible) return;
+      if (this.changeHandled) return;
+      if (this.editData[index].matDrugId !== this.editOriginalMatDrugId) {
+        this.doManualMapping(index);
+      }
+      this.activeEditIndex = -1;
+    },
+    async doManualMapping(index) {
+      try {
+        const row = this.tableData[index];
+        const item = this.editData[index];
+        let params = {
+          deptId: this.searchData.deptId,
+          firstName: row.firstLevel || "",
+          organizationid: this.searchData.appId,
+          platformClassifyId: row.id || "",
+          secondName: row.secondLevel || "",
+          sititutionNondrugId: item.matDrugId || "",
+          sititutionid: this.searchData.institutionCode,
+        };
+        const loading = this.$loading({
+          lock: true,
+          text: "正在映射",
+          spinner: "el-icon-loading",
+          background: "rgba(0, 0, 0, 0.7)",
+        });
+        const res = await manualMapping(params).catch((err) => {
+          loading.close();
+        });
+        if (res.ResultCode == 0) {
+          loading.close();
+          this.$message.success("映射保存成功");
+          await this.getList();
+        }
+      } catch (e) {
+        this.$message.error(e.message);
+      }
+    },
+    updateEditRow(index, value) {
+      const item = this.editData[index];
+      if (value) {
+        const option = item.options.find((o) => o.value === value);
+        item.displayName = option.label;
+        item.matDrugName = option.label;
+        item.matDrugDw = option.dw || "";
+      } else {
+        item.displayName = "-";
+        item.matDrugName = "";
+        item.matDrugDw = "";
+      }
+    },
+    async matSearchRemoteMethod(name, index) {
+      if (index == null) index = this.editIndex;
+      const item = this.editData[index];
+      if (!name) {
+        item.options = item.matDrugId
+          ? [{ value: item.matDrugId, label: item.matDrugName }]
+          : [];
+      } else {
+        item.loading = true;
+        item.options = await materialQuery({
+          name: name.trim(),
+          appId: this.searchData.appId,
+          deptId: this.searchData.deptId,
+          institutionCode: this.searchData.institutionCode,
+        })
+          .then((res) => {
+            if (res.ResultCode === 0)
+              return (res.Data || []).map((d) => ({
+                value: d.pid,
+                label: d.itemName || d.name,
+                dw: d.pricingUnit || d.dw,
+              }));
+            return [];
+          })
+          .catch(() => []);
+        item.loading = false;
+      }
+      return item.options;
+    },
+    // 自动映射
+    autoMap() {
+      this.$confirm("确认自动映射所有未映射的非药物疗法?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(async () => {
+          try {
+            const res = await autoMapNondrug({
+              basisNondrugcatalogueId: this.searchData.pid,
+            });
+            if (res.ResultCode == 0) {
+              this.$message.success("自动映射成功");
+              this.getList();
+            }
+          } catch (e) {
+            this.$message.error(e.message);
+          }
+        })
+        .catch(() => {});
+    },
+    // 清空映射
+    clearMap() {
+      this.$confirm("确认清空本列表的全部映射关系吗?", "提示", {
+        confirmButtonText: "确认",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(async () => {
+          try {
+            const res = await clearMapNondrug({
+              basisNondrugcatalogueId: this.searchData.pid,
+            });
+            if (res.ResultCode == 0) {
+              this.$message.success("清空映射成功");
+              this.getList();
+            } 
+          } catch (e) {
+            this.$message.error(e.message);
+          }
+        })
+        .catch(() => {});
+    },
+    indexMethod(index) {
+      return (this.page - 1) * this.limit + index + 1;
+    },
+    headerCellStyle({ rowIndex, columnIndex }) {
+      if (rowIndex === 0) {
+        // 序号列
+        if (columnIndex === 0) return { backgroundColor: "#f3fffb" };
+        // 平台非药物疗法
+        if (columnIndex === 1) return { backgroundColor: "#efe1c7" };
+        // 第三方非药物疗法
+        if (columnIndex === 2) return { backgroundColor: "#c7efef" };
+      }
+      if (rowIndex === 1) return { backgroundColor: "#c7efef" };
+      return {};
+    },
+  },
+  computed: {
+    ...mapGetters(["getuserinfo"]),
+  },
+};
+</script>
+<style lang="scss" scoped>
+@import "../../style/common.scss";
+@import "../../style/base.scss";
+
+.table {
+  padding: 5px 5px;
+  background: #ffffff;
+  border-radius: 5px;
+  margin-top: 10px;
+  height: 72vh;
+
+  .flex-vertical-center-r {
+    justify-content: space-between;
+  }
+
+  .table-container {
+    height: 90%;
+  }
+
+  .today-table {
+    height: 100%;
+  }
+}
+
+.clickable-name {
+  cursor: pointer;
+  min-height: 28px;
+  line-height: 28px;
+}
+
+.today-table::v-deep .el-table .cell {
+  text-align: center;
+}
+</style>
+
+<style lang="scss" scoped>
+@media screen and (min-width: 1681px) and (max-width: 1920px) {
+  .table {
+    height: 82vh;
+
+    .table-container {
+      height: 94%;
+    }
+  }
+
+  .today-table::v-deep .el-table td {
+    padding: 18px 0;
+  }
+
+  .today-table::v-deep .el-table th {
+    padding: 18px 0;
+  }
+}
+
+@media screen and (min-width: 1601px) and (max-width: 1680px) {
+  .table {
+    height: 81vh;
+
+    .table-container {
+      height: 94%;
+    }
+  }
+
+  .today-table::v-deep .el-table td {
+    padding: 18px 0;
+  }
+
+  .today-table::v-deep .el-table th {
+    padding: 18px 0;
+  }
+}
+
+@media screen and (min-width: 1361px) and (max-width: 1600px) {
+  .table {
+    height: 73vh;
+
+    .table-container {
+      height: 90%;
+    }
+  }
+
+  .today-table::v-deep .el-table td {
+    padding: 5px 0;
+  }
+
+  .today-table::v-deep .el-table th {
+    padding: 5px 0;
+  }
+}
+
+@media screen and(min-width:1281px) and (max-width: 1360px) {
+  .table {
+    height: 74vh;
+
+    .table-container {
+      height: 90%;
+    }
+  }
+
+  .today-table::v-deep .el-table td {
+    padding: 5px 0;
+  }
+
+  .today-table::v-deep .el-table th {
+    padding: 5px 0;
+  }
+}
+</style>

+ 2 - 3
vue.config.js

@@ -10,17 +10,16 @@ module.exports = {
         proxy: {
             // detail: https://cli.vuejs.org/config/#devserver-proxy
             [process.env.VUE_APP_BASE_API]: {
-
                 // target: `http://192.168.1.10:8080/`, //王志飞本地
                 // target: `http://cloudclinicapi.9czn.cn/`, // 测试地址
                 // target: `http://115.236.184.102:8081/`, // 萧山物理机
                 // target: 'http://192.168.204.124:8081/', // 客户正式服务器"
                 // target: `http://121.43.162.141:80/`, // [萧山] 测试环境的后端地址
                 // target: `https://wx.hzliuzhi.com:4433/fz/`, // [测试] 测试环境的后端地址
-                target: `https://tcm.hzliuzhi.com/`, // @six 演示环境
+                target: `https://tcm.hzliuzhi.com/kd`, // @six 演示环境
                 // target: `http://www.hzxunmai.com/`, // 正式域名
                 // target: `http://10.250.11.48:8080/`, // 正式域名
-
+                // target: `http://192.168.1.64:8068/`, // 本地环境
                 changeOrigin: true,
                 pathRewrite: {
                     ['^' + process.env.VUE_APP_BASE_API]: ''