Quellcode durchsuchen

部门管理模块

zouzs vor 3 Wochen
Ursprung
Commit
ce8c2fca13
3 geänderte Dateien mit 454 neuen und 4 gelöschten Zeilen
  1. 42 0
      src/api/system/dept.ts
  2. 405 0
      src/views/system/dept/index.vue
  3. 7 4
      src/views/system/user/index.vue

+ 42 - 0
src/api/system/dept.ts

@@ -0,0 +1,42 @@
+import { http } from "@/utils/http";
+import { baseUrlApi } from "../utils";
+
+export interface BasicResponseModel<T = any> {
+  code: number;
+  msg: string;
+  data: T;
+}
+
+export const getSystemDeptList = (query?: object) => {
+  return http.request<BasicResponseModel>(
+    "get",
+    baseUrlApi("system/dept/list"),
+    { params: query }
+  );
+};
+
+export const addDept = (query?: object) => {
+  return http.request<BasicResponseModel>("post", baseUrlApi("system/dept"), {
+    data: query
+  });
+};
+
+export const updateDept = (query?: object) => {
+  return http.request<BasicResponseModel>("put", baseUrlApi("system/dept"), {
+    data: query
+  });
+};
+
+export const deleteDept = (id: number) => {
+  return http.request<BasicResponseModel>(
+    "delete",
+    baseUrlApi(`system/dept/${id}`)
+  );
+};
+
+export const getDept = (id: number) => {
+  return http.request<BasicResponseModel>(
+    "get",
+    baseUrlApi(`system/dept/${id}`)
+  );
+};

+ 405 - 0
src/views/system/dept/index.vue

@@ -0,0 +1,405 @@
+<template>
+  <div>
+    <PlusPage
+      ref="plusPageInstance"
+      :columns="tableConfig"
+      :request="getList"
+      :before-search-submit="handleBeforeSearch"
+      :is-card="true"
+      :search="{
+        labelWidth: 100,
+        showNumber: 3
+      }"
+      :table="{
+        actionBar: { buttons, type: 'link', width: 140 },
+        adaptive: { offsetBottom: 50 },
+        treeProps: { children: 'children' },
+        rowKey: 'deptId'
+      }"
+      :pagination="false"
+    >
+      <template #table-title>
+        <el-row class="button-row">
+          <el-button size="default" type="success" @click="handleCreate">
+            新增
+          </el-button>
+        </el-row>
+      </template>
+    </PlusPage>
+    <!-- 弹窗编辑 -->
+    <PlusDialogForm
+      ref="dialogForm"
+      v-model="form"
+      v-model:visible="dialogVisible"
+      :form="{
+        columns,
+        labelPosition: 'right',
+        labelWidth: 100,
+        rules,
+        rowProps: { gutter: 20 },
+        colProps: { span: 12 }
+      }"
+      :dialog="{ title: dialogTitle + '部门', width: 800, confirmLoading }"
+      @confirm="handleSubmit"
+      @close="handleClose"
+    />
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { computed, defineOptions, reactive, ref, toRefs } from "vue";
+import type { FormRules } from "element-plus";
+import { ElMessage } from "element-plus";
+import {
+  type FieldValues,
+  type PlusColumn,
+  PlusDialogForm,
+  PlusPage,
+  PlusPageInstance,
+  useTable
+} from "plus-pro-components";
+import { cloneDeep } from "lodash-es";
+import {
+  addDept,
+  deleteDept,
+  getDept,
+  getSystemDeptList,
+  updateDept
+} from "@/api/system/dept";
+
+defineOptions({
+  name: "Dept"
+});
+
+interface TableRow {
+  id: number;
+  name: string;
+  status: string;
+  tag: string;
+  time: Date;
+}
+
+// 菜单列表
+const deptList = ref([]);
+const plusPageInstance = ref<PlusPageInstance | null>(null);
+
+const getList = async (query: Record<string, any>) => {
+  let res = await getSystemDeptList(query);
+  let list = listToTree(res.data);
+  deptList.value = list;
+  return {
+    data: list,
+    total: list.length
+  };
+};
+
+const listToTree = (data: object[]) => {
+  // * 先生成parent建立父子关系
+  const obj = {};
+  data.forEach((item: any) => {
+    obj[item.deptId] = item;
+  });
+  // * obj -> {1001: {id: 1001, parentId: 0, name: 'AA'}, 1002: {...}}
+  // console.log(obj, "obj")
+  const parentList = [];
+  data.forEach((item: any) => {
+    const parent = obj[item.parentId];
+    if (parent) {
+      // * 当前项有父节点
+      parent.children = parent.children || [];
+      parent.children.push(item);
+    } else {
+      // * 当前项没有父节点 -> 顶层
+      parentList.push(item);
+    }
+  });
+  return parentList;
+};
+
+// 重新请求列表接口
+const refresh = () => {
+  plusPageInstance.value?.getList();
+};
+
+// 搜索之前函数
+const handleBeforeSearch = (values: any) => {
+  // 返回新的参数
+  return cloneDeep(values);
+};
+
+const dialogTitle = computed(() => (state.isCreate ? "新增" : "编辑"));
+
+const { buttons } = useTable<TableRow[]>();
+
+// 表格数据
+const tableConfig: PlusColumn[] = [
+  {
+    label: "部门名称",
+    prop: "deptName",
+    width: 180,
+    tableColumnProps: {
+      showOverflowTooltip: true
+    }
+  },
+  {
+    label: "排序",
+    prop: "orderNum",
+    width: 80,
+    hideInSearch: true
+  },
+  {
+    label: "状态",
+    prop: "status",
+    valueType: "tag",
+    hideInSearch: true,
+    fieldProps: value => ({
+      type: value === "0" ? "primary" : "danger"
+    }),
+    fieldSlots: {
+      default: ({ value }) => (value === "0" ? "正常" : "停用")
+    }
+  },
+  {
+    label: "状态",
+    prop: "status",
+    valueType: "select",
+    options: [
+      { label: "正常", value: "0" },
+      { label: "停用", value: "1" }
+    ],
+    hideInTable: true,
+    fieldProps: {
+      clearable: true,
+      placeholder: "请选择部门状态",
+      style: { width: "100%" }
+    }
+  },
+  {
+    label: "创建时间",
+    prop: "createTime",
+    valueType: "date-picker",
+    hideInSearch: true,
+    minWidth: 180
+  }
+];
+
+/*--------------------表单--------------------*/
+
+// 表单实例
+const dialogForm = ref(null);
+
+interface State {
+  dialogVisible: boolean;
+  detailsVisible: boolean;
+  confirmLoading: boolean;
+  selectedIds: number[];
+  isCreate: boolean;
+  form: {};
+  rules: FormRules;
+}
+
+const state = reactive<State>({
+  dialogVisible: false,
+  detailsVisible: false,
+  confirmLoading: false,
+  selectedIds: [],
+  isCreate: false,
+  form: {},
+  rules: {
+    parentId: [
+      { required: true, message: "请选择上级部门", trigger: "change" }
+    ],
+    deptName: [{ required: true, message: "请输入部门名称", trigger: "blur" }],
+    orderNum: [{ required: true, message: "请输入显示排序", trigger: "blur" }]
+  }
+});
+
+const columns: PlusColumn[] = [
+  {
+    label: "上级部门",
+    prop: "parentId",
+    colProps: { span: 24 },
+    valueType: "tree-select",
+    fieldProps: {
+      clearable: true,
+      style: { width: "100%" },
+      props: { children: "children", label: "deptName", value: "deptId" },
+      data: computed(() => deptList.value)
+    }
+  },
+  {
+    label: "部门名称",
+    prop: "deptName",
+    valueType: "input",
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "显示排序",
+    prop: "orderNum",
+    valueType: "input-number",
+    fieldProps: {
+      clearable: true,
+      min: 0
+    }
+  },
+  {
+    label: "负责人",
+    prop: "leader",
+    valueType: "input",
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "联系电话",
+    prop: "phone",
+    valueType: "input",
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "邮箱",
+    prop: "email",
+    valueType: "input",
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "部门状态",
+    prop: "status",
+    valueType: "radio",
+    options: [
+      { label: "正常", value: "0" },
+      { label: "停用", value: "1" }
+    ],
+    fieldProps: {
+      style: { width: "100%" }
+    }
+  }
+];
+
+// 创建
+const handleCreate = (): void => {
+  form.value = {
+    status: "0"
+  };
+  state.isCreate = true;
+  state.dialogVisible = true;
+};
+
+const handleSubmit = async (values: FieldValues) => {
+  console.log(values, "Submit");
+  confirmLoading.value = true;
+  if (state.isCreate) {
+    try {
+      let params = form.value;
+      let res = await addDept(params);
+      if (res.code === 200) {
+        ElMessage.success("新增成功");
+        confirmLoading.value = false;
+        dialogVisible.value = false;
+        refresh();
+      } else {
+        ElMessage.error(res.msg);
+      }
+    } finally {
+      confirmLoading.value = false;
+    }
+  } else {
+    // 编辑
+    try {
+      let params = form.value;
+      let res = await updateDept(params);
+      if (res.code === 200) {
+        ElMessage.success("修改成功");
+        confirmLoading.value = false;
+        dialogVisible.value = false;
+        refresh();
+      } else {
+        ElMessage.error(res.msg);
+      }
+    } finally {
+      confirmLoading.value = false;
+    }
+  }
+};
+
+const handleClose = () => {
+  /*// 重置表单
+  nextTick(() => {
+    if (dialogForm.value) {
+      dialogForm.value.formInstance.resetFields()
+    }
+  })*/
+  console.log(dialogForm.value.formInstance);
+};
+
+buttons.value = [
+  {
+    // 修改
+    text: "修改",
+    code: "edit",
+    // props v0.1.16 版本新增函数类型
+    props: {
+      type: "primary"
+    },
+    onClick(params) {
+      getDept(params.row.deptId).then(res => {
+        form.value = res.data;
+        state.isCreate = false;
+        state.dialogVisible = true;
+      });
+    }
+  },
+  {
+    // 新增
+    text: "新增",
+    code: "view",
+    props: {
+      type: "success"
+    },
+    onClick(params) {
+      console.log("新增", params);
+      form.value = {
+        parentId: params.row.deptId, // 上级菜单
+        status: "0"
+      };
+      state.isCreate = true;
+      state.dialogVisible = true;
+    }
+  },
+  {
+    // 删除
+    text: "删除",
+    code: "delete",
+    // props v0.1.16 版本新增计算属性支持
+    props: computed(() => ({ type: "danger" })),
+    show: (row: any) => row.parentId !== 0,
+    confirm: {
+      options: {
+        draggable: true,
+        message: "确定删除此数据吗?"
+      }
+    },
+    onConfirm: async params => {
+      try {
+        let res = await deleteDept(params.row.deptId);
+        if (res.code === 200) {
+          ElMessage.success("删除成功");
+          refresh();
+        } else {
+          ElMessage.error(res.msg);
+        }
+      } catch (e) {
+        ElMessage.error("删除失败");
+      }
+    }
+  }
+];
+
+const { form, confirmLoading, rules, dialogVisible } = toRefs(state);
+</script>

+ 7 - 4
src/views/system/user/index.vue

@@ -85,8 +85,6 @@ onMounted(async () => {
   await getRoleOptions();
 });
 
-// 菜单列表
-const menuList = ref([]);
 const plusPageInstance = ref<PlusPageInstance | null>(null);
 
 const getList = async (query: Record<string, any>) => {
@@ -192,6 +190,9 @@ const state = reactive<State>({
   isCreate: false,
   form: {},
   rules: {
+    userName: [
+      { required: true, message: "登录账号不能为空", trigger: "blur" }
+    ],
     password2: [
       { required: true, message: "二次密码不能为空", trigger: "blur" },
       {
@@ -317,7 +318,7 @@ const columns: PlusColumn[] = [
   {
     label: "状态",
     prop: "status",
-    valueType: "select",
+    valueType: "radio",
     fieldProps: {
       placeholder: "请选择状态",
       clearable: true,
@@ -331,7 +332,9 @@ const columns: PlusColumn[] = [
 
 // 创建
 const handleCreate = (): void => {
-  form.value = {};
+  form.value = {
+    status: "0"
+  };
   state.isCreate = true;
   state.dialogVisible = true;
 };