diff --git a/src/views/system/roles/form.vue b/src/views/system/roles/form.vue
new file mode 100644
index 0000000..65d4ef0
--- /dev/null
+++ b/src/views/system/roles/form.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/roles/index.vue b/src/views/system/roles/index.vue
new file mode 100644
index 0000000..9c6aada
--- /dev/null
+++ b/src/views/system/roles/index.vue
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+
+ 重置
+
+
+
+
+
+
+
+ 新增角色
+
+
+
+
+
+
+ 修改
+
+
+ 菜单权限
+
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/roles/utils/hook.tsx b/src/views/system/roles/utils/hook.tsx
new file mode 100644
index 0000000..c871d21
--- /dev/null
+++ b/src/views/system/roles/utils/hook.tsx
@@ -0,0 +1,288 @@
+import dayjs from "dayjs";
+import editForm from "../form.vue";
+import { message } from "@/utils/message";
+// import { getRoleList } from "@/api/system";
+import { ElMessageBox } from "element-plus";
+import { usePublicHooks } from "../../hooks";
+import { addDialog } from "@/components/ReDialog";
+import { type FormItemProps } from "../utils/types";
+import { type PaginationProps } from "@pureadmin/table";
+import { reactive, ref, onMounted, h } from "vue";
+
+export function useRole() {
+ const form = reactive({
+ name: "",
+ code: "",
+ status: ""
+ });
+ const formRef = ref();
+ const dataList = ref([]);
+ const loading = ref(true);
+ const switchLoadMap = ref({});
+ const { switchStyle } = usePublicHooks();
+ const pagination = reactive({
+ total: 0,
+ pageSize: 10,
+ currentPage: 1,
+ background: true
+ });
+ const columns: TableColumnList = [
+ {
+ label: "角色编号",
+ prop: "id",
+ minWidth: 100
+ },
+ {
+ label: "角色名称",
+ prop: "name",
+ minWidth: 120
+ },
+ {
+ label: "角色标识",
+ prop: "code",
+ minWidth: 150
+ },
+ {
+ label: "状态",
+ minWidth: 130,
+ cellRenderer: scope => (
+ onChange(scope as any)}
+ />
+ )
+ },
+ {
+ label: "备注",
+ prop: "remark",
+ minWidth: 150
+ },
+ {
+ label: "创建时间",
+ minWidth: 180,
+ prop: "createTime",
+ formatter: ({ createTime }) =>
+ dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
+ },
+ {
+ label: "操作",
+ fixed: "right",
+ width: 240,
+ slot: "operation"
+ }
+ ];
+ // const buttonClass = computed(() => {
+ // return [
+ // "!h-[20px]",
+ // "reset-margin",
+ // "!text-gray-500",
+ // "dark:!text-white",
+ // "dark:hover:!text-primary"
+ // ];
+ // });
+
+ function onChange({ row, index }) {
+ ElMessageBox.confirm(
+ `确认要${
+ row.status === 0 ? "停用" : "启用"
+ }${
+ row.name
+ }吗?`,
+ "系统提示",
+ {
+ confirmButtonText: "确定",
+ cancelButtonText: "取消",
+ type: "warning",
+ dangerouslyUseHTMLString: true,
+ draggable: true
+ }
+ )
+ .then(() => {
+ switchLoadMap.value[index] = Object.assign(
+ {},
+ switchLoadMap.value[index],
+ {
+ loading: true
+ }
+ );
+ setTimeout(() => {
+ switchLoadMap.value[index] = Object.assign(
+ {},
+ switchLoadMap.value[index],
+ {
+ loading: false
+ }
+ );
+ message(`已${row.status === 0 ? "停用" : "启用"}${row.name}`, {
+ type: "success"
+ });
+ }, 300);
+ })
+ .catch(() => {
+ row.status === 0 ? (row.status = 1) : (row.status = 0);
+ });
+ }
+
+ function handleDelete(row) {
+ message(`您删除了角色名称为${row.name}的这条数据`, { type: "success" });
+ const updatedListData = roleList.value.list.filter(
+ item => item.id !== row.id
+ );
+ roleList.value.list = updatedListData;
+ onSearch();
+ }
+
+ function handleSizeChange(val: number) {
+ console.log(`${val} items per page`);
+ }
+
+ function handleCurrentChange(val: number) {
+ console.log(`current page: ${val}`);
+ }
+
+ function handleSelectionChange(val) {
+ console.log("handleSelectionChange", val);
+ }
+ const roleList = ref({
+ list: [
+ {
+ createTime: 1605456000000, // 时间戳(毫秒ms)
+ updateTime: 1684512000000,
+ creator: "admin",
+ id: 1,
+ name: "超级管理员",
+ code: "admin",
+ status: 1, // 状态 1 启用 0 停用
+ remark: "超级管理员拥有最高权限"
+ },
+ {
+ createTime: 1605456000000,
+ updateTime: 1684512000000,
+ creator: "admin",
+ id: 2,
+ name: "普通角色",
+ code: "common",
+ status: 1,
+ remark: "普通角色拥有部分权限"
+ }
+ ],
+ total: 2, // 总条目数
+ pageSize: 10, // 每页显示条目个数
+ currentPage: 1 // 当前页数
+ });
+ function getRoleList() {
+ // http.request("post", "/login")
+ return roleList;
+ }
+
+ async function onSearch() {
+ loading.value = true;
+ // const { data } = await getRoleList(toRaw(form));
+ const data = getRoleList();
+ dataList.value = data.value.list;
+ pagination.total = data.value.total;
+ pagination.pageSize = data.value.pageSize;
+ pagination.currentPage = data.value.currentPage;
+
+ setTimeout(() => {
+ loading.value = false;
+ }, 500);
+ }
+
+ const resetForm = formEl => {
+ if (!formEl) return;
+ formEl.resetFields();
+ onSearch();
+ };
+
+ function openDialog(title = "新增", row?: FormItemProps) {
+ addDialog({
+ title: `${title}角色`,
+ props: {
+ formInline: {
+ name: row?.name ?? "",
+ code: row?.code ?? "",
+ remark: row?.remark ?? ""
+ }
+ },
+ width: "40%",
+ draggable: true,
+ fullscreenIcon: true,
+ closeOnClickModal: false,
+ contentRenderer: () => h(editForm, { ref: formRef }),
+ beforeSure: (done, { options }) => {
+ const FormRef = formRef.value.getRef();
+ const curData = options.props.formInline as FormItemProps;
+ function chores() {
+ message(`您${title}了角色名称为${curData.name}的这条数据`, {
+ type: "success"
+ });
+ done(); // 关闭弹框
+ onSearch(); // 刷新表格数据
+ }
+ FormRef.validate(valid => {
+ if (valid) {
+ console.log("curData", curData);
+ // 表单规则校验通过
+ if (title === "新增") {
+ // 实际开发先调用新增接口,再进行下面操作
+ const addItem = {
+ createTime: 1605456000000, // 时间戳(毫秒ms)
+ updateTime: 1684512000000,
+ creator: curData.name,
+ id: 3,
+ name: "员工",
+ code: curData.code,
+ status: 1, // 状态 1 启用 0 停用
+ remark: curData.remark
+ };
+ roleList.value.list.push(addItem);
+ chores();
+ } else {
+ // 实际开发先调用编辑接口,再进行下面操作
+ chores();
+ }
+ }
+ });
+ }
+ });
+ }
+
+ /** 菜单权限 */
+ function handleMenu() {
+ message("等菜单管理页面开发后完善");
+ }
+
+ /** 数据权限 可自行开发 */
+ // function handleDatabase() {}
+
+ onMounted(() => {
+ onSearch();
+ });
+
+ return {
+ form,
+ loading,
+ columns,
+ dataList,
+ pagination,
+ // buttonClass,
+ onSearch,
+ resetForm,
+ openDialog,
+ handleMenu,
+ handleDelete,
+ // handleDatabase,
+ handleSizeChange,
+ handleCurrentChange,
+ handleSelectionChange
+ };
+}
diff --git a/src/views/system/roles/utils/rule.ts b/src/views/system/roles/utils/rule.ts
new file mode 100644
index 0000000..ea1dd19
--- /dev/null
+++ b/src/views/system/roles/utils/rule.ts
@@ -0,0 +1,8 @@
+import { reactive } from "vue";
+import type { FormRules } from "element-plus";
+
+/** 自定义表单规则校验 */
+export const formRules = reactive({
+ name: [{ required: true, message: "角色名称为必填项", trigger: "blur" }],
+ code: [{ required: true, message: "角色标识为必填项", trigger: "blur" }]
+});
diff --git a/src/views/system/roles/utils/types.ts b/src/views/system/roles/utils/types.ts
new file mode 100644
index 0000000..a17e900
--- /dev/null
+++ b/src/views/system/roles/utils/types.ts
@@ -0,0 +1,15 @@
+// 虽然字段很少 但是抽离出来 后续有扩展字段需求就很方便了
+
+interface FormItemProps {
+ /** 角色名称 */
+ name: string;
+ /** 角色编号 */
+ code: string;
+ /** 备注 */
+ remark: string;
+}
+interface FormProps {
+ formInline: FormItemProps;
+}
+
+export type { FormItemProps, FormProps };
diff --git a/src/views/system/user/form.vue b/src/views/system/user/form.vue
new file mode 100644
index 0000000..39e2dad
--- /dev/null
+++ b/src/views/system/user/form.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/user/utils/hook.tsx b/src/views/system/user/utils/hook.tsx
new file mode 100644
index 0000000..0baff91
--- /dev/null
+++ b/src/views/system/user/utils/hook.tsx
@@ -0,0 +1,358 @@
+import dayjs from "dayjs";
+import { message } from "@/utils/message";
+import editForm from "../form.vue";
+import { addDialog } from "@/components/ReDialog";
+import { type FormItemProps } from "../utils/types";
+// import { getUserList } from "@/api/system";
+import { ElMessageBox } from "element-plus";
+import { type PaginationProps } from "@pureadmin/table";
+import { reactive, ref, computed, h, onMounted } from "vue";
+// import { http } from "@/utils/http";
+import { number } from "echarts";
+
+export function useUser() {
+ const form = reactive({
+ /** 角色名称 */
+ username: "",
+ /** 手机号 */
+ mobile: "",
+ /** 状态 */
+ status: number
+ });
+ const formRef = ref();
+ const dataList = ref([]);
+ const loading = ref(true);
+ const switchLoadMap = ref({});
+ const pagination = reactive({
+ total: 0,
+ pageSize: 10,
+ currentPage: 1,
+ background: true
+ });
+ const columns: TableColumnList = [
+ {
+ label: "序号",
+ type: "index",
+ width: 70,
+ fixed: "left"
+ },
+ // {
+ // label: "用户编号",
+ // prop: "id",
+ // minWidth: 130
+ // },
+ {
+ label: "用户名称",
+ prop: "username",
+ minWidth: 130
+ },
+ // {
+ // label: "用户昵称",
+ // prop: "nickname",
+ // minWidth: 130
+ // },
+ {
+ label: "性别",
+ prop: "sex",
+ minWidth: 90,
+ cellRenderer: ({ row, props }) => (
+
+ {row.sex === 1 ? "女" : "男"}
+
+ )
+ },
+ {
+ label: "组织",
+ prop: "dept",
+ minWidth: 90,
+ formatter: ({ dept }) => dept.name
+ },
+ {
+ label: "手机号码",
+ prop: "mobile",
+ minWidth: 90
+ },
+ {
+ label: "状态",
+ prop: "status",
+ minWidth: 90,
+ cellRenderer: scope => (
+ onChange(scope as any)}
+ />
+ )
+ },
+ {
+ label: "创建时间",
+ minWidth: 90,
+ prop: "createTime",
+ formatter: ({ createTime }) =>
+ dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
+ },
+ {
+ label: "操作",
+ fixed: "right",
+ width: 180,
+ slot: "operation"
+ }
+ ];
+ const buttonClass = computed(() => {
+ return [
+ "!h-[20px]",
+ "reset-margin",
+ "!text-gray-500",
+ "dark:!text-white",
+ "dark:hover:!text-primary"
+ ];
+ });
+
+ function onChange({ row, index }) {
+ ElMessageBox.confirm(
+ `确认要${
+ row.status === 0 ? "停用" : "启用"
+ }${
+ row.username
+ }用户吗?`,
+ "系统提示",
+ {
+ confirmButtonText: "确定",
+ cancelButtonText: "取消",
+ type: "warning",
+ dangerouslyUseHTMLString: true,
+ draggable: true
+ }
+ )
+ .then(() => {
+ switchLoadMap.value[index] = Object.assign(
+ {},
+ switchLoadMap.value[index],
+ {
+ loading: true
+ }
+ );
+ setTimeout(() => {
+ switchLoadMap.value[index] = Object.assign(
+ {},
+ switchLoadMap.value[index],
+ {
+ loading: false
+ }
+ );
+ message("已成功修改用户状态", {
+ type: "success"
+ });
+ }, 300);
+ })
+ .catch(() => {
+ row.status === 0 ? (row.status = 1) : (row.status = 0);
+ });
+ }
+
+ function handleUpdate(row) {
+ console.log(row);
+ }
+
+ function handleDelete(row) {
+ message(`您删除了角色名称为${row.username}的这条数据`, { type: "success" });
+ const deleteListData = userList.value.list.filter(
+ item => item.id !== row.id
+ );
+ userList.value.list = deleteListData;
+ onSearch();
+ }
+
+ function handleSizeChange(val: number) {
+ console.log(`${val} items per page`);
+ }
+
+ function handleCurrentChange(val: number) {
+ console.log(`current page: ${val}`);
+ }
+
+ function handleSelectionChange(val) {
+ console.log("handleSelectionChange", val);
+ }
+
+ const userList = ref({
+ list: [
+ {
+ username: "admin",
+ nickname: "admin",
+ remark: "管理员",
+ deptId: 103,
+ postIds: [1],
+ mobile: "15888888888",
+ sex: 0,
+ id: 1,
+ status: 0,
+ createTime: 1605456000000,
+ dept: {
+ id: 103,
+ name: "研发部门"
+ }
+ },
+ {
+ username: "pure",
+ nickname: "pure",
+ remark: "不要吓我",
+ deptId: 104,
+ postIds: [1],
+ mobile: "15888888888",
+ sex: 0,
+ id: 100,
+ status: 1,
+ createTime: 1605456000000,
+ dept: {
+ id: 104,
+ name: "市场部门"
+ }
+ },
+ {
+ username: "lucy",
+ nickname: "girl",
+ remark: null,
+ deptId: 106,
+ postIds: null,
+ mobile: "15888888888",
+ sex: 1,
+ id: 103,
+ status: 1,
+ createTime: 1605456000000,
+ dept: {
+ id: 106,
+ name: "财务部门"
+ }
+ },
+ {
+ username: "mike",
+ nickname: "boy",
+ remark: null,
+ deptId: 107,
+ postIds: [],
+ mobile: "15888888888",
+ sex: 0,
+ id: 104,
+ status: 0,
+ createTime: 1605456000000,
+ dept: {
+ id: 107,
+ name: "运维部门"
+ }
+ }
+ ],
+ total: 4
+ });
+
+ function getUserList() {
+ // http.request("post", "/login")
+ return userList;
+ }
+
+ async function onSearch() {
+ loading.value = true;
+ const data = getUserList();
+ console.log(data);
+ dataList.value = data.value.list;
+ pagination.total = data.value.total;
+ setTimeout(() => {
+ loading.value = false;
+ }, 500);
+ }
+
+ const resetForm = formEl => {
+ if (!formEl) return;
+ formEl.resetFields();
+ onSearch();
+ };
+ function openDialog(title = "新增", row?: FormItemProps) {
+ addDialog({
+ title: `${title}用户`,
+ props: {
+ formInline: {
+ username: row?.username ?? "",
+ mobile: row?.mobile ?? "",
+ status: row?.status ?? ""
+ }
+ },
+ width: "40%",
+ draggable: true,
+ fullscreenIcon: true,
+ closeOnClickModal: false,
+ contentRenderer: () => h(editForm, { ref: formRef }),
+ beforeSure: (done, { options }) => {
+ const FormRef = formRef.value.getRef();
+ const curData = options.props.formInline as FormItemProps;
+ function chores() {
+ message(`您${title}了角色名称为${curData.username}的这条数据`, {
+ type: "success"
+ });
+ done(); // 关闭弹框
+ onSearch(); // 刷新表格数据
+ }
+ FormRef.validate(valid => {
+ if (valid) {
+ console.log("curData", curData);
+ // 表单规则校验通过
+ if (title === "新增") {
+ // 实际开发先调用新增接口,再进行下面操作
+ const addItem = {
+ username: curData.username,
+ mobile: "15888888888",
+ status: curData.status,
+ nickname: "boy",
+ remark: null,
+ deptId: 107,
+ postIds: [],
+ sex: 0,
+ id: 105,
+ createTime: 1605456000000,
+ dept: {
+ id: 107,
+ name: "运维部门"
+ }
+ };
+ userList.value.list.push(addItem);
+ chores();
+ } else {
+ // 实际开发先调用编辑接口,再进行下面操作
+ chores();
+ }
+ }
+ });
+ }
+ });
+ }
+
+ onMounted(() => {
+ onSearch();
+ });
+
+ return {
+ form,
+ loading,
+ columns,
+ dataList,
+ pagination,
+ buttonClass,
+ onSearch,
+ openDialog,
+ resetForm,
+ handleUpdate,
+ handleDelete,
+ handleSizeChange,
+ handleCurrentChange,
+ handleSelectionChange
+ };
+}
diff --git a/src/views/system/user/utils/rule.ts b/src/views/system/user/utils/rule.ts
new file mode 100644
index 0000000..def4b71
--- /dev/null
+++ b/src/views/system/user/utils/rule.ts
@@ -0,0 +1,8 @@
+import { reactive } from "vue";
+import type { FormRules } from "element-plus";
+
+/** 自定义表单规则校验 */
+export const formRules = reactive({
+ username: [{ required: true, message: "角色名称为必填项", trigger: "blur" }],
+ code: [{ required: true, message: "角色标识为必填项", trigger: "blur" }]
+});
diff --git a/src/views/system/user/utils/types.ts b/src/views/system/user/utils/types.ts
new file mode 100644
index 0000000..204a739
--- /dev/null
+++ b/src/views/system/user/utils/types.ts
@@ -0,0 +1,15 @@
+// 虽然字段很少 但是抽离出来 后续有扩展字段需求就很方便了
+
+interface FormItemProps {
+ /** 角色名称 */
+ username: string;
+ /** 状态 */
+ status: number;
+ /** 手机 */
+ mobile: string;
+}
+interface FormProps {
+ formInline: FormItemProps;
+}
+
+export type { FormItemProps, FormProps };