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 };