WXL (wul)
6 天以前 a5cba9ab040f6f97558046885dce3017f9bab7e9
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;
        // 解析已保存的科室/病区级联路径(hospInfo = 科室, 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>