Ver código fonte

用户管理模块

zouzs 3 semanas atrás
pai
commit
c3c4eab5f5

+ 1 - 1
public/platform-config.json

@@ -19,7 +19,7 @@
   "ShowLogo": true,
   "ShowModel": "smart",
   "MenuArrowIconNoTransition": false,
-  "CachingAsyncRoutes": true,
+  "CachingAsyncRoutes": false,
   "TooltipEffect": "light",
   "ResponsiveStorageNameSpace": "responsive-",
   "MenuSearchHistory": 6

+ 7 - 0
src/api/system/role.ts

@@ -81,3 +81,10 @@ export const putSystemRoleDataScope = (data: object) => {
     { data }
   );
 };
+
+export const getSystemRoleOptionselect = () => {
+  return http.request<BasicResponseModel>(
+    "get",
+    baseUrlApi("system/role/optionselect")
+  );
+};

+ 38 - 0
src/api/system/user.ts

@@ -0,0 +1,38 @@
+import { http } from "@/utils/http";
+import { baseUrlApi } from "../utils";
+
+export interface BasicResponseModel<T = any> {
+  code: number;
+  msg: string;
+  rows: T;
+  data: T;
+  total: number;
+}
+
+export const getSystemUserList = (query?: object) => {
+  return http.post<BasicResponseModel, any>(baseUrlApi("system/user/list"), {
+    data: query
+  });
+};
+
+export const getUserInfoById = (id?: string) => {
+  return http.get<BasicResponseModel, any>(baseUrlApi(`system/user/${id}`));
+};
+
+export const editUser = (data?: object) => {
+  return http.post<BasicResponseModel, any>(baseUrlApi("system/user/edit"), {
+    data
+  });
+};
+
+export const addUser = (data?: object) => {
+  return http.post<BasicResponseModel, any>(baseUrlApi("system/user/add"), {
+    data
+  });
+};
+
+export const deleteUser = (id?: string) => {
+  return http.post<BasicResponseModel, any>(baseUrlApi("system/user/delete"), {
+    data: [id]
+  });
+};

+ 2 - 3
src/views/system/role/components/deptTree.vue

@@ -102,7 +102,7 @@ const setCheckedKeys = (keys: number[], leafOnly: boolean) => {
     </el-row>
     <el-tree
       ref="menuRef"
-      class="tree-border"
+      class="dark:tree-border"
       :data="deptList"
       show-checkbox
       node-key="id"
@@ -118,8 +118,7 @@ const setCheckedKeys = (keys: number[], leafOnly: boolean) => {
 .tree-border {
   width: 100%;
   margin-top: 5px;
-  border: 1px solid #e5e6e7;
-  background: #ffffff none;
+  border: 1px solid #4c4d4f;
   border-radius: 4px;
 }
 </style>

+ 1 - 2
src/views/system/role/components/menuTree.vue

@@ -138,8 +138,7 @@ watch(menuCheckStrictly, () => {
 .tree-border {
   width: 100%;
   margin-top: 5px;
-  border: 1px solid #e5e6e7;
-  background: #ffffff none;
+  border: 1px solid #4c4d4f;
   border-radius: 4px;
 }
 </style>

+ 422 - 6
src/views/system/user/index.vue

@@ -1,11 +1,427 @@
-<script setup lang="ts">
+<template>
+  <div>
+    <PlusPage
+      ref="plusPageInstance"
+      :columns="tableConfig"
+      :request="getList"
+      :is-card="true"
+      :search="{
+        labelWidth: 100,
+        showNumber: 3
+      }"
+      :table="{
+        actionBar: { buttons, type: 'link', width: 140 },
+        adaptive: { offsetBottom: 50 }
+      }"
+      :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,
+  onMounted,
+  reactive,
+  ref,
+  toRefs,
+  type Ref
+} from "vue";
+import type { FormRules } from "element-plus";
+import { ElMessage } from "element-plus";
+import {
+  type FieldValues,
+  type PlusColumn,
+  type OptionsRow,
+  PlusDialogForm,
+  PlusPage,
+  PlusPageInstance,
+  useTable
+} from "plus-pro-components";
+import {
+  addUser,
+  deleteUser,
+  editUser,
+  getSystemUserList,
+  getUserInfoById
+} from "@/api/system/user";
+import {
+  getSystemRoleDeptTree,
+  getSystemRoleOptionselect
+} from "@/api/system/role";
+
 defineOptions({
   name: "User"
 });
-</script>
 
-<template>
-  <div />
-</template>
+onMounted(async () => {
+  await getDeptList();
+  await getRoleOptions();
+});
+
+// 菜单列表
+const menuList = ref([]);
+const plusPageInstance = ref<PlusPageInstance | null>(null);
+
+const getList = async (query: Record<string, any>) => {
+  let res = await getSystemUserList(query);
+  return {
+    data: res.rows,
+    total: res.total
+  };
+};
+
+// 重新请求列表接口
+const refresh = () => {
+  plusPageInstance.value?.getList();
+};
+
+const dialogTitle = computed(() => (state.isCreate ? "新增" : "编辑"));
+
+const { buttons } = useTable();
+
+// 表格数据
+const tableConfig: PlusColumn[] = [
+  {
+    label: "用户姓名",
+    prop: "nickName",
+    width: 180,
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "登录账号",
+    prop: "userName",
+    width: 180,
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "角色",
+    prop: "roleName",
+    hideInSearch: true
+  },
+  {
+    label: "所属部门",
+    prop: "deptName",
+    hideInSearch: true
+  },
+  {
+    label: "岗位",
+    prop: "postName",
+    hideInSearch: true
+  },
+  /*{
+    label: "用户类型",
+    prop: "menuName",
+    hideInSearch: true
+  },*/
+  {
+    label: "状态",
+    prop: "status",
+    hideInSearch: true,
+    valueType: "select",
+    options: [
+      { label: "启用", value: "0" },
+      { label: "停用", value: "1" }
+    ],
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "最近IP",
+    prop: "loginIp",
+    hideInSearch: true
+  },
+  {
+    label: "最近登录时间",
+    prop: "loginDate",
+    hideInSearch: true
+  }
+];
 
-<style scoped lang="scss"></style>
+/*--------------------表单--------------------*/
+
+// 表单实例
+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: {
+    password2: [
+      { required: true, message: "二次密码不能为空", trigger: "blur" },
+      {
+        validator: (rule, value, callback) => {
+          if (value !== state.form["password"]) {
+            callback(new Error("两次输入的密码不一致"));
+          } else {
+            callback();
+          }
+        },
+        trigger: "blur"
+      }
+    ],
+    phonenumber: [
+      {
+        pattern: /^1[3-9]\d{9}$/,
+        message: "请输入正确的手机号",
+        trigger: "blur"
+      }
+    ]
+  }
+});
+
+const deptList = ref([]);
+const roleList: Ref<OptionsRow[]> = ref([]);
+
+const getDeptList = async () => {
+  let res = await getSystemRoleDeptTree("2");
+  if (res.code === 200) {
+    deptList.value = res.depts;
+  }
+};
+
+const getRoleOptions = async () => {
+  let res = await getSystemRoleOptionselect();
+  if (res.code === 200) {
+    roleList.value = res.data;
+  }
+};
+
+const columns: PlusColumn[] = [
+  {
+    label: "所属部门",
+    prop: "deptId",
+    valueType: "tree-select",
+    fieldProps: {
+      placeholder: "请选择所属部门",
+      clearable: true,
+      props: {
+        label: "label",
+        value: "id",
+        children: "children"
+      },
+      data: deptList
+    }
+  },
+  {
+    label: "登录账号",
+    prop: "userName",
+    valueType: "input",
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "登录密码",
+    prop: "password",
+    valueType: "input",
+    fieldProps: {
+      clearable: true,
+      type: "password",
+      showPassword: false
+    }
+  },
+  {
+    label: "二次密码",
+    prop: "password2",
+    valueType: "input",
+    fieldProps: {
+      clearable: true,
+      type: "password",
+      showPassword: false
+    }
+  },
+  {
+    label: "用户姓名",
+    prop: "nickName",
+    valueType: "input",
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "手机号",
+    prop: "phonenumber",
+    valueType: "input",
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "角色",
+    prop: "roleId",
+    valueType: "select",
+    options: computed(() => roleList.value),
+    optionsMap: {
+      value: "roleId",
+      label: "roleName"
+    },
+    fieldProps: {
+      placeholder: "请选择角色",
+      clearable: true
+    }
+  },
+  {
+    label: "岗位",
+    prop: "postName",
+    valueType: "input",
+    fieldProps: {
+      clearable: true
+    }
+  },
+  {
+    label: "状态",
+    prop: "status",
+    valueType: "select",
+    fieldProps: {
+      placeholder: "请选择状态",
+      clearable: true,
+      options: [
+        { label: "启用", value: "0" },
+        { label: "停用", value: "1" }
+      ]
+    }
+  }
+];
+
+// 创建
+const handleCreate = (): void => {
+  form.value = {};
+  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 addUser(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 editUser(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 = () => {
+  console.log(dialogForm.value.formInstance);
+};
+
+buttons.value = [
+  {
+    // 修改
+    text: "修改",
+    code: "edit",
+    // props v0.1.16 版本新增函数类型
+    props: {
+      type: "primary"
+    },
+    onClick(params) {
+      getUserInfoById(params.row.userId).then(res => {
+        form.value = res.data;
+        form.value.password2 = res.data.password;
+        state.isCreate = false;
+        state.dialogVisible = true;
+      });
+    }
+  },
+  {
+    // 删除
+    text: "删除",
+    code: "delete",
+    // props v0.1.16 版本新增计算属性支持
+    props: computed(() => ({ type: "danger" })),
+    confirm: {
+      options: {
+        draggable: true,
+        message: "确定删除此数据吗?"
+      }
+    },
+    onConfirm: async params => {
+      try {
+        let res = await deleteUser(params.row.userId);
+        if (res.code === 200) {
+          ElMessage.success("删除成功");
+          refresh();
+        } else {
+          ElMessage.error(res.msg);
+        }
+      } catch (e) {
+        ElMessage.error("删除失败");
+      }
+    }
+  }
+];
+
+const { form, confirmLoading, rules, dialogVisible } = toRefs(state);
+</script>