fix: 修改bug
This commit is contained in:
parent
1540cd71f8
commit
e482e158f6
|
@ -3445,6 +3445,30 @@ export default [
|
|||
permission: 'role',
|
||||
actions: ['query'],
|
||||
},
|
||||
{
|
||||
permission: 'role-group',
|
||||
actions: ['query']
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'groupUpdate',
|
||||
name: '角色组编辑',
|
||||
permissions: [
|
||||
{
|
||||
permission: 'role-group',
|
||||
actions: ['query','save']
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'groupDelete',
|
||||
name: '角色组删除',
|
||||
permissions: [
|
||||
{
|
||||
permission: 'role-group',
|
||||
actions: ['query','delete']
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -1,85 +1,68 @@
|
|||
<template>
|
||||
<div class="left-contain">
|
||||
<j-input placeholder="字典名称" v-model:value="searchValue" @pressEnter="search" @change="searchChange">
|
||||
<template #suffix>
|
||||
<AIcon type="SearchOutlined" @click="search" />
|
||||
</template>
|
||||
</j-input>
|
||||
<div class="controls">
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
hasPermission="system/Dictionary:add"
|
||||
@click="showSave"
|
||||
style="width: 60%"
|
||||
>
|
||||
新增字典
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
type="text"
|
||||
hasPermission="system/Dictionary:down"
|
||||
@click="downVisible=true"
|
||||
>
|
||||
下载
|
||||
</PermissionButton>
|
||||
<j-upload
|
||||
:before-upload="beforeUpload"
|
||||
accept=".json"
|
||||
:show-upload-list="false"
|
||||
>
|
||||
<PermissionButton
|
||||
type="text"
|
||||
hasPermission="system/Dictionary:import"
|
||||
>
|
||||
导入
|
||||
</PermissionButton>
|
||||
</j-upload>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<j-tree :tree-data="listData" v-if="listData.length" :fieldNames="{title:'name',key:'id'}" blockNode :selectedKeys="selectedKeys">
|
||||
<template #title="item">
|
||||
<div class="treeItem" @click="()=>selectDic(item.data)">
|
||||
<div class="itemText"><Ellipsis style="width: calc(100%-100px)">{{ item.name }}</Ellipsis></div>
|
||||
<div @click="(e) => e.stopPropagation()">
|
||||
<j-popconfirm v-if="hasPermission('system/Dictionary:action')" :title="item.data.status === 1 ? '确定禁用?' : '确定启用?'" @confirm="()=>updateDic(item.data)">
|
||||
<j-switch :checked="item.status" :disabled="!hasPermission('system/Dictionary:action')" :checkedValue="1" :unCheckedValue="0"></j-switch>
|
||||
</j-popconfirm>
|
||||
<j-tooltip v-else placement="top" title="暂无权限,请联系管理员">
|
||||
<j-switch :checked="item.status" :disabled="!hasPermission('system/Dictionary:action')" :checkedValue="1" :unCheckedValue="0"></j-switch>
|
||||
</j-tooltip>
|
||||
<PermissionButton
|
||||
type="text"
|
||||
hasPermission="system/Dictionary:delete"
|
||||
:popConfirm="{
|
||||
title: `确定要删除?`,
|
||||
onConfirm: () => deleteDic(item.id),
|
||||
}"
|
||||
>
|
||||
删除
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
type="text"
|
||||
hasPermission="system/Dictionary:update"
|
||||
@click="showEdit(item.data)"
|
||||
>
|
||||
编辑
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="left-contain">
|
||||
<j-input placeholder="字典名称" v-model:value="searchValue" @pressEnter="search" @change="searchChange">
|
||||
<template #suffix>
|
||||
<AIcon type="SearchOutlined" @click="search" />
|
||||
</template>
|
||||
</j-tree>
|
||||
<j-empty v-else style="margin-top: 100px;"/>
|
||||
</j-input>
|
||||
<div class="controls">
|
||||
<PermissionButton type="primary" hasPermission="system/Dictionary:add" @click="showSave" style="width: 160px">
|
||||
新增字典
|
||||
</PermissionButton>
|
||||
<PermissionButton type="text" hasPermission="system/Dictionary:down" @click="downVisible = true">
|
||||
下载
|
||||
</PermissionButton>
|
||||
<j-upload :before-upload="beforeUpload" accept=".json" :show-upload-list="false"
|
||||
:disabled="!hasPermission('system/Dictionary:import')">
|
||||
<PermissionButton type="text" hasPermission="system/Dictionary:import">
|
||||
导入
|
||||
</PermissionButton>
|
||||
</j-upload>
|
||||
</div>
|
||||
<div class="tree">
|
||||
<j-tree :tree-data="listData" v-if="listData.length" :fieldNames="{ title: 'name', key: 'id' }" blockNode
|
||||
:selectedKeys="selectedKeys">
|
||||
<template #title="item">
|
||||
<div class="treeItem" @click="() => selectDic(item.data)">
|
||||
<div class="itemText">
|
||||
<Ellipsis style="width: calc(100%-100px)">{{ item.name }}</Ellipsis>
|
||||
</div>
|
||||
<div @click="(e) => e.stopPropagation()">
|
||||
<j-popconfirm v-if="hasPermission('system/Dictionary:action')"
|
||||
:title="item.data.status === 1 ? '确定禁用?' : '确定启用?'" @confirm="() => updateDic(item.data)">
|
||||
<j-switch :checked="item.status" :disabled="!hasPermission('system/Dictionary:action')"
|
||||
:checkedValue="1" :unCheckedValue="0"></j-switch>
|
||||
</j-popconfirm>
|
||||
<j-tooltip v-else placement="top" title="暂无权限,请联系管理员">
|
||||
<j-switch :checked="item.status" :disabled="!hasPermission('system/Dictionary:action')"
|
||||
:checkedValue="1" :unCheckedValue="0"></j-switch>
|
||||
</j-tooltip>
|
||||
<PermissionButton type="text" hasPermission="system/Dictionary:delete" :popConfirm="{
|
||||
title: `确定要删除?`,
|
||||
onConfirm: () => deleteDic(item.id),
|
||||
}">
|
||||
删除
|
||||
</PermissionButton>
|
||||
<PermissionButton type="text" hasPermission="system/Dictionary:update"
|
||||
@click="showEdit(item.data)">
|
||||
编辑
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</j-tree>
|
||||
<j-empty v-else style="margin-top: 100px;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Save v-if="saveShow" :type="addType" @close-save="saveShow = false" @success="saveSuccess" :data="editData"/>
|
||||
<Export v-if="downVisible" @closeDown="closeDown"/>
|
||||
<Import/>
|
||||
<Save v-if="saveShow" :type="addType" @close-save="saveShow = false" @success="saveSuccess" :data="editData" />
|
||||
<Export v-if="downVisible" @closeDown="closeDown" />
|
||||
<Import />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getDicList ,deleteDictionary,addDictionary} from '@/api/system/dictionary';
|
||||
import { getDicList, deleteDictionary, addDictionary } from '@/api/system/dictionary';
|
||||
import Save from './save/index.vue'
|
||||
import { onlyMessage} from '@/utils/comm';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import Export from './Export/index.vue'
|
||||
import { usePermissionStore } from '@/store/permission';
|
||||
const emit = defineEmits(['selectData'])
|
||||
|
@ -88,34 +71,34 @@ const saveShow = ref(false)
|
|||
const addType = ref('add')
|
||||
const listData = ref<any[]>([])
|
||||
const editData = ref()
|
||||
const selectedKeys:any = ref([])
|
||||
const showSave = () =>{
|
||||
const selectedKeys: any = ref([])
|
||||
const showSave = () => {
|
||||
saveShow.value = true
|
||||
addType.value = 'add'
|
||||
}
|
||||
const downVisible = ref(false)
|
||||
const searchValue = ref()
|
||||
const queryData = (first?:Boolean,searchName?:any) =>{
|
||||
const params = searchName ? {sorts: [{ name: 'createTime', order: 'desc' }],terms:[{terms:[{value:'%'+ searchName +'%',termType:'like',column:'name'}]}]} : {sorts: [{ name: 'createTime', order: 'desc' }]}
|
||||
getDicList(params).then((res:any)=>{
|
||||
if(res.status === 200){
|
||||
const queryData = (first?: Boolean, searchName?: any) => {
|
||||
const params = searchName ? { sorts: [{ name: 'createTime', order: 'desc' }], terms: [{ terms: [{ value: '%' + searchName + '%', termType: 'like', column: 'name' }] }] } : { sorts: [{ name: 'createTime', order: 'desc' }] }
|
||||
getDicList(params).then((res: any) => {
|
||||
if (res.status === 200) {
|
||||
listData.value = res.result
|
||||
if(first && res.result.length){
|
||||
if (first && res.result.length) {
|
||||
selectDic(res.result[0])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
const search = () =>{
|
||||
queryData(true,searchValue.value)
|
||||
const search = () => {
|
||||
queryData(true, searchValue.value)
|
||||
}
|
||||
const searchChange = () =>{
|
||||
console.log(searchValue.value ==='')
|
||||
if(searchValue.value === ''){
|
||||
const searchChange = () => {
|
||||
console.log(searchValue.value === '')
|
||||
if (searchValue.value === '') {
|
||||
queryData(true)
|
||||
}
|
||||
}
|
||||
const showEdit = (data:any) =>{
|
||||
const showEdit = (data: any) => {
|
||||
saveShow.value = true
|
||||
addType.value = 'edit'
|
||||
editData.value = data
|
||||
|
@ -123,10 +106,10 @@ const showEdit = (data:any) =>{
|
|||
/**
|
||||
* 重新请求数据
|
||||
*/
|
||||
const reload = () =>{
|
||||
const reload = () => {
|
||||
queryData()
|
||||
}
|
||||
const saveSuccess = () =>{
|
||||
const saveSuccess = () => {
|
||||
saveShow.value = false
|
||||
reload()
|
||||
}
|
||||
|
@ -135,49 +118,49 @@ const saveSuccess = () =>{
|
|||
* @param id 字典id
|
||||
* 删除字典
|
||||
*/
|
||||
const deleteDic = (id:string) =>{
|
||||
deleteDictionary(id).then((res:any)=>{
|
||||
if(res.status === 200){
|
||||
const deleteDic = (id: string) => {
|
||||
deleteDictionary(id).then((res: any) => {
|
||||
if (res.status === 200) {
|
||||
onlyMessage('操作成功!')
|
||||
queryData(true)
|
||||
}else{
|
||||
onlyMessage('操作失败!','error')
|
||||
} else {
|
||||
onlyMessage('操作失败!', 'error')
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 更新字典
|
||||
*/
|
||||
const updateDic = (data:any)=>{
|
||||
const updateDic = (data: any) => {
|
||||
data.status = data.status === 1 ? 0 : 1
|
||||
addDictionary(data).then((res:any)=>{
|
||||
if(res.status===200){
|
||||
addDictionary(data).then((res: any) => {
|
||||
if (res.status === 200) {
|
||||
onlyMessage('操作成功!')
|
||||
reload()
|
||||
}else{
|
||||
onlyMessage('操作失败!','error')
|
||||
} else {
|
||||
onlyMessage('操作失败!', 'error')
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 切换选中字典
|
||||
*/
|
||||
const selectDic = (selectKeys:any)=>{
|
||||
const selectDic = (selectKeys: any) => {
|
||||
selectedKeys.value = [selectKeys.id]
|
||||
emit('selectData',selectKeys)
|
||||
emit('selectData', selectKeys)
|
||||
}
|
||||
/**
|
||||
* 导入字典
|
||||
*/
|
||||
const beforeUpload = (file:any) => {
|
||||
if(file.type === 'application/json') {
|
||||
const beforeUpload = (file: any) => {
|
||||
if (file.type === 'application/json') {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(file);
|
||||
reader.onload = async(json) => {
|
||||
if(json.target?.result){
|
||||
reader.onload = async (json) => {
|
||||
if (json.target?.result) {
|
||||
const data = JSON.parse(json.target?.result);
|
||||
const res =await addDictionary(data)
|
||||
if(res.status === 200){
|
||||
const res = await addDictionary(data)
|
||||
if (res.status === 200) {
|
||||
reload()
|
||||
onlyMessage('操作成功!')
|
||||
}
|
||||
|
@ -190,26 +173,39 @@ const selectDic = (selectKeys:any)=>{
|
|||
}
|
||||
};
|
||||
|
||||
const closeDown = () =>{
|
||||
const closeDown = () => {
|
||||
downVisible.value = false
|
||||
}
|
||||
onMounted(()=>{
|
||||
onMounted(() => {
|
||||
queryData(true)
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-tree-switcher){
|
||||
.left-contain {
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-tree-switcher) {
|
||||
display: none;
|
||||
}
|
||||
.controls{
|
||||
|
||||
.tree {
|
||||
height: calc(100% - 110px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.controls {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.treeItem{
|
||||
|
||||
.treeItem {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.itemText{
|
||||
|
||||
.itemText {
|
||||
line-height: 32px;
|
||||
max-width:40%
|
||||
max-width: 40%;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -66,7 +66,7 @@ const validateInput = async (_rule: Rule, value: string) => {
|
|||
* 校验value唯一
|
||||
*/
|
||||
const validateValue = async (_rule: Rule, value: string) => {
|
||||
if (value) {
|
||||
if (value && props.type === 'add') {
|
||||
const res:any = await verifyValue({
|
||||
terms: [
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="des">
|
||||
<div class="des_head">
|
||||
<div>字典ID:<span>{{ data.id }}</span></div>
|
||||
<div>说明:<span>{{ data.describe }}</span></div>
|
||||
|
@ -12,7 +12,7 @@
|
|||
}}</span></div>
|
||||
</div>
|
||||
<div class="contain">
|
||||
<pro-search :columns="columns" @search="handleSearch" />
|
||||
<pro-search :columns="columns" @search="handleSearch" target="system_dictionary"/>
|
||||
<JProTable :columns="columns" model="TABLE" :request="queryItem" :params="params" ref="tableRef">
|
||||
<template #headerTitle>
|
||||
<PermissionButton type="primary" @click="add" hasPermission="system/Dictionary:add">
|
||||
|
@ -167,7 +167,7 @@ const queryItem = async (_params: any) => {
|
|||
if (props.data?.id) {
|
||||
const params = {
|
||||
..._params,
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
sorts: [{ name: 'ordinal', order: 'asc' }],
|
||||
terms: [
|
||||
..._params.terms,
|
||||
{
|
||||
|
@ -209,6 +209,7 @@ watch(() => props?.data?.id, () => {
|
|||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
||||
.des_head {
|
||||
padding: 10px 20px;
|
||||
background-color: rgb(242, 242, 242);
|
||||
|
|
|
@ -63,7 +63,7 @@ const form = reactive({
|
|||
if (props.type === 'add') {
|
||||
const res:any = await verifyId(value);
|
||||
if (res.status === 200 && res.result) {
|
||||
return Promise.reject('ID重复');
|
||||
return Promise.reject('该字典ID已存在');
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
|
|
@ -1,40 +1,45 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<page-container>
|
||||
<FullPage>
|
||||
<div class="dictionary_contain">
|
||||
<div class="dictionary_left">
|
||||
<Left @selectData="selectData"/>
|
||||
<Left @selectData="selectData" />
|
||||
</div>
|
||||
<div class="dictionary_right">
|
||||
<Right :data="data"/>
|
||||
<Right :data="data" />
|
||||
</div>
|
||||
</div>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Left from './components/Left.vue'
|
||||
import Right from './components/Right/index.vue'
|
||||
const data = ref()
|
||||
const selectData = (i:any)=>{
|
||||
data.value= i
|
||||
const selectData = (i: any) => {
|
||||
data.value = i
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.dictionary_contain{
|
||||
display: flex;
|
||||
.dictionary_contain {
|
||||
background-color: #fff;
|
||||
padding: 24px;
|
||||
padding-bottom: 0;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
.dictionary_left{
|
||||
|
||||
.dictionary_left {
|
||||
position: absolute;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
padding-right: 24px;
|
||||
flex:1;
|
||||
height:100%
|
||||
width: 310px;
|
||||
height: 100%;
|
||||
}
|
||||
.dictionary_right{
|
||||
flex:4
|
||||
|
||||
.dictionary_right {
|
||||
margin-left: 317px;
|
||||
width: calc(100% - 317px);
|
||||
}
|
||||
</style>
|
|
@ -315,6 +315,7 @@ const form = reactive({
|
|||
getMenuInfo_api(routeParams.id).then((resp: any) => {
|
||||
form.data = {
|
||||
...(resp.result as formType),
|
||||
permissions: resp.result?.permissions ? resp.result.permissions : [],
|
||||
accessSupport:
|
||||
resp.result?.accessSupport?.value || 'unsupported',
|
||||
};
|
||||
|
|
|
@ -65,6 +65,7 @@ import {
|
|||
import {
|
||||
filterMenu,
|
||||
initData,
|
||||
inItSelected,
|
||||
drop,
|
||||
select,
|
||||
getMaxDepth,
|
||||
|
@ -128,7 +129,38 @@ const getProvidersFn = async () => {
|
|||
}
|
||||
}
|
||||
getProvidersFn();
|
||||
function filterTree(nodes: Array<any>, selectedKeys: Array<any>,parentId?:string) {
|
||||
/**
|
||||
* 作用:过滤掉非选中菜单重新组成新的数组
|
||||
*/
|
||||
// function filterTree(nodes: Array<any>, selectedKeys: Array<any>,parentId?:string) {
|
||||
// const filtered = [];
|
||||
// for (let i = 0; i < nodes.length; i++) {
|
||||
// const node = nodes[i];
|
||||
// if (!node.code) {
|
||||
// continue;
|
||||
// }
|
||||
// node.parentId = parentId ? undefined : parentId
|
||||
// if (selectedKeys.indexOf(node.code) !== -1) {
|
||||
// filtered.push(node);
|
||||
// if (node.children) {
|
||||
// node.children = filterTree(node.children, selectedKeys,node.id);
|
||||
// }
|
||||
// } else if (node.children) {
|
||||
// node.children = filterTree(node.children, selectedKeys,node.id);
|
||||
// if (node.children.length > 0) {
|
||||
// filtered.push(node);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return filtered;
|
||||
// }
|
||||
/**
|
||||
*
|
||||
* @param nodes 菜单数据
|
||||
* @param selectedKeys 选中的菜单
|
||||
* 选中和非选中改变show的值
|
||||
*/
|
||||
const dealTree = (nodes: Array<any>, selectedKeys: Array<any>,parentId?:string) =>{
|
||||
const filtered = [];
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i];
|
||||
|
@ -136,26 +168,33 @@ function filterTree(nodes: Array<any>, selectedKeys: Array<any>,parentId?:string
|
|||
continue;
|
||||
}
|
||||
node.parentId = parentId ? undefined : parentId
|
||||
node?.options ? node.options.show = false : node.options = { show : false }
|
||||
|
||||
if (selectedKeys.indexOf(node.code) !== -1) {
|
||||
filtered.push(node);
|
||||
node.options.show = true
|
||||
if (node.children) {
|
||||
node.children = filterTree(node.children, selectedKeys,node.id);
|
||||
node.children = dealTree(node.children, selectedKeys,node.id);
|
||||
}
|
||||
} else if (node.children) {
|
||||
node.children = filterTree(node.children, selectedKeys,node.id);
|
||||
if (node.children.length > 0) {
|
||||
filtered.push(node);
|
||||
node.children = dealTree(node.children, selectedKeys,node.id);
|
||||
const children =node.children.filter((item:any)=>{
|
||||
item.options.show === true
|
||||
})
|
||||
if (children.length > 0) {
|
||||
node.options.show = true
|
||||
}
|
||||
}else{
|
||||
node.options.show = false
|
||||
}
|
||||
filtered.push(node)
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
const handleOk = async () => {
|
||||
const _dataArr = filterTree(cloneDeep(treeData.value), selectedKeys.value);
|
||||
// const _dataArr = filterTree(cloneDeep(treeData.value), selectedKeys.value);
|
||||
const _dataArr = dealTree(cloneDeep(treeData.value),selectedKeys.value)
|
||||
const _dataSorts = handleSorts(_dataArr)
|
||||
loading.value = true;
|
||||
console.log(_dataSorts)
|
||||
const res = await updateMenus(_dataSorts).catch(() => {});
|
||||
if (res?.status === 200) {
|
||||
onlyMessage('操作成功', 'success');
|
||||
|
@ -204,13 +243,13 @@ const onDragend = (info: AntTreeNodeDropEvent) => {
|
|||
|
||||
onMounted(() => {
|
||||
getSystemPermission_api().then((resp: any) => {
|
||||
const filterBaseMenu = BaseMenu.filter(item => ![
|
||||
USER_CENTER_MENU_CODE,messageSubscribe
|
||||
].includes(item.code))
|
||||
baseMenu.value = filterMenu(
|
||||
resp.result.map((item: any) => JSON.parse(item).id),
|
||||
filterBaseMenu,
|
||||
);
|
||||
// const filterBaseMenu = BaseMenu.filter(item => ![
|
||||
// USER_CENTER_MENU_CODE,messageSubscribe
|
||||
// ].includes(item.code))
|
||||
// baseMenu.value = filterMenu(
|
||||
// resp.result.map((item: any) => JSON.parse(item).id),
|
||||
// filterBaseMenu,
|
||||
// );
|
||||
getMenuTree_api(params).then((resp: any) => {
|
||||
if (resp.status == 200) {
|
||||
systemMenu.value = resp.result?.filter(
|
||||
|
@ -220,15 +259,14 @@ onMounted(() => {
|
|||
].includes(item.code),
|
||||
);
|
||||
//初始化菜单
|
||||
initData(baseMenu.value); // 不要克隆,通过引用 处理key和name
|
||||
const systemMenuData = initData(systemMenu.value);
|
||||
// initData(baseMenu.value); // 不要克隆,通过引用 处理key和name
|
||||
const systemMenuData = inItSelected(systemMenu.value);
|
||||
selectedKeys.value = systemMenuData.checkedKeys;
|
||||
|
||||
const AllMenu = filterMenus(mergeArr(
|
||||
cloneDeep(baseMenu.value),
|
||||
cloneDeep(systemMenu.value),
|
||||
))
|
||||
console.log(AllMenu);
|
||||
// const AllMenu = filterMenus(mergeArr(
|
||||
// cloneDeep(baseMenu.value),
|
||||
// cloneDeep(systemMenu.value),
|
||||
// ))
|
||||
// console.log(AllMenu);
|
||||
// 处理排序
|
||||
treeData.value = handleSortsArr(systemMenu.value);
|
||||
}
|
||||
|
|
|
@ -115,9 +115,7 @@ export const initData = (Menu: any) => {
|
|||
arr.forEach((item: any) => {
|
||||
item.title = item.code;
|
||||
item.key = item.code; // treeData需要唯一key
|
||||
|
||||
checkedKeys.push(item.code);
|
||||
|
||||
if (item?.children) {
|
||||
getMap(item?.children);
|
||||
}
|
||||
|
@ -127,6 +125,23 @@ export const initData = (Menu: any) => {
|
|||
return { checkedKeys };
|
||||
};
|
||||
|
||||
/**通过options判断选中菜单 */
|
||||
export const inItSelected = (Menu:any) =>{
|
||||
const checkedKeys: any = [];
|
||||
const getMap = (arr: any) => {
|
||||
arr.forEach((item: any) => {
|
||||
item.title = item.code;
|
||||
item.key = item.code; // treeData需要唯一key
|
||||
item?.options?.show ? checkedKeys.push(item.code) : '';
|
||||
if (item?.children) {
|
||||
getMap(item?.children);
|
||||
}
|
||||
});
|
||||
};
|
||||
getMap(Menu);
|
||||
return { checkedKeys };
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找父级、子级code
|
||||
* @param data 当前完整的菜单
|
||||
|
|
|
@ -41,11 +41,12 @@
|
|||
<template #action="slotProps">
|
||||
<j-space :size="16">
|
||||
<j-tooltip>
|
||||
<template #title>编辑</template>
|
||||
<template #title>{{ slotProps?.options?.LowCode ? '低码创建的菜单不支持编辑' : '编辑' }}</template>
|
||||
<j-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
@click="table.toDetails(slotProps)"
|
||||
:disabled="slotProps?.options?.LowCode"
|
||||
>
|
||||
<AIcon type="EditOutlined" />
|
||||
</j-button>
|
||||
|
@ -53,8 +54,8 @@
|
|||
<PermissionButton
|
||||
type="link"
|
||||
:hasPermission="`${permission}:add`"
|
||||
:tooltip="{ title: slotProps?.options?.LowCode ? '低码创建的菜单不支持编辑' : slotProps.level >= 3 ? '仅支持3级菜单' : '新增子菜单' }"
|
||||
:disabled="slotProps.level >= 3 || slotProps?.options?.LowCode"
|
||||
:tooltip="{ title: slotProps.level >= 3 ? '仅支持3级菜单' : '新增子菜单' }"
|
||||
:disabled="slotProps.level >= 3"
|
||||
@click="table.addChildren(slotProps)"
|
||||
>
|
||||
<AIcon type="PlusCircleOutlined" />
|
||||
|
|
|
@ -10,22 +10,9 @@
|
|||
class="edit-dialog-container"
|
||||
>
|
||||
<j-form ref="formRef" :model="form.data" layout="vertical">
|
||||
<j-form-item
|
||||
label="名称"
|
||||
name="name"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入名称' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="form.data.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
name="relation"
|
||||
label="标识"
|
||||
label="关系标识"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入标识' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
|
@ -83,6 +70,32 @@
|
|||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-form-item
|
||||
label="正向关系名称"
|
||||
name="name"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入名称' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="form.data.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="反向关系名称"
|
||||
name="reverseName"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入名称' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="form.data.reverseName"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item name="description" label="说明">
|
||||
<j-textarea
|
||||
v-model:value="form.data.description"
|
||||
|
@ -203,6 +216,7 @@ form.getObjectList();
|
|||
|
||||
type formType = {
|
||||
name: string;
|
||||
reverseName: string;
|
||||
relation: string;
|
||||
objectType: string | undefined;
|
||||
targetType: string | undefined;
|
||||
|
|
|
@ -80,7 +80,7 @@ const permission = 'system/Relationship';
|
|||
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
title: '正向关系名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true,
|
||||
|
@ -89,6 +89,16 @@ const columns = [
|
|||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '正向关系名称',
|
||||
dataIndex: 'reverseName',
|
||||
key: 'reverseName',
|
||||
ellipsis: true,
|
||||
fixed: 'left',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '关联方',
|
||||
dataIndex: 'objectTypeName',
|
||||
|
|
|
@ -15,38 +15,45 @@
|
|||
</j-button>
|
||||
</div>
|
||||
<div class="listBox">
|
||||
<j-tree :tree-data="listData" v-if="listData.length" :fieldNames="{title:'name',key:'id'}" blockNode :selectedKeys="selectedKeys">
|
||||
<j-tree
|
||||
:tree-data="listData"
|
||||
v-if="listData.length"
|
||||
:fieldNames="{title:'name',key:'id',children:'children'}"
|
||||
blockNode
|
||||
:selectedKeys="selectedKeys"
|
||||
:default-expanded-keys="['global_role']"
|
||||
:showLine="{ showLeafIcon: false }"
|
||||
>
|
||||
<template #title="item">
|
||||
<div class="treeItem" @click="()=>selectGroup(item.data.id)" v-if="!item.data?.edit">
|
||||
<div class="itemText">
|
||||
<Ellipsis style="width: calc(100%-100px)">{{ item.name }}</Ellipsis>
|
||||
|
||||
<div class="treeItem" @click="()=>selectGroup(item.data.id)" v-if="!item.data?.edit">
|
||||
<template v-if="!item?.children">
|
||||
<div class="itemText">
|
||||
<Ellipsis style="width: calc(100%-100px)">{{ item.name }}</Ellipsis>
|
||||
</div>
|
||||
<div @click="(e) => e.stopPropagation()" v-if="item.id !== 'default_group'">
|
||||
<PermissionButton
|
||||
type="text"
|
||||
hasPermission="system/Role:groupDelete"
|
||||
:popConfirm="{
|
||||
title: `确定要删除?`,
|
||||
onConfirm: () => deleteGroup(item.id),
|
||||
}"
|
||||
:disabled="item.id === 'default_group'"
|
||||
>
|
||||
删除
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
type="text"
|
||||
hasPermission="system/Role:groupUpdate"
|
||||
@click="editGroup(item.data)"
|
||||
:disabled="item.id === 'default_group'"
|
||||
>
|
||||
编辑
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else><Ellipsis style="width: calc(100%-100px)">{{ item.name }}</Ellipsis></template>
|
||||
</div>
|
||||
<div @click="(e) => e.stopPropagation()">
|
||||
<PermissionButton
|
||||
type="text"
|
||||
hasPermission="system/Role:delete"
|
||||
:popConfirm="{
|
||||
title: `确定要删除?`,
|
||||
onConfirm: () => deleteGroup(item.id),
|
||||
}"
|
||||
:disabled="item.id === 'default_group'"
|
||||
>
|
||||
删除
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
type="text"
|
||||
hasPermission="system/Role:update"
|
||||
@click="editGroup(item.data)"
|
||||
:disabled="item.id === 'default_group'"
|
||||
>
|
||||
编辑
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<j-input v-model:value="addName" @blur="()=>saveGroup(item.data)" ref="inputRef" :maxlength="64"></j-input>
|
||||
</div>
|
||||
</template>
|
||||
</j-tree>
|
||||
<j-empty v-else style="margin-top: 100px;"/>
|
||||
|
@ -66,8 +73,12 @@ const { userInfos } = storeToRefs(userInfoStore)
|
|||
const admin = computed(() => {
|
||||
return userInfos.value?.username === 'admin';
|
||||
})
|
||||
const listData:any = ref([])
|
||||
const selectedKeys = ref<string[]>([])
|
||||
const listData:any = ref([{
|
||||
name:'全局角色',
|
||||
id:'global_role',
|
||||
children:[]
|
||||
}])
|
||||
const selectedKeys = ref<string[]>(['global_role'])
|
||||
const searchValue = ref()
|
||||
const inputRef = ref()
|
||||
const addName = ref()
|
||||
|
@ -76,10 +87,10 @@ const queryGroup = async(select?:Boolean,searchName?:string) =>{
|
|||
const params = searchName ? {sorts: [{ name: 'createTime', order: 'desc' }],terms:[{terms:[{value:'%'+ searchName +'%',termType:'like',column:'name'}]}]} : {sorts: [{ name: 'createTime', order: 'desc' }]}
|
||||
const req:any = await queryRoleGroup(params)
|
||||
if(req.status === 200){
|
||||
listData.value = req.result
|
||||
if(req.result.length && select){
|
||||
selectGroup(req.result[0].id)
|
||||
}
|
||||
listData.value[0].children = req.result
|
||||
// if(req.result.length && select){
|
||||
// selectGroup(req.result[0].id)
|
||||
// }
|
||||
}
|
||||
}
|
||||
const addGroup = () =>{
|
||||
|
@ -121,7 +132,8 @@ const searchChange = () =>{
|
|||
}
|
||||
const selectGroup = (id:string) =>{
|
||||
selectedKeys.value = [id]
|
||||
emit('selectData',selectedKeys.value)
|
||||
id === 'global_role' ? emit('selectData','') : emit('selectData',selectedKeys.value)
|
||||
|
||||
}
|
||||
const deleteGroup = async(id:string)=>{
|
||||
const res:any = await deleteRoleGroup(id)
|
||||
|
@ -144,10 +156,7 @@ onMounted(()=>{
|
|||
queryGroup(true)
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-tree-switcher){
|
||||
display: none;
|
||||
}
|
||||
<style lang="less" scoped>
|
||||
.controls{
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,12 @@
|
|||
<pro-search :columns="columns" target="system-role" @search="handelSearch" />
|
||||
<FullPage>
|
||||
<j-pro-table ref="tableRef" :columns="columns" :request="getRoleList_api" model="TABLE"
|
||||
:params="queryParams" :defaultParams="defaultParams">
|
||||
:params="queryParams" :defaultParams="{
|
||||
sorts: [
|
||||
{ name: 'createTime', order: 'desc' },
|
||||
{ name: 'id', order: 'desc' },
|
||||
]
|
||||
}">
|
||||
<template #headerTitle>
|
||||
<PermissionButton type="primary" :hasPermission="`${permission}:add`" @click="addRole">
|
||||
<AIcon type="PlusOutlined" />新增
|
||||
|
@ -16,8 +21,8 @@
|
|||
<template v-for="i in getActions(slotProps, 'table')" :key="i.key">
|
||||
<PermissionButton :disabled="i.disabled" :popConfirm="i.popConfirm" :tooltip="{
|
||||
...i.tooltip,
|
||||
}" @click="i.onClick" type="link" style="padding: 0 5px"
|
||||
:danger="i.key === 'delete'" :hasPermission="'system/Role:' + i.key
|
||||
}" @click="i.onClick" type="link" style="padding: 0 5px" :danger="i.key === 'delete'"
|
||||
:hasPermission="'system/Role:' + i.key
|
||||
">
|
||||
<template #icon>
|
||||
<AIcon :type="i.icon" />
|
||||
|
@ -53,22 +58,7 @@ const { jumpPage } = useMenuStore();
|
|||
const modalType = ref('add')
|
||||
const current = ref()
|
||||
const isSave = !!useRoute().query.save;
|
||||
const queryParams = ref({});
|
||||
const defaultParams = ref({
|
||||
sorts: [
|
||||
{ name: 'createTime', order: 'desc' },
|
||||
{ name: 'id', order: 'desc' },
|
||||
],
|
||||
terms: [
|
||||
{
|
||||
terms: [{
|
||||
value: props.groupId,
|
||||
termType: 'eq',
|
||||
column: 'groupId'
|
||||
}]
|
||||
}
|
||||
]
|
||||
})
|
||||
const queryParams = ref<any>({terms:[]});
|
||||
// 表格
|
||||
const tableRef = ref<Record<string, any>>();
|
||||
const dialogVisible = ref(isSave);
|
||||
|
@ -168,16 +158,27 @@ const getActions = (
|
|||
return actions;
|
||||
};
|
||||
|
||||
const addRole = () =>{
|
||||
const addRole = () => {
|
||||
dialogVisible.value = true
|
||||
modalType.value = 'add'
|
||||
}
|
||||
const handelSearch = (search: any) => {
|
||||
queryParams.value = search
|
||||
queryParams.value.terms =props.groupId ? [{
|
||||
value: props.groupId,
|
||||
termType: 'eq',
|
||||
column: 'groupId'
|
||||
}, ...search.terms] : [...search.terms]
|
||||
}
|
||||
watch(() => props.groupId, () => {
|
||||
defaultParams.value.terms[0].terms[0].value = props.groupId
|
||||
tableRef.value?.reload()
|
||||
watch(() => props.groupId, (value) => {
|
||||
queryParams.value = value ? {
|
||||
terms: [{
|
||||
value: props.groupId,
|
||||
termType: 'eq',
|
||||
column: 'groupId'
|
||||
}]
|
||||
} : {
|
||||
terms: []
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Reference in New Issue