feat: 角色管理改造

This commit is contained in:
leiqiaochu 2023-09-08 16:27:32 +08:00
parent a3b29ae01e
commit 99533a38be
12 changed files with 398 additions and 143 deletions

View File

@ -1,3 +1,4 @@
import request from '@/utils/request';
import server from '@/utils/request';
// 获取角色列表
@ -26,3 +27,9 @@ export const getUserByRole_api = (data: any): Promise<any> => server.post(`/user
export const bindUser_api = (roleId:string, data: string[]): Promise<any> => server.post(`/role/${roleId}/users/_bind`, data);
// 将用户与角色解绑
export const unbindUser_api = (roleId:string, data: string[]): Promise<any> => server.post(`/role/${roleId}/users/_unbind`, data);
//查询分组
export const queryRoleGroup = (data:any) => request.post('/role/group/_query/no-paging',data)
//保存分组
export const saveRoleGroup = (data:any) => request.patch('/role/group',data)
//删除分组
export const deleteRoleGroup = (id:string) => request.remove(`/role/group/${id}`)

View File

@ -0,0 +1,154 @@
<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="addGroup"
style="width: 100%"
>
新增分组
</PermissionButton>
</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="()=>selectGroup(item.data.id)" v-if="!item.data?.edit">
<div class="itemText">
<Ellipsis style="width: calc(100%-100px)">{{ item.name }}</Ellipsis>
</div>
<div @click="(e) => e.stopPropagation()">
<PermissionButton
type="text"
hasPermission="system/Role:delete"
:popConfirm="{
title: `确定要删除?`,
onConfirm: () => deleteGroup(item.id),
}"
>
删除
</PermissionButton>
<PermissionButton
type="text"
hasPermission="system/Role:update"
@click="editGroup(item.data)"
>
编辑
</PermissionButton>
</div>
</div>
<div v-else>
<j-input v-model:value="addName" @blur="()=>saveGroup(item.data)" ref="inputRef"></j-input>
<div style="color: red;" v-if="validateTip">分组名称不能为空</div>
</div>
</template>
</j-tree>
<j-empty v-else style="margin-top: 100px;"/>
</div>
</div>
</template>
<script lang="ts" setup>
import { onlyMessage } from '@/utils/comm';
import { queryRoleGroup , saveRoleGroup , deleteRoleGroup } from '@/api/system/role'
import { randomString } from '@/utils/utils'
const emit = defineEmits(['selectData'])
const listData:any = ref([])
const selectedKeys = ref<string[]>([])
const searchValue = ref()
const inputRef = ref()
const validateTip = ref()
const addName = ref()
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)
}
}
}
const addGroup = () =>{
listData.value.push({
name:'',
edit:true,
id: randomString()
})
nextTick(()=>{
inputRef.value.focus()
})
}
const saveGroup = async(data:any) =>{
if(addName.value === ''){
validateTip.value = true
}else{
validateTip.value = false
const saveData = {
name:addName.value,
id:data.id
}
const res = await saveRoleGroup(saveData)
if(res.status === 200){
onlyMessage('操作成功!')
queryGroup()
}else{
onlyMessage('操作失败!')
}
}
}
const search = () =>{
queryGroup(true,searchValue.value)
}
const searchChange = () =>{
if(searchValue.value === '' ){
queryGroup()
}
}
const selectGroup = (id:string) =>{
selectedKeys.value = [id]
emit('selectData',selectedKeys.value)
}
const deleteGroup = async(id:string)=>{
const res:any = await deleteRoleGroup(id)
if(res.status === 200){
onlyMessage('操作成功!')
queryGroup(true)
}else{
onlyMessage('操作失败!')
}
}
const editGroup = (data:any) => {
addName.value = data.name
listData.value.forEach((item:any)=>{
if(item.id === data.id){
item.edit = true
}
})
}
onMounted(()=>{
queryGroup(true)
})
</script>
<style lang="less" scoped>
:deep(.ant-tree-switcher){
display: none;
}
.controls{
margin: 10px 0;
}
.treeItem{
display: flex;
justify-content: space-between;
.itemText{
line-height: 32px;
max-width:40%
}
}
</style>

View File

@ -22,6 +22,19 @@
allow-clear
/>
</j-form-item>
<j-form-item
name="groupId"
label="分组"
:rules="[
{ required: true, message: '请选择分组' },
]"
>
<j-select
v-model:value="form.groupId"
placeholder="请选择分组"
:options="groupOptions"
/>
</j-form-item>
<j-form-item name="name" label="说明">
<j-textarea
v-model:value="form.description"
@ -37,7 +50,7 @@
<script setup lang="ts">
import { FormInstance } from 'ant-design-vue';
import { saveRole_api } from '@/api/system/role';
import { saveRole_api , queryRoleGroup} from '@/api/system/role';
import { useMenuStore } from '@/store/menu';
import { onlyMessage } from '@/utils/comm';
const route = useRoute();
@ -46,12 +59,20 @@ const { jumpPage } = useMenuStore();
const emits = defineEmits(['update:visible']);
const props = defineProps<{
visible: boolean;
groupId:{
type:String,
default:""
}
}>();
//
const loading = ref(false);
const form = ref<any>({});
const form = ref<any>({
name:'',
groupId:'',
description:''
});
const formRef = ref<FormInstance>();
const groupOptions = ref<any>([])
const confirm = () => {
loading.value = true;
formRef.value
@ -74,6 +95,22 @@ const confirm = () => {
.finally(() => (loading.value = false));
};
//
const getGroupOptions = ()=>{
queryRoleGroup({sorts: [{ name: 'createTime', order: 'desc' }]}).then((res:any)=>{
if(res.status ===200){
groupOptions.value = res.result.map((item:any)=>{
return {
label:item.name,
value:item.id
}
})
}
})
}
onMounted(()=>{
getGroupOptions()
form.value.groupId = props.groupId
})
</script>
<style scoped></style>

View File

@ -0,0 +1,159 @@
<template>
<page-container>
<div class="role-container">
<pro-search
:columns="columns"
target="system-role"
@search="(params:any)=>queryParams = {...params}"
/>
<FullPage>
<j-pro-table
ref="tableRef"
:columns="columns"
:request="getRoleList_api"
model="TABLE"
:params="queryParams"
:defaultParams="{
sorts: [
{ name: 'createTime', order: 'desc' },
{ name: 'id', order: 'desc' },
],
terms:[
{
terms:[{
value: groupId,
termType:'eq',
column:'groupId'
}]
}
]
}"
>
<template #headerTitle>
<PermissionButton
type="primary"
:hasPermission="`${permission}:add`"
@click="dialogVisible = true"
>
<AIcon type="PlusOutlined" />新增
</PermissionButton>
</template>
<template #action="slotProps">
<j-space :size="16">
<PermissionButton
:hasPermission="`${permission}:update`"
type="link"
:tooltip="{
title: '编辑',
}"
@click="
jumpPage(`system/Role/Detail`, {
id: slotProps.id,
})
"
>
<AIcon type="EditOutlined" />
</PermissionButton>
<PermissionButton
type="link"
:hasPermission="`${permission}:delete`"
:tooltip="{ title: '删除' }"
:popConfirm="{
title: `确定要删除吗`,
onConfirm: () => clickDel(slotProps),
}"
>
<AIcon type="DeleteOutlined" />
</PermissionButton>
</j-space>
</template>
</j-pro-table>
</FullPage>
<AddDialog v-if="dialogVisible" v-model:visible="dialogVisible" :groupId="groupId"/>
</div>
</page-container>
</template>
<script setup lang="ts" name="Role">
import PermissionButton from '@/components/PermissionButton/index.vue';
import AddDialog from './components/AddDialog.vue';
import { getRoleList_api, delRole_api } from '@/api/system/role';
import { useMenuStore } from '@/store/menu';
import { onlyMessage } from '@/utils/comm';
const props = defineProps({
groupId:{
type:String,
default:''
}
})
const permission = 'system/Role';
const { jumpPage } = useMenuStore();
const isSave = !!useRoute().query.save;
const columns = [
{
title: '标识',
dataIndex: 'id',
key: 'id',
ellipsis: true,
fixed: 'left',
search: {
type: 'string',
},
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
ellipsis: true,
search: {
type: 'string',
},
},
{
title: '说明',
key: 'description',
ellipsis: true,
dataIndex: 'description',
search: {
type: 'string',
},
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
width: 120,
fixed: 'right',
scopedSlots: true,
},
];
const queryParams = ref({});
//
const tableRef = ref<Record<string, any>>();
const clickDel = (row: any) => {
delRole_api(row.id).then((resp: any) => {
if (resp.status === 200) {
tableRef.value?.reload();
onlyMessage('操作成功!');
}
});
};
const dialogVisible = ref(isSave);
watch(()=>props.groupId,()=>{
tableRef.value?.reload()
})
</script>
<style lang="less" scoped>
.role-container {
:deep(.ant-table-cell) {
.ant-btn-link {
padding: 0;
}
}
}
</style>

View File

@ -1,142 +1,40 @@
<template>
<page-container>
<div class="role-container">
<pro-search
:columns="columns"
target="system-role"
@search="(params:any)=>queryParams = {...params}"
/>
<FullPage>
<j-pro-table
ref="tableRef"
:columns="columns"
:request="getRoleList_api"
model="TABLE"
:params="queryParams"
:defaultParams="{
sorts: [
{ name: 'createTime', order: 'desc' },
{ name: 'id', order: 'desc' },
],
}"
>
<template #headerTitle>
<PermissionButton
type="primary"
:hasPermission="`${permission}:add`"
@click="dialogVisible = true"
>
<AIcon type="PlusOutlined" />新增
</PermissionButton>
</template>
<template #action="slotProps">
<j-space :size="16">
<PermissionButton
:hasPermission="`${permission}:update`"
type="link"
:tooltip="{
title: '编辑',
}"
@click="
jumpPage(`system/Role/Detail`, {
id: slotProps.id,
})
"
>
<AIcon type="EditOutlined" />
</PermissionButton>
<PermissionButton
type="link"
:hasPermission="`${permission}:delete`"
:tooltip="{ title: '删除' }"
:popConfirm="{
title: `确定要删除吗`,
onConfirm: () => clickDel(slotProps),
}"
>
<AIcon type="DeleteOutlined" />
</PermissionButton>
</j-space>
</template>
</j-pro-table>
</FullPage>
<AddDialog v-if="dialogVisible" v-model:visible="dialogVisible" />
<div class="dictionary_contain">
<div class="dictionary_left">
<Left @select-data="selectData"/>
</div>
<div class="dictionary_right">
<Right :groupId="groupId"/>
</div>
</div>
</FullPage>
</page-container>
</template>
<script setup lang="ts" name="Role">
import PermissionButton from '@/components/PermissionButton/index.vue';
import AddDialog from './components/AddDialog.vue';
import { getRoleList_api, delRole_api } from '@/api/system/role';
import { useMenuStore } from '@/store/menu';
import { onlyMessage } from '@/utils/comm';
const permission = 'system/Role';
const { jumpPage } = useMenuStore();
const isSave = !!useRoute().query.save;
const columns = [
{
title: '标识',
dataIndex: 'id',
key: 'id',
ellipsis: true,
fixed: 'left',
search: {
type: 'string',
},
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
ellipsis: true,
search: {
type: 'string',
},
},
{
title: '说明',
key: 'description',
ellipsis: true,
dataIndex: 'description',
search: {
type: 'string',
},
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
width: 120,
fixed: 'right',
scopedSlots: true,
},
];
const queryParams = ref({});
//
const tableRef = ref<Record<string, any>>();
const clickDel = (row: any) => {
delRole_api(row.id).then((resp: any) => {
if (resp.status === 200) {
tableRef.value?.reload();
onlyMessage('操作成功!');
<script lang="ts" setup>
import Left from './RoleLeft/index.vue'
import Right from './RoleRight/index.vue'
const groupId = ref()
const selectData = (data:any)=>{
groupId.value = data[0]
}
});
};
const dialogVisible = ref(isSave);
</script>
<style lang="less" scoped>
.role-container {
:deep(.ant-table-cell) {
.ant-btn-link {
padding: 0;
.dictionary_contain{
display: flex;
background-color: #fff;
padding: 24px;
height: 100%;
}
.dictionary_left{
border-right: 1px solid #f0f0f0;
padding-right: 24px;
flex:1;
height:100%
}
.dictionary_right{
flex:4
}
</style>