feature:新增角色库

This commit is contained in:
fangyunong 2025-07-12 15:48:30 +08:00
parent c95ff9fa2c
commit 4ef3ad8d3f
4 changed files with 167 additions and 32 deletions

3
auto-imports.d.ts vendored
View File

@ -14,8 +14,11 @@ declare global {
const defineComponent: typeof import('vue')['defineComponent'] const defineComponent: typeof import('vue')['defineComponent']
const deleteUser: typeof import('./src/api/roleApi')['deleteUser'] const deleteUser: typeof import('./src/api/roleApi')['deleteUser']
const effectScope: typeof import('vue')['effectScope'] const effectScope: typeof import('vue')['effectScope']
const enable: typeof import('./src/api/roleApi')['enable']
const enableRole: typeof import('./src/api/roleApi')['enableRole']
const getCurrentInstance: typeof import('vue')['getCurrentInstance'] const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope'] const getCurrentScope: typeof import('vue')['getCurrentScope']
const getRoleList: typeof import('./src/api/roleApi')['getRoleList']
const getUserInfo: typeof import('./src/api/userApi')['getUserInfo'] const getUserInfo: typeof import('./src/api/userApi')['getUserInfo']
const getUserList: typeof import('./src/api/roleApi')['getUserList'] const getUserList: typeof import('./src/api/roleApi')['getUserList']
const h: typeof import('vue')['h'] const h: typeof import('vue')['h']

View File

@ -1,29 +1,56 @@
import http from "@/utils/request"; import http from "@/utils/request";
// 用户列表 // 用户列表
interface UserListQuery{ interface UserListQuery {
roleName?:string roleName?: string;
page:number page: number;
pageSize:number pageSize: number;
} }
interface UserListReturn{ interface UserListReturn {
totalCount:number, totalCount: number;
users:UserRaw[] users: UserRaw[];
} }
export function getUserList(data:UserListQuery):Promise<UserListReturn>{ export function getUserList(data: UserListQuery): Promise<UserListReturn> {
return http({ return http({
url:"/api/v1/AdminRoleControllers/SearchUserFromRole", url: "/api/v1/AdminRoleControllers/SearchUserFromRole",
method:'POST', method: "POST",
data data,
}) });
} }
// 删除用户 // 删除用户
export function deleteUser(userId:string){ export function deleteUser(userId: string) {
return http({ return http({
url:'/api/v1/AdminRoleControllers/DelUser', url: "/api/v1/AdminRoleControllers/DelUser",
method:'POST', method: "POST",
params:{ params: {
userId userId,
} },
}) });
} }
// 获取角色列表
export interface RoleListReturn {
concurrencyStamp?: string;
id: string;
name: string;
normalizedName: string;
}
export function getRoleList(): Promise<RoleListReturn[]> {
return http({
url: "/api/v1/AdminRoleControllers/AllRole",
method: "GET",
});
}
// 授权角色
interface EnableRoleQuery {
userId: string;
roleName: string;
}
export function enableRole(data:EnableRoleQuery) {
return http({
url: "/api/v1/AdminRoleControllers/EndowRole",
method: "POST",
data,
});
}

View File

@ -0,0 +1,63 @@
<template>
<n-modal v-model:show="show">
<n-card style="width: 450px" title="角色库" :bordered="false" size="huge" role="dialog" aria-modal="true">
<n-table :bordered="false" :single-line="false">
<thead>
<tr>
<th>角色Code</th>
<th>角色Name</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{ item.name }}</td>
<td>{{ item.normalizedName }}</td>
<td>
<n-button type="primary" size="small" @click="chooseRole(item)">选择</n-button>
</td>
</tr>
</tbody>
</n-table>
<template #footer>
<div class="flex-content right">
<n-button type="primary" size="small">新增角色</n-button>
<n-button @click="show = false" size="small"> </n-button>
</div>
</template>
</n-card>
</n-modal>
</template>
<script setup lang='ts'>
import { getRoleList } from '@/api/roleApi';
import { useMessage } from 'naive-ui';
import type { RoleListReturn } from '@/api/roleApi';
const emit = defineEmits<{
(event: 'choose', row:RoleListReturn): void
}>()
const show = ref(false);
const list = ref([]);
const message = useMessage();
const chooseRole = (row:RoleListReturn) => {
emit('choose', toRaw(row));
show.value = false;
}
const openDialog = () => {
show.value = true;
}
const init = async () => {
try {
const result = await getRoleList();
list.value = result;
} catch (error) {
message.error(error instanceof Error ? error.message : error);
}
};
init();
defineExpose({
openDialog
})
</script>
<style scoped lang='scss'></style>

View File

@ -2,18 +2,19 @@
<div class="main__container table"> <div class="main__container table">
<header class="table-header"> <header class="table-header">
<div class="table-header__search"> <div class="table-header__search">
<n-input placeholder="请输入用户名称" v-model:value="queryInfo.userName" size="small" style="width: 240px;" clearable /> <n-input placeholder="请输入用户名称" v-model:value="queryInfo.userName" size="small" style="width: 240px;"
clearable />
<n-select placeholder="请选择角色" v-model:value="queryInfo.roleName" :options="options" size="small" <n-select placeholder="请选择角色" v-model:value="queryInfo.roleName" :options="options" size="small"
style="width: 240px;" clearable/> style="width: 240px;" clearable />
</div> </div>
<ls-list-button @search="init" @reset="resetList"></ls-list-button> <ls-list-button @search="init" @reset="resetList"></ls-list-button>
</header> </header>
<main class="table-main" ref="tableMainRef"> <main class="table-main" ref="tableMainRef">
<n-data-table v-if="height" :columns="columns" :data="data" :max-height="`${height}px`" <n-data-table v-if="height" :columns="columns" :data="data" :max-height="`${height}px`"
:min-height="`${height}px`"> :min-height="`${height}px`">
<template #empty> <template #empty>
<LsEmpty type="no-data" title="暂无数据" description="Not Found 404"></LsEmpty> <LsEmpty type="no-data" title="暂无数据" description="Not Found 404"></LsEmpty>
</template> </template>
</n-data-table> </n-data-table>
<div class="table-main__pagination"> <div class="table-main__pagination">
<n-pagination v-model:page="pagination.page" v-model:page-size="pagination.pageSize" :item-count="data.length" <n-pagination v-model:page="pagination.page" v-model:page-size="pagination.pageSize" :item-count="data.length"
@ -29,8 +30,8 @@
<n-modal v-model:show="addRoleDialog"> <n-modal v-model:show="addRoleDialog">
<n-card style="width: 450px" title="授权角色" :bordered="false" size="huge" role="dialog" aria-modal="true"> <n-card style="width: 450px" title="授权角色" :bordered="false" size="huge" role="dialog" aria-modal="true">
<n-input-group> <n-input-group>
<n-input readonly :style="{ width: '70%' }" placeholder="请从角色库选择角色" /> <n-input v-model:value="roleName" readonly :style="{ width: '70%' }" placeholder="请从角色库选择角色" />
<n-button type="warning" strong secondary :style="{ width: '30%' }"> <n-button type="warning" strong secondary :style="{ width: '30%' }" @click="openRoleDialog">
角色库 角色库
<template #icon> <template #icon>
<n-icon> <n-icon>
@ -41,22 +42,26 @@
</n-input-group> </n-input-group>
<template #footer> <template #footer>
<div class="flex-content right"> <div class="flex-content right">
<n-button type="primary" size="small"> </n-button> <n-button type="primary" size="small" @click="handleEnableRole"> </n-button>
<n-button @click="addRoleDialog = false" size="small"> </n-button> <n-button @click="addRoleDialog = false" size="small"> </n-button>
</div> </div>
</template> </template>
</n-card> </n-card>
</n-modal> </n-modal>
<!-- 角色库 -->
<LsRoleBase ref="roleRef" @choose="chooseRole"></LsRoleBase>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
import { Server } from '@vicons/ionicons5'; import { Server } from '@vicons/ionicons5';
import { getUserList, deleteUser } from '@/api/roleApi'; import { getUserList, deleteUser, enableRole } from '@/api/roleApi';
import { DataTableColumns, NButton, NTag, useDialog, useMessage } from 'naive-ui'; import { DataTableColumns, NButton, NTag, useDialog, useMessage } from 'naive-ui';
import LsEmpty from '@/components/Ls-UI/LsEmpty.vue'; import LsEmpty from '@/components/Ls-UI/LsEmpty.vue';
import LsRoleBase from '@/components/Ls-UI/LsRoleBase.vue';
const message = useMessage(); const message = useMessage();
const tableMainRef = ref<HTMLElement | null>(null); const tableMainRef = ref<HTMLElement | null>(null);
const roleRef = ref<InstanceType<typeof LsRoleBase> | null>(null);
const queryInfo = reactive({ const queryInfo = reactive({
roleName: void 0, roleName: void 0,
userName: '' userName: ''
@ -67,11 +72,13 @@ const pagination = reactive<PageController>({
page: 1, page: 1,
}); });
const options = ref([]); const options = ref([]);
const data = ref([]); const data = ref([]);
const height = ref(null); const height = ref(null);
const dialog = useDialog(); const dialog = useDialog();
const addRoleDialog = ref(false); const addRoleDialog = ref(false);
const operationUuid = ref(''); const operationUuid = ref('');
const roleName = ref(''); //
// render - // render -
function createColumns({ function createColumns({
@ -234,9 +241,44 @@ onMounted(() => {
if (tableMainRef.value) { if (tableMainRef.value) {
height.value = tableMainRef.value.clientHeight - 64 - 50; // - height.value = tableMainRef.value.clientHeight - 64 - 50; // -
}; };
initRoleList();
init(); init();
}); });
const openRoleDialog = () => {
roleRef.value?.openDialog();
}
const handleEnableRole = async () => {
try {
const query = {
userId: operationUuid.value,
roleName: roleName.value
}
await enableRole(query);
init();
message.success('授权成功!');
} catch (error) {
message.error(error.message);
}
}
//
const initRoleList = async () => {
try {
const result = await getRoleList();
options.value = result.map(item => {
return {
label:item.normalizedName,
value:item.name
}
});
} catch (error) {
message.error(error instanceof Error ? error.message : error);
}
};
//
const chooseRole = (row) => {
console.log(row, 'row');
roleName.value = row.name;
}
</script> </script>
<style scoped lang='scss'> <style scoped lang='scss'>
.table-header { .table-header {