From a5cba9ab040f6f97558046885dce3017f9bab7e9 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期二, 11 八月 2026 14:12:29 +0800
Subject: [PATCH] 提交

---
 src/views/system/user/profile/index.vue |  316 ++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 241 insertions(+), 75 deletions(-)

diff --git a/src/views/system/user/profile/index.vue b/src/views/system/user/profile/index.vue
index 0918602..2533e08 100644
--- a/src/views/system/user/profile/index.vue
+++ b/src/views/system/user/profile/index.vue
@@ -23,95 +23,144 @@
                 <svg-icon icon-class="email" />鐢ㄦ埛閭
                 <div class="pull-right">{{ user.email }}</div>
               </li>
-              <li class="list-group-item" v-if="user.belongWards[0]">
+
+              <!-- ===== 鎵�灞炵梾鍖� ===== -->
+              <li class="list-group-item" v-if="user.belongWards && user.belongWards.length">
                 <svg-icon icon-class="tree" />鎵�灞炵梾鍖�
                 <div class="pull-right">
-                  <el-popover
-                    v-model="showAllWardsPopover"
-                    placement="right-start"
-                    :width="300"
-                    trigger="manual"
-                    popper-class="ward-popover"
-                  >
-                    <div class="popover-content">
-                      <p
-                        v-for="ward in user.belongWards"
-                        :key="ward.districtId"
-                        class="popover-item"
-                      >
-                        {{ ward.districtName }}
-                      </p>
-                    </div>
-                    <!-- 闇�瑕佷竴涓┖鍏冪礌浣滀负瑙﹀彂鍣ㄧ殑寮曠敤 -->
-                    <!-- <div style="display: none" slot="reference"></div> -->
-                    <div slot="reference">
-                      <el-tag
-                        v-for="(ward, index) in displayWards"
-                        :key="ward.districtId"
-                        size="small"
-                        class="ward-tag"
-                        >{{ ward.districtName }}</el-tag
-                      >
-                      <!-- 鏄剧ず闅愯棌鏁伴噺鐨勬爣绛撅紝鐐瑰嚮瑙﹀彂Popover -->
-                      <el-tag
-                        v-if="user.belongWards.length > maxTagCount"
-                        size="small"
-                        class="more-tag"
-                        @click="showAllWardsPopover = !showAllWardsPopover"
-                        >+{{ user.belongWards.length - maxTagCount }}</el-tag
-                      >
-                    </div>
-                  </el-popover>
+                  <!-- 鍗楀崕闄勪竴锛氬彲缂栬緫妯″紡 -->
+                  <template v-if="isNanhua && editing">
+                    <el-cascader
+                      v-model="formWardCodes"
+                      :options="deptOptionsbq"
+                      :props="cascaderProps"
+                      filterable
+                      clearable
+                      size="small"
+                      style="width: 100%"
+                      @remove-tag="onWardRemoveTag"
+                    />
+                  </template>
+                  <!-- 鍗楀崕闄勪竴锛氬彧璇绘ā寮� -->
+                  <template v-else-if="isNanhua">
+                    <el-tag
+                      v-for="ward in user.belongWards"
+                      :key="ward.districtId"
+                      size="small"
+                      class="ward-tag"
+                    >{{ ward.districtName }}</el-tag>
+                  </template>
+                  <!-- 鍏朵粬鏈烘瀯锛氬師鏈� Popover 灞曠ず -->
+                  <template v-else>
+                    <el-popover
+                      v-model="showAllWardsPopover"
+                      placement="right-start"
+                      :width="300"
+                      trigger="manual"
+                      popper-class="ward-popover"
+                    >
+                      <div class="popover-content">
+                        <p v-for="ward in user.belongWards" :key="ward.districtId" class="popover-item">
+                          {{ ward.districtName }}
+                        </p>
+                      </div>
+                      <div slot="reference">
+                        <el-tag
+                          v-for="(ward, index) in displayWards"
+                          :key="ward.districtId"
+                          size="small"
+                          class="ward-tag"
+                        >{{ ward.districtName }}</el-tag>
+                        <el-tag
+                          v-if="user.belongWards.length > maxTagCount"
+                          size="small"
+                          class="more-tag"
+                          @click="showAllWardsPopover = !showAllWardsPopover"
+                        >+{{ user.belongWards.length - maxTagCount }}</el-tag>
+                      </div>
+                    </el-popover>
+                  </template>
                 </div>
               </li>
               <li class="list-group-item" v-else>
-                <svg-icon icon-class="tree" />鎵�灞為櫌鍖�
+                <svg-icon icon-class="tree" />鎵�灞炵梾鍖�
                 <div class="pull-right">鏈厤缃�</div>
               </li>
-              <li class="list-group-item" v-if="user.belongDepts[0]">
+
+              <!-- ===== 鎵�灞炵瀹� ===== -->
+              <li class="list-group-item" v-if="user.belongDepts && user.belongDepts.length">
                 <svg-icon icon-class="tree" />鎵�灞炵瀹�
                 <div class="pull-right">
-                  <el-popover
-                    v-model="showAllDeptsPopover"
-                    placement="right-start"
-                    :width="300"
-                    style="top: 130px; left: 0px"
-                    trigger="manual"
-                    popper-class="dept-popover"
-                  >
-                    <div class="popover-content">
-                      <p
-                        v-for="dept in user.belongDepts"
-                        :key="dept.deptId"
-                        class="popover-item"
-                      >
-                        {{ dept.deptName }}
-                      </p>
-                    </div>
-                    <!-- <div style="display: none" slot="reference"></div> -->
-                    <div slot="reference">
-                      <el-tag
-                        v-for="(dept, index) in displayDepts"
-                        :key="dept.deptId"
-                        size="small"
-                        class="dept-tag"
-                        >{{ dept.deptName }}</el-tag
-                      >
-                      <el-tag
-                        v-if="user.belongDepts.length > maxTagCount"
-                        size="small"
-                        class="more-tag"
-                        @click="showAllDeptsPopover = !showAllDeptsPopover"
-                        >+{{ user.belongDepts.length - maxTagCount }}</el-tag
-                      >
-                    </div>
-                  </el-popover>
+                  <!-- 鍗楀崕闄勪竴锛氬彲缂栬緫妯″紡 -->
+                  <template v-if="isNanhua && editing">
+                    <el-cascader
+                      v-model="formDeptCodes"
+                      :options="deptOptionsks"
+                      :props="cascaderProps"
+                      filterable
+                      clearable
+                      size="small"
+                      style="width: 100%"
+                      @remove-tag="onDeptRemoveTag"
+                    />
+                  </template>
+                  <!-- 鍗楀崕闄勪竴锛氬彧璇绘ā寮� -->
+                  <template v-else-if="isNanhua">
+                    <el-tag
+                      v-for="dept in user.belongDepts"
+                      :key="dept.deptId"
+                      size="small"
+                      class="dept-tag"
+                    >{{ dept.deptName }}</el-tag>
+                  </template>
+                  <!-- 鍏朵粬鏈烘瀯锛氬師鏈� Popover 灞曠ず -->
+                  <template v-else>
+                    <el-popover
+                      v-model="showAllDeptsPopover"
+                      placement="right-start"
+                      :width="300"
+                      trigger="manual"
+                      popper-class="dept-popover"
+                    >
+                      <div class="popover-content">
+                        <p v-for="dept in user.belongDepts" :key="dept.deptId" class="popover-item">
+                          {{ dept.deptName }}
+                        </p>
+                      </div>
+                      <div slot="reference">
+                        <el-tag
+                          v-for="(dept, index) in displayDepts"
+                          :key="dept.deptId"
+                          size="small"
+                          class="dept-tag"
+                        >{{ dept.deptName }}</el-tag>
+                        <el-tag
+                          v-if="user.belongDepts.length > maxTagCount"
+                          size="small"
+                          class="more-tag"
+                          @click="showAllDeptsPopover = !showAllDeptsPopover"
+                        >+{{ user.belongDepts.length - maxTagCount }}</el-tag>
+                      </div>
+                    </el-popover>
+                  </template>
                 </div>
               </li>
               <li class="list-group-item" v-else>
                 <svg-icon icon-class="tree" />鎵�灞炵瀹�
                 <div class="pull-right">鏈厤缃�</div>
               </li>
+
+              <!-- 鍗楀崕闄勪竴锛氱紪杈�/淇濆瓨鎸夐挳 -->
+              <li class="list-group-item" v-if="isNanhua" style="justify-content: center; padding-top: 16px;">
+                <template v-if="!editing">
+                  <el-button type="primary" size="small" icon="el-icon-edit" @click="startEdit">缂栬緫绉戝/鐥呭尯</el-button>
+                </template>
+                <template v-else>
+                  <el-button size="small" @click="cancelEdit">鍙栨秷</el-button>
+                  <el-button type="primary" size="small" :loading="saving" @click="saveEdit">淇濆瓨</el-button>
+                </template>
+              </li>
+
               <li class="list-group-item">
                 <svg-icon icon-class="peoples" />鎵�灞炶鑹�
                 <div class="pull-right">{{ roleGroup }}</div>
@@ -147,7 +196,7 @@
 import userAvatar from "./userAvatar";
 import userInfo from "./userInfo";
 import resetPwd from "./resetPwd";
-import { getUserProfile } from "@/api/system/user";
+import { getUserProfile, updateUser, deptTreeSelect, adduserdept, removeusertd } from "@/api/system/user";
 
 export default {
   name: "Profile",
@@ -161,6 +210,16 @@
       maxTagCount: 3, // 鎺у埗榛樿鏄剧ず鐨勬爣绛炬暟閲�
       showAllWardsPopover: false, // 鎺у埗鐥呭尯Popover鐨勬樉绀�
       showAllDeptsPopover: false, // 鎺у埗绉戝Popover鐨勬樉绀�
+      // 缂栬緫妯″紡锛堜粎鍗楀崕闄勪竴锛�
+      editing: false,
+      saving: false,
+      deptOptionsks: [],  // 绉戝绾ц仈鏍�
+      deptOptionsbq: [],  // 鐥呭尯绾ц仈鏍�
+      formDeptCodes: [],  // 绉戝绾ц仈缁戝畾鍊�
+      formWardCodes: [],  // 鐥呭尯绾ц仈缁戝畾鍊�
+      originalDeptCodes: [], // 鍘熷绉戝鍊硷紙鍙栨秷鏃舵仮澶嶏級
+      originalWardCodes: [], // 鍘熷鐥呭尯鍊硷紙鍙栨秷鏃舵仮澶嶏級
+      cascaderProps: { multiple: true, value: "deptCode", label: "label" },
     };
   },
   computed: {
@@ -174,9 +233,16 @@
       if (!this.user.belongDepts) return [];
       return this.user.belongDepts.slice(0, this.maxTagCount);
     },
+    // 鍗楀崕澶у闄勫睘绗竴鍖婚櫌 鍏佽缂栬緫绉戝/鐥呭尯
+    isNanhua() {
+      return localStorage.getItem("orgname") === "鍗楀崕澶у闄勫睘绗竴鍖婚櫌";
+    },
   },
   created() {
     this.getUser();
+    if (localStorage.getItem("orgname") === "鍗楀崕澶у闄勫睘绗竴鍖婚櫌") {
+      this.loadDeptTree();
+    }
   },
   methods: {
     getUser() {
@@ -184,6 +250,102 @@
         this.user = response.data;
         this.roleGroup = response.roleGroup;
         this.postGroup = response.postGroup;
+        // 瑙f瀽宸蹭繚瀛樼殑绉戝/鐥呭尯绾ц仈璺緞锛坔ospInfo = 绉戝, deptInfo = 鐥呭尯锛�
+        try {
+          this.formDeptCodes = this.user.hospInfo ? JSON.parse(this.user.hospInfo) : [];
+        } catch (e) { this.formDeptCodes = []; }
+        try {
+          this.formWardCodes = this.user.deptInfo ? JSON.parse(this.user.deptInfo) : [];
+        } catch (e) { this.formWardCodes = []; }
+        this.originalDeptCodes = JSON.parse(JSON.stringify(this.formDeptCodes));
+        this.originalWardCodes = JSON.parse(JSON.stringify(this.formWardCodes));
+      });
+    },
+    // 鍔犺浇绉戝/鐥呭尯绾ц仈鏍�
+    loadDeptTree() {
+      deptTreeSelect(1).then((res) => { this.deptOptionsks = res.data || []; });
+      deptTreeSelect(2).then((res) => { this.deptOptionsbq = res.data || []; });
+    },
+    // 杩涘叆缂栬緫妯″紡
+    startEdit() {
+      this.originalDeptCodes = JSON.parse(JSON.stringify(this.formDeptCodes));
+      this.originalWardCodes = JSON.parse(JSON.stringify(this.formWardCodes));
+      this.editing = true;
+    },
+    // 鍙栨秷缂栬緫
+    cancelEdit() {
+      this.formDeptCodes = JSON.parse(JSON.stringify(this.originalDeptCodes));
+      this.formWardCodes = JSON.parse(JSON.stringify(this.originalWardCodes));
+      this.editing = false;
+    },
+    // 淇濆瓨绉戝/鐥呭尯
+    saveEdit() {
+      if (!this.user.userId) return;
+      this.saving = true;
+
+      const deptCodes = this.formDeptCodes.length
+        ? this.formDeptCodes.map(arr => arr[arr.length - 1])
+        : [];
+      const wardCodes = this.formWardCodes.length
+        ? this.formWardCodes.map(arr => arr[arr.length - 1])
+        : [];
+
+      const params = {
+        userId: this.user.userId,
+        hospInfo: JSON.stringify(this.formDeptCodes),
+        deptInfo: JSON.stringify(this.formWardCodes),
+        deptCodes: deptCodes,
+        wardCodes: wardCodes,
+      };
+
+      updateUser(params).then(() => {
+        // 鍚屾鏂板/鍒犻櫎鐨勭瀹ょ梾鍖�
+        this.syncUserDept(wardCodes, 2);
+        this.syncUserDept(deptCodes, 1);
+        this.$modal.msgSuccess("绉戝/鐥呭尯淇敼鎴愬姛");
+        this.editing = false;
+        this.saving = false;
+        this.getUser(); // 鍒锋柊鐢ㄦ埛淇℃伅
+      }).catch(() => {
+        this.saving = false;
+      });
+    },
+    // 鍚屾鐢ㄦ埛绉戝/鐥呭尯锛堟柊澧炲拰鍒犻櫎宸紓锛�
+    syncUserDept(codes, deptType) {
+      const original = deptType === 1
+        ? this.originalDeptCodes.map(arr => arr[arr.length - 1])
+        : this.originalWardCodes.map(arr => arr[arr.length - 1]);
+
+      // 鏂板
+      codes.forEach(code => {
+        if (!original.includes(code)) {
+          adduserdept({ deptCode: code, deptType, userId: this.user.userId });
+        }
+      });
+      // 鍒犻櫎
+      original.forEach(code => {
+        if (!codes.includes(code)) {
+          removeusertd(this.user.userId, code);
+        }
+      });
+    },
+    // 绾ц仈閫夋嫨鍣� remove-tag 浜嬩欢
+    onDeptRemoveTag(removedValues) {
+      const currentCodes = (removedValues || []).map(arr => arr[arr.length - 1]);
+      const prevCodes = (this.originalDeptCodes || []).map(arr => arr[arr.length - 1]);
+      prevCodes.forEach(code => {
+        if (!currentCodes.includes(code)) {
+          removeusertd(this.user.userId, code);
+        }
+      });
+    },
+    onWardRemoveTag(removedValues) {
+      const currentCodes = (removedValues || []).map(arr => arr[arr.length - 1]);
+      const prevCodes = (this.originalWardCodes || []).map(arr => arr[arr.length - 1]);
+      prevCodes.forEach(code => {
+        if (!currentCodes.includes(code)) {
+          removeusertd(this.user.userId, code);
+        }
       });
     },
   },
@@ -213,6 +375,10 @@
   flex: 1;
   text-align: right;
 }
+/* 绾ц仈閫夋嫨鍣ㄥ唴閮ㄦ牱寮� */
+.pull-right .el-cascader {
+  width: 100%;
+}
 </style>
 
 <style>

--
Gitblit v1.9.3