fix: 修改bug

This commit is contained in:
leiqiaochu 2023-09-26 18:15:21 +08:00
parent 1540cd71f8
commit e482e158f6
14 changed files with 357 additions and 242 deletions

View File

@ -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']
}
],
},
],

View File

@ -6,62 +6,45 @@
</template>
</j-input>
<div class="controls">
<PermissionButton
type="primary"
hasPermission="system/Dictionary:add"
@click="showSave"
style="width: 60%"
>
<PermissionButton type="primary" hasPermission="system/Dictionary:add" @click="showSave" style="width: 160px">
新增字典
</PermissionButton>
<PermissionButton
type="text"
hasPermission="system/Dictionary:down"
@click="downVisible=true"
>
<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"
>
<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>
<j-tree :tree-data="listData" v-if="listData.length" :fieldNames="{title:'name',key:'id'}" blockNode :selectedKeys="selectedKeys">
<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 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 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-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="{
<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 type="text" hasPermission="system/Dictionary:update"
@click="showEdit(item.data)">
编辑
</PermissionButton>
</div>
@ -198,18 +181,31 @@ onMounted(()=>{
})
</script>
<style lang="less" scoped>
.left-contain {
width: 300px;
height: 100%;
}
:deep(.ant-tree-switcher) {
display: none;
}
.tree {
height: calc(100% - 110px);
overflow-y: auto;
}
.controls {
margin: 10px 0;
}
.treeItem {
display: flex;
justify-content: space-between;
.itemText {
line-height: 32px;
max-width:40%
max-width: 40%;
}
}
</style>

View File

@ -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: [
{

View File

@ -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);

View File

@ -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();
}

View File

@ -23,18 +23,23 @@ const selectData = (i:any)=>{
</script>
<style lang="less" scoped>
.dictionary_contain {
display: flex;
background-color: #fff;
padding: 24px;
padding-bottom: 0;
position: relative;
height: 100%;
}
.dictionary_left {
position: absolute;
border-right: 1px solid #f0f0f0;
padding-right: 24px;
flex:1;
height:100%
width: 310px;
height: 100%;
}
.dictionary_right {
flex:4
margin-left: 317px;
width: calc(100% - 317px);
}
</style>

View File

@ -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',
};

View File

@ -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); // keyname
const systemMenuData = initData(systemMenu.value);
// initData(baseMenu.value); // keyname
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);
}

View File

@ -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

View File

@ -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" />

View File

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

View File

@ -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',

View File

@ -15,17 +15,25 @@
</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">
<template v-if="!item?.children">
<div class="itemText">
<Ellipsis style="width: calc(100%-100px)">{{ item.name }}</Ellipsis>
</div>
<div @click="(e) => e.stopPropagation()">
<div @click="(e) => e.stopPropagation()" v-if="item.id !== 'default_group'">
<PermissionButton
type="text"
hasPermission="system/Role:delete"
hasPermission="system/Role:groupDelete"
:popConfirm="{
title: `确定要删除?`,
onConfirm: () => deleteGroup(item.id),
@ -36,16 +44,15 @@
</PermissionButton>
<PermissionButton
type="text"
hasPermission="system/Role:update"
hasPermission="system/Role:groupUpdate"
@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>
</template>
<template v-else><Ellipsis style="width: calc(100%-100px)">{{ item.name }}</Ellipsis></template>
</div>
</template>
</j-tree>
@ -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)
@ -145,9 +157,6 @@ onMounted(()=>{
})
</script>
<style lang="less" scoped>
:deep(.ant-tree-switcher){
display: none;
}
.controls{
margin: 10px 0;
}

View File

@ -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);
@ -173,11 +163,22 @@ const addRole = () =>{
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, (value) => {
queryParams.value = value ? {
terms: [{
value: props.groupId,
termType: 'eq',
column: 'groupId'
}]
} : {
terms: []
}
watch(() => props.groupId, () => {
defaultParams.value.terms[0].terms[0].value = props.groupId
tableRef.value?.reload()
})
</script>