新增权限组页面,增删改查(未完成)

This commit is contained in:
王创世 2025-04-28 14:32:47 +08:00
parent d4457b9f30
commit 4dd21ebc53
8 changed files with 377 additions and 8 deletions

View File

@ -41,16 +41,26 @@ export function useTable<A extends NaiveUI.TableApiFn>(config: NaiveUI.NaiveTabl
transformer: res => { transformer: res => {
console.log(res); console.log(res);
const { data = [], current = 1, size = 10, total = 0 } = res || {}; const { data = [], current = 1, size = 10, total = 0 } = res || {};
console.log(total);
// Ensure that the size is greater than 0, If it is less than 0, it will cause paging calculation errors.
const pageSize = size <= 0 ? 10 : size; const pageSize = size <= 0 ? 10 : size;
const recordsWithIndex = data.map((item, index) => { if(data.data){
return { var recordsWithIndex = data.data.map((item, index) => {
...item, return {
index: (current - 1) * pageSize + index + 1 ...item,
}; index: (current - 1) * pageSize + index + 1
}); };
});
}else{
var recordsWithIndex = data.map((item, index) => {
return {
...item,
index: (current - 1) * pageSize + index + 1
};
});
}
console.log(recordsWithIndex); console.log(recordsWithIndex);
return { return {
data: recordsWithIndex, data: recordsWithIndex,

View File

@ -21,6 +21,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
"iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"), "iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"),
login: () => import("@/views/_builtin/login/index.vue"), login: () => import("@/views/_builtin/login/index.vue"),
home: () => import("@/views/home/index.vue"), home: () => import("@/views/home/index.vue"),
system_auth: () => import("@/views/system/auth/index.vue"),
system_menu: () => import("@/views/system/menu/index.vue"), system_menu: () => import("@/views/system/menu/index.vue"),
system_user: () => import("@/views/system/user/index.vue"), system_user: () => import("@/views/system/user/index.vue"),
}; };

View File

@ -84,6 +84,15 @@ export const generatedRoutes: GeneratedRoute[] = [
i18nKey: 'route.system' i18nKey: 'route.system'
}, },
children: [ children: [
{
name: 'system_auth',
path: '/system/auth',
component: 'view.system_auth',
meta: {
title: 'system_auth',
i18nKey: 'route.system_auth'
}
},
{ {
name: 'system_menu', name: 'system_menu',
path: '/system/menu', path: '/system/menu',

View File

@ -170,6 +170,7 @@ const routeMap: RouteMap = {
"iframe-page": "/iframe-page/:url", "iframe-page": "/iframe-page/:url",
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?", "login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
"system": "/system", "system": "/system",
"system_auth": "/system/auth",
"system_menu": "/system/menu", "system_menu": "/system/menu",
"system_user": "/system/user" "system_user": "/system/user"
}; };

36
src/service/api/group.ts Normal file
View File

@ -0,0 +1,36 @@
import { request } from '../request';
/** 获取API权限组列表 */
export function fetchGetGroups(params?: Api.Common.CommonSearchParams) {
return request<GroupApi.GroupListResponse>({
url: '/adminapi/group/index',
method: 'get',
params
});
}
/** 添加API权限组 */
export function addGroup(data: Partial<GroupApi.Group>) {
return request({
url: '/adminapi/group/add',
method: 'post',
data
});
}
/** 编辑API权限组 */
export function editGroup(data: Partial<GroupApi.Group>) {
return request({
url: `/adminapi/group/edit/ids/${data.id}`,
method: 'post',
data
});
}
/** 删除API权限组 */
export function deleteGroup(id: number) {
return request({
url: `/adminapi/group/del/ids/${id}`,
method: 'get'
});
}

View File

@ -24,6 +24,7 @@ declare module "@elegant-router/types" {
"iframe-page": "/iframe-page/:url"; "iframe-page": "/iframe-page/:url";
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?"; "login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
"system": "/system"; "system": "/system";
"system_auth": "/system/auth";
"system_menu": "/system/menu"; "system_menu": "/system/menu";
"system_user": "/system/user"; "system_user": "/system/user";
}; };
@ -86,6 +87,7 @@ declare module "@elegant-router/types" {
| "iframe-page" | "iframe-page"
| "login" | "login"
| "home" | "home"
| "system_auth"
| "system_menu" | "system_menu"
| "system_user" | "system_user"
>; >;

32
src/typings/group.d.ts vendored Normal file
View File

@ -0,0 +1,32 @@
/**
*
*/
declare namespace GroupApi {
/** 权限组数据类型 */
interface Group {
/** 权限组ID */
id: number;
/** 权限组名称 */
name: string;
/** 规则ID */
rules: string;
/** 创建时间 */
createtime: string;
/** 更新时间 */
updatetime: string;
/** 状态 */
status: string;
}
/** 权限组列表响应 */
interface GroupListResponse {
/** 权限组列表 */
data: Group[];
/** 当前页码 */
current: number;
/** 每页条数 */
size: number;
/** 总条数 */
total: number;
}
}

View File

@ -0,0 +1,278 @@
<script setup lang="tsx">
import { ref } from 'vue';
import type { Ref } from 'vue';
import { NButton, NPopconfirm, NTag, NTreeSelect } from 'naive-ui';
import { useBoolean } from '@sa/hooks';
import { useAppStore } from '@/store/modules/app';
import { useTable, useTableOperate } from '@/hooks/common/table';
import { $t } from '@/locales';
import { yesOrNoRecord } from '@/constants/common';
import SvgIcon from '@/components/custom/svg-icon.vue';
import { fetchGetGroups, addGroup, editGroup, deleteGroup } from '@/service/api/group';
import { fetchGetUserRoutes } from '@/service/api/route';
const appStore = useAppStore();
const { bool: visible, setTrue: openModal } = useBoolean();
const wrapperRef = ref<HTMLElement | null>(null);
const title = ref('');
const rulesTree = ref<any[]>([]);
const rulesLoading = ref(false);
const model = ref<Partial<GroupApi.Group & { rulesArray: (string | number)[] }>>({
id: 0,
name: '',
rules: '',
status: '',
rulesArray: []
});
const rules = {};
const { columns, columnChecks, data, loading, pagination, getData, getDataByPage } = useTable({
apiFn: fetchGetGroups,
columns: () => [
{
key: 'id',
title: 'ID',
align: 'center',
width: 100,
},
{
key: 'name',
title: '权限组名称',
align: 'center',
width: 250,
},
{
key: 'rules',
title: '规则ID',
align: 'center',
width: 300,
},
{
key: 'createtime',
title: '创建时间',
align: 'center',
width: 200,
},
{
key: 'updatetime',
title: '更新时间',
align: 'center',
width: 200,
},
{
key: 'status',
title: '状态',
align: 'center',
width: 120,
render: (row) => {
const status: CommonType.YesOrNo = row.status === 'hidden' ? 'N' : 'Y';
const tagMap: Record<CommonType.YesOrNo, NaiveUI.ThemeColor> = {
Y: 'error',
N: 'default'
};
const label = $t(yesOrNoRecord[status]);
return <NTag type={ tagMap[status] }> { label } </NTag>;
}
},
{
key: 'operate',
title: '操作',
align: 'center',
width: 230,
render: (row) => (
<div class= "flex-center justify-end gap-8px" >
<NButton type="primary" ghost size="small" onClick={() => handleEdit(row)}>
编辑
</NButton>
< NPopconfirm onPositiveClick = {() => handleDelete(row.id as number)}>
{{
default: () => '确定删除吗?',
trigger: () => (
<NButton type= "error" ghost size = "small" >
删除
</NButton>
)
}}
</NPopconfirm>
</div>
)
}
]
});
const { checkedRowKeys, onBatchDeleted, onDeleted } = useTableOperate(data, getData);
const operateType = ref('add');
function handleAdd() {
operateType.value = 'add';
title.value = '新增API权限组';
// model
model.value = {
id: 0,
name: '',
rules: '',
status: '',
rulesArray: []
};
openModal();
}
async function handleDelete(id: number) {
// request
const { response } = await deleteGroup(id);
console.log(response);
if (response?.data?.code === 1) {
window.$message?.success(response.data.msg);
getData();
} else {
window.$message?.error(response?.data?.msg || '删除失败');
}
}
function handleEdit(item: any) {
operateType.value = 'edit';
title.value = '编辑API权限组';
model.value = {
id: item.id,
name: item.name,
rules: item.rules,
status: item.status,
rulesArray: rulesStrToArray(item.rules)
};
openModal();
}
function init() {
initRulesTree();
}
//
async function initRulesTree() {
rulesLoading.value = true;
try {
const { response } = await fetchGetUserRoutes();
if (response?.data?.code === 1) {
// tree
rulesTree.value = formatRulesTree(response.data.data || []);
} else {
window.$message?.error(response?.data?.msg || '获取规则列表失败');
}
} catch (error) {
console.error('获取规则列表失败', error);
window.$message?.error('获取规则列表失败');
} finally {
rulesLoading.value = false;
}
}
//
function formatRulesTree(data: any[]) {
// API
// API
// idkeynamelabel
return data.map(item => ({
key: item.id,
label: item.title || item.name,
children: item.children ? formatRulesTree(item.children) : undefined
}));
}
// ID
function rulesStrToArray(rulesStr: string): (string | number)[] {
if (!rulesStr) return [];
return rulesStr.split(',').map(item => {
// ID
const numId = Number(item);
return isNaN(numId) ? item : numId;
});
}
// ID
function rulesArrayToStr(rulesArray: (string | number)[]): string {
if (!rulesArray || !rulesArray.length) return '';
return rulesArray.join(',');
}
// init
init();
async function handleSubmit() {
//
if (model.value.rulesArray) {
model.value.rules = rulesArrayToStr(model.value.rulesArray);
}
let res;
if (operateType.value === 'add') {
res = await addGroup(model.value);
} else {
res = await editGroup(model.value);
}
console.log('response: ', res.response);
if (res.response?.data?.code === 1) {
window.$message?.success(res.response.data.msg);
visible.value = false;
getData();
} else {
window.$message?.error(res.response?.data?.msg || '操作失败');
}
}
</script>
<template>
<div ref="wrapperRef" class="flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
<NCard title="API权限组管理" :bordered="false" size="small" class="sm:flex-1-hidden card-wrapper">
<template #header-extra>
<TableHeaderOperation v-model:columns="columnChecks" :disabled-delete="checkedRowKeys.length === 0"
:loading="loading" @add="handleAdd" @refresh="getData" />
</template>
<NDataTable v-model:checked-row-keys="checkedRowKeys" :columns="columns" :data="data" size="small"
:flex-height="!appStore.isMobile" :scroll-x="1088" :loading="loading" :row-key="row => row.id" remote
:pagination="pagination" class="sm:h-full" />
</NCard>
<NModal v-model:show="visible" :title="title" preset="card" class="w-800px">
<NScrollbar class="h-480px pr-20px">
<NForm ref="formRef" :model="model" :rules="rules" label-placement="left" :label-width="100">
<NGrid responsive="screen" item-responsive>
<NFormItemGi span="24" label="权限组名称" path="name">
<NInput v-model:value="model.name" placeholder="请输入权限组名称" />
</NFormItemGi>
<NFormItemGi span="24" label="规则ID" path="rulesArray">
<NTreeSelect
v-model:value="model.rulesArray"
placeholder="请选择规则"
:options="rulesTree"
:loading="rulesLoading"
multiple
cascade
checkable
clearable
/>
</NFormItemGi>
<NFormItemGi span="24 m:12" label="状态" path="status">
<NRadioGroup v-model:value="model.status">
<NRadio value="hidden" label="禁用" />
<NRadio value="normal" label="正常" />
</NRadioGroup>
</NFormItemGi>
</NGrid>
</NForm>
</NScrollbar>
<template #footer>
<NSpace justify="end" :size="16">
<NButton @click="visible = false">取消</NButton>
<NButton type="primary" @click="handleSubmit">确认</NButton>
</NSpace>
</template>
</NModal>
</div>
</template>
<style scoped></style>