杨磊
2025-05-26 96be59a64cc1d8fcaf1034e787717663c68df4a7
src/views/system/index.vue
@@ -1,16 +1,618 @@
<template>
  <div class="pageContainer">
    <div class="menuBox">
      <treeMenu :menuItem="menuItem"/>
    <div class="menuBox" v-if="$route.name == 'userManage'">
      <div class="btnGroup">
        <el-dropdown>
          <el-icon class="icon1"><FolderAdd /></el-icon>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item @click="addBtn('parent')"
                >机构</el-dropdown-item
              >
              <el-dropdown-item
                @click="addBtn('child')"
                :disabled="dataPath?.type !== 'ModelOrg'"
                >部门</el-dropdown-item
              >
            </el-dropdown-menu>
          </template>
        </el-dropdown>
        <el-icon class="icon2" @click="editBtn"><Edit /></el-icon>
        <el-icon class="icon3" @click="delBtn"><Delete /></el-icon>
      </div>
      <div class="treeBox">
        <el-tree
          ref="treeRef"
          :key="treeKey"
          :props="defaultProps"
          :highlight-current="true"
          @node-click="handleNodeClick"
          :current-node-key="currentNodeKey"
          node-key="key"
          :data="treeData"
          :load="loadNode"
          :expand-on-click-node="false"
          lazy
        />
      </div>
    </div>
    <div class="menuBox" v-if="$route.name == 'roleManage'">
      <div class="btnGroup">
        <el-icon class="icon1" @click="addRoleBtn"><FolderAdd /></el-icon>
        <el-icon class="icon2" @click="editRoleBtn"><Edit /></el-icon>
        <el-icon class="icon3" @click="delRoleBtn"><Delete /></el-icon>
      </div>
      <div class="treeBox">
        <el-tree
          ref="treeRef"
          :key="roleTreeKey"
          :props="defaultProps"
          :highlight-current="true"
          @node-click="handleRoleNodeClick"
          :current-node-key="currentRoleNodeKey"
          node-key="key"
          :data="roleTreeData"
          :expand-on-click-node="false"
        />
      </div>
    </div>
    <el-dialog
      v-model="dialogFormVisible"
      :title="dialogTitle"
      width="500"
      @close="closeDialog(formRef)"
    >
      <el-form
        :model="form"
        ref="formRef"
        :rules="formRules"
        label-width="140px"
      >
        <el-form-item label="名称" prop="name">
          <el-input
            v-model="form.name"
            autocomplete="off"
            placeholder="请输入"
            style="width: 240px"
          />
        </el-form-item>
        <el-form-item label="编码" prop="refCode">
          <el-input
            v-model="form.refCode"
            autocomplete="off"
            placeholder="请输入"
            style="width: 240px"
          />
        </el-form-item>
        <el-form-item label="描述">
          <el-input
            v-model="form.description"
            style="width: 240px"
            :rows="2"
            type="textarea"
            placeholder="请输入"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDialog(formRef)">取消</el-button>
          <el-button type="primary" @click="submitBtn(formRef)">
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog
      v-model="roleDialogVisible"
      :title="roleDialog"
      @close="closeRoleDialog(roleFormRef)"
      width="500"
    >
      <el-form
        :model="roleForm"
        ref="roleFormRef"
        :rules="roleFormRules"
        label-width="140px"
      >
        <el-form-item label="名称" prop="name">
          <el-input
            v-model="roleForm.name"
            autocomplete="off"
            placeholder="请输入"
            style="width: 240px"
          />
        </el-form-item>
        <el-form-item label="描述">
          <el-input
            v-model="roleForm.description"
            style="width: 240px"
            :rows="2"
            type="textarea"
            placeholder="请输入"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeRoleDialog(roleFormRef)">取消</el-button>
          <el-button type="primary" @click="submitRoleBtn(roleFormRef)">
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>
    <div class="contentBox"><RouterView /></div>
  </div>
</template>
<script setup lang="ts">
import { ref} from "vue";
import treeMenu from "@/components/treeMenu.vue";
const menuItem = ref('systemManage')
import { ElMessage, ElMessageBox, FormInstance, FormRules } from "element-plus";
import { inject, onMounted, onUnmounted, reactive, ref, watch } from "vue";
const MG: any = inject("MG");
const config: any = inject("config");
const defaultProps = {
  children: "children",
  label: "label",
  isLeaf: "leaf",
  key: "key",
};
const treeData = ref([]);
const roleTreeData = ref([]);
const treeRef = ref(null);
const currentNodeKey = ref(1);
const currentRoleNodeKey = ref(1);
const dialogFormVisible = ref(false);
const roleDialogVisible = ref(false);
const dialogTitle = ref();
const roleDialog = ref();
const formRef = ref<FormInstance>();
const roleFormRef = ref<FormInstance>();
const dataPath = ref();
const treeKey = ref(0);
const roleTreeKey = ref(0);
const searchKeyword = ref("");
const form = reactive({
  name: "",
  refCode: "",
  description: "",
});
const roleForm = reactive({
  name: "",
  description: "",
});
interface formInfo {
  name: string;
  refCode: string;
}
import { curStoreInfo } from "@/store/index";
import { useRoute } from "vue-router";
const seleStore = curStoreInfo();
const formRules = reactive<FormRules<formInfo>>({
  name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
  refCode: [{ required: true, message: "编码不能为空", trigger: "blur" }],
});
const roleFormRules = reactive<FormRules<formInfo>>({
  name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
});
const route = useRoute();
watch(
  () => route,
  (newRoute) => {
    console.log("路由变化:", newRoute.name);
    // 处理路由变化逻辑
    if (newRoute.name == "roleManage") {
      getRoleList();
    }
  },
  { deep: true }
);
import emitter from "../eventBus";
onMounted(() => {
  emitter.on("refreshTree", getRoleList);
});
onUnmounted(() => {
  emitter.off("refreshTree", getRoleList); // 清理监听,避免内存泄漏
});
const getRoleList = async () => {
  const res = await MG.dps5.GetOrgManageRoleList({
    orgId: seleStore.OrgInfo.id,
  });
  const fomartData = handleTreeData(res, null, false);
  roleTreeData.value = fomartData;
  currentRoleNodeKey.value = fomartData[0].key;
  seleStore.setCurSelectRole(fomartData[0].data);
};
//新增角色
const addRoleBtn = () => {
  roleDialogVisible.value = true;
  roleDialog.value = "新建角色";
};
//编辑角色
const editRoleBtn = () => {
  console.log(seleStore.curSelectRole, "curSelectRole");
  roleForm.name = seleStore.curSelectRole.name;
  roleForm.description = seleStore.curSelectRole.description;
  roleDialogVisible.value = true;
  roleDialog.value = "编辑角色";
};
//删除角色
const delRoleBtn = async () => {
  ElMessageBox.confirm("是否删除当前角色", "删除角色", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      const data = {
        roleIds: [seleStore.curSelectRole.id],
      };
      const res = await MG.dps5.DelRole(data);
      getRoleList();
      if (res) {
        ElMessage({
          type: "success",
          message: "删除成功",
        });
      }
    })
    .catch(() => {});
};
const handleSearch = () => {};
const showCreateDialog = () => {};
//提交角色表单
const submitRoleBtn = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      if (roleDialog.value == "新建角色") {
        const body = {
          ...roleForm,
          icon: "",
          appLinks: [config.appId],
          departmentLinks: [],
          orgLinks: [
            {
              appId: config.appId,
              orgId: seleStore.OrgInfo.id,
            },
          ],
          state: "Normal",
          type: "User",
        };
        const res = await MG.dps5.NewRole(body);
        if (res) {
          roleDialogVisible.value = false;
          getRoleList();
          formEl.resetFields();
        }
        ElMessage({
          type: "success",
          message: "新建成功",
        });
      } else {
        const body = {
          ...roleForm,
          icon: "",
          roleId: seleStore.curSelectRole.id,
          state: "Normal",
          type: "Normal",
        };
        const res = await MG.dps5.UpdateRole(body);
        if (res) {
          roleDialogVisible.value = false;
          getRoleList();
          formEl.resetFields();
          ElMessage({
            type: "success",
            message: "编辑成功",
          });
        }
      }
    }
  });
};
const submitBtn = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      if (dialogTitle.value == "新建机构") {
        const body = {
          name: form.name,
          refCode: form.refCode + "_ModelOrg",
          description: form.description,
          icon: "",
          isEnable: true,
          state: "Visible",
          type: "ModelOrg",
        };
        const res = await MG.dps5.NewOrg(body);
        console.log(res, "res");
        if (res) {
          ElMessage({
            message: "新建机构成功",
            type: "success",
          });
          formEl.resetFields();
          treeKey.value += 1;
          dialogFormVisible.value = false;
        }
      } else if (dialogTitle.value == "新建部门") {
        const body = {
          name: form.name,
          refCode: form.refCode + "_ModelDep",
          description: form.description,
          isEnable: true,
          state: "Normal",
          type: "Normal",
          parentId: "",
          orgId: dataPath.value.id,
        };
        const res = await MG.dps5.NewDepartment(body);
        if (res) {
          ElMessage({
            message: "新建部门成功",
            type: "success",
          });
          formEl.resetFields();
          treeKey.value += 1;
          dialogFormVisible.value = false;
        }
      } else if (dialogTitle.value == "编辑机构") {
        const body = {
          name: form.name,
          refCode: form.refCode + "_ModelOrg",
          description: form.description,
          icon: "",
          isEnable: true,
          state: "Visible",
          type: "ModelOrg",
          id: dataPath.value.id,
        };
        const res = await MG.dps5.UpdateOrg(body);
        formEl.resetFields();
        treeKey.value += 1;
        dialogFormVisible.value = false;
      } else if (dialogTitle.value == "编辑部门") {
        const body = {
          name: form.name,
          refCode: form.refCode + "_ModelDep",
          description: form.description,
          isEnable: true,
          orgId: dataPath.value.org.id,
          departmentId: dataPath.value.id,
          state: "Normal",
          type: "Normal",
        };
        const res = await MG.dps5.UpdateDepartment(body);
        formEl.resetFields();
        treeKey.value += 1;
        dialogFormVisible.value = false;
      }
    }
  });
};
const closeDialog = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.resetFields();
  dialogFormVisible.value = false;
};
const closeRoleDialog = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.resetFields();
  roleDialogVisible.value = false;
};
const loadNode = async (node: any, resolve: any) => {
  console.log(node, "node");
  if (node.level == 0) {
    const treeData = await getOrgList();
    currentNodeKey.value = treeData[0].key;
    dataPath.value = treeData[0].data;
    seleStore.setOrgInfo(treeData[0].data);
    return resolve(treeData);
  } else if (node.level == 1) {
    const data = {
      isIncludeAll: false,
      orgId: node.data.data.id,
    };
    const res = await MG.dps5.GetOrgChildrenDepartment(data);
    const fomartData = handleTreeData(res, node.data.data, false);
    seleStore.setDepartmentInfo(fomartData[0].data);
    return resolve(fomartData);
  } else if (node.level == 2) {
    const data = {
      departmentId: node.data.data.id,
    };
    const res = await MG.dps5.GetChildrenDepartment(data);
    const fomartData = handleTreeData(res, node.data.data, false);
    return resolve(fomartData);
  }
};
const getOrgList = async () => {
  const params = {
    filterList: [],
    searchList: [
      { field: "refCode", keywords: "_ModelOrg", compareType: "Contains" },
    ],
    size: 100,
    start: 0,
  };
  const res = await MG.dps5.GetOrgList(params);
  res.datas.map((item) => (item.childrenCount = item.childrenDepartmentCount));
  const fomartData = handleTreeData(res.datas, null, false);
  console.log(fomartData, "fomartData");
  return fomartData;
};
const addBtn = (type) => {
  console.log("addBtn");
  if (type == "parent") {
    dialogTitle.value = "新建机构";
  } else {
    dialogTitle.value = "新建部门";
  }
  dialogFormVisible.value = true;
};
const editBtn = () => {
  console.log(dataPath.value, "editBtn");
  dialogTitle.value = "新建部门";
  if (dataPath.value.refCode.includes("_ModelOrg")) {
    dialogTitle.value = "编辑机构";
  } else {
    dialogTitle.value = "编辑部门";
  }
  form.name = dataPath.value.name;
  form.description = dataPath.value.description;
  form.refCode = dataPath.value.refCode.split("_")[0];
  dialogFormVisible.value = true;
};
const delBtn = () => {
  if (dataPath.value.refCode.includes("_ModelOrg")) {
    ElMessageBox.confirm("是否删除当前机构", "删除机构", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(async () => {
        const data = {
          orgId: dataPath.value.id,
        };
        const res = await MG.dps5.DelOrg(data);
        getRoleList();
        if (res) {
          ElMessage({
            type: "success",
            message: "删除成功",
          });
          treeKey.value += 1;
        }
      })
      .catch(() => {});
  } else {
    dialogTitle.value = "编辑部门";
    ElMessageBox.confirm("是否删除当前部门", "删除部门", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(async () => {
        const data = {
          departmentId: dataPath.value.id,
        };
        const res = await MG.dps5.DelDepartment(data);
        getRoleList();
        if (res) {
          ElMessage({
            type: "success",
            message: "删除成功",
          });
          treeKey.value += 1;
        }
      })
      .catch(() => {});
  }
};
const handleNodeClick = (data: any) => {
  if (data.data.type == "ModelOrg") {
    seleStore.setOrgInfo(data.data);
  } else {
    seleStore.setDepartmentInfo(data.data);
  }
  dataPath.value = data.data;
  currentNodeKey.value = data.key;
};
const handleRoleNodeClick = (data: any) => {
  seleStore.setCurSelectRole(data.data);
  currentRoleNodeKey.value = data.key;
};
const handleTreeData = (datas: any[], parent, noTriggerSelect = false) => {
  let parentData = {};
  if (parent) {
    parentData = { ...parent, parent: null };
  } else {
    parentData = null;
  }
  const list = [];
  for (let i = 0; i < datas.length; i++) {
    const data = datas[i];
    const obj = {
      label: data.name,
      key: parentData ? parentData.key + "_" + i : i + "",
      namePath: parentData ? parentData.namePath + "\\" + data.name : data.name,
      icon: data.icon,
      data: data,
      parent: parentData,
      leaf: false,
      children: [],
    };
    if (data["children"] && data["children"].length) {
      obj.leaf = false;
      obj.children = handleTreeData(
        data["children"],
        {
          ...data,
          key: obj.key,
          namePath: obj.namePath,
        },
        i == 0 ? false : true // 如果有子数据处理,只有第一条数据需要展开和回调
      );
    } else {
      obj.leaf = !data["childrenCount"] || data["childrenCount"] == 0;
    }
    list.push(obj);
  }
  console.log(list, "list");
  return list;
};
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
.menuBox {
  width: 300px;
  height: 100vh;
  background-color: #fff;
  border: 1px solid #ebeef5;
}
.btnGroup {
  display: flex;
  gap: 12px;
  cursor: pointer;
  justify-content: end;
  align-items: center;
  padding: 8px;
  border-bottom: 1px solid #ebeef5;
  .icon1,
  .icon2,
  .icon3 {
    font-size: 18px;
    color: #606266;
    &:hover {
      color: #409eff;
    }
  }
}
.treeBox {
  padding-top: 10px;
}
.tableBox {
  flex: 1;
}
</style>