1.删除旧代码
This commit is contained in:
@@ -231,8 +231,7 @@ class RoleApiPermissionViewSet(CustomModelViewSet):
|
|||||||
"""
|
"""
|
||||||
params = request.query_params
|
params = request.query_params
|
||||||
is_superuser = request.user.is_superuser
|
is_superuser = request.user.is_superuser
|
||||||
is_admin = request.user.role.values_list('admin', flat=True)
|
if is_superuser:
|
||||||
if is_superuser or True in is_admin:
|
|
||||||
queryset = Dept.objects.values('id', 'name', 'parent')
|
queryset = Dept.objects.values('id', 'name', 'parent')
|
||||||
else:
|
else:
|
||||||
if not params:
|
if not params:
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ import { DictionaryStore } from '/@/stores/dictionary';
|
|||||||
/**
|
/**
|
||||||
* @method 获取指定name字典
|
* @method 获取指定name字典
|
||||||
*/
|
*/
|
||||||
export const dictionary = (key: string,value:string|number) => {
|
export const dictionary = (key: string,value:string|number|null=null) => {
|
||||||
const dict = DictionaryStore()
|
const dict = DictionaryStore()
|
||||||
const dictionary = toRaw(dict.data)
|
const dictionary = toRaw(dict.data)
|
||||||
if(value!==null || value !==''){
|
if(value!==null){
|
||||||
for (let item of dictionary[key]) {
|
for (let item of dictionary[key]) {
|
||||||
if (item.value === value) {
|
if (item.value === value) {
|
||||||
return item.label
|
return item.label
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ''
|
return []
|
||||||
}
|
}
|
||||||
return dictionary[key]
|
return dictionary[key]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
import { request } from '/@/utils/service';
|
|
||||||
import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
|
|
||||||
|
|
||||||
export const apiPrefix = '/api/system/menu_button/';
|
|
||||||
export function GetList(query: PageQuery) {
|
|
||||||
return request({
|
|
||||||
url: apiPrefix,
|
|
||||||
method: 'get',
|
|
||||||
params: query,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
export function GetObj(id: InfoReq) {
|
|
||||||
return request({
|
|
||||||
url: apiPrefix + id,
|
|
||||||
method: 'get',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function AddObj(obj: AddReq) {
|
|
||||||
return request({
|
|
||||||
url: apiPrefix,
|
|
||||||
method: 'post',
|
|
||||||
data: obj,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function UpdateObj(obj: any) {
|
|
||||||
return request({
|
|
||||||
url: apiPrefix + obj.id + '/',
|
|
||||||
method: 'put',
|
|
||||||
data: obj,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function DelObj(id: DelReq) {
|
|
||||||
return request({
|
|
||||||
url: apiPrefix + id + '/',
|
|
||||||
method: 'delete',
|
|
||||||
data: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
import { AddReq, DelReq, EditReq, dict, CreateCrudOptionsRet, CreateCrudOptionsProps } from '@fast-crud/fast-crud';
|
|
||||||
import * as api from './api';
|
|
||||||
|
|
||||||
import { request } from '/@/utils/service';
|
|
||||||
//此处为crudOptions配置
|
|
||||||
export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
|
||||||
const pageRequest = async () => {
|
|
||||||
if (context!.selectOptions.value.id) {
|
|
||||||
return await api.GetList({ menu: context!.selectOptions.value.id } as any);
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const editRequest = async ({ form, row }: EditReq) => {
|
|
||||||
return await api.UpdateObj({ ...form, menu: row.menu });
|
|
||||||
};
|
|
||||||
const delRequest = async ({ row }: DelReq) => {
|
|
||||||
return await api.DelObj(row.id);
|
|
||||||
};
|
|
||||||
const addRequest = async ({ form }: AddReq) => {
|
|
||||||
return await api.AddObj({ ...form, ...{ menu: context!.selectOptions.value.id } });
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
crudOptions: {
|
|
||||||
search: {
|
|
||||||
container: {
|
|
||||||
action: {
|
|
||||||
//按钮栏配置
|
|
||||||
col: {
|
|
||||||
span: 8,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rowHandle: {
|
|
||||||
//固定右侧
|
|
||||||
fixed: 'right',
|
|
||||||
width: 200,
|
|
||||||
buttons: {
|
|
||||||
view: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
edit: {
|
|
||||||
icon: '',
|
|
||||||
type: 'primary',
|
|
||||||
},
|
|
||||||
remove: {
|
|
||||||
icon: '',
|
|
||||||
type: 'primary',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
request: {
|
|
||||||
pageRequest,
|
|
||||||
addRequest,
|
|
||||||
editRequest,
|
|
||||||
delRequest,
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
col: { span: 24 },
|
|
||||||
labelWidth: '100px',
|
|
||||||
wrapper: {
|
|
||||||
is: 'el-dialog',
|
|
||||||
width: '600px',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
columns: {
|
|
||||||
_index: {
|
|
||||||
title: '序号',
|
|
||||||
form: { show: false },
|
|
||||||
column: {
|
|
||||||
type: 'index',
|
|
||||||
align: 'center',
|
|
||||||
width: '70px',
|
|
||||||
columnSetDisabled: true, //禁止在列设置中选择
|
|
||||||
},
|
|
||||||
},
|
|
||||||
search: {
|
|
||||||
title: '关键词',
|
|
||||||
column: { show: false },
|
|
||||||
type: 'text',
|
|
||||||
search: { show: true },
|
|
||||||
form: {
|
|
||||||
show: false,
|
|
||||||
component: {
|
|
||||||
placeholder: '输入关键词搜索',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
title: 'ID',
|
|
||||||
type: 'text',
|
|
||||||
column: { show: false },
|
|
||||||
search: { show: false },
|
|
||||||
form: { show: false },
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
title: '权限名称',
|
|
||||||
type: 'text',
|
|
||||||
search: { show: true },
|
|
||||||
column: {
|
|
||||||
minWidth: 120,
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
rules: [{ required: true, message: '权限名称必填' }],
|
|
||||||
component: {
|
|
||||||
placeholder: '输入权限名称搜索',
|
|
||||||
props: {
|
|
||||||
clearable: true,
|
|
||||||
allowCreate: true,
|
|
||||||
filterable: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
helper: {
|
|
||||||
render() {
|
|
||||||
return <el-alert title="手动输入" type="warning" description="页面中按钮的名称或者自定义一个名称" />;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
title: '权限值',
|
|
||||||
type: 'text',
|
|
||||||
search: { show: false },
|
|
||||||
column: {
|
|
||||||
width: 120,
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
rules: [{ required: true, message: '权限标识必填' }],
|
|
||||||
placeholder: '输入权限标识',
|
|
||||||
helper: {
|
|
||||||
render() {
|
|
||||||
return <el-alert title="唯一值" type="warning" description="用于判断前端按钮权限或接口权限" />;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
method: {
|
|
||||||
title: '请求方式',
|
|
||||||
search: { show: false },
|
|
||||||
type: 'dict-select',
|
|
||||||
column: {
|
|
||||||
width: 120,
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
dict: dict({
|
|
||||||
data: [
|
|
||||||
{ label: 'GET', value: 0 },
|
|
||||||
{ label: 'POST', value: 1, color: 'success' },
|
|
||||||
{ label: 'PUT', value: 2, color: 'warning' },
|
|
||||||
{ label: 'DELETE', value: 3, color: 'danger' },
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
form: {
|
|
||||||
rules: [{ required: true, message: '必填项' }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
api: {
|
|
||||||
title: '接口地址',
|
|
||||||
search: { show: false },
|
|
||||||
type: 'dict-select',
|
|
||||||
dict: dict({
|
|
||||||
getData() {
|
|
||||||
return request({ url: '/swagger.json' }).then((res: any) => {
|
|
||||||
const ret = Object.keys(res.paths);
|
|
||||||
const data = [];
|
|
||||||
for (const item of ret) {
|
|
||||||
const obj: any = {};
|
|
||||||
obj.label = item;
|
|
||||||
obj.value = item;
|
|
||||||
data.push(obj);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
column: {
|
|
||||||
minWidth: 250,
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
rules: [{ required: true, message: '必填项' }],
|
|
||||||
component: {
|
|
||||||
props: {
|
|
||||||
allowCreate: true,
|
|
||||||
filterable: true,
|
|
||||||
clearable: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
helper: {
|
|
||||||
render() {
|
|
||||||
return <el-alert title="请正确填写,以免请求时被拦截。匹配单例使用正则,例如:/api/xx/.*?/" type="warning" />;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<template>
|
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { useFs } from '@fast-crud/fast-crud';
|
|
||||||
import { createCrudOptions } from './crud';
|
|
||||||
import { MenuTreeItemType } from '../../types';
|
|
||||||
|
|
||||||
// 当前选择的菜单信息
|
|
||||||
let selectOptions: any = ref({ name: null });
|
|
||||||
|
|
||||||
const { crudRef, crudBinding, crudExpose, context } = useFs({ createCrudOptions, context: { selectOptions } });
|
|
||||||
const { doRefresh, setTableData } = crudExpose;
|
|
||||||
|
|
||||||
const handleRefreshTable = (record: MenuTreeItemType) => {
|
|
||||||
if (!record.is_catalog && record.id) {
|
|
||||||
selectOptions.value = record;
|
|
||||||
doRefresh();
|
|
||||||
} else {
|
|
||||||
//清空表格数据
|
|
||||||
setTableData([]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({ selectOptions, handleRefreshTable });
|
|
||||||
</script>
|
|
||||||
@@ -1,279 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="menu-form-com">
|
|
||||||
<div class="menu-form-alert">
|
|
||||||
1.红色星号表示必填;<br />
|
|
||||||
2.添加菜单,如果是目录,组件地址为空即可;<br />
|
|
||||||
3.添加根节点菜单,父级菜单为空即可;
|
|
||||||
</div>
|
|
||||||
<el-form ref="formRef" :rules="rules" :model="menuFormData" label-width="80px" label-position="right">
|
|
||||||
<el-form-item label="菜单名称" prop="name">
|
|
||||||
<el-input v-model="menuFormData.name" placeholder="请输入菜单名称" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="父级菜单" prop="parent">
|
|
||||||
<el-tree-select
|
|
||||||
v-model="menuFormData.parent"
|
|
||||||
:props="defaultTreeProps"
|
|
||||||
:data="deptDefaultList"
|
|
||||||
:cache-data="props.cacheData"
|
|
||||||
lazy
|
|
||||||
check-strictly
|
|
||||||
clearable
|
|
||||||
:load="handleTreeLoad"
|
|
||||||
placeholder="请选择父级菜单"
|
|
||||||
style="width: 100%"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="路由地址" prop="web_path">
|
|
||||||
<el-input v-model="menuFormData.web_path" placeholder="请输入路由地址,请以/开头" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="图标" prop="icon">
|
|
||||||
<IconSelector clearable v-model="menuFormData.icon" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item required label="状态">
|
|
||||||
<el-switch v-model="menuFormData.status" width="60" inline-prompt active-text="启用" inactive-text="禁用" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item v-if="menuFormData.status" required label="侧边显示">
|
|
||||||
<el-switch v-model="menuFormData.visible" width="60" inline-prompt active-text="显示" inactive-text="隐藏" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item required label="是否目录">
|
|
||||||
<el-switch v-model="menuFormData.is_catalog" width="60" inline-prompt active-text="是" inactive-text="否" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item v-if="!menuFormData.is_catalog" required label="外链接">
|
|
||||||
<el-switch v-model="menuFormData.is_link" width="60" inline-prompt active-text="是" inactive-text="否" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-form-item label="备注">
|
|
||||||
<el-input v-model="menuFormData.description" maxlength="200" show-word-limit type="textarea" placeholder="请输入备注" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-divider></el-divider>
|
|
||||||
|
|
||||||
<div style="min-height: 184px">
|
|
||||||
<el-form-item v-if="!menuFormData.is_catalog && !menuFormData.is_link" label="组件地址" prop="component">
|
|
||||||
<el-autocomplete
|
|
||||||
class="w-full"
|
|
||||||
v-model="menuFormData.component"
|
|
||||||
:fetch-suggestions="querySearch"
|
|
||||||
:trigger-on-focus="false"
|
|
||||||
clearable
|
|
||||||
:debounce="100"
|
|
||||||
placeholder="输入组件地址"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item v-if="!menuFormData.is_catalog && !menuFormData.is_link" label="组件名称" prop="component_name">
|
|
||||||
<el-input v-model="menuFormData.component_name" placeholder="请输入组件名称" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item v-if="!menuFormData.is_catalog && menuFormData.is_link" label="Url" prop="web_path">
|
|
||||||
<el-input v-model="menuFormData.web_path" placeholder="请输入Url" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item v-if="!menuFormData.is_catalog" label="缓存">
|
|
||||||
<el-switch v-model="menuFormData.cache" width="60" inline-prompt active-text="启用" inactive-text="禁用" />
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider></el-divider>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<div class="menu-form-btns">
|
|
||||||
<el-button @click="handleSubmit" type="primary" :loading="menuBtnLoading">保存</el-button>
|
|
||||||
<el-button @click="handleCancel">取消</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, onMounted, reactive } from 'vue';
|
|
||||||
import { ElForm, FormRules } from 'element-plus';
|
|
||||||
import IconSelector from '/@/components/iconSelector/index.vue';
|
|
||||||
import { lazyLoadMenu, AddObj, UpdateObj } from '../../api';
|
|
||||||
import { successNotification } from '/@/utils/message';
|
|
||||||
import { MenuFormDataType, MenuTreeItemType, ComponentFileItem, APIResponseData } from '../../types';
|
|
||||||
import type Node from 'element-plus/es/components/tree/src/model/node';
|
|
||||||
|
|
||||||
interface IProps {
|
|
||||||
initFormData: Partial<MenuTreeItemType> | null;
|
|
||||||
treeData: MenuTreeItemType[];
|
|
||||||
cacheData: MenuTreeItemType[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultTreeProps: any = {
|
|
||||||
children: 'children',
|
|
||||||
label: 'name',
|
|
||||||
value: 'id',
|
|
||||||
isLeaf: (data: MenuTreeItemType[], node: Node) => {
|
|
||||||
if (node?.data.hasChild) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const validateWebPath = (rule: any, value: string, callback: Function) => {
|
|
||||||
let pattern = /^\/.*?/;
|
|
||||||
let patternUrl = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
|
|
||||||
const reg = menuFormData.is_link ? patternUrl.test(value) : pattern.test(value);
|
|
||||||
if (reg) {
|
|
||||||
callback();
|
|
||||||
} else {
|
|
||||||
callback(new Error('请输入正确的地址'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<IProps>(), {
|
|
||||||
initFormData: () => null,
|
|
||||||
treeData: () => [],
|
|
||||||
cacheData: () => [],
|
|
||||||
});
|
|
||||||
const emit = defineEmits(['drawerClose']);
|
|
||||||
|
|
||||||
const formRef = ref<InstanceType<typeof ElForm>>();
|
|
||||||
|
|
||||||
const rules = reactive<FormRules>({
|
|
||||||
web_path: [{ required: true, message: '请输入正确的地址', validator: validateWebPath, trigger: 'blur' }],
|
|
||||||
name: [{ required: true, message: '菜单名称必填', trigger: 'blur' }],
|
|
||||||
component: [{ required: true, message: '请输入组件地址', trigger: 'blur' }],
|
|
||||||
component_name: [{ required: true, message: '请输入组件名称', trigger: 'blur' }],
|
|
||||||
});
|
|
||||||
|
|
||||||
let deptDefaultList = ref<MenuTreeItemType[]>([]);
|
|
||||||
let menuFormData = reactive<MenuFormDataType>({
|
|
||||||
parent: '',
|
|
||||||
name: '',
|
|
||||||
component: '',
|
|
||||||
web_path: '',
|
|
||||||
icon: '',
|
|
||||||
cache: true,
|
|
||||||
status: true,
|
|
||||||
visible: true,
|
|
||||||
component_name: '',
|
|
||||||
description: '',
|
|
||||||
is_catalog: false,
|
|
||||||
is_link: false,
|
|
||||||
});
|
|
||||||
let menuBtnLoading = ref(false);
|
|
||||||
|
|
||||||
const setMenuFormData = () => {
|
|
||||||
if (props.initFormData?.id) {
|
|
||||||
menuFormData.id = props.initFormData?.id || '';
|
|
||||||
menuFormData.name = props.initFormData?.name || '';
|
|
||||||
menuFormData.parent = props.initFormData?.parent || '';
|
|
||||||
menuFormData.component = props.initFormData?.component || '';
|
|
||||||
menuFormData.web_path = props.initFormData?.web_path || '';
|
|
||||||
menuFormData.icon = props.initFormData?.icon || '';
|
|
||||||
menuFormData.status = props.initFormData?.status || true;
|
|
||||||
menuFormData.visible = props.initFormData?.visible || true;
|
|
||||||
menuFormData.cache = props.initFormData?.cache || true;
|
|
||||||
menuFormData.component_name = props.initFormData?.component_name || '';
|
|
||||||
menuFormData.description = props.initFormData?.description || '';
|
|
||||||
menuFormData.is_catalog = props.initFormData?.is_catalog || false;
|
|
||||||
menuFormData.is_link = props.initFormData?.is_link || false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const querySearch = (queryString: string, cb: any) => {
|
|
||||||
const files: any = import.meta.glob('@views/**/*.vue');
|
|
||||||
let fileLists: Array<any> = [];
|
|
||||||
Object.keys(files).forEach((queryString: string) => {
|
|
||||||
fileLists.push({
|
|
||||||
label: queryString.replace(/(\.\/|\.vue)/g, ''),
|
|
||||||
value: queryString.replace(/(\.\/|\.vue)/g, ''),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const results = queryString ? fileLists.filter(createFilter(queryString)) : fileLists;
|
|
||||||
// 统一去掉/src/views/前缀
|
|
||||||
results.forEach((val) => {
|
|
||||||
val.label = val.label.replace('/src/views/', '');
|
|
||||||
val.value = val.value.replace('/src/views/', '');
|
|
||||||
});
|
|
||||||
cb(results);
|
|
||||||
};
|
|
||||||
|
|
||||||
const createFilter = (queryString: string) => {
|
|
||||||
return (file: ComponentFileItem) => {
|
|
||||||
return file.value.toLowerCase().indexOf(queryString.toLowerCase()) !== -1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 树的懒加载
|
|
||||||
*/
|
|
||||||
const handleTreeLoad = (node: Node, resolve: Function) => {
|
|
||||||
if (node.level !== 0) {
|
|
||||||
lazyLoadMenu({ parent: node.data.id }).then((res: APIResponseData) => {
|
|
||||||
resolve(res.data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
if (!formRef.value) return;
|
|
||||||
formRef.value.validate(async (valid) => {
|
|
||||||
if (!valid) return;
|
|
||||||
try {
|
|
||||||
let res;
|
|
||||||
menuBtnLoading.value = true;
|
|
||||||
if (menuFormData.id) {
|
|
||||||
res = await UpdateObj(menuFormData);
|
|
||||||
} else {
|
|
||||||
res = await AddObj(menuFormData);
|
|
||||||
}
|
|
||||||
if (res?.code === 2000) {
|
|
||||||
successNotification(res.msg as string);
|
|
||||||
handleCancel('submit');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
menuBtnLoading.value = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCancel = (type: string = '') => {
|
|
||||||
emit('drawerClose', type);
|
|
||||||
formRef.value?.resetFields();
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
props.treeData.map((item) => {
|
|
||||||
deptDefaultList.value.push(item);
|
|
||||||
});
|
|
||||||
setMenuFormData();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.menu-form-com {
|
|
||||||
margin: 10px;
|
|
||||||
overflow-y: auto;
|
|
||||||
.menu-form-alert {
|
|
||||||
color: #fff;
|
|
||||||
line-height: 24px;
|
|
||||||
padding: 8px 16px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
.menu-form-btns {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,318 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-input v-model="filterVal" :prefix-icon="Search" placeholder="请输入菜单名称" />
|
|
||||||
<div class="menu-tree-com">
|
|
||||||
<div class="mtc-head">
|
|
||||||
<el-icon size="16" color="#606266" class="mtc-head-icon">
|
|
||||||
<Menu />
|
|
||||||
</el-icon>
|
|
||||||
菜单列表
|
|
||||||
<el-tooltip
|
|
||||||
effect="dark"
|
|
||||||
placement="right"
|
|
||||||
content="1.红色菜单代表状态禁用; 2.添加菜单,如果是目录,组件地址为空即可; 3.添加根节点菜单,父级ID为空即可; 4.支持拖拽菜单;"
|
|
||||||
>
|
|
||||||
<el-icon size="16" color="var(--el-color-primary)" class="mtc-tooltip">
|
|
||||||
<QuestionFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-tree
|
|
||||||
ref="treeRef"
|
|
||||||
:data="treeData"
|
|
||||||
:props="defaultTreeProps"
|
|
||||||
:filter-node-method="filterNode"
|
|
||||||
:load="handleTreeLoad"
|
|
||||||
lazy
|
|
||||||
:indent="45"
|
|
||||||
@node-click="handleNodeClick"
|
|
||||||
highlight-current
|
|
||||||
>
|
|
||||||
<template #default="{ node, data }">
|
|
||||||
<element-tree-line :node="node" :showLabelLine="false" :indent="32">
|
|
||||||
<span v-if="data.status" class="text-center font-black font-normal">
|
|
||||||
<SvgIcon :name="node.data.icon" color="var(--el-color-primary)" />
|
|
||||||
{{ node.label }}
|
|
||||||
</span>
|
|
||||||
<span v-else class="text-center font-black text-red-700 font-normal"> <SvgIcon :name="node.data.icon" /> {{ node.label }} </span>
|
|
||||||
</element-tree-line>
|
|
||||||
</template>
|
|
||||||
</el-tree>
|
|
||||||
|
|
||||||
<div class="mtc-tags">
|
|
||||||
<el-tooltip effect="dark" content="新增">
|
|
||||||
<el-icon size="16" @click="handleUpdateMenu('create')" class="mtc-tags-icon">
|
|
||||||
<Plus />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
|
|
||||||
<el-tooltip effect="dark" content="编辑">
|
|
||||||
<el-icon size="16" @click="handleUpdateMenu('update')" class="mtc-tags-icon">
|
|
||||||
<Edit />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
|
|
||||||
<el-tooltip effect="dark" content="上移">
|
|
||||||
<el-icon size="16" @click="handleSort('up')" class="mtc-tags-icon">
|
|
||||||
<Top />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
|
|
||||||
<el-tooltip effect="dark" content="下移">
|
|
||||||
<el-icon size="16" @click="handleSort('down')" class="mtc-tags-icon">
|
|
||||||
<Bottom />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
|
|
||||||
<el-tooltip effect="dark" content="删除">
|
|
||||||
<el-icon size="16" @click="handleDeleteMenu()" class="mtc-tags-icon">
|
|
||||||
<Delete />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, toRaw, watch, h } from 'vue';
|
|
||||||
import { ElTree } from 'element-plus';
|
|
||||||
import { getElementLabelLine } from 'element-tree-line';
|
|
||||||
import { Search } from '@element-plus/icons-vue';
|
|
||||||
import SvgIcon from '/@/components/svgIcon/index.vue';
|
|
||||||
import { lazyLoadMenu, menuMoveUp, menuMoveDown } from '../../api';
|
|
||||||
import { warningNotification } from '/@/utils/message';
|
|
||||||
import { TreeTypes, MenuTreeItemType } from '../../types';
|
|
||||||
import type Node from 'element-plus/es/components/tree/src/model/node';
|
|
||||||
|
|
||||||
interface IProps {
|
|
||||||
treeData: TreeTypes[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const ElementTreeLine = getElementLabelLine(h);
|
|
||||||
|
|
||||||
const defaultTreeProps: any = {
|
|
||||||
children: 'children',
|
|
||||||
label: 'name',
|
|
||||||
icon: 'icon',
|
|
||||||
isLeaf: (data: TreeTypes[], node: Node) => {
|
|
||||||
if (node.data.is_catalog) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const treeRef = ref<InstanceType<typeof ElTree>>();
|
|
||||||
|
|
||||||
withDefaults(defineProps<IProps>(), {
|
|
||||||
treeData: () => [],
|
|
||||||
});
|
|
||||||
const emit = defineEmits(['treeClick', 'deleteDept', 'updateDept']);
|
|
||||||
|
|
||||||
let filterVal = ref('');
|
|
||||||
let sortDisable = ref(false);
|
|
||||||
let treeSelectMenu = ref<Partial<MenuTreeItemType>>({});
|
|
||||||
let treeSelectNode = ref<Node | null>(null);
|
|
||||||
|
|
||||||
watch(filterVal, (val) => {
|
|
||||||
treeRef.value!.filter(val);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 树的搜索事件
|
|
||||||
*/
|
|
||||||
const filterNode = (value: string, data: any) => {
|
|
||||||
if (!value) return true;
|
|
||||||
return toRaw(data).name.indexOf(value) !== -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 树的懒加载
|
|
||||||
*/
|
|
||||||
const handleTreeLoad = (node: Node, resolve: Function) => {
|
|
||||||
if (node.level !== 0) {
|
|
||||||
lazyLoadMenu({ parent: node.data.id }).then((res: APIResponseData) => {
|
|
||||||
resolve(res.data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 树的点击事件
|
|
||||||
*/
|
|
||||||
const handleNodeClick = (record: MenuTreeItemType, node: Node) => {
|
|
||||||
treeSelectMenu.value = record;
|
|
||||||
treeSelectNode.value = node;
|
|
||||||
emit('treeClick', record);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 点击左侧编辑按钮
|
|
||||||
*/
|
|
||||||
const handleUpdateMenu = (type: string) => {
|
|
||||||
if (type === 'update') {
|
|
||||||
if (!treeSelectMenu.value.id) {
|
|
||||||
warningNotification('请选择菜单!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emit('updateDept', type, treeSelectMenu.value);
|
|
||||||
} else {
|
|
||||||
emit('updateDept', type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除菜单
|
|
||||||
*/
|
|
||||||
const handleDeleteMenu = () => {
|
|
||||||
if (!treeSelectMenu.value.id) {
|
|
||||||
warningNotification('请选择菜单!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emit('deleteDept', treeSelectMenu.value.id, () => {
|
|
||||||
treeSelectMenu.value = {};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移动操作
|
|
||||||
*/
|
|
||||||
const handleSort = async (type: string) => {
|
|
||||||
if (!treeSelectMenu.value.id) {
|
|
||||||
warningNotification('请选择菜单!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sortDisable.value) return;
|
|
||||||
|
|
||||||
const parentList = treeSelectNode.value?.parent.childNodes || [];
|
|
||||||
const index = parentList.findIndex((i) => i.data.id === treeSelectMenu.value.id);
|
|
||||||
const record = parentList.find((i) => i.data.id === treeSelectMenu.value.id);
|
|
||||||
|
|
||||||
if (type === 'up') {
|
|
||||||
if (index === 0) return;
|
|
||||||
parentList.splice(index - 1, 0, record as any);
|
|
||||||
parentList.splice(index + 1, 1);
|
|
||||||
sortDisable.value = true;
|
|
||||||
await menuMoveUp({ menu_id: treeSelectMenu.value.id });
|
|
||||||
sortDisable.value = false;
|
|
||||||
}
|
|
||||||
if (type === 'down') {
|
|
||||||
parentList.splice(index + 2, 0, record as any);
|
|
||||||
parentList.splice(index, 1);
|
|
||||||
sortDisable.value = true;
|
|
||||||
await menuMoveDown({ menu_id: treeSelectMenu.value.id });
|
|
||||||
sortDisable.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
treeRef,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.menu-tree-com {
|
|
||||||
.mtc-head {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-left: -8px;
|
|
||||||
color: #606266;
|
|
||||||
font-weight: 600;
|
|
||||||
|
|
||||||
.mtc-head-icon {
|
|
||||||
margin-right: 8px;
|
|
||||||
position: relative;
|
|
||||||
top: -1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mtc-tooltip {
|
|
||||||
margin-left: 5px;
|
|
||||||
position: relative;
|
|
||||||
top: -1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mtc-tags {
|
|
||||||
height: 40px;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
padding: 0 20px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-around;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.mtc-tags-icon {
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.menu-tree-com {
|
|
||||||
height: calc(100% - 60px);
|
|
||||||
padding: 20px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.el-tree-node__content {
|
|
||||||
height: 32px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree .el-tree-node__expand-icon svg {
|
|
||||||
display: none !important;
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree-node__expand-icon {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree-node__content > .el-tree-node__expand-icon {
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-right: 5px;
|
|
||||||
margin-left: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree .el-tree-node__expand-icon.expanded {
|
|
||||||
-webkit-transform: rotate(0deg);
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree .el-tree-node__expand-icon.is-leaf {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree .el-tree-node__expand-icon:before {
|
|
||||||
background: url('../../../../../assets/img/menu-tree-show-icon.png') no-repeat center / 100%;
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree .el-tree-node__expand-icon.expanded:before {
|
|
||||||
background: url('../../../../../assets/img/menu-tree-hidden-icon.png') no-repeat center / 100%;
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree .is-leaf.el-tree-node__expand-icon::before {
|
|
||||||
display: block;
|
|
||||||
background: none !important;
|
|
||||||
content: '';
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -95,28 +95,6 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
|
|||||||
form: {
|
form: {
|
||||||
labelWidth: '120px',
|
labelWidth: '120px',
|
||||||
row: { gutter: 20 },
|
row: { gutter: 20 },
|
||||||
// group: {
|
|
||||||
// groupType: 'tabs', //collapse, tabs
|
|
||||||
// accordion: false,
|
|
||||||
// groups: {
|
|
||||||
// catalog: {
|
|
||||||
// label: '目录',
|
|
||||||
// icon: 'el-icon-goods',
|
|
||||||
// columns: ['name', 'icon', 'sort', 'status'],
|
|
||||||
// },
|
|
||||||
// menu: {
|
|
||||||
// label: '菜单',
|
|
||||||
// icon: 'el-icon-price-tag',
|
|
||||||
// columns: ['parent', 'name', 'icon', 'is_link', 'web_path', 'component', 'cache', 'visible', 'frame_out', 'sort', 'status'],
|
|
||||||
// },
|
|
||||||
// info: {
|
|
||||||
// label: '按钮',
|
|
||||||
// collapsed: true, //默认折叠
|
|
||||||
// icon: 'el-icon-warning-outline',
|
|
||||||
// columns: ['name', 'component'],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
lazy: true,
|
lazy: true,
|
||||||
@@ -150,6 +128,9 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
|
|||||||
}),
|
}),
|
||||||
form: {
|
form: {
|
||||||
value:0,
|
value:0,
|
||||||
|
component:{
|
||||||
|
optionName: "el-radio-button"
|
||||||
|
},
|
||||||
valueChange({ form, value, getComponentRef }) {
|
valueChange({ form, value, getComponentRef }) {
|
||||||
if (value) {
|
if (value) {
|
||||||
getComponentRef("parent")?.reloadDict(); // 执行city的select组件的reloadDict()方法,触发“city”重新加载字典
|
getComponentRef("parent")?.reloadDict(); // 执行city的select组件的reloadDict()方法,触发“city”重新加载字典
|
||||||
@@ -259,11 +240,29 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
|
|||||||
show: false,
|
show: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
component_name: {
|
||||||
|
title: '组件名称',
|
||||||
|
form: {
|
||||||
|
show:compute(({form})=>{
|
||||||
|
return [1].includes(form.menu_type);
|
||||||
|
}),
|
||||||
|
rules: [{ required: true, message: '请输入组件名称', trigger: 'blur' }],
|
||||||
|
component: {
|
||||||
|
placeholder: '请输入组件名称',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
component: {
|
component: {
|
||||||
title: compute(({ form }) => {
|
title: compute(({ form }) => {
|
||||||
return form.menu_type === 1 ? '组件地址' : '按钮权限值';
|
return form.menu_type === 1 ? '组件地址' : '按钮权限值';
|
||||||
}),
|
}),
|
||||||
form: {
|
form: {
|
||||||
|
col:{
|
||||||
|
span:24,
|
||||||
|
},
|
||||||
show: compute(({ form }) => {
|
show: compute(({ form }) => {
|
||||||
return [1,2].includes(form.menu_type)
|
return [1,2].includes(form.menu_type)
|
||||||
}),
|
}),
|
||||||
@@ -271,7 +270,9 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
|
|||||||
return form.menu_type === 1 ? 'src/views下的文件夹地址' : '按钮权限值是唯一的标识';
|
return form.menu_type === 1 ? 'src/views下的文件夹地址' : '按钮权限值是唯一的标识';
|
||||||
}),
|
}),
|
||||||
rules: [{ required: true, message: '请输入组件地址', trigger: 'blur' }],
|
rules: [{ required: true, message: '请输入组件地址', trigger: 'blur' }],
|
||||||
|
|
||||||
component: {
|
component: {
|
||||||
|
|
||||||
style: {
|
style: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
import { request } from "/@/utils/service";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取角色所拥有的菜单
|
|
||||||
* @param params
|
|
||||||
*/
|
|
||||||
export function GetMenu(params:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_get_menu/',
|
|
||||||
method: 'get',
|
|
||||||
params:params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 新增权限
|
|
||||||
* @param data
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function SaveMenuPermission(data:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_permission/save_auth/',
|
|
||||||
method: 'post',
|
|
||||||
data:data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取菜单下的按钮
|
|
||||||
* @param params
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function GetMenuButton(params:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_menu_get_button/',
|
|
||||||
method: 'get',
|
|
||||||
params:params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 根据角色获取已授权的菜单
|
|
||||||
* @param params
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function role_to_menu (params:any={}) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_to_menu/',
|
|
||||||
method: 'get',
|
|
||||||
params: params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 根据角色获取数据权限范围
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function GetDataScope (params:any={}) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/data_scope/',
|
|
||||||
method: 'get',
|
|
||||||
params: params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 获取权限部门
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function GetDataScopeDept (params:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_to_dept_all/',
|
|
||||||
method: 'get',
|
|
||||||
params: params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 新增权限
|
|
||||||
* @param data
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function CreatePermission(data:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/',
|
|
||||||
method: 'post',
|
|
||||||
data:data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 根据菜单获取菜单下按钮
|
|
||||||
* @param params
|
|
||||||
*/
|
|
||||||
export function getObj(params:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/menu_to_button/',
|
|
||||||
method: 'get',
|
|
||||||
params:params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除按钮权限
|
|
||||||
* @param data
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function DeletePermission(data:any) {
|
|
||||||
return request({
|
|
||||||
url: `/api/system/role_menu_button_permission/${data.id}/`,
|
|
||||||
method: 'delete',
|
|
||||||
data:{}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-drawer size="70%" v-model="drawer" direction="rtl" destroy-on-close :before-close="handleClose">
|
|
||||||
<template #header>
|
|
||||||
<div>
|
|
||||||
<el-tag>当前角色:{{ editedRoleInfo.name }}</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div style="padding: 1em">
|
|
||||||
<div style="margin-bottom: 10px">
|
|
||||||
<el-button type="primary" @click="onSaveAuth">保存菜单授权</el-button>
|
|
||||||
</div>
|
|
||||||
<vxe-table
|
|
||||||
ref="tableRef"
|
|
||||||
border
|
|
||||||
resizable
|
|
||||||
:row-config="{ keyField: 'menu_id' }"
|
|
||||||
:tree-config="{ transform: true, rowField: 'menu_id', parentField: 'parent' }"
|
|
||||||
:checkbox-config="{ labelField: 'menu_id', checkRowKeys: multipleTableData, checkStrictly: true }"
|
|
||||||
:expand-config="{ accordion: true }"
|
|
||||||
@toggle-row-expand="menuNodeClick"
|
|
||||||
:data="menuData"
|
|
||||||
>
|
|
||||||
<vxe-column type="checkbox" title="ID" width="200" tree-node></vxe-column>
|
|
||||||
<vxe-column field="name" title="目录/菜单"></vxe-column>
|
|
||||||
<vxe-column type="expand" title="已授予权限" width="120">
|
|
||||||
<template #content="{ row, rowIndex }">
|
|
||||||
<div style="padding: 10px 0px" v-if="!row.is_catalog">
|
|
||||||
<el-button type="primary" size="small" style="margin-bottom: 0.5em" @click="createBtnPermission">新增 </el-button>
|
|
||||||
<el-table size="small" :data="buttonPermissionData" border style="width: 100%">
|
|
||||||
<el-table-column prop="menu_button" label="权限名称" width="100">
|
|
||||||
<template #default="scope">
|
|
||||||
<div>{{ scope.row.menu_button__name }}</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="menu_button__value" label="权限值" width="150"> </el-table-column>
|
|
||||||
<el-table-column prop="data_range" label="权限范围" width="140">
|
|
||||||
<template #default="scope">
|
|
||||||
<div>{{ formatDataRange(scope.row.data_range) }}</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="dept" label="权限涉及部门" />
|
|
||||||
<el-table-column fixed="right" label="操作" width="120">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-button type="danger" size="small" @click="onDeleteBtn(scope)">删除 </el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</vxe-column>
|
|
||||||
</vxe-table>
|
|
||||||
<!-- 弹窗-->
|
|
||||||
<el-dialog v-model="dialogFormVisible" append-to-body width="400px" title="配置按钮权限">
|
|
||||||
<el-form ref="buttonFormRef" :model="buttonForm" :rules="buttonRules" label-width="120px">
|
|
||||||
<el-form-item label="按钮" prop="menu_button">
|
|
||||||
<el-select v-model="buttonForm.menu_button" placeholder="请选择按钮" @change="onChangeButton">
|
|
||||||
<el-option v-for="(item, index) in buttonOptions" :key="index" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="权限范围" prop="data_range">
|
|
||||||
<el-select v-model="buttonForm.data_range" placeholder="请选择按钮">
|
|
||||||
<el-option v-for="(item, index) in dataScopeOptions" :key="index" :label="item.label" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="数据部门" prop="dept" v-show="buttonForm.data_range === 4">
|
|
||||||
<div class="dept-tree">
|
|
||||||
<el-tree
|
|
||||||
:data="deptOptions"
|
|
||||||
show-checkbox
|
|
||||||
default-expand-all
|
|
||||||
:default-checked-keys="deptCheckedKeys"
|
|
||||||
ref="deptTree"
|
|
||||||
node-key="dept_id"
|
|
||||||
:check-strictly="true"
|
|
||||||
:props="{ label: 'name' }"
|
|
||||||
></el-tree>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="dialogFormVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="onSaveButtonForm"> 确定 </el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</el-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, defineExpose, reactive, toRefs } from 'vue';
|
|
||||||
import { ElMessageBox, ElTable } from 'element-plus';
|
|
||||||
import * as api from './api.ts';
|
|
||||||
import type { FormRules, FormInstance } from 'element-plus';
|
|
||||||
import { ElMessage } from 'element-plus';
|
|
||||||
import XEUtils from 'xe-utils';
|
|
||||||
import { VXETable, VxeTableInstance, VxeTableEvents } from 'vxe-table';
|
|
||||||
|
|
||||||
interface tableRow {
|
|
||||||
menu_id: number;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
//抽屉是否显示
|
|
||||||
const drawer = ref(false);
|
|
||||||
//当前编辑的角色信息
|
|
||||||
const editedRoleInfo = ref({});
|
|
||||||
|
|
||||||
//抽屉关闭确认
|
|
||||||
const handleClose = (done: () => void) => {
|
|
||||||
ElMessageBox.confirm('您确定要关闭?', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
// catch error
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*****菜单的配置项***/
|
|
||||||
const defaultProps = {
|
|
||||||
children: 'children',
|
|
||||||
label: 'name',
|
|
||||||
isLeaf: 'hasChild',
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Tree {
|
|
||||||
name: string;
|
|
||||||
children?: Tree[];
|
|
||||||
id: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
let menuData = ref<Tree>();
|
|
||||||
//获取菜单
|
|
||||||
const getMenuData = () => {
|
|
||||||
api.GetMenu({}).then((res: any) => {
|
|
||||||
const { data } = res;
|
|
||||||
menuData.value = data;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//获取已授权的菜单
|
|
||||||
const tableRef = ref<VxeTableInstance<tableRow>>();
|
|
||||||
const multipleTableData = ref();
|
|
||||||
const getRoleToMenu = () => {
|
|
||||||
api.role_to_menu({ role: editedRoleInfo.value.id }).then((res: any) => {
|
|
||||||
const { data } = res;
|
|
||||||
multipleTableData.value = data;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let isBtnPermissionShow = ref(false);
|
|
||||||
let buttonOptions = ref<[]>();
|
|
||||||
let editedMenuInfo = ref();
|
|
||||||
//菜单节点点击事件
|
|
||||||
const menuNodeClick: VxeTableEvents.ToggleRowExpand<tableRow> = ({ expanded, row }) => {
|
|
||||||
// isBtnPermissionShow.value = !node.is_catalog
|
|
||||||
if (!row.is_catalog) {
|
|
||||||
buttonOptions.value = [];
|
|
||||||
editedMenuInfo.value = row;
|
|
||||||
api.GetMenuButton({ menu: row.menu_id }).then((res: any) => {
|
|
||||||
const { data } = res;
|
|
||||||
buttonOptions.value = data;
|
|
||||||
});
|
|
||||||
api.getObj({ menu: row.menu_id, role: editedRoleInfo.value.id }).then((res: any) => {
|
|
||||||
const { data } = res;
|
|
||||||
buttonPermissionData.value = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const menuTree = ref();
|
|
||||||
/*****菜单的配置项***/
|
|
||||||
/***按钮授权的弹窗****/
|
|
||||||
//是否显示新增表单
|
|
||||||
const dialogFormVisible = ref(false);
|
|
||||||
//部门树
|
|
||||||
const deptTree = ref();
|
|
||||||
//自定义部门数据
|
|
||||||
const deptOptions = ref();
|
|
||||||
//选中的部门数据
|
|
||||||
const deptCheckedKeys = [];
|
|
||||||
//按钮表单
|
|
||||||
const buttonForm = reactive({
|
|
||||||
menu_button: null,
|
|
||||||
role: null,
|
|
||||||
menu: null,
|
|
||||||
data_range: null,
|
|
||||||
dept: [],
|
|
||||||
});
|
|
||||||
//按钮表格数据
|
|
||||||
let buttonPermissionData = ref([]);
|
|
||||||
//按钮表单验证
|
|
||||||
const buttonRules = reactive<FormRules>({
|
|
||||||
menu_button: [{ required: true, message: '必填项' }],
|
|
||||||
data_range: [{ required: true, message: '必填项' }],
|
|
||||||
});
|
|
||||||
//新增按钮
|
|
||||||
const buttonFormRef = ref<FormInstance>();
|
|
||||||
const createBtnPermission = () => {
|
|
||||||
dialogFormVisible.value = true;
|
|
||||||
buttonForm.menu_button = null;
|
|
||||||
buttonForm.menu = null;
|
|
||||||
buttonForm.role = null;
|
|
||||||
buttonForm.data_range = null;
|
|
||||||
buttonForm.dept = [];
|
|
||||||
};
|
|
||||||
//权限范围数据
|
|
||||||
const dataScopeOptions = ref<[]>();
|
|
||||||
//按钮值变化事件
|
|
||||||
const onChangeButton = (val: any) => {
|
|
||||||
dataScopeOptions.value = [];
|
|
||||||
//获取权限值范围
|
|
||||||
api.GetDataScope({ menu_button: val }).then((res: any) => {
|
|
||||||
dataScopeOptions.value = res.data;
|
|
||||||
});
|
|
||||||
//获取权限部门值
|
|
||||||
api.GetDataScopeDept({ menu_button: val }).then((res: any) => {
|
|
||||||
deptOptions.value = XEUtils.toArrayTree(res.data, { parentKey: 'parent', strict: false });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
//过滤按钮名称
|
|
||||||
const formatMenuBtn = (val: any) => {
|
|
||||||
let obj: any = buttonOptions.value?.find((item: any) => {
|
|
||||||
return item.id === val;
|
|
||||||
});
|
|
||||||
return obj ? obj.name : null;
|
|
||||||
};
|
|
||||||
//过滤权限范围
|
|
||||||
const formatDataRange = (val: any) => {
|
|
||||||
let obj: any = [
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
label: '仅本人数据权限',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 1,
|
|
||||||
label: '本部门及以下数据权限',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 2,
|
|
||||||
label: '本部门数据权限',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 3,
|
|
||||||
label: '全部数据权限',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 4,
|
|
||||||
label: '自定义数据权限',
|
|
||||||
},
|
|
||||||
].find((item: any) => {
|
|
||||||
return item.value === val;
|
|
||||||
});
|
|
||||||
return obj ? obj.label : null;
|
|
||||||
};
|
|
||||||
//保存按钮表单
|
|
||||||
|
|
||||||
const onSaveButtonForm = async () => {
|
|
||||||
const { id: roleId } = editedRoleInfo.value;
|
|
||||||
const { id: menuId } = editedMenuInfo.value;
|
|
||||||
const form: any = Object.assign({}, buttonForm);
|
|
||||||
form.role = roleId;
|
|
||||||
form.menu = menuId;
|
|
||||||
//选中的部门
|
|
||||||
const checkedList = deptTree.value.getCheckedKeys();
|
|
||||||
form.dept = checkedList;
|
|
||||||
if (!buttonFormRef.value) return;
|
|
||||||
await buttonFormRef.value.validate((valid, fields) => {
|
|
||||||
if (valid) {
|
|
||||||
api.CreatePermission(form).then((res: any) => {
|
|
||||||
const { data } = res;
|
|
||||||
buttonPermissionData.value.push(data);
|
|
||||||
dialogFormVisible.value = false;
|
|
||||||
ElMessage({
|
|
||||||
type: 'success',
|
|
||||||
message: res.msg,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
ElMessage({
|
|
||||||
type: 'error',
|
|
||||||
title: '提交错误',
|
|
||||||
message: 'F12控制台看详情',
|
|
||||||
});
|
|
||||||
console.log('提交错误', fields);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
//删除按钮权限
|
|
||||||
const onDeleteBtn = (scope: any) => {
|
|
||||||
const { row, $index } = scope;
|
|
||||||
ElMessageBox.confirm('您是否要删除数据?', '温馨提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
api.DeletePermission({ id: row.id }).then((res: any) => {
|
|
||||||
buttonPermissionData.value.splice($index, 1);
|
|
||||||
ElMessage({
|
|
||||||
type: 'success',
|
|
||||||
message: res.msg,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
ElMessage({
|
|
||||||
type: 'info',
|
|
||||||
message: '取消删除',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
/***按钮授权的弹窗****/
|
|
||||||
//初始化数据
|
|
||||||
const initGet = () => {
|
|
||||||
getMenuData();
|
|
||||||
getRoleToMenu();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存授权
|
|
||||||
*/
|
|
||||||
const onSaveAuth = () => {
|
|
||||||
const $table = tableRef.value;
|
|
||||||
if ($table) {
|
|
||||||
const selectRecords = $table.getCheckboxRecords();
|
|
||||||
const menuIdList = selectRecords.map((record: any) => record.menu_id);
|
|
||||||
const { id: roleId } = editedRoleInfo.value;
|
|
||||||
const data = {
|
|
||||||
role: roleId,
|
|
||||||
menu: menuIdList,
|
|
||||||
};
|
|
||||||
api.SaveMenuPermission(data).then((res: any) => {
|
|
||||||
ElMessage({
|
|
||||||
message: res.msg,
|
|
||||||
type: 'success',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({ drawer, editedRoleInfo, initGet });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { request } from "/@/utils/service";
|
|
||||||
|
|
||||||
export function getDataPermissionRange() {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/data_scope/',
|
|
||||||
method: 'get',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function getDataPermissionDept() {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_to_dept_all/',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDataPermissionMenu() {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/get_role_permissions/',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,235 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="permission-com">
|
|
||||||
<div class="pc-item">
|
|
||||||
<p class="pc-title">数据授权</p>
|
|
||||||
<div class="pc-cell">
|
|
||||||
<el-radio-group v-model="dataPermission" class="pc-data-permission">
|
|
||||||
<el-radio v-for="item in dataPermissionRange" :key="item.label" :label="item.value" @change="handleChange">{{ item.label }}</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
<el-tree-select
|
|
||||||
v-if="dataPermission === 4"
|
|
||||||
node-key="id"
|
|
||||||
v-model="customDataPermission"
|
|
||||||
:props="defaultTreeProps"
|
|
||||||
:data="deptData"
|
|
||||||
multiple
|
|
||||||
check-strictly
|
|
||||||
:render-after-expand="false"
|
|
||||||
show-checkbox
|
|
||||||
class="pc-custom-dept"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pc-item pc-menu">
|
|
||||||
<p class="pc-title">菜单授权</p>
|
|
||||||
<div>
|
|
||||||
<el-tree
|
|
||||||
:props="defaultTreeProps"
|
|
||||||
:data="menuData"
|
|
||||||
show-checkbox
|
|
||||||
node-key="id"
|
|
||||||
default-expand-all
|
|
||||||
:expand-on-click-node="false"
|
|
||||||
class="dc-menu-tree"
|
|
||||||
>
|
|
||||||
<template #default="{ node, data }">
|
|
||||||
<div class="pc-tree-node" :class="{ 'tree-node-label-border': !data.is_catalog }">
|
|
||||||
<p class="tree-node-label">{{ node.label }}</p>
|
|
||||||
<div v-if="!data.is_catalog">
|
|
||||||
<ul class="menu-permission-list">
|
|
||||||
<li v-for="m in data.menuPermission" :key="m.id" class="menu-permission-item">
|
|
||||||
<el-checkbox v-model="m.id" :label="m.name" />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul class="menu-permission-list">
|
|
||||||
<li v-for="m in data.columns" :key="m.id" class="menu-permission-item">
|
|
||||||
<el-checkbox v-model="m.id" :label="m.title" />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-tree>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pc-btn">
|
|
||||||
<el-button type="primary">确定</el-button>
|
|
||||||
<el-button>取消</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, onMounted } from 'vue';
|
|
||||||
import XEUtils from 'xe-utils';
|
|
||||||
import { getDataPermissionRange, getDataPermissionDept, getDataPermissionMenu } from './api';
|
|
||||||
import { DataPermissionRangeType, CustomDataPermissionDeptType, CustomDataPermissionMenuType } from './types';
|
|
||||||
|
|
||||||
const defaultTreeProps = {
|
|
||||||
children: 'children',
|
|
||||||
label: 'name',
|
|
||||||
value: 'id',
|
|
||||||
};
|
|
||||||
|
|
||||||
const data: any[] = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
label: 'Level one 1',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
label: 'Level two 1-1',
|
|
||||||
isPenultimate: true,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 9,
|
|
||||||
label: 'Level three 1-1-1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10,
|
|
||||||
label: 'Level three 1-1-2',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
label: 'Level one 2',
|
|
||||||
isPenultimate: true,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
label: 'Level two 2-1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
label: 'Level two 2-2',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
label: 'Level one 3',
|
|
||||||
isPenultimate: true,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
label: 'Level two 3-1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
label: 'Level two 3-2',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
let dataPermission = ref();
|
|
||||||
let dataPermissionRange = ref<DataPermissionRangeType[]>([]);
|
|
||||||
let customDataPermission = ref();
|
|
||||||
let deptData = ref<CustomDataPermissionDeptType[]>([]);
|
|
||||||
let menuData = ref<CustomDataPermissionMenuType[]>([]);
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
|
||||||
try {
|
|
||||||
const resRange = await getDataPermissionRange();
|
|
||||||
const resMenu = await getDataPermissionMenu();
|
|
||||||
|
|
||||||
if (resRange?.code === 2000) {
|
|
||||||
dataPermissionRange.value = resRange.data;
|
|
||||||
}
|
|
||||||
if (resMenu?.code === 2000) {
|
|
||||||
console.log(resMenu.data);
|
|
||||||
menuData.value = resMenu.data;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = async () => {
|
|
||||||
if (dataPermission.value === 4) {
|
|
||||||
const res = await getDataPermissionDept();
|
|
||||||
const data = XEUtils.toArrayTree(res.data, { parentKey: 'parent', strict: false });
|
|
||||||
deptData.value = data;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTestClick = (node: any, data: any) => {
|
|
||||||
console.log(node, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
fetchData();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.permission-com {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 15px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
.pc-item {
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
border-bottom: 1px #dcdfe6 solid;
|
|
||||||
}
|
|
||||||
.pc-title {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.pc-cell {
|
|
||||||
display: flex;
|
|
||||||
padding: 10px;
|
|
||||||
overflow-x: auto;
|
|
||||||
.pc-data-permission {
|
|
||||||
min-width: 800px;
|
|
||||||
}
|
|
||||||
.pc-custom-dept {
|
|
||||||
min-width: 200px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pc-menu {
|
|
||||||
height: calc(100% - 140px);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pc-tree-node {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.tree-node-label {
|
|
||||||
font-size: 16px;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
.menu-permission-list {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
.menu-permission-item {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tree-node-label-border {
|
|
||||||
border-bottom: 1px #dcdfe6 solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pc-btn {
|
|
||||||
padding-bottom: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.dc-menu-tree {
|
|
||||||
.el-tree-node__content {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
export interface DataPermissionRangeType {
|
|
||||||
label: string;
|
|
||||||
value: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CustomDataPermissionDeptType {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
patent: number;
|
|
||||||
children: CustomDataPermissionDeptType[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CustomDataPermissionMenuType {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
is_catalog: boolean;
|
|
||||||
menuPermission: { id: number; name: string; value: string }[] | null;
|
|
||||||
columns: { id: number; name: string; title: string }[] | null;
|
|
||||||
children: CustomDataPermissionMenuType[]
|
|
||||||
}
|
|
||||||
@@ -167,6 +167,9 @@ export const createCrudOptions = function ({
|
|||||||
title: '状态',
|
title: '状态',
|
||||||
search: { show: true },
|
search: { show: true },
|
||||||
type: 'dict-radio',
|
type: 'dict-radio',
|
||||||
|
dict: dict({
|
||||||
|
data: dictionary('button_status_bool'),
|
||||||
|
}),
|
||||||
column: {
|
column: {
|
||||||
width: 100,
|
width: 100,
|
||||||
component: {
|
component: {
|
||||||
@@ -189,10 +192,7 @@ export const createCrudOptions = function ({
|
|||||||
},
|
},
|
||||||
editForm: {
|
editForm: {
|
||||||
show: columnPermission('status', 'is_update'),
|
show: columnPermission('status', 'is_update'),
|
||||||
},
|
}
|
||||||
dict: dict({
|
|
||||||
data: dictionary('button_status_bool'),
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
update_datetime: {
|
update_datetime: {
|
||||||
title: '更新时间',
|
title: '更新时间',
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
import { request } from "/@/utils/service";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取角色所拥有的菜单
|
|
||||||
* @param params
|
|
||||||
*/
|
|
||||||
export function GetMenu(params:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_get_menu/',
|
|
||||||
method: 'get',
|
|
||||||
params:params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 新增权限
|
|
||||||
* @param data
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function SaveMenuPermission(data:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_permission/save_auth/',
|
|
||||||
method: 'post',
|
|
||||||
data:data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取菜单下的按钮
|
|
||||||
* @param params
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function GetMenuButton(params:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_menu_get_button/',
|
|
||||||
method: 'get',
|
|
||||||
params:params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 根据角色获取数据权限范围
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function GetDataScope (params:any={}) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/data_scope/',
|
|
||||||
method: 'get',
|
|
||||||
params: params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 获取权限部门
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function GetDataScopeDept (params:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_to_dept_all/',
|
|
||||||
method: 'get',
|
|
||||||
params: params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 新增权限
|
|
||||||
* @param data
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function CreatePermission(data:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/',
|
|
||||||
method: 'post',
|
|
||||||
data:data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 根据菜单获取菜单下按钮
|
|
||||||
* @param params
|
|
||||||
*/
|
|
||||||
export function getObj(params:any) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/menu_to_button/',
|
|
||||||
method: 'get',
|
|
||||||
params:params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除按钮权限
|
|
||||||
* @param data
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export function DeletePermission(data:any) {
|
|
||||||
return request({
|
|
||||||
url: `/api/system/role_menu_button_permission/${data.id}/`,
|
|
||||||
method: 'delete',
|
|
||||||
data:{}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,432 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-drawer
|
|
||||||
size="70%"
|
|
||||||
v-model="drawer"
|
|
||||||
direction="rtl"
|
|
||||||
destroy-on-close
|
|
||||||
:before-close="handleClose"
|
|
||||||
>
|
|
||||||
<template #header>
|
|
||||||
<div>
|
|
||||||
<el-tag size="large" type="primary">当前角色:{{ editedRoleInfo.name }}</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div style="padding: 1em">
|
|
||||||
<el-row :gutter="10">
|
|
||||||
<el-col :xs="24" :sm="24" :md="8" :lg="6" :xl="6">
|
|
||||||
<el-card header="菜单页面授权">
|
|
||||||
<template #header>
|
|
||||||
<div class="card-header">
|
|
||||||
<el-tooltip effect="dark" content="点击菜单项,可对菜单下的按钮/接口授权"
|
|
||||||
placement="right">
|
|
||||||
<div>
|
|
||||||
<span>菜单页面</span>
|
|
||||||
<el-icon>
|
|
||||||
<QuestionFilled/>
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
<el-button size="mini" type="primary" @click="onSaveAuth">保存菜单授权</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-tree :data="menuData"
|
|
||||||
ref="menuTree"
|
|
||||||
show-checkbox
|
|
||||||
node-key="id"
|
|
||||||
highlight-current
|
|
||||||
:expand-on-click-node="false"
|
|
||||||
:check-on-click-node="true"
|
|
||||||
:props="defaultProps"
|
|
||||||
@node-click="menuNodeClick"
|
|
||||||
/>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="16" :lg="18" :xl="18">
|
|
||||||
<!-- <el-alert title="对页面菜单下按钮授权" description="新增或删除对菜单下的按钮/接口授权" type="warning" />-->
|
|
||||||
<el-card v-if="isBtnPermissionShow">
|
|
||||||
<template #header>
|
|
||||||
<div class="card-header">
|
|
||||||
<el-tooltip effect="dark" content="新增或删除对菜单下的按钮/接口授权" placement="right">
|
|
||||||
<div>
|
|
||||||
<span>按钮/接口授权</span>
|
|
||||||
<el-icon>
|
|
||||||
<QuestionFilled/>
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div>
|
|
||||||
<el-divider content-position="left">{{ editedMenuInfo.name }}</el-divider>
|
|
||||||
<el-button type="primary" size="small" style="margin-bottom: 0.5em"
|
|
||||||
@click="createBtnPermission">新增
|
|
||||||
</el-button>
|
|
||||||
<el-table size="small" :data="buttonPermissionData" border style="width: 100%">
|
|
||||||
<el-table-column prop="menu_button" label="权限名称" width="100">
|
|
||||||
<template #default="scope">
|
|
||||||
<div>{{ formatMenuBtn(scope.row.menu_button) }}</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="data_range" label="权限范围" width="140">
|
|
||||||
<template #default="scope">
|
|
||||||
<div>{{ formatDataRange(scope.row.data_range) }}</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="dept" label="权限涉及部门"/>
|
|
||||||
<el-table-column fixed="right" label="操作" width="120">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-button type="danger" size="small" @click="onDeleteBtn(scope)">删除
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <el-divider content-position="left">字段授权</el-divider>-->
|
|
||||||
<!-- <el-table size="small" :data="crudPermissionData" border style="width: 100%">-->
|
|
||||||
<!-- <el-table-column prop="field" label="字段"></el-table-column>-->
|
|
||||||
<!-- <el-table-column prop="table" label="列表显示">-->
|
|
||||||
<!-- <template #default="scope">-->
|
|
||||||
<!-- <div>-->
|
|
||||||
<!-- <el-switch size="mini" v-model="scope.row.table"/>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </el-table-column>-->
|
|
||||||
<!-- <el-table-column prop="view" label="表单查看">-->
|
|
||||||
<!-- <template #default="scope">-->
|
|
||||||
<!-- <div>-->
|
|
||||||
<!-- <el-switch size="mini" v-model="scope.row.view"/>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </el-table-column>-->
|
|
||||||
<!-- <el-table-column prop="edit" label="表单编辑">-->
|
|
||||||
<!-- <template #default="scope">-->
|
|
||||||
<!-- <div>-->
|
|
||||||
<!-- <el-switch size="mini" v-model="scope.row.edit"/>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </el-table-column>-->
|
|
||||||
<!-- </el-table>-->
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-dialog v-model="dialogFormVisible" width="400px" title="配置按钮权限">
|
|
||||||
<el-form ref="buttonFormRef" :model="buttonForm" :rules="buttonRules" label-width="120px">
|
|
||||||
<el-form-item label="按钮" prop="menu_button">
|
|
||||||
<el-select v-model="buttonForm.menu_button" placeholder="请选择按钮" @change="onChangeButton">
|
|
||||||
<el-option v-for="(item,index) in buttonOptions" :key="index" :label="item.name"
|
|
||||||
:value="item.id"/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="权限范围" prop="data_range">
|
|
||||||
<el-select v-model="buttonForm.data_range" placeholder="请选择按钮">
|
|
||||||
<el-option v-for="(item,index) in dataScopeOptions" :key="index" :label="item.label"
|
|
||||||
:value="item.value"/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="数据部门" prop="dept" v-show="buttonForm.data_range === 4">
|
|
||||||
<div class="dept-tree">
|
|
||||||
<el-tree
|
|
||||||
:data="deptOptions"
|
|
||||||
show-checkbox
|
|
||||||
default-expand-all
|
|
||||||
:default-checked-keys="deptCheckedKeys"
|
|
||||||
ref="deptTree"
|
|
||||||
node-key="id"
|
|
||||||
:check-strictly="true"
|
|
||||||
:props="{ label: 'name' }"
|
|
||||||
></el-tree>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="dialogFormVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="onSaveButtonForm">
|
|
||||||
确定
|
|
||||||
</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</el-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup name="rolePermission">
|
|
||||||
import {ref, defineExpose, reactive, toRefs} from 'vue'
|
|
||||||
import {ElMessageBox} from 'element-plus'
|
|
||||||
import * as api from './api'
|
|
||||||
import type {FormRules, FormInstance} from 'element-plus'
|
|
||||||
import {ElMessage} from 'element-plus'
|
|
||||||
import XEUtils from 'xe-utils'
|
|
||||||
//抽屉是否显示
|
|
||||||
const drawer = ref(false)
|
|
||||||
//当前编辑的角色信息
|
|
||||||
const editedRoleInfo = ref({})
|
|
||||||
|
|
||||||
//抽屉关闭确认
|
|
||||||
const handleClose = (done: () => void) => {
|
|
||||||
ElMessageBox.confirm('您确定要关闭?', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
// catch error
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****菜单的配置项***/
|
|
||||||
const defaultProps = {
|
|
||||||
children: 'children',
|
|
||||||
label: 'name',
|
|
||||||
isLeaf: 'hasChild'
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Tree {
|
|
||||||
name: string
|
|
||||||
children?: Tree[],
|
|
||||||
id: number
|
|
||||||
}
|
|
||||||
|
|
||||||
let menuData = ref<Tree>()
|
|
||||||
//获取菜单
|
|
||||||
const getMenuData = () => {
|
|
||||||
api.GetMenu({}).then((res: any) => {
|
|
||||||
const {data} = res
|
|
||||||
const list = XEUtils.toArrayTree(data, {parentKey: "parent", key:'menu_id',strict: true})
|
|
||||||
menuData.value = list
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let isBtnPermissionShow = ref(false)
|
|
||||||
let buttonOptions = ref<[]>()
|
|
||||||
let editedMenuInfo = ref()
|
|
||||||
//菜单节点点击事件
|
|
||||||
const menuNodeClick = (node: any, obj: any) => {
|
|
||||||
isBtnPermissionShow.value = !node.is_catalog
|
|
||||||
if (!node.is_catalog) {
|
|
||||||
buttonOptions.value = []
|
|
||||||
editedMenuInfo.value = node
|
|
||||||
api.GetMenuButton({menu: node.menu_id}).then((res: any) => {
|
|
||||||
const {data} = res
|
|
||||||
buttonOptions.value = data
|
|
||||||
})
|
|
||||||
api.getObj({menu: node.menu_id, role: editedRoleInfo.value.id}).then((res: any) => {
|
|
||||||
const {data} = res
|
|
||||||
buttonPermissionData.value = data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
const menuTree = ref()
|
|
||||||
/*****菜单的配置项***/
|
|
||||||
/***按钮授权的弹窗****/
|
|
||||||
//是否显示新增表单
|
|
||||||
const dialogFormVisible = ref(false)
|
|
||||||
//部门树
|
|
||||||
const deptTree = ref()
|
|
||||||
//自定义部门数据
|
|
||||||
const deptOptions = ref()
|
|
||||||
//选中的部门数据
|
|
||||||
const deptCheckedKeys = []
|
|
||||||
//按钮表单
|
|
||||||
const buttonForm = reactive({
|
|
||||||
menu_button: null,
|
|
||||||
role: null,
|
|
||||||
menu: null,
|
|
||||||
data_range: null,
|
|
||||||
dept: []
|
|
||||||
})
|
|
||||||
//按钮表格数据
|
|
||||||
let buttonPermissionData = ref([])
|
|
||||||
//按钮表单验证
|
|
||||||
const buttonRules = reactive<FormRules>({
|
|
||||||
menu_button: [
|
|
||||||
{required: true, message: '必填项'}
|
|
||||||
],
|
|
||||||
data_range: [
|
|
||||||
{required: true, message: '必填项'}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
//新增按钮
|
|
||||||
const buttonFormRef = ref<FormInstance>()
|
|
||||||
const createBtnPermission = () => {
|
|
||||||
dialogFormVisible.value = true
|
|
||||||
buttonForm.menu_button = null
|
|
||||||
buttonForm.menu = null
|
|
||||||
buttonForm.role = null
|
|
||||||
buttonForm.data_range = null
|
|
||||||
buttonForm.dept = []
|
|
||||||
}
|
|
||||||
//权限范围数据
|
|
||||||
const dataScopeOptions = ref<[]>()
|
|
||||||
//按钮值变化事件
|
|
||||||
const onChangeButton = (val: any) => {
|
|
||||||
dataScopeOptions.value = []
|
|
||||||
//获取权限值范围
|
|
||||||
api.GetDataScope({menu_button: val}).then((res: any) => {
|
|
||||||
dataScopeOptions.value = res.data
|
|
||||||
})
|
|
||||||
//获取权限部门值
|
|
||||||
api.GetDataScopeDept({menu_button: val}).then((res: any) => {
|
|
||||||
deptOptions.value = XEUtils.toArrayTree(res.data, {parentKey: 'parent', strict: false})
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
//过滤按钮名称
|
|
||||||
const formatMenuBtn = (val: any) => {
|
|
||||||
let obj: any = buttonOptions.value?.find((item: any) => {
|
|
||||||
return item.id === val
|
|
||||||
})
|
|
||||||
return obj ? obj.name : null
|
|
||||||
}
|
|
||||||
//过滤权限范围
|
|
||||||
const formatDataRange = (val: any) => {
|
|
||||||
let obj: any = [
|
|
||||||
{
|
|
||||||
"value": 0,
|
|
||||||
"label": '仅本人数据权限'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 1,
|
|
||||||
"label": '本部门及以下数据权限'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 2,
|
|
||||||
"label": '本部门数据权限'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 3,
|
|
||||||
"label": '全部数据权限'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 4,
|
|
||||||
"label": '自定义数据权限'
|
|
||||||
}
|
|
||||||
].find((item: any) => {
|
|
||||||
return item.value === val
|
|
||||||
})
|
|
||||||
return obj ? obj.label : null
|
|
||||||
}
|
|
||||||
//保存按钮表单
|
|
||||||
|
|
||||||
const onSaveButtonForm = async () => {
|
|
||||||
const {id: roleId} = editedRoleInfo.value
|
|
||||||
const {id: menuId} = editedMenuInfo.value
|
|
||||||
const form: any = Object.assign({}, buttonForm)
|
|
||||||
form.role = roleId
|
|
||||||
form.menu = menuId
|
|
||||||
//选中的部门
|
|
||||||
const checkedList = deptTree.value.getCheckedKeys()
|
|
||||||
form.dept = checkedList
|
|
||||||
if (!buttonFormRef.value) return
|
|
||||||
await buttonFormRef.value.validate((valid, fields) => {
|
|
||||||
if (valid) {
|
|
||||||
api.CreatePermission(form).then((res: any) => {
|
|
||||||
const {data} = res
|
|
||||||
buttonPermissionData.value.push(data)
|
|
||||||
dialogFormVisible.value = false
|
|
||||||
ElMessage({
|
|
||||||
type: 'success',
|
|
||||||
message: res.msg,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
ElMessage({
|
|
||||||
type: 'error',
|
|
||||||
title: '提交错误',
|
|
||||||
message: 'F12控制台看详情',
|
|
||||||
})
|
|
||||||
console.log('提交错误', fields)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
//删除按钮权限
|
|
||||||
const onDeleteBtn = (scope: any) => {
|
|
||||||
const {row, $index} = scope
|
|
||||||
ElMessageBox.confirm(
|
|
||||||
'您是否要删除数据?',
|
|
||||||
'温馨提示',
|
|
||||||
{
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
}
|
|
||||||
).then(() => {
|
|
||||||
api.DeletePermission({id: row.id}).then((res: any) => {
|
|
||||||
buttonPermissionData.value.splice($index, 1)
|
|
||||||
ElMessage({
|
|
||||||
type: 'success',
|
|
||||||
message: res.msg,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
ElMessage({
|
|
||||||
type: 'info',
|
|
||||||
message: '取消删除',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
/***按钮授权的弹窗****/
|
|
||||||
//初始化数据
|
|
||||||
const initGet = () => {
|
|
||||||
getMenuData()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存授权
|
|
||||||
*/
|
|
||||||
const onSaveAuth = () => {
|
|
||||||
//选中的菜单
|
|
||||||
const checkedList = menuTree.value.getCheckedKeys()
|
|
||||||
//半选中的菜单
|
|
||||||
const halfCheckedList = menuTree.value.getHalfCheckedKeys()
|
|
||||||
//合并的菜单数据
|
|
||||||
const menuIdList = [...checkedList, ...halfCheckedList]
|
|
||||||
// console.log(menuIdList)
|
|
||||||
const {id: roleId} = editedRoleInfo.value
|
|
||||||
const data = {
|
|
||||||
role: roleId,
|
|
||||||
menu: menuIdList
|
|
||||||
}
|
|
||||||
api.SaveMenuPermission(data).then((res: any) => {
|
|
||||||
ElMessage({
|
|
||||||
message: res.msg,
|
|
||||||
type: 'success',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
defineExpose({drawer, editedRoleInfo, initGet})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.card-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dept-tree::-webkit-scrollbar {
|
|
||||||
display: none; /* Chrome Safari */
|
|
||||||
}
|
|
||||||
|
|
||||||
.dept-tree {
|
|
||||||
height: 160px;
|
|
||||||
overflow-y: scroll;
|
|
||||||
scrollbar-width: none; /* firefox */
|
|
||||||
-ms-overflow-style: none; /* IE 10+ */
|
|
||||||
border: 1px solid #e1e1e1;
|
|
||||||
width: 16em;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Reference in New Issue
Block a user