feat(projects): pef manage role

This commit is contained in:
Soybean 2024-03-23 15:51:04 +08:00
parent 0abbfa5d0c
commit 187098136e
10 changed files with 279 additions and 1 deletions

View File

@ -14,5 +14,6 @@
"i18n-ally.localesPaths": ["src/locales/langs"],
"prettier.enable": false,
"unocss.root": ["./"],
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"vue.server.hybridMode": true
}

View File

@ -12,6 +12,7 @@ const local: App.I18n.Schema = {
close: 'Close',
check: 'Check',
columnSetting: 'Column Setting',
config: 'Config',
confirm: 'Confirm',
delete: 'Delete',
deleteSuccess: 'Delete Success',
@ -277,6 +278,8 @@ const local: App.I18n.Schema = {
roleCode: 'Role Code',
roleStatus: 'Role Status',
roleDesc: 'Role Description',
menuAuth: 'Menu Auth',
buttonAuth: 'Button Auth',
form: {
roleName: 'Please enter role name',
roleCode: 'Please enter role code',
@ -312,6 +315,7 @@ const local: App.I18n.Schema = {
}
},
menu: {
home: 'Home',
title: 'Menu List',
id: 'ID',
parentId: 'Parent ID',
@ -338,6 +342,7 @@ const local: App.I18n.Schema = {
buttonDesc: 'Button Desc',
menuStatus: 'Menu Status',
form: {
home: 'Please select home',
menuType: 'Please select menu type',
menuName: 'Please enter menu name',
routeName: 'Please enter route name',

View File

@ -12,6 +12,7 @@ const local: App.I18n.Schema = {
close: '关闭',
check: '勾选',
columnSetting: '列设置',
config: '配置',
confirm: '确认',
delete: '删除',
deleteSuccess: '删除成功',
@ -277,6 +278,8 @@ const local: App.I18n.Schema = {
roleCode: '角色编码',
roleStatus: '角色状态',
roleDesc: '角色描述',
menuAuth: '菜单权限',
buttonAuth: '按钮权限',
form: {
roleName: '请输入角色名称',
roleCode: '请输入角色编码',
@ -312,6 +315,7 @@ const local: App.I18n.Schema = {
}
},
menu: {
home: '首页',
title: '菜单列表',
id: 'ID',
parentId: '父级菜单ID',
@ -338,6 +342,7 @@ const local: App.I18n.Schema = {
buttonDesc: '按钮描述',
menuStatus: '菜单状态',
form: {
home: '请选择首页',
menuType: '请选择菜单类型',
menuName: '请输入菜单名称',
routeName: '请输入路由名称',

View File

@ -57,3 +57,11 @@ export function fetchGetAllPages() {
method: 'get'
});
}
/** get menu tree */
export function fetchGetMenuTree() {
return request<Api.SystemManage.MenuTree[]>({
url: '/systemManage/getMenuTree',
method: 'get'
});
}

View File

@ -222,5 +222,12 @@ declare namespace Api {
/** menu list */
type MenuList = Common.PaginatingQueryRecord<Menu>;
type MenuTree = {
id: number;
label: string;
pId: number;
children?: MenuTree[];
};
}
}

View File

@ -258,6 +258,7 @@ declare namespace App {
close: string;
check: string;
columnSetting: string;
config: string;
confirm: string;
delete: string;
deleteSuccess: string;
@ -468,6 +469,8 @@ declare namespace App {
};
addRole: string;
editRole: string;
menuAuth: string;
buttonAuth: string;
};
user: {
title: string;
@ -495,6 +498,7 @@ declare namespace App {
};
};
menu: {
home: string;
title: string;
id: string;
parentId: string;
@ -521,6 +525,7 @@ declare namespace App {
buttonDesc: string;
menuStatus: string;
form: {
home: string;
menuType: string;
menuName: string;
routeName: string;

View File

@ -79,6 +79,7 @@ declare module 'vue' {
NTag: typeof import('naive-ui')['NTag']
NThing: typeof import('naive-ui')['NThing']
NTooltip: typeof import('naive-ui')['NTooltip']
NTree: typeof import('naive-ui')['NTree']
PinToggler: typeof import('./../components/common/pin-toggler.vue')['default']
ReloadButton: typeof import('./../components/common/reload-button.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']

View File

@ -0,0 +1,101 @@
<script setup lang="ts">
import { computed, shallowRef } from 'vue';
import { $t } from '@/locales';
defineOptions({
name: 'ButtonAuthModal'
});
interface Props {
/** the roleId */
roleId: number;
}
const props = defineProps<Props>();
const visible = defineModel<boolean>('visible', {
default: false
});
function closeModal() {
visible.value = false;
}
const title = computed(() => $t('common.edit') + $t('page.manage.role.buttonAuth'));
type ButtonConfig = {
id: number;
label: string;
code: string;
};
const tree = shallowRef<ButtonConfig[]>([]);
async function getAllButtons() {
// request
tree.value = [
{ id: 1, label: 'button1', code: 'code1' },
{ id: 2, label: 'button2', code: 'code2' },
{ id: 3, label: 'button3', code: 'code3' },
{ id: 4, label: 'button4', code: 'code4' },
{ id: 5, label: 'button5', code: 'code5' },
{ id: 6, label: 'button6', code: 'code6' },
{ id: 7, label: 'button7', code: 'code7' },
{ id: 8, label: 'button8', code: 'code8' },
{ id: 9, label: 'button9', code: 'code9' },
{ id: 10, label: 'button10', code: 'code10' }
];
}
const checks = shallowRef<number[]>([]);
async function getChecks() {
console.log(props.roleId);
// request
checks.value = [1, 2, 3, 4, 5];
}
function handleSubmit() {
console.log(checks.value, props.roleId);
// request
window.$message?.success?.($t('common.modifySuccess'));
closeModal();
}
function init() {
getAllButtons();
getChecks();
}
// init
init();
</script>
<template>
<NModal v-model:show="visible" :title="title" preset="card" class="w-480px">
<NTree
v-model:checked-keys="checks"
:data="tree"
key-field="id"
block-line
checkable
expand-on-click
virtual-scroll
class="h-280px"
/>
<template #footer>
<NSpace justify="end">
<NButton size="small" class="mt-16px" @click="closeModal">
{{ $t('common.cancel') }}
</NButton>
<NButton type="primary" size="small" class="mt-16px" @click="handleSubmit">
{{ $t('common.confirm') }}
</NButton>
</NSpace>
</template>
</NModal>
</template>
<style scoped></style>

View File

@ -0,0 +1,130 @@
<script setup lang="ts">
import { computed, shallowRef, watch } from 'vue';
import { $t } from '@/locales';
import { fetchGetAllPages, fetchGetMenuTree } from '@/service/api';
defineOptions({
name: 'MenuAuthModal'
});
interface Props {
/** the roleId */
roleId: number;
}
const props = defineProps<Props>();
const visible = defineModel<boolean>('visible', {
default: false
});
function closeModal() {
visible.value = false;
}
const title = computed(() => $t('common.edit') + $t('page.manage.role.menuAuth'));
const home = shallowRef('');
async function getHome() {
console.log(props.roleId);
home.value = 'home';
}
async function updateHome(val: string) {
// request
home.value = val;
}
const pages = shallowRef<string[]>([]);
async function getPages() {
const { error, data } = await fetchGetAllPages();
if (!error) {
pages.value = data;
}
}
const pageSelectOptions = computed(() => {
const opts: CommonType.Option[] = pages.value.map(page => ({
label: page,
value: page
}));
return opts;
});
const tree = shallowRef<Api.SystemManage.MenuTree[]>([]);
async function getTree() {
const { error, data } = await fetchGetMenuTree();
if (!error) {
tree.value = data;
}
}
const checks = shallowRef<number[]>([]);
async function getChecks() {
console.log(props.roleId);
// request
checks.value = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21];
}
function handleSubmit() {
console.log(checks.value, props.roleId);
// request
window.$message?.success?.($t('common.modifySuccess'));
closeModal();
}
function init() {
getHome();
getPages();
getTree();
getChecks();
}
watch(visible, val => {
if (val) {
init();
}
});
</script>
<template>
<NModal v-model:show="visible" :title="title" preset="card" class="w-480px">
<div class="flex-y-center gap-16px pb-12px">
<div>{{ $t('page.manage.menu.home') }}</div>
<NSelect :value="home" :options="pageSelectOptions" size="small" class="w-160px" @update:value="updateHome" />
</div>
<NTree
v-model:checked-keys="checks"
:data="tree"
key-field="id"
checkable
expand-on-click
virtual-scroll
block-line
class="h-280px"
/>
<template #footer>
<NSpace justify="end">
<NButton size="small" class="mt-16px" @click="closeModal">
{{ $t('common.cancel') }}
</NButton>
<NButton type="primary" size="small" class="mt-16px" @click="handleSubmit">
{{ $t('common.confirm') }}
</NButton>
</NSpace>
</template>
</NModal>
</template>
<style scoped></style>

View File

@ -1,8 +1,11 @@
<script setup lang="ts">
import { computed, reactive, watch } from 'vue';
import { useBoolean } from '@sa/hooks';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
import { enableStatusOptions } from '@/constants/business';
import MenuAuthModal from './menu-auth-modal.vue';
import ButtonAuthModal from './button-auth-modal.vue';
defineOptions({
name: 'RoleOperateDrawer'
@ -29,6 +32,8 @@ const visible = defineModel<boolean>('visible', {
const { formRef, validate, restoreValidation } = useNaiveForm();
const { defaultRequiredRule } = useFormRules();
const { bool: menuAuthVisible, setTrue: openMenuAuthModal } = useBoolean();
const { bool: buttonAuthVisible, setTrue: openButtonAuthModal } = useBoolean();
const title = computed(() => {
const titles: Record<NaiveUI.TableOperateType, string> = {
@ -59,6 +64,10 @@ const rules: Record<RuleKey, App.Global.FormRule> = {
status: defaultRequiredRule
};
const roleId = computed(() => props.rowData?.id || -1);
const isEdit = computed(() => props.operateType === 'edit');
function handleUpdateModelWhenEdit() {
if (props.operateType === 'add') {
Object.assign(model, createDefaultModel());
@ -109,6 +118,12 @@ watch(visible, () => {
<NInput v-model:value="model.roleDesc" :placeholder="$t('page.manage.role.form.roleDesc')" />
</NFormItem>
</NForm>
<NSpace v-if="isEdit">
<NButton @click="openMenuAuthModal">{{ $t('page.manage.role.menuAuth') }}</NButton>
<MenuAuthModal v-model:visible="menuAuthVisible" :role-id="roleId" />
<NButton @click="openButtonAuthModal">{{ $t('page.manage.role.buttonAuth') }}</NButton>
<ButtonAuthModal v-model:visible="buttonAuthVisible" :role-id="roleId" />
</NSpace>
<template #footer>
<NSpace :size="16">
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>