Sfoglia il codice sorgente

task-244 业务管理/药品目录管理 修改编辑弹窗,医疗机构 / 科室名称 采用级联

cc12458 6 mesi fa
parent
commit
a03c6be0c7
2 ha cambiato i file con 209 aggiunte e 237 eliminazioni
  1. 6 2
      src/components/Propup.vue
  2. 203 235
      src/views/business/DrugList.vue

+ 6 - 2
src/components/Propup.vue

@@ -13,14 +13,14 @@
         <span>{{title}}</span>
         <div @click="closePropup()">+</div>
       </div>
-      <div class="popup-container" v-if="showBody">
+      <div class="popup-container" v-if="showBody" v-loading="loading">
         <slot name="body"></slot>
         <div class="btns flex-center" v-if="showBtns">
           <div class="confim flex-center" @click="confim()" v-if="confimText">{{confimText}}</div>
           <div class="cancle flex-center" @click="cancle()" v-if="!hideCancleButton" :style="cancleStyle">{{cancleText}}</div>
         </div>
       </div>
-      <div v-else>
+      <div v-else v-loading="loading">
         <slot name="body"></slot>
         <div class="btns flex-center" v-if="showBtns">
           <div class="confim flex-center" @click="confim()" v-if="confimText">{{confimText}}</div>
@@ -37,6 +37,10 @@ export default {
       type: Boolean,
       default: true
     },
+    loading: {
+      type: Boolean,
+      default: false
+    },
     title: {
       type: String,
       default: "添加信息"

+ 203 - 235
src/views/business/DrugList.vue

@@ -9,12 +9,8 @@
         <div class="screening-item flex-vertical-center-l">
           <span>医共体名称:</span>
           <div class="input">
-            <el-select
-              size="mini"
-              v-model="doctorBody"
-              placeholder="请选择"
-              @change="getMedSelect(doctorBody)"
-            >
+            <el-select size="mini" placeholder="请选择"
+                       v-model="searchData.ygtid" @change="searchData.cascader = [];getCascaderB($event)">
               <el-option
                 :label="item.name"
                 :value="item.pid"
@@ -25,41 +21,24 @@
           </div>
         </div>
         <div class="screening-item flex-vertical-center-l">
-          <span>医疗机构名称:</span>
+          <span>医疗机构 / 科室名称:</span>
           <div class="input">
-            <el-select
-              size="mini"
-              v-model="medName"
-              placeholder="请选择"
-              @change="getDepartSelect(medName)"
-            >
-              <el-option
-                :label="item.name"
-                :value="item.pid"
-                v-for="(item,index) in medSelectList"
-                :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" v-model="departName" placeholder="请选择" clearable>
-              <el-option
-                :label="item.name"
-                :value="item.pid"
-                v-for="(item,index) in departSelect"
-                :key="index"
-              ></el-option>
-            </el-select>
+            <el-cascader v-if="searchData.ygtid" style="width: 100%" size="mini" clearable
+                         :props="{ ...cascaderProp, checkStrictly: true }" :options="cascaderList"
+                         v-model="searchData.cascader" @change="lazyLoadMethod"
+            />
+            <div v-else class="el-select el-select--mini">
+              <div class="el-input el-input--mini el-input--suffix">
+                <input class="el-input__inner" type="text" readonly="readonly" autocomplete="off" placeholder="请选择">
+              </div>
+            </div>
           </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="addData" v-if="showAdd">新增</el-button>
+        <el-button type="primary" size="mini" @click="openEditDialog()" v-if="showAdd">新增</el-button>
         <!-- <el-button type="danger" size="mini" v-if="showMapAuto" @click="autoMap(null)">自动映射</el-button> -->
       </div>
     </div>
@@ -82,7 +61,7 @@
               <div class="flex-center operation" slot-scope="scope">
                 <!-- <div class="flex-center" style="margin-right:20px;" v-if="showAdd" @click="add(scope)">
                 新增</div>-->
-                <div class="flex-center" v-if="showEdit" @click="edit(scope)">修改</div>
+                <div class="flex-center" v-if="showEdit" @click="openEditDialog(scope.row)">修改</div>
                 <div
                   class="flex-center bg-yellow"
                   v-if="showMap"
@@ -117,9 +96,10 @@
 
     <popup
       distanceTop="5vh"
-      :showDialog="showDialog"
-      @cancle="showDialog=false"
-      @confim="submit()"
+      :showDialog="showEditDialog"
+      :loading="editLoading"
+      @cancle="showEditDialog=false"
+      @confim="submitEditData()"
       title="药品目录管理"
     >
       <div class="flex-center" slot="body">
@@ -128,30 +108,13 @@
             <span>*</span>
             <div class="name">医共体:</div>
             <div class="input">
-              <el-select v-model="ygt" placeholder="请选择医共体" @change="getMedSelect1(ygt)">
-                <el-option
-                  :label="item.name"
-                  :value="item.pid"
-                  v-for="(item,index) in list1"
-                  :key="index"
-                ></el-option>
-              </el-select>
-            </div>
-          </div>
-          <div class="form-item flex flex-col-center">
-            <span style="opacity:0;">*</span>
-            <div class="name">医疗机构:</div>
-            <div class="input">
-              <el-select
-                clearable
-                v-model="yljg"
-                placeholder="请选择"
-                @change="getDepartSelect1(yljg)"
+              <el-select style="width: 100%" placeholder="请选择医共体"
+                         v-model="editData.ygtid" @change="editData.cascader = [];getCascaderB($event)"
               >
                 <el-option
                   :label="item.name"
                   :value="item.pid"
-                  v-for="(item,index) in list2"
+                  v-for="(item,index) in doctorBodyList"
                   :key="index"
                 ></el-option>
               </el-select>
@@ -159,25 +122,31 @@
           </div>
           <div class="form-item flex flex-col-center">
             <span style="opacity:0;">*</span>
-            <div class="name">科室:</div>
+            <div class="name">医疗机构 / 科室:</div>
             <div class="input">
-              <el-select clearable v-model="ks" placeholder="请选择">
-                <el-option
-                  :label="item.name"
-                  :value="item.pid"
-                  v-for="(item,index) in list3"
-                  :key="index"
-                ></el-option>
-              </el-select>
+              <el-cascader v-if="editCascaderListLoaded" style="width: 100%" clearable collapse-tags
+                           :props="{ multiple: true, }" :options="cascaderList"
+                           v-model="editData.cascader"
+              />
+              <el-cascader v-else-if="editData.ygtid" style="width: 100%" clearable collapse-tags
+                           :props="{ ...cascaderProp, multiple: true, }"
+                           v-model="editData.cascader" @change="lazyLoadMethod"
+              />
+              <div v-else class="el-select" style="width: 100%;">
+                <div class="el-input el-input--suffix">
+                  <input type="text" readonly="readonly" autocomplete="off" placeholder="请选择"
+                         class="el-input__inner">
+                </div>
+              </div>
             </div>
           </div>
           <div class="form-item flex flex-col-center">
             <span>*</span>
             <div class="name">类型:</div>
             <div class="input">
-              <el-select v-model="type" placeholder="请选择类型">
-                <el-option label="中心药房" :value="0"></el-option>
-                <el-option label="HIS" :value="1"></el-option>
+              <el-select style="width: 100%" v-model="editData.type" placeholder="请选择类型">
+                <el-option label="中心药房" value="0"></el-option>
+                <el-option label="HIS" value="1"></el-option>
               </el-select>
             </div>
           </div>
@@ -185,14 +154,14 @@
             <span>*</span>
             <div class="name">药品目录名称:</div>
             <div class="input">
-              <el-input v-model="name" placeholder="请输入"></el-input>
+              <el-input v-model="editData.name" placeholder="请输入"></el-input>
             </div>
           </div>
           <div class="form-item flex-plane-center-l">
             <span>*</span>
             <div class="name">药品目录描述:</div>
             <div class="input">
-              <el-input type="textarea" v-model="desc" placeholder="请输入"></el-input>
+              <el-input type="textarea" v-model="editData.describe" placeholder="请输入"></el-input>
             </div>
           </div>
         </div>
@@ -212,93 +181,169 @@ import {
 
 import { fileImport } from "@/api/upload.js";
 import { mapState, mapGetters, mapActions, mapMutations } from "vuex";
-import { doctorBodySelect } from "@/api/city.js";
 import {
   getDoctorBodySelect,
   getMedSelect,
   getDepartSelect
 } from "@/api/system.js";
+
+let cache = new Map();
 export default {
   components: {
     popup
   },
   data() {
     return {
-      departName: "", // 科室
-      doctorBody: "", // 医共体
-      medName: "", // 医疗机构
-      yigt: "", // 医工体
-      medSelectList: [],
-      doctorBodyList: [],
-      departSelect: [],
+      searchData: {
+        ygtid: '',
+        cascader: [],
+      },
       tableData: [],
       page: 1,
       limit: 10,
       total: 0,
 
       // 新增 表单字段
-      desc: "", // 药品目录描述
-      ygt: "",
-      name: "",
-      type: "",
-      yljg: "",
-      ks: "",
-
+      showEditDialog: false,
+      editLoading: false,
+      editData: {
+        ygtid: '',
+        cascader: [],
+      },
+      editCascaderListLoaded: false,
       showAdd: true,
       showImport: true,
       showMapAuto: true,
       showEdit: true,
       showMap: true,
-      showDialog: false,
 
       pid: "",
       nowPid: "",
 
-      list1: [],
-      list2: [],
-      list3: []
+      // 医共体
+      doctorBodyList: [],
+      // 机构 / 科室
+      cascaderList: [],
+      cascaderProp: {
+        lazy: true,
+        lazyLoad: (node, resolve) => {
+          if (Array.isArray(node.children) && node.children.length > 0) resolve();
+          else switch (node.level) {
+            case 0:
+              /* 编辑表单没有添加 :options="cascaderList" */
+              /* el bug 直接选择子选项 不能选中  */
+              return this.editData.ygtid && this.getCascaderB(this.editData.ygtid).then(resolve);
+            case 1:
+              return this.getCascaderC(node.value).then(resolve);
+            case 2:
+              resolve();
+          }
+        },
+      },
     };
   },
   created() {
-    this.getDoctorBodySelect();
-    this.getDoctorBodySelect1();
+    this.getCascaderA();
     this.getDrugList();
     this.getDrugBM();
     this.nowPid = this.getuserinfo.organizationid;
   },
+  destroyed() { cache.clear(); },
   methods: {
-    addData() {
-      this.desc = "";
-      this.name = "";
-      this.ygt = "";
-      this.type = "";
-      this.showDialog = true;
+    lazyLoadMethod(value) {
+      if (Array.isArray(value) && value.length === 1) {
+        const parent = this.cascaderList.find(item => item.value === value[0]);
+        if (parent && !parent.leaf && !parent.children.length) this.cascaderProp.lazyLoad({
+          value: value[0],
+          level: 1,
+        }, () => void 0);
+      }
+    },
+    async openEditDialog(row = {}) {
+      this.editData = {
+        pid: row.pid,
+        describe: row.describe || '',
+        name: row.name || '',
+        type: row.type,
+        ygtid: row.ygtid || this.searchData.ygtid,
+        cascader: row.stitutionsId || !this.searchData.cascader.length ? [] : [this.searchData.cascader],
+      };
+      this.editCascaderListLoaded = this.editData.cascader.length > 0 || !!row.stitutionsId;
+      this.showEditDialog = true;
+      if (this.editCascaderListLoaded) {
+        this.editLoading = true;
+        if (this.editData.ygtid) await this.getCascaderB(this.editData.ygtid);
+        const list = await Promise.all(this.cascaderList.map(item => this.getCascaderC(item.value))).then(() => this.cascaderList);
+        if (row.stitutionsId) {
+          const cascader = [];
+          const stitutionsId = (row.stitutionsId || '').split(',').filter(Boolean);
+          const departmentidSelsource = (row.departmentidSelsource || '').split(',').filter(Boolean);
+          for (const s of stitutionsId) {
+            try {
+              const nodes = list.find(item => item.value === s).children.map(node => node.value);
+              let i = 0;
+              let has = 0;
+              do {
+                const d = departmentidSelsource[i];
+                if (nodes.includes(d)) {
+                  has = cascader.push([s, d]);
+                  departmentidSelsource.splice(i, 1);
+                } else if (d) i += 1;
+              } while (departmentidSelsource.length < i);
+              if (!has) cascader.push(...nodes.map(d => [s, d]));
+            } catch (e) { }
+          }
+          this.editData.cascader = [...cascader];
+        }
+        this.editLoading = false;
+      }
     },
-    edit(scope) {
-      this.pid = scope.row.pid;
-      this.desc = scope.row.describe ? scope.row.describe : "";
-      this.name = scope.row.name;
-      this.type = Number(scope.row.type);
-      this.ygt = scope.row.ygtid;
-      this.showDialog = true;
-      this.yljg = scope.row.stitutionsId;
-      this.ks = scope.row.departmentidSelsource;
-
-      this.getMedSelect1(this.ygt, "auto");
-      this.getDepartSelect1(this.yljg, "auto");
+    async submitEditData() {
+      const {cascader = [], ...params} = this.editData;
+      const stitutionsId = new Set();
+      const departmentidSelsource = new Set();
+      if (cascader.length) {
+        for (const [s, d] of cascader) {
+          stitutionsId.add(s);
+          departmentidSelsource.add(d);
+        }
+      }
+      params.stitutionsId = [...stitutionsId].join(',');
+      params.departmentidSelsource = [...departmentidSelsource].join(',');
+      // 构造 医共体 / 机构 / 科室 树
+      params.groupInfo = [{
+        pid: params.ygtid,
+        name: this.doctorBodyList.find(item => item.pid === params.ygtid).name,
+        children: [],
+      }];
+      if (stitutionsId.size) {
+        const group = params.groupInfo[0].children;
+        for (const s of stitutionsId) {
+          const item1 = this.cascaderList.find(item => item.value === s);
+          if (!item1) continue;
+          const length = group.push({pid: item1.value, name: item1.label, children: []});
+          if (item1.leaf || !Array.isArray(item1.children) || !item1.children.length) continue;
+          for (const d of departmentidSelsource) {
+            const item2 = item1.children.find(item => item.value === d);
+            if (!item2) continue;
+            group[length - 1].children.push({pid: item2.value, name: item2.label, children: []});
+            departmentidSelsource.delete(d);
+          }
+        }
+      }
+      params.groupInfo = JSON.stringify(params.groupInfo);
+      const res = await (params.pid ? updateDrugDesc(params) : addDrugList(params));
+      if (res.ResultCode == 0) {
+        this.$message.success(params.pid ? '操作成功' : '添加成功');
+        this.showEditDialog = false;
+        await this.getDrugList();
+      }
     },
     add(scope) {
       this.$router.push({
         path: "/index/drugmaplist?id=" + scope.row.pid
       });
     },
-    submit() {
-      if (!this.pid) {
-        this._addDrugList();
-        return;
-      }
-      this.updateDrugDesc();
-    },
     sizeC(e) {
       this.page = e;
       this.getDrugList();
@@ -309,11 +354,11 @@ export default {
     },
     // 清空搜索条件
     clearFilter() {
-      this.yigt = "";
-      this.doctorBody = "";
-      this.departName = "";
-      this.medName = "";
-      this.medSelectList = [];
+      this.searchData = {
+        ygtid: '',
+        cascader: [],
+      };
+      this.cascaderList = [];
       this.getDrugList();
     },
     doctorBodyC() {
@@ -326,98 +371,43 @@ export default {
       formData.append("file", e.target.files[0]);
       this.fileImport(formData);
     },
-    // 新增药品目录
-    async _addDrugList() {
-      let params = {
-        describe: this.desc,
-        name: this.name,
-        type: this.type,
-        ygtid: this.ygt,
-        departmentidSelsource: this.ks,
-        stitutionsId: this.yljg
-      };
-      let res = await addDrugList(params);
-      if (res.ResultCode == 0) {
-        this.$message.success("添加成功");
-        this.showDialog = false;
-        this.getDrugList();
-      }
-    },
     // 获取医共体选择器数据
-    async getDoctorBodySelect() {
-      let res = await getDoctorBodySelect();
-      if (res.ResultCode == 0) {
+    async getCascaderA() {
+      const res = await getDoctorBodySelect();
+      if (res && +res.ResultCode === 0) {
         this.doctorBodyList = res.Data;
       }
     },
-    // 获取医疗机构选择器
-    async getMedSelect(id, type = "change") {
-      let params = {
-        organizationId: id
-      };
-      let res = await getMedSelect(params);
-      if (res.ResultCode == 0) {
-        this.medSelectList = res.Data;
-        if (type == "change") {
-          this.medName = "";
-          this.departName = "";
-        }
-      }
-    },
-    // 获取科室选择器
-    async getDepartSelect(id, type = "change") {
-      let res = await getDepartSelect({
-        // institutionId: this.getuserinfo.sititutionid
-        institutionId: id
-      });
-      if (res.ResultCode == 0) {
-        this.departSelect = res.Data;
-        if (type == "change") {
-          this.departName = "";
-        }
-      }
-    },
-
-    // 获取医共体选择器数据
-    async getDoctorBodySelect1() {
-      let res = await getDoctorBodySelect();
-      if (res.ResultCode == 0) {
-        this.list1 = res.Data;
-      }
-    },
-    // 获取医疗机构选择器
-    async getMedSelect1(id, type = "change") {
-      let params = {
-        organizationId: id
-      };
-      let res = await getMedSelect(params);
-      if (res.ResultCode == 0) {
-        this.list2 = res.Data;
-        if (type == "change") {
-          this.yljg = "";
-          this.ks = "";
-        }
-      }
+    async getCascaderB(organizationId) {
+      const nodes = cache.has(organizationId) ? cache.get(organizationId) : await getMedSelect({organizationId}).then(res => res && +res.ResultCode === 0
+          ? res.Data.map(item => ({
+            children: [], leaf: false,
+            label: item.name, value: item.pid,
+          }))
+          : [],
+      ).catch(() => []);
+
+      cache.set(organizationId, nodes);
+      this.cascaderList = nodes;
+      return nodes;
     },
-    // 获取科室选择器
-    async getDepartSelect1(id, type = "change") {
-      let res = await getDepartSelect({
-        // institutionId: this.getuserinfo.sititutionid
-        institutionId: id
-      });
-      if (res.ResultCode == 0) {
-        this.list3 = res.Data;
-        if (type == "change") {
-          this.ks = "";
-        }
-      }
-    },
-    // 获取医共体选择器数据
-    async doctorBodySelect() {
-      let res = await doctorBodySelect();
-      if (res.ResultCode == 0) {
-        this.doctorBody = res.Data;
+    async getCascaderC(institutionId) {
+      const parent = this.cascaderList.find(item => item.value === institutionId);
+      if (parent && (parent.leaf || parent.children.length)) return parent.children || [];
+
+      const nodes = await getDepartSelect({institutionId}).then(res => res && +res.ResultCode === 0
+          ? res.Data.map(item => ({
+            leaf: true,
+            label: item.name, value: item.pid,
+          }))
+          : [],
+      ).catch(() => []);
+
+      if (parent) {
+        parent.children = nodes;
+        if (!nodes.length) parent.leaf = true;
       }
+      return nodes;
     },
     // 获取药品列表
     async getDrugList() {
@@ -427,9 +417,9 @@ export default {
         // jgmc: this.yigt
         // ygtid: this.yigt,
 
-        departmentidSelsource: this.departName,
-        ygtid: this.doctorBody,
-        stitutionsId: this.medName
+        ygtid: this.searchData.ygtid,
+        stitutionsId: this.searchData.cascader[0],
+        departmentidSelsource: this.searchData.cascader[1],
       };
       let res = await getDrugList(params);
       if (res.ResultCode == 0) {
@@ -452,28 +442,6 @@ export default {
       this.showImport = res.Data.indexOf("edit") != -1;
       this.showMapAuto = res.Data.indexOf("del") != -1;
     },
-
-    /// 修改药品目录描述
-    async updateDrugDesc() {
-      let res = await updateDrugDesc({
-        describe: this.desc,
-        name: this.name,
-        type: this.type,
-        ygtid: this.ygt,
-        pid: this.pid,
-        departmentidSelsource: this.ks,
-        stitutionsId: this.yljg
-      });
-      if (res.ResultCode == 0) {
-        this.$message({
-          type: "success",
-          message: "操作成功",
-          showClose: true
-        });
-        this.showDialog = false;
-        this.getDrugList();
-      }
-    },
     // 自动映射
     async autoMap(scope) {
       // console.log(scope, '一共提')
@@ -703,7 +671,7 @@ export default {
     }
 
     .name {
-      width: 100px;
+      width: 120px;
     }
 
     .input {