mirror of
https://github.com/pure-admin/pure-admin-thin.git
synced 2025-04-25 16:07:19 +08:00
feat: 新增角色管理、岗位管理
This commit is contained in:
parent
6719fd8290
commit
b068518ba6
@ -1,4 +1,5 @@
|
|||||||
import { http } from "@/utils/http";
|
import { http } from "@/utils/http";
|
||||||
|
import { Tree } from "@/utils/tree";
|
||||||
|
|
||||||
export interface MenuQuery {
|
export interface MenuQuery {
|
||||||
isButton: boolean;
|
isButton: boolean;
|
||||||
@ -7,7 +8,7 @@ export interface MenuQuery {
|
|||||||
/**
|
/**
|
||||||
* MenuDTO
|
* MenuDTO
|
||||||
*/
|
*/
|
||||||
export interface MenuDTO {
|
export interface MenuDTO extends Tree {
|
||||||
createTime?: Date;
|
createTime?: Date;
|
||||||
isButton?: number;
|
isButton?: number;
|
||||||
id?: number;
|
id?: number;
|
||||||
|
70
src/api/system/post.ts
Normal file
70
src/api/system/post.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { http } from "@/utils/http";
|
||||||
|
|
||||||
|
export interface PostListCommand extends BasePageQuery {
|
||||||
|
postCode?: string;
|
||||||
|
postName?: string;
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PostPageResponse {
|
||||||
|
createTime: string;
|
||||||
|
postCode: string;
|
||||||
|
postId: number;
|
||||||
|
postName: string;
|
||||||
|
postSort: number;
|
||||||
|
remark: string;
|
||||||
|
status: number;
|
||||||
|
statusStr: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPostListApi(params: PostListCommand) {
|
||||||
|
return http.request<ResponseData<PageDTO<PostPageResponse>>>(
|
||||||
|
"get",
|
||||||
|
"/system/post/list",
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const exportPostExcelApi = (
|
||||||
|
params: PostListCommand,
|
||||||
|
fileName: string
|
||||||
|
) => {
|
||||||
|
return http.download("/system/post/excel", fileName, {
|
||||||
|
params
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deletePostApi = (data: Array<number>) => {
|
||||||
|
return http.request<ResponseData<void>>("delete", "/system/post", {
|
||||||
|
params: {
|
||||||
|
// 需要将数组转换为字符串 否则Axios会将参数变成 noticeIds[0]:1 noticeIds[1]:2 这种格式,后端接收参数不成功
|
||||||
|
ids: data.toString()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface AddPostCommand {
|
||||||
|
postCode: string;
|
||||||
|
postName: string;
|
||||||
|
postSort: number;
|
||||||
|
remark?: string;
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addPostApi = (data: AddPostCommand) => {
|
||||||
|
return http.request<ResponseData<void>>("post", "/system/post", {
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface UpdatePostCommand extends AddPostCommand {
|
||||||
|
postId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updatePostApi = (data: UpdatePostCommand) => {
|
||||||
|
return http.request<ResponseData<void>>("put", "/system/post", {
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
65
src/api/system/role.ts
Normal file
65
src/api/system/role.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { http } from "@/utils/http";
|
||||||
|
|
||||||
|
export interface RoleQuery extends BasePageQuery {
|
||||||
|
roleKey?: string;
|
||||||
|
roleName?: string;
|
||||||
|
status?: string;
|
||||||
|
timeRangeColumn?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RoleDTO {
|
||||||
|
createTime: Date;
|
||||||
|
dataScope: number;
|
||||||
|
remark: string;
|
||||||
|
roleId: number;
|
||||||
|
roleKey: string;
|
||||||
|
roleName: string;
|
||||||
|
roleSort: number;
|
||||||
|
selectedDeptList: number[];
|
||||||
|
selectedMenuList: number[];
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRoleListApi(params: RoleQuery) {
|
||||||
|
return http.request<ResponseData<PageDTO<RoleDTO>>>(
|
||||||
|
"get",
|
||||||
|
"/system/role/list",
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRoleInfoApi(roleId: number) {
|
||||||
|
return http.request<ResponseData<RoleDTO>>("get", "/system/role/" + roleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AddRoleCommand {
|
||||||
|
dataScope?: string;
|
||||||
|
menuIds: number[];
|
||||||
|
remark?: string;
|
||||||
|
roleKey: string;
|
||||||
|
roleName: string;
|
||||||
|
roleSort: number;
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addRoleApi(data: AddRoleCommand) {
|
||||||
|
return http.request<void>("post", "/system/role", {
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateRoleCommand extends AddRoleCommand {
|
||||||
|
roleId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateRoleApi(data: UpdateRoleCommand) {
|
||||||
|
return http.request<void>("put", "/system/role", {
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteRoleApi(roleId: number) {
|
||||||
|
return http.request<void>("delete", "/system/role/" + roleId);
|
||||||
|
}
|
1
src/assets/svg/FullScreenMaximize.svg
Normal file
1
src/assets/svg/FullScreenMaximize.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20"><g fill="none"><path d="M3 5a2 2 0 0 1 2-2h2a.5.5 0 0 1 0 1H5a1 1 0 0 0-1 1v2a.5.5 0 0 1-1 0V5zm9.5-1.5A.5.5 0 0 1 13 3h2a2 2 0 0 1 2 2v2a.5.5 0 0 1-1 0V5a1 1 0 0 0-1-1h-2a.5.5 0 0 1-.5-.5zm-9 9a.5.5 0 0 1 .5.5v2a1 1 0 0 0 1 1h2a.5.5 0 0 1 0 1H5a2 2 0 0 1-2-2v-2a.5.5 0 0 1 .5-.5zm13 0a.5.5 0 0 1 .5.5v2a2 2 0 0 1-2 2h-2a.5.5 0 0 1 0-1h2a1 1 0 0 0 1-1v-2a.5.5 0 0 1 .5-.5z" fill="currentColor"/></g></svg>
|
After Width: | Height: | Size: 508 B |
1
src/assets/svg/FullScreenMinimize.svg
Normal file
1
src/assets/svg/FullScreenMinimize.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none"><path d="M8.5 3.75a.75.75 0 0 0-1.5 0v2.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 0 0 1.5h2.5A2.25 2.25 0 0 0 8.5 6.25v-2.5zm0 16.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 0-.75-.75h-2.5a.75.75 0 0 1 0-1.5h2.5a2.25 2.25 0 0 1 2.25 2.25v2.5zM16.25 3a.75.75 0 0 0-.75.75v2.5a2.25 2.25 0 0 0 2.25 2.25h2.5a.75.75 0 0 0 0-1.5h-2.5a.75.75 0 0 1-.75-.75v-2.5a.75.75 0 0 0-.75-.75zm-.75 17.25a.75.75 0 0 0 1.5 0v-2.5a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 0 0-1.5h-2.5a2.25 2.25 0 0 0-2.25 2.25v2.5z" fill="currentColor"/></g></svg>
|
After Width: | Height: | Size: 631 B |
173
src/components/VDialog/VDialog.vue
Normal file
173
src/components/VDialog/VDialog.vue
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
:fullscreen="fullScreen"
|
||||||
|
class="v-dialog"
|
||||||
|
:class="dialogClazz"
|
||||||
|
:draggable="props.draggable"
|
||||||
|
:show-close="false"
|
||||||
|
v-bind="$attrs"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<slot name="header">
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: rgb(118 131 164);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div v-text="props.title" />
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="props.showFullScreen"
|
||||||
|
:icon="fullScreen ? FullScreenMinimize : FullScreenMaximize"
|
||||||
|
link
|
||||||
|
@click="requestFullScreen"
|
||||||
|
class="header-btn"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
:icon="Close"
|
||||||
|
link
|
||||||
|
@click="handleCloseClick"
|
||||||
|
class="header-btn"
|
||||||
|
style="margin-left: 0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
<template v-if="useBodyScrolling">
|
||||||
|
<el-scrollbar :max-height="bodyHeight" always>
|
||||||
|
<slot name="default" />
|
||||||
|
</el-scrollbar>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<slot name="default" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<slot name="footer" v-if="!props.hiddenFooter">
|
||||||
|
<div style="display: flex; justify-content: center">
|
||||||
|
<el-button
|
||||||
|
:loading="props.loading"
|
||||||
|
type="primary"
|
||||||
|
@click="handleConfirm"
|
||||||
|
>{{ props.confirmText }}</el-button
|
||||||
|
>
|
||||||
|
<el-button :loading="props.loading" @click="handleCancel">{{
|
||||||
|
cancelText
|
||||||
|
}}</el-button>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import { ElDialog, ElButton, ElScrollbar } from "element-plus";
|
||||||
|
import { DialogEmits, DialogProps } from "./dialog";
|
||||||
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import FullScreenMaximize from "@/assets/svg/FullScreenMaximize.svg?component";
|
||||||
|
import FullScreenMinimize from "@/assets/svg/FullScreenMinimize.svg?component";
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<DialogProps>(), {
|
||||||
|
fullScreen: undefined,
|
||||||
|
confirmText: "确定",
|
||||||
|
cancelText: "取消",
|
||||||
|
disableFooter: false,
|
||||||
|
useBodyScrolling: false,
|
||||||
|
fixedBodyHeight: true,
|
||||||
|
draggable: true,
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
const emits = defineEmits<DialogEmits>();
|
||||||
|
|
||||||
|
const visible = computed<boolean>({
|
||||||
|
get: () => {
|
||||||
|
return props.modelValue;
|
||||||
|
},
|
||||||
|
set: v => emits("update:modelValue", v)
|
||||||
|
});
|
||||||
|
|
||||||
|
const fullScreenState = ref(!!props.initFullScreen);
|
||||||
|
const fullScreen = computed<boolean>({
|
||||||
|
get: () => {
|
||||||
|
console.log("fullScreen getter", props.fullScreen, fullScreenState.value);
|
||||||
|
// 非受控模式,状态完全由组件内部控制
|
||||||
|
if (props.fullScreen === undefined) {
|
||||||
|
return fullScreenState.value;
|
||||||
|
} else {
|
||||||
|
return props.fullScreen;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set: v => {
|
||||||
|
fullScreenState.value = v;
|
||||||
|
console.log("fullScreen setter", v, props.fullScreen);
|
||||||
|
// 受控模式,将状态更新到父组件
|
||||||
|
if (props.fullScreen !== undefined) {
|
||||||
|
emits("update:fullScreen", v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// const fullScreen = ref<boolean>(false)
|
||||||
|
function requestFullScreen() {
|
||||||
|
fullScreen.value = !fullScreen.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bodyHeight = computed(() => {
|
||||||
|
const footerHeight = props.hiddenFooter ? "0" : "52px";
|
||||||
|
if (props.fullScreen) {
|
||||||
|
// footerHeight=52,headerHeight=44,padding=12
|
||||||
|
return `calc(100dvh - ${footerHeight} - 44px)`;
|
||||||
|
} else {
|
||||||
|
return `calc(70dvh - ${footerHeight} - 44px)`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const dialogClazz = computed(() => {
|
||||||
|
const classList: string[] = ["v-dialog"];
|
||||||
|
if (!props.fixedBodyHeight) {
|
||||||
|
classList.push("flex-body");
|
||||||
|
}
|
||||||
|
if (props.hiddenFooter) {
|
||||||
|
classList.push("hidden-footer");
|
||||||
|
}
|
||||||
|
return classList;
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleConfirm() {
|
||||||
|
emits("confirm");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCancel() {
|
||||||
|
emits("cancel");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCloseClick() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header-btn :deep(.el-icon),
|
||||||
|
.header-btn :deep(.el-icon svg) {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
62
src/components/VDialog/dialog.css
Normal file
62
src/components/VDialog/dialog.css
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
html.dark .v-dialog {
|
||||||
|
--header-bg-color: #171d1e;
|
||||||
|
--footer-bg-color: #171d1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog {
|
||||||
|
--header-bg-color: #f5f7fa;
|
||||||
|
--footer-bg-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog.el-dialog.hidden-footer .el-dialog__footer {
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__footer {
|
||||||
|
padding: 10px;
|
||||||
|
/*border-top: 1px solid var(--el-border-color);*/
|
||||||
|
/*border-bottom: 1px solid var(--el-border-color);*/
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: var(--header-bg-color);
|
||||||
|
position: relative; /* 防止被表单覆盖底部 */
|
||||||
|
z-index: calc(var(--el-index-normal) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog.el-dialog {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 15dvh auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog.el-dialog.is-fullscreen {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog.el-dialog .el-dialog__header {
|
||||||
|
padding: 10px 16px;
|
||||||
|
/*border-bottom: 1px solid var(--el-border-color);*/
|
||||||
|
margin-right: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: var(--header-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog.el-dialog--center .el-dialog__body,
|
||||||
|
.el-dialog__body {
|
||||||
|
padding: 16px 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog.el-dialog.is-fullscreen .el-dialog__body {
|
||||||
|
height: calc(100dvh - 44px - 52px);
|
||||||
|
max-height: calc(100dvh - 44px - 52px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog.el-dialog .el-dialog__body {
|
||||||
|
height: calc(70dvh - 44px - 52px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-dialog.el-dialog.flex-body:not(.is-fullscreen) .el-dialog__body {
|
||||||
|
height: initial;
|
||||||
|
max-height: calc(70dvh - 44px - 52px);
|
||||||
|
}
|
47
src/components/VDialog/dialog.ts
Normal file
47
src/components/VDialog/dialog.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
export interface DialogProps {
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
title: string;
|
||||||
|
/**
|
||||||
|
* 显隐
|
||||||
|
*/
|
||||||
|
modelValue: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化全屏状态
|
||||||
|
*/
|
||||||
|
initFullScreen?: boolean | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展示全屏按钮
|
||||||
|
*/
|
||||||
|
showFullScreen?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全屏
|
||||||
|
*/
|
||||||
|
fullScreen?: boolean | undefined;
|
||||||
|
confirmText?: string;
|
||||||
|
cancelText?: string;
|
||||||
|
loading?: boolean;
|
||||||
|
/**
|
||||||
|
* 使用el-scrollbar包裹对话框body
|
||||||
|
*/
|
||||||
|
useBodyScrolling?: boolean;
|
||||||
|
/**
|
||||||
|
* 固定对话框body高度
|
||||||
|
*/
|
||||||
|
fixedBodyHeight?: boolean;
|
||||||
|
|
||||||
|
draggable?: boolean;
|
||||||
|
|
||||||
|
hiddenFooter?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DialogEmits = {
|
||||||
|
"update:modelValue": [val: boolean];
|
||||||
|
"update:fullScreen": [val: boolean];
|
||||||
|
confirm: [];
|
||||||
|
cancel: [];
|
||||||
|
};
|
@ -21,6 +21,7 @@ import "element-plus/dist/index.css";
|
|||||||
// 导入字体图标
|
// 导入字体图标
|
||||||
import "./assets/iconfont/iconfont.js";
|
import "./assets/iconfont/iconfont.js";
|
||||||
import "./assets/iconfont/iconfont.css";
|
import "./assets/iconfont/iconfont.css";
|
||||||
|
import "@/components/VDialog/dialog.css";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
|
@ -42,5 +42,5 @@ export type userType = {
|
|||||||
/** 字典ListMap 用于下拉框直接展示 */
|
/** 字典ListMap 用于下拉框直接展示 */
|
||||||
dictionaryList: Map<String, Array<DictionaryData>>;
|
dictionaryList: Map<String, Array<DictionaryData>>;
|
||||||
/** 字典MapMap 用于匹配值展示 */
|
/** 字典MapMap 用于匹配值展示 */
|
||||||
dictionaryMap: Map<String, Map<String, DictionaryData>>;
|
dictionaryMap: Record<string, Record<string, DictionaryData>>;
|
||||||
};
|
};
|
||||||
|
@ -205,3 +205,25 @@ export const handleTree = (
|
|||||||
}
|
}
|
||||||
return tree;
|
return tree;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface Tree {
|
||||||
|
children?: this[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toTree<T extends Tree>(
|
||||||
|
src: T[],
|
||||||
|
keyField: keyof T,
|
||||||
|
parentField: keyof T
|
||||||
|
): T[] {
|
||||||
|
const map = new Map<unknown, T>(src.map(it => [it[keyField], it]));
|
||||||
|
src.forEach(it => {
|
||||||
|
if (map.has(it[parentField])) {
|
||||||
|
const parent = map.get(it[parentField])!;
|
||||||
|
if (!parent.children) {
|
||||||
|
parent.children = [];
|
||||||
|
}
|
||||||
|
parent.children.push(it);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return src.filter(it => !it[parentField]);
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useLoginLogHook } from "./utils/hook";
|
import { usePostHook } from "./utils/hook";
|
||||||
import { PureTableBar } from "@/components/RePureTableBar";
|
import { PureTableBar } from "@/components/RePureTableBar";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
|
|
||||||
@ -10,14 +10,17 @@ import Refresh from "@iconify-icons/ep/refresh";
|
|||||||
import { useUserStoreHook } from "@/store/modules/user";
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
// TODO 这个导入声明好长 看看如何优化
|
// TODO 这个导入声明好长 看看如何优化
|
||||||
import { CommonUtils } from "@/utils/common";
|
import { CommonUtils } from "@/utils/common";
|
||||||
|
import PostFormModal from "@/views/system/post/post-form-modal.vue";
|
||||||
|
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||||
|
import { PostPageResponse } from "@/api/system/post";
|
||||||
|
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||||
|
|
||||||
/** 组件name最好和菜单表中的router_name一致 */
|
/** 组件name最好和菜单表中的router_name一致 */
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "SystemOperationLog"
|
name: "Post"
|
||||||
});
|
});
|
||||||
|
|
||||||
const loginLogStatusList =
|
const loginLogStatusList = useUserStoreHook().dictionaryList["common.status"];
|
||||||
useUserStoreHook().dictionaryList["sysLoginLog.status"];
|
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
|
||||||
@ -33,11 +36,21 @@ const {
|
|||||||
multipleSelection,
|
multipleSelection,
|
||||||
onSearch,
|
onSearch,
|
||||||
resetForm,
|
resetForm,
|
||||||
|
onSortChanged,
|
||||||
exportAllExcel,
|
exportAllExcel,
|
||||||
getLoginLogList,
|
getPostList,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handleBulkDelete
|
handleBulkDelete
|
||||||
} = useLoginLogHook();
|
} = usePostHook();
|
||||||
|
|
||||||
|
const opType = ref<"add" | "update">("add");
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const opRow = ref<PostPageResponse>();
|
||||||
|
function openDialog(type: "add" | "update", row?: PostPageResponse) {
|
||||||
|
opType.value = type;
|
||||||
|
opRow.value = row;
|
||||||
|
modalVisible.value = true;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -49,18 +62,18 @@ const {
|
|||||||
:model="searchFormParams"
|
:model="searchFormParams"
|
||||||
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]"
|
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]"
|
||||||
>
|
>
|
||||||
<el-form-item label="登录IP:" prop="ipAddress">
|
<el-form-item label="岗位编码" prop="postCode">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="searchFormParams.ipAddress"
|
v-model="searchFormParams.postCode"
|
||||||
placeholder="请输入IP地址"
|
placeholder="请输入岗位编码"
|
||||||
clearable
|
clearable
|
||||||
class="!w-[200px]"
|
class="!w-[200px]"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="用户名:" prop="username">
|
<el-form-item label="岗位名称" prop="postName">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="searchFormParams.username"
|
v-model="searchFormParams.postName"
|
||||||
placeholder="请选择用户名称"
|
placeholder="请选择岗位名称"
|
||||||
clearable
|
clearable
|
||||||
class="!w-[200px]"
|
class="!w-[200px]"
|
||||||
/>
|
/>
|
||||||
@ -81,11 +94,7 @@ const {
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item label="创建时间">
|
||||||
<label class="el-form-item__label is-required font-bold"
|
|
||||||
>登录时间:</label
|
|
||||||
>
|
|
||||||
<!-- TODO 如何消除这个v-model的warning -->
|
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
class="!w-[240px]"
|
class="!w-[240px]"
|
||||||
v-model="timeRange"
|
v-model="timeRange"
|
||||||
@ -115,9 +124,16 @@ const {
|
|||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<!-- table bar 包裹 table -->
|
<!-- table bar 包裹 table -->
|
||||||
<PureTableBar title="登录日志列表" :columns="columns" @refresh="onSearch">
|
<PureTableBar title="岗位列表" :columns="columns" @refresh="onSearch">
|
||||||
<!-- 表格操作栏 -->
|
<!-- 表格操作栏 -->
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:icon="useRenderIcon(AddFill)"
|
||||||
|
@click="openDialog('add')"
|
||||||
|
>
|
||||||
|
新增岗位
|
||||||
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="danger"
|
type="danger"
|
||||||
:icon="useRenderIcon(Delete)"
|
:icon="useRenderIcon(Delete)"
|
||||||
@ -127,7 +143,7 @@ const {
|
|||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="CommonUtils.exportExcel(columns, dataList, '登录日志列表')"
|
@click="CommonUtils.exportExcel(columns, dataList, '岗位列表')"
|
||||||
>单页导出</el-button
|
>单页导出</el-button
|
||||||
>
|
>
|
||||||
<el-button type="primary" @click="exportAllExcel">全部导出</el-button>
|
<el-button type="primary" @click="exportAllExcel">全部导出</el-button>
|
||||||
@ -151,16 +167,26 @@ const {
|
|||||||
background: 'var(--el-table-row-hover-bg-color)',
|
background: 'var(--el-table-row-hover-bg-color)',
|
||||||
color: 'var(--el-text-color-primary)'
|
color: 'var(--el-text-color-primary)'
|
||||||
}"
|
}"
|
||||||
@page-size-change="getLoginLogList"
|
@page-size-change="getPostList"
|
||||||
@page-current-change="getLoginLogList"
|
@page-current-change="getPostList"
|
||||||
@sort-change="getLoginLogList"
|
@sort-change="onSortChanged"
|
||||||
@selection-change="
|
@selection-change="
|
||||||
rows => (multipleSelection = rows.map(item => item.logId))
|
rows => (multipleSelection = rows.map(item => item.postId))
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
|
<el-button
|
||||||
|
class="reset-margin"
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
:size="size"
|
||||||
|
:icon="useRenderIcon(EditPen)"
|
||||||
|
@click="openDialog('update', row)"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
<el-popconfirm
|
<el-popconfirm
|
||||||
:title="`是否确认删除编号为${row.logId}的这条日志`"
|
:title="`是否确认删除编号为${row.postId}的这个岗位`"
|
||||||
@confirm="handleDelete(row)"
|
@confirm="handleDelete(row)"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
@ -179,6 +205,13 @@ const {
|
|||||||
</pure-table>
|
</pure-table>
|
||||||
</template>
|
</template>
|
||||||
</PureTableBar>
|
</PureTableBar>
|
||||||
|
|
||||||
|
<post-form-modal
|
||||||
|
v-model="modalVisible"
|
||||||
|
:type="opType"
|
||||||
|
:row="opRow"
|
||||||
|
@success="onSearch"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
131
src/views/system/post/post-form-modal.vue
Normal file
131
src/views/system/post/post-form-modal.vue
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import VDialog from "@/components/VDialog/VDialog.vue";
|
||||||
|
import { computed, reactive, ref } from "vue";
|
||||||
|
import {
|
||||||
|
AddPostCommand,
|
||||||
|
PostPageResponse,
|
||||||
|
UpdatePostCommand,
|
||||||
|
addPostApi,
|
||||||
|
updatePostApi
|
||||||
|
} from "@/api/system/post";
|
||||||
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
|
import { ElMessage, FormInstance, FormRules } from "element-plus";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
type: "add" | "update";
|
||||||
|
modelValue: boolean;
|
||||||
|
row?: PostPageResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: "update:modelValue", v: boolean): void;
|
||||||
|
(e: "success"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const visible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set(v) {
|
||||||
|
emits("update:modelValue", v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const formData = reactive<AddPostCommand | UpdatePostCommand>({
|
||||||
|
postId: 0,
|
||||||
|
postCode: "",
|
||||||
|
postName: "",
|
||||||
|
postSort: 1,
|
||||||
|
remark: "",
|
||||||
|
status: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
const statusList = useUserStoreHook().dictionaryMap["common.status"];
|
||||||
|
|
||||||
|
const rules: FormRules = {
|
||||||
|
postName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "岗位名称不能为空"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
postCode: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "岗位编码不能为空"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
postSort: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "岗位序号不能为空"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
function handleOpened() {
|
||||||
|
if (props.row) {
|
||||||
|
Object.assign(formData, props.row);
|
||||||
|
} else {
|
||||||
|
formRef.value?.resetFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
async function handleConfirm() {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
if (props.type === "add") {
|
||||||
|
await addPostApi(formData);
|
||||||
|
} else if (props.type === "update") {
|
||||||
|
await updatePostApi(formData as UpdatePostCommand);
|
||||||
|
}
|
||||||
|
ElMessage.info("提交成功");
|
||||||
|
visible.value = false;
|
||||||
|
emits("success");
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
ElMessage.error((e as Error)?.message || "提交失败");
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-dialog
|
||||||
|
show-full-screen
|
||||||
|
:fixed-body-height="false"
|
||||||
|
use-body-scrolling
|
||||||
|
:title="type === 'add' ? '新增岗位' : '更新岗位'"
|
||||||
|
v-model="visible"
|
||||||
|
:loading="loading"
|
||||||
|
@confirm="handleConfirm"
|
||||||
|
@cancel="visible = false"
|
||||||
|
@opened="handleOpened"
|
||||||
|
>
|
||||||
|
<el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
|
||||||
|
<el-form-item prop="postName" label="岗位名称" required inline-message>
|
||||||
|
<el-input v-model="formData.postName" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="postCode" label="岗位编码" required>
|
||||||
|
<el-input v-model="formData.postCode" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="postSort" label="岗位顺序" required>
|
||||||
|
<el-input-number :min="1" v-model="formData.postSort" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="status" label="岗位状态">
|
||||||
|
<el-radio-group v-model="formData.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="item in Object.keys(statusList)"
|
||||||
|
:key="item"
|
||||||
|
:label="statusList[item].value"
|
||||||
|
>{{ statusList[item].label }}</el-radio
|
||||||
|
>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="remark" label="备注" style="margin-bottom: 0">
|
||||||
|
<el-input type="textarea" v-model="formData.remark" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
@ -1,23 +1,22 @@
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { ElMessageBox, Sort } from "element-plus";
|
import { ElMessageBox, Sort } from "element-plus";
|
||||||
import {
|
import { reactive, ref, onMounted, toRaw, computed } from "vue";
|
||||||
getLoginLogListApi,
|
|
||||||
deleteLoginLogApi,
|
|
||||||
exportLoginLogExcelApi,
|
|
||||||
LoginLogQuery
|
|
||||||
} from "@/api/system/log";
|
|
||||||
import { reactive, ref, onMounted, toRaw } from "vue";
|
|
||||||
import { useUserStoreHook } from "@/store/modules/user";
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
import { CommonUtils } from "@/utils/common";
|
import { CommonUtils } from "@/utils/common";
|
||||||
import { PaginationProps } from "@pureadmin/table";
|
import { PaginationProps } from "@pureadmin/table";
|
||||||
|
import {
|
||||||
|
PostListCommand,
|
||||||
|
getPostListApi,
|
||||||
|
exportPostExcelApi,
|
||||||
|
deletePostApi
|
||||||
|
} from "@/api/system/post";
|
||||||
|
|
||||||
const loginLogStatusMap =
|
const statusMap = useUserStoreHook().dictionaryMap["common.status"];
|
||||||
useUserStoreHook().dictionaryMap["sysLoginLog.status"];
|
|
||||||
|
|
||||||
export function useLoginLogHook() {
|
export function usePostHook() {
|
||||||
const defaultSort: Sort = {
|
const defaultSort: Sort = {
|
||||||
prop: "loginTime",
|
prop: "createTime",
|
||||||
order: "descending"
|
order: "descending"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,20 +27,35 @@ export function useLoginLogHook() {
|
|||||||
background: true
|
background: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const timeRange = ref([]);
|
const timeRange = computed<[string, string] | null>({
|
||||||
|
get() {
|
||||||
|
if (searchFormParams.beginTime && searchFormParams.endTime) {
|
||||||
|
return [searchFormParams.beginTime, searchFormParams.endTime];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
if (v?.length === 2) {
|
||||||
|
searchFormParams.beginTime = v[0];
|
||||||
|
searchFormParams.endTime = v[1];
|
||||||
|
} else {
|
||||||
|
searchFormParams.beginTime = undefined;
|
||||||
|
searchFormParams.endTime = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const searchFormParams = reactive<LoginLogQuery>({
|
const searchFormParams = reactive<PostListCommand>({
|
||||||
ipAddress: undefined,
|
postCode: "",
|
||||||
username: undefined,
|
postName: "",
|
||||||
status: undefined,
|
status: undefined
|
||||||
beginTime: undefined,
|
|
||||||
endTime: undefined,
|
|
||||||
timeRangeColumn: defaultSort.prop
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const dataList = ref([]);
|
const dataList = ref([]);
|
||||||
const pageLoading = ref(true);
|
const pageLoading = ref(true);
|
||||||
const multipleSelection = ref([]);
|
const multipleSelection = ref([]);
|
||||||
|
const sortState = ref<Sort>(defaultSort);
|
||||||
|
|
||||||
const columns: TableColumnList = [
|
const columns: TableColumnList = [
|
||||||
{
|
{
|
||||||
@ -49,34 +63,23 @@ export function useLoginLogHook() {
|
|||||||
align: "left"
|
align: "left"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "日志编号",
|
label: "岗位编号",
|
||||||
prop: "logId",
|
prop: "postId",
|
||||||
minWidth: 100
|
minWidth: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "用户名",
|
label: "岗位编码",
|
||||||
prop: "username",
|
prop: "postCode",
|
||||||
minWidth: 120,
|
|
||||||
sortable: "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "IP地址",
|
|
||||||
prop: "ipAddress",
|
|
||||||
minWidth: 120
|
minWidth: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "登录地点",
|
label: "岗位名称",
|
||||||
prop: "loginLocation",
|
prop: "postName",
|
||||||
minWidth: 120
|
minWidth: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "操作系统",
|
label: "岗位排序",
|
||||||
prop: "operationSystem",
|
prop: "postSort",
|
||||||
minWidth: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "浏览器",
|
|
||||||
prop: "browser",
|
|
||||||
minWidth: 120
|
minWidth: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -86,26 +89,20 @@ export function useLoginLogHook() {
|
|||||||
cellRenderer: ({ row, props }) => (
|
cellRenderer: ({ row, props }) => (
|
||||||
<el-tag
|
<el-tag
|
||||||
size={props.size}
|
size={props.size}
|
||||||
type={loginLogStatusMap[row.status].cssTag}
|
type={statusMap[row.status].cssTag}
|
||||||
effect="plain"
|
effect="plain"
|
||||||
>
|
>
|
||||||
{loginLogStatusMap[row.status].label}
|
{statusMap[row.status].label}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "状态名",
|
label: "创建时间",
|
||||||
prop: "statusStr",
|
|
||||||
minWidth: 120,
|
|
||||||
hide: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "登录时间",
|
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
prop: "loginTime",
|
prop: "createTime",
|
||||||
sortable: "custom",
|
sortable: "custom",
|
||||||
formatter: ({ loginTime }) =>
|
formatter: ({ createTime }) =>
|
||||||
dayjs(loginTime).format("YYYY-MM-DD HH:mm:ss")
|
dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "操作",
|
label: "操作",
|
||||||
@ -115,10 +112,15 @@ export function useLoginLogHook() {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function onSortChanged(sort: Sort) {
|
||||||
|
sortState.value = sort;
|
||||||
|
onSearch();
|
||||||
|
}
|
||||||
|
|
||||||
async function onSearch() {
|
async function onSearch() {
|
||||||
// 点击搜索的时候 需要重置分页
|
// 点击搜索的时候 需要重置分页
|
||||||
pagination.currentPage = 1;
|
pagination.currentPage = 1;
|
||||||
getLoginLogList();
|
getPostList();
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetForm(formEl, tableRef) {
|
function resetForm(formEl, tableRef) {
|
||||||
@ -130,7 +132,6 @@ export function useLoginLogHook() {
|
|||||||
searchFormParams.orderDirection = undefined;
|
searchFormParams.orderDirection = undefined;
|
||||||
// 清空时间查询 TODO 这块有点繁琐 有可以优化的地方吗?
|
// 清空时间查询 TODO 这块有点繁琐 有可以优化的地方吗?
|
||||||
// Form组件的resetFields方法无法清除datepicker里面的数据。
|
// Form组件的resetFields方法无法清除datepicker里面的数据。
|
||||||
timeRange.value = [];
|
|
||||||
searchFormParams.beginTime = undefined;
|
searchFormParams.beginTime = undefined;
|
||||||
searchFormParams.endTime = undefined;
|
searchFormParams.endTime = undefined;
|
||||||
tableRef.getTableRef().clearSort();
|
tableRef.getTableRef().clearSort();
|
||||||
@ -138,15 +139,14 @@ export function useLoginLogHook() {
|
|||||||
onSearch();
|
onSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getLoginLogList(sort: Sort = defaultSort) {
|
async function getPostList(sort: Sort = defaultSort) {
|
||||||
pageLoading.value = true;
|
pageLoading.value = true;
|
||||||
if (sort != null) {
|
if (sort != null) {
|
||||||
CommonUtils.fillSortParams(searchFormParams, sort);
|
CommonUtils.fillSortParams(searchFormParams, sort);
|
||||||
}
|
}
|
||||||
CommonUtils.fillPaginationParams(searchFormParams, pagination);
|
CommonUtils.fillPaginationParams(searchFormParams, pagination);
|
||||||
CommonUtils.fillTimeRangeParams(searchFormParams, timeRange.value);
|
|
||||||
|
|
||||||
const { data } = await getLoginLogListApi(toRaw(searchFormParams)).finally(
|
const { data } = await getPostListApi(toRaw(searchFormParams)).finally(
|
||||||
() => {
|
() => {
|
||||||
pageLoading.value = false;
|
pageLoading.value = false;
|
||||||
}
|
}
|
||||||
@ -155,23 +155,23 @@ export function useLoginLogHook() {
|
|||||||
pagination.total = data.total;
|
pagination.total = data.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function exportAllExcel(sort: Sort = defaultSort) {
|
async function exportAllExcel() {
|
||||||
if (sort != null) {
|
if (sortState.value != null) {
|
||||||
CommonUtils.fillSortParams(searchFormParams, sort);
|
CommonUtils.fillSortParams(searchFormParams, sortState.value);
|
||||||
}
|
}
|
||||||
CommonUtils.fillPaginationParams(searchFormParams, pagination);
|
CommonUtils.fillPaginationParams(searchFormParams, pagination);
|
||||||
CommonUtils.fillTimeRangeParams(searchFormParams, timeRange.value);
|
CommonUtils.fillTimeRangeParams(searchFormParams, timeRange.value);
|
||||||
|
|
||||||
exportLoginLogExcelApi(toRaw(searchFormParams), "登录日志.xls");
|
exportPostExcelApi(toRaw(searchFormParams), "岗位数据.xls");
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDelete(row) {
|
async function handleDelete(row) {
|
||||||
await deleteLoginLogApi([row.logId]).then(() => {
|
await deletePostApi([row.logId]).then(() => {
|
||||||
message(`您删除了操作编号为${row.logId}的这条数据`, {
|
message(`您删除了操作编号为${row.logId}的这条数据`, {
|
||||||
type: "success"
|
type: "success"
|
||||||
});
|
});
|
||||||
// 刷新列表
|
// 刷新列表
|
||||||
getLoginLogList();
|
getPostList();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,12 +193,12 @@ export function useLoginLogHook() {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
await deleteLoginLogApi(multipleSelection.value).then(() => {
|
await deletePostApi(multipleSelection.value).then(() => {
|
||||||
message(`您删除了日志编号为[ ${multipleSelection.value} ]的数据`, {
|
message(`您删除了日志编号为[ ${multipleSelection.value} ]的数据`, {
|
||||||
type: "success"
|
type: "success"
|
||||||
});
|
});
|
||||||
// 刷新列表
|
// 刷新列表
|
||||||
getLoginLogList();
|
getPostList();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@ -210,9 +210,7 @@ export function useLoginLogHook() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(getPostList);
|
||||||
getLoginLogList();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
searchFormParams,
|
searchFormParams,
|
||||||
@ -224,9 +222,10 @@ export function useLoginLogHook() {
|
|||||||
timeRange,
|
timeRange,
|
||||||
multipleSelection,
|
multipleSelection,
|
||||||
onSearch,
|
onSearch,
|
||||||
|
onSortChanged,
|
||||||
exportAllExcel,
|
exportAllExcel,
|
||||||
// exportExcel,
|
// exportExcel,
|
||||||
getLoginLogList,
|
getPostList,
|
||||||
resetForm,
|
resetForm,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handleBulkDelete
|
handleBulkDelete
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { formRules } from "./utils/rule";
|
|
||||||
import { FormProps } from "./utils/types";
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<FormProps>(), {
|
|
||||||
formInline: () => ({
|
|
||||||
name: "",
|
|
||||||
code: "",
|
|
||||||
remark: ""
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const ruleFormRef = ref();
|
|
||||||
const newFormInline = ref(props.formInline);
|
|
||||||
|
|
||||||
function getRef() {
|
|
||||||
return ruleFormRef.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ getRef });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<el-form
|
|
||||||
ref="ruleFormRef"
|
|
||||||
:model="newFormInline"
|
|
||||||
:rules="formRules"
|
|
||||||
label-width="82px"
|
|
||||||
>
|
|
||||||
<el-form-item label="角色名称" prop="name">
|
|
||||||
<el-input
|
|
||||||
v-model="newFormInline.name"
|
|
||||||
clearable
|
|
||||||
placeholder="请输入角色名称"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="角色标识" prop="code">
|
|
||||||
<el-input
|
|
||||||
v-model="newFormInline.code"
|
|
||||||
clearable
|
|
||||||
placeholder="请输入角色标识"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="备注">
|
|
||||||
<el-input
|
|
||||||
v-model="newFormInline.remark"
|
|
||||||
placeholder="请输入备注信息"
|
|
||||||
type="textarea"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</template>
|
|
@ -4,17 +4,17 @@ import { useRole } from "./utils/hook";
|
|||||||
import { PureTableBar } from "@/components/RePureTableBar";
|
import { PureTableBar } from "@/components/RePureTableBar";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
|
|
||||||
// import Database from "@iconify-icons/ri/database-2-line";
|
|
||||||
// import More from "@iconify-icons/ep/more-filled";
|
|
||||||
import Delete from "@iconify-icons/ep/delete";
|
import Delete from "@iconify-icons/ep/delete";
|
||||||
import EditPen from "@iconify-icons/ep/edit-pen";
|
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||||
import Search from "@iconify-icons/ep/search";
|
import Search from "@iconify-icons/ep/search";
|
||||||
import Refresh from "@iconify-icons/ep/refresh";
|
import Refresh from "@iconify-icons/ep/refresh";
|
||||||
import Menu from "@iconify-icons/ep/menu";
|
|
||||||
import AddFill from "@iconify-icons/ri/add-circle-line";
|
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||||
|
import { getRoleInfoApi, RoleDTO } from "@/api/system/role";
|
||||||
|
import RoleFormModal from "@/views/system/role/role-form-modal.vue";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "Role"
|
name: "SystemRole"
|
||||||
});
|
});
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
@ -24,19 +24,34 @@ const {
|
|||||||
columns,
|
columns,
|
||||||
dataList,
|
dataList,
|
||||||
pagination,
|
pagination,
|
||||||
// buttonClass,
|
|
||||||
onSearch,
|
onSearch,
|
||||||
resetForm,
|
resetForm,
|
||||||
openDialog,
|
menuTree,
|
||||||
handleMenu,
|
getMenuTree,
|
||||||
handleDelete,
|
handleDelete
|
||||||
// handleDatabase,
|
|
||||||
handleSizeChange,
|
|
||||||
handleCurrentChange,
|
|
||||||
handleSelectionChange
|
|
||||||
} = useRole();
|
} = useRole();
|
||||||
</script>
|
|
||||||
|
|
||||||
|
const opType = ref<"add" | "update">("add");
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const opRow = ref<RoleDTO>();
|
||||||
|
async function openDialog(type: "add" | "update", row?: RoleDTO) {
|
||||||
|
debugger;
|
||||||
|
try {
|
||||||
|
await getMenuTree();
|
||||||
|
if (row) {
|
||||||
|
const { data } = await getRoleInfoApi(row.roleId);
|
||||||
|
row.selectedMenuList = data.selectedMenuList;
|
||||||
|
row.selectedDeptList = data.selectedDeptList;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
ElMessage.error((e as Error)?.message || "加载菜单失败");
|
||||||
|
}
|
||||||
|
opType.value = type;
|
||||||
|
opRow.value = row;
|
||||||
|
modalVisible.value = true;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<el-form
|
<el-form
|
||||||
@ -47,7 +62,7 @@ const {
|
|||||||
>
|
>
|
||||||
<el-form-item label="角色名称:" prop="name">
|
<el-form-item label="角色名称:" prop="name">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.name"
|
v-model="form.roleName"
|
||||||
placeholder="请输入角色名称"
|
placeholder="请输入角色名称"
|
||||||
clearable
|
clearable
|
||||||
class="!w-[200px]"
|
class="!w-[200px]"
|
||||||
@ -55,7 +70,7 @@ const {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色标识:" prop="code">
|
<el-form-item label="角色标识:" prop="code">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.code"
|
v-model="form.roleKey"
|
||||||
placeholder="请输入角色标识"
|
placeholder="请输入角色标识"
|
||||||
clearable
|
clearable
|
||||||
class="!w-[180px]"
|
class="!w-[180px]"
|
||||||
@ -96,7 +111,7 @@ const {
|
|||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
:icon="useRenderIcon(AddFill)"
|
:icon="useRenderIcon(AddFill)"
|
||||||
@click="openDialog()"
|
@click="openDialog('add')"
|
||||||
>
|
>
|
||||||
新增角色
|
新增角色
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -129,22 +144,12 @@ const {
|
|||||||
type="primary"
|
type="primary"
|
||||||
:size="size"
|
:size="size"
|
||||||
:icon="useRenderIcon(EditPen)"
|
:icon="useRenderIcon(EditPen)"
|
||||||
@click="openDialog('编辑', row)"
|
@click="openDialog('update', row)"
|
||||||
>
|
>
|
||||||
修改
|
修改
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
|
||||||
class="reset-margin"
|
|
||||||
link
|
|
||||||
type="primary"
|
|
||||||
:size="size"
|
|
||||||
:icon="useRenderIcon(Menu)"
|
|
||||||
@click="handleMenu"
|
|
||||||
>
|
|
||||||
菜单权限
|
|
||||||
</el-button>
|
|
||||||
<el-popconfirm
|
<el-popconfirm
|
||||||
:title="`是否确认删除角色名称为${row.name}的这条数据`"
|
:title="`是否确认删除角色名称为${row.roleName}的这条数据`"
|
||||||
@confirm="handleDelete(row)"
|
@confirm="handleDelete(row)"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
@ -200,6 +205,13 @@ const {
|
|||||||
</pure-table>
|
</pure-table>
|
||||||
</template>
|
</template>
|
||||||
</PureTableBar>
|
</PureTableBar>
|
||||||
|
|
||||||
|
<role-form-modal
|
||||||
|
v-model="modalVisible"
|
||||||
|
:type="opType"
|
||||||
|
:row="opRow"
|
||||||
|
:menu-options="menuTree"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
158
src/views/system/role/role-form-modal.vue
Normal file
158
src/views/system/role/role-form-modal.vue
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import VDialog from "@/components/VDialog/VDialog.vue";
|
||||||
|
import { computed, reactive, ref } from "vue";
|
||||||
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
|
import { ElMessage, FormInstance, FormRules } from "element-plus";
|
||||||
|
import {
|
||||||
|
AddRoleCommand,
|
||||||
|
RoleDTO,
|
||||||
|
UpdateRoleCommand,
|
||||||
|
addRoleApi,
|
||||||
|
updateRoleApi
|
||||||
|
} from "@/api/system/role";
|
||||||
|
import { MenuDTO } from "@/api/system/menu";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
type: "add" | "update";
|
||||||
|
modelValue: boolean;
|
||||||
|
row?: RoleDTO;
|
||||||
|
menuOptions: MenuDTO[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: "update:modelValue", v: boolean): void;
|
||||||
|
(e: "success"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const visible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set(v) {
|
||||||
|
emits("update:modelValue", v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const formData = reactive<AddRoleCommand | UpdateRoleCommand>({
|
||||||
|
roleId: 0,
|
||||||
|
dataScope: "",
|
||||||
|
menuIds: [],
|
||||||
|
remark: "",
|
||||||
|
roleKey: "",
|
||||||
|
roleName: "",
|
||||||
|
roleSort: 1,
|
||||||
|
status: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
const statusList = useUserStoreHook().dictionaryMap["common.status"];
|
||||||
|
|
||||||
|
const rules: FormRules = {
|
||||||
|
roleName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "角色名称不能为空"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roleKey: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "权限标识不能为空"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roleSort: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "角色序号不能为空"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
function handleOpened() {
|
||||||
|
console.log("opened", props.row);
|
||||||
|
if (props.row) {
|
||||||
|
Object.assign(formData, props.row);
|
||||||
|
formData.menuIds = props.row.selectedMenuList;
|
||||||
|
} else {
|
||||||
|
formRef.value?.resetFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const treeRef = ref<InstanceType<typeof ElTree>>();
|
||||||
|
function handleCheckChange() {
|
||||||
|
formData.menuIds = treeRef.value.getCheckedKeys(false) as number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
async function handleConfirm() {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
if (props.type === "add") {
|
||||||
|
await addRoleApi(formData);
|
||||||
|
} else if (props.type === "update") {
|
||||||
|
await updateRoleApi(formData as UpdateRoleCommand);
|
||||||
|
}
|
||||||
|
ElMessage.info("提交成功");
|
||||||
|
visible.value = false;
|
||||||
|
emits("success");
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
ElMessage.error((e as Error)?.message || "提交失败");
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-dialog
|
||||||
|
show-full-screen
|
||||||
|
fixed-body-height
|
||||||
|
use-body-scrolling
|
||||||
|
:title="type === 'add' ? '新增角色' : '更新角色'"
|
||||||
|
v-model="visible"
|
||||||
|
:loading="loading"
|
||||||
|
@confirm="handleConfirm"
|
||||||
|
@cancel="visible = false"
|
||||||
|
@opened="handleOpened"
|
||||||
|
>
|
||||||
|
<el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
|
||||||
|
<el-form-item prop="roleName" label="角色名称" required inline-message>
|
||||||
|
<el-input v-model="formData.roleName" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="roleKey" label="权限字符" required>
|
||||||
|
<el-input v-model="formData.roleKey" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="roleSort" label="角色顺序" required>
|
||||||
|
<el-input-number :min="1" v-model="formData.roleSort" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="status" label="角色状态">
|
||||||
|
<el-radio-group v-model="formData.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="item in Object.keys(statusList)"
|
||||||
|
:key="item"
|
||||||
|
:label="statusList[item].value"
|
||||||
|
>{{ statusList[item].label }}</el-radio
|
||||||
|
>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="菜单权限" prop="menuIds">
|
||||||
|
<el-tree
|
||||||
|
ref="treeRef"
|
||||||
|
:props="{ label: 'menuName', children: 'children' }"
|
||||||
|
:data="props.menuOptions"
|
||||||
|
node-key="id"
|
||||||
|
check-strictly
|
||||||
|
show-checkbox
|
||||||
|
default-expand-all
|
||||||
|
check-on-click-node
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
:default-checked-keys="formData.menuIds"
|
||||||
|
@check-change="handleCheckChange"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="remark" label="备注" style="margin-bottom: 0">
|
||||||
|
<el-input type="textarea" v-model="formData.remark" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
@ -1,21 +1,24 @@
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import editForm from "../form.vue";
|
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { getRoleList } from "@/api/system";
|
import {
|
||||||
import { ElMessageBox } from "element-plus";
|
deleteRoleApi,
|
||||||
|
getRoleListApi,
|
||||||
|
RoleDTO,
|
||||||
|
RoleQuery
|
||||||
|
} from "@/api/system/role";
|
||||||
|
import { getMenuListApi, MenuDTO } from "@/api/system/menu";
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { usePublicHooks } from "../../hooks";
|
import { usePublicHooks } from "../../hooks";
|
||||||
import { addDialog } from "@/components/ReDialog";
|
|
||||||
import { type FormItemProps } from "../utils/types";
|
|
||||||
import { type PaginationProps } from "@pureadmin/table";
|
import { type PaginationProps } from "@pureadmin/table";
|
||||||
import { reactive, ref, onMounted, h, toRaw } from "vue";
|
import { reactive, ref, onMounted, toRaw } from "vue";
|
||||||
|
import { toTree } from "@/utils/tree";
|
||||||
|
|
||||||
export function useRole() {
|
export function useRole() {
|
||||||
const form = reactive({
|
const form = reactive<RoleQuery>({
|
||||||
name: "",
|
roleKey: "",
|
||||||
code: "",
|
roleName: "",
|
||||||
status: ""
|
status: undefined
|
||||||
});
|
});
|
||||||
const formRef = ref();
|
|
||||||
const dataList = ref([]);
|
const dataList = ref([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const switchLoadMap = ref({});
|
const switchLoadMap = ref({});
|
||||||
@ -29,17 +32,17 @@ export function useRole() {
|
|||||||
const columns: TableColumnList = [
|
const columns: TableColumnList = [
|
||||||
{
|
{
|
||||||
label: "角色编号",
|
label: "角色编号",
|
||||||
prop: "id",
|
prop: "roleId",
|
||||||
minWidth: 100
|
minWidth: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "角色名称",
|
label: "角色名称",
|
||||||
prop: "name",
|
prop: "roleName",
|
||||||
minWidth: 120
|
minWidth: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "角色标识",
|
label: "角色标识",
|
||||||
prop: "code",
|
prop: "roleKey",
|
||||||
minWidth: 150
|
minWidth: 150
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -131,34 +134,33 @@ export function useRole() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDelete(row) {
|
async function handleDelete(row: RoleDTO) {
|
||||||
message(`您删除了角色名称为${row.name}的这条数据`, { type: "success" });
|
try {
|
||||||
onSearch();
|
loading.value = true;
|
||||||
}
|
await deleteRoleApi(row.roleId);
|
||||||
|
message(`您删除了角色名称为${row.roleName}的这条数据`, { type: "info" });
|
||||||
function handleSizeChange(val: number) {
|
onSearch();
|
||||||
console.log(`${val} items per page`);
|
} catch (e) {
|
||||||
}
|
console.error(e);
|
||||||
|
message((e as Error)?.message || "删除失败", { type: "error" });
|
||||||
function handleCurrentChange(val: number) {
|
} finally {
|
||||||
console.log(`current page: ${val}`);
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelectionChange(val) {
|
|
||||||
console.log("handleSelectionChange", val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSearch() {
|
async function onSearch() {
|
||||||
loading.value = true;
|
try {
|
||||||
const { data } = await getRoleList(toRaw(form));
|
loading.value = true;
|
||||||
dataList.value = data.list;
|
const { data } = await getRoleListApi(toRaw(form));
|
||||||
pagination.total = data.total;
|
console.log("role list", data);
|
||||||
pagination.pageSize = data.pageSize;
|
dataList.value = data.rows;
|
||||||
pagination.currentPage = data.currentPage;
|
pagination.total = data.total;
|
||||||
|
} catch (e) {
|
||||||
setTimeout(() => {
|
console.error(e);
|
||||||
|
ElMessage.error((e as Error)?.message || "加载失败");
|
||||||
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}, 500);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetForm = formEl => {
|
const resetForm = formEl => {
|
||||||
@ -167,59 +169,22 @@ export function useRole() {
|
|||||||
onSearch();
|
onSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
function openDialog(title = "新增", row?: FormItemProps) {
|
const menuTree = ref<MenuDTO[]>([]);
|
||||||
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 === "新增") {
|
|
||||||
// 实际开发先调用新增接口,再进行下面操作
|
|
||||||
chores();
|
|
||||||
} else {
|
|
||||||
// 实际开发先调用编辑接口,再进行下面操作
|
|
||||||
chores();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 菜单权限 */
|
/** 菜单权限 */
|
||||||
function handleMenu() {
|
async function getMenuTree() {
|
||||||
message("等菜单管理页面开发后完善");
|
if (menuTree.value?.length) {
|
||||||
|
return menuTree.value;
|
||||||
|
}
|
||||||
|
const { data } = await getMenuListApi({ isButton: false });
|
||||||
|
console.log("menu data", data);
|
||||||
|
menuTree.value = toTree(data, "id", "parentId");
|
||||||
|
return menuTree.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 数据权限 可自行开发 */
|
/** 数据权限 可自行开发 */
|
||||||
// function handleDatabase() {}
|
// function handleDatabase() {}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(onSearch);
|
||||||
onSearch();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
@ -227,15 +192,10 @@ export function useRole() {
|
|||||||
columns,
|
columns,
|
||||||
dataList,
|
dataList,
|
||||||
pagination,
|
pagination,
|
||||||
// buttonClass,
|
|
||||||
onSearch,
|
onSearch,
|
||||||
resetForm,
|
resetForm,
|
||||||
openDialog,
|
menuTree,
|
||||||
handleMenu,
|
getMenuTree,
|
||||||
handleDelete,
|
handleDelete
|
||||||
// handleDatabase,
|
|
||||||
handleSizeChange,
|
|
||||||
handleCurrentChange,
|
|
||||||
handleSelectionChange
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
import { reactive } from "vue";
|
|
||||||
import type { FormRules } from "element-plus";
|
|
||||||
|
|
||||||
/** 自定义表单规则校验 */
|
|
||||||
export const formRules = reactive(<FormRules>{
|
|
||||||
name: [{ required: true, message: "角色名称为必填项", trigger: "blur" }],
|
|
||||||
code: [{ required: true, message: "角色标识为必填项", trigger: "blur" }]
|
|
||||||
});
|
|
@ -1,15 +0,0 @@
|
|||||||
// 虽然字段很少 但是抽离出来 后续有扩展字段需求就很方便了
|
|
||||||
|
|
||||||
interface FormItemProps {
|
|
||||||
/** 角色名称 */
|
|
||||||
name: string;
|
|
||||||
/** 角色编号 */
|
|
||||||
code: string;
|
|
||||||
/** 备注 */
|
|
||||||
remark: string;
|
|
||||||
}
|
|
||||||
interface FormProps {
|
|
||||||
formInline: FormItemProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type { FormItemProps, FormProps };
|
|
Loading…
x
Reference in New Issue
Block a user