!55 使用accessMenus增强用户存储 & 优化 自定义API组件

Merge pull request !55 from chenminjie/dev-v5_cmj
pull/56/MERGE
xingyu 2024-11-30 03:30:55 +00:00 committed by Gitee
commit 5e22a00da7
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
8 changed files with 215 additions and 20 deletions

View File

@ -160,22 +160,24 @@ const handleMenuClick = (e: any) => {
</Button> </Button>
</slot> </slot>
<template #overlay> <template #overlay>
<Menu @click="handleMenuClick"> <Menu class="w-full" @click="handleMenuClick">
<MenuItem v-for="(action, index) in getDropdownList" :key="index"> <MenuItem v-for="(action, index) in getDropdownList" :key="index">
<template v-if="action.popConfirm"> <template v-if="action.popConfirm">
<Popconfirm v-bind="getPopConfirmProps(action.popConfirm)"> <Popconfirm v-bind="getPopConfirmProps(action.popConfirm)">
<template v-if="action.popConfirm.icon" #icon> <template v-if="action.popConfirm.icon" #icon>
<IconifyIcon :icon="action.popConfirm.icon" /> <IconifyIcon :icon="action.popConfirm.icon" />
</template> </template>
<div> <div class="flex items-center">
<IconifyIcon v-if="action.icon" :icon="action.icon" /> <IconifyIcon v-if="action.icon" :icon="action.icon" />
<span class="ml-1">{{ action.text }}</span> <span class="ml-1">{{ action.text }}</span>
</div> </div>
</Popconfirm> </Popconfirm>
</template> </template>
<template v-else> <template v-else>
<IconifyIcon v-if="action.icon" :icon="action.icon" /> <div class="flex items-center">
<span class="ml-1">{{ action.label }}</span> <IconifyIcon v-if="action.icon" :icon="action.icon" />
<span class="ml-1">{{ action.text }}</span>
</div>
</template> </template>
</MenuItem> </MenuItem>
</Menu> </Menu>

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, type PropType } from 'vue'; import { computed, type PropType } from 'vue';
import { requestClient } from '#/api/request'; import { useDictStore } from '@vben/stores';
import { ApiCheckboxGroup, ApiRadioGroup, ApiSelect } from '..'; import { ApiCheckboxGroup, ApiRadioGroup, ApiSelect } from '..';
@ -42,9 +42,10 @@ const DictComponent = computed(() => {
return ApiSelect; return ApiSelect;
}); });
const fetch = () => { const fetch = () => {
return requestClient.post('/sys/dict/getByDictType', { return new Promise<OptionsItem[]>((resolve) => {
dictType: props.code, const dict = useDictStore().getDictOptions(props.code!);
...props.params, const options: OptionsItem[] = dict as OptionsItem[];
resolve(options);
}); });
}; };
</script> </script>

View File

@ -111,6 +111,7 @@ export const useAuthStore = defineStore('auth', () => {
authPermissionInfo = await getAuthPermissionInfoApi(); authPermissionInfo = await getAuthPermissionInfoApi();
userStore.setUserInfo(authPermissionInfo.user); userStore.setUserInfo(authPermissionInfo.user);
userStore.setUserRoles(authPermissionInfo.roles); userStore.setUserRoles(authPermissionInfo.roles);
userStore.setAccessMenus(authPermissionInfo.menus as []);
accessStore.setAccessCodes(authPermissionInfo.permissions); accessStore.setAccessCodes(authPermissionInfo.permissions);
return authPermissionInfo; return authPermissionInfo;
} }

View File

@ -1,10 +1,12 @@
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table'; import type { VxeGridProps } from '#/adapter/vxe-table';
import type { CodegenApi } from '#/api/infra/codegen'; import type { CodegenApi } from '#/api/infra/codegen';
import { type VbenFormProps, z } from '@vben/common-ui';
import { useUserStore } from '@vben/stores';
import { getDataSourceConfigList } from '#/api/infra/data-source-config'; import { getDataSourceConfigList } from '#/api/infra/data-source-config';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { DICT_TYPE } from '#/utils/dict';
export namespace CodegenDefaultData { export namespace CodegenDefaultData {
/** /**
@ -114,3 +116,138 @@ export namespace CodegenImportTableModalData {
}, },
]; ];
} }
//* ****************************** CodegenOptionsModal.vue *******************************//
export namespace CodegenOptionsModalData {
export const formSchema: VbenFormProps['schema'] = [
{
label: '表名称',
fieldName: 'tableName',
component: 'Input',
componentProps: {
placeholder: '请输入表名称',
},
rules: z.string().min(1, { message: '表名称不能为空' }),
},
{
label: '表描述',
fieldName: 'tableComment',
component: 'Input',
componentProps: {
placeholder: '请输入表描述',
},
rules: z.string().min(1, { message: '表描述不能为空' }),
},
{
label: '实体类名',
fieldName: 'className',
component: 'Input',
rules: z.string().min(1, { message: '实体类名不能为空' }),
componentProps: {
tooltip:
'默认去除表名的前缀。如果存在重复,则需要手动添加前缀,避免 MyBatis 报 Alias 重复的问题。',
placeholder: '请输入实体类名',
},
},
{
label: '作者',
fieldName: 'author',
component: 'Input',
rules: z.string().min(1, { message: '作者不能为空' }),
componentProps: {
placeholder: '请输入作者',
},
},
{
label: '备注',
fieldName: 'remark',
component: 'Input',
componentProps: {
placeholder: '请输入备注',
},
},
{
label: '生成模版',
fieldName: 'template',
component: 'ApiDict',
componentProps: {
code: DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE,
class: 'w-full',
placeholder: '请选择生成模版',
},
rules: z.string().min(1, { message: '生成模版不能为空' }),
defaultValue: '1',
},
{
label: '前端类型',
fieldName: 'frontType',
component: 'ApiDict',
componentProps: {
code: DICT_TYPE.INFRA_CODEGEN_FRONT_TYPE,
class: 'w-full',
placeholder: '请选择前端类型',
},
rules: z.string().min(1, { message: '前端类型不能为空' }),
defaultValue: '31',
},
{
label: '生成场景',
fieldName: 'scene',
component: 'ApiDict',
componentProps: {
code: DICT_TYPE.INFRA_CODEGEN_SCENE,
class: 'w-full',
placeholder: '请选择生成场景',
},
rules: z.string().min(1, { message: '生成场景不能为空' }),
defaultValue: '1',
},
{
label: '上级菜单',
fieldName: 'parentMenuId',
component: 'ApiTreeSelect',
componentProps: {
class: 'w-full',
api: () => {
const { accessMenus } = useUserStore();
return accessMenus;
},
labelField: 'name',
valueField: 'id',
placeholder: '请选择上级菜单',
},
rules: z.number().min(1, { message: '上级菜单不能为空' }),
defaultValue: null,
},
{
label: '模块名',
fieldName: 'moduleName',
component: 'Input',
rules: z.string().min(1, { message: '模块名不能为空' }),
componentProps: {
placeholder: '请输入模块名',
},
},
{
label: '业务名',
fieldName: 'businessName',
component: 'Input',
rules: z.string().min(1, { message: '业务名不能为空' }),
componentProps: {
placeholder: '请输入业务名',
},
},
{
label: '类名',
fieldName: 'className',
component: 'Input',
rules: z.string().min(1, { message: '类名不能为空' }),
},
{
label: '类描述',
fieldName: 'classComment',
component: 'Input',
rules: z.string().min(1, { message: '类描述不能为空' }),
},
];
}

View File

@ -0,0 +1,37 @@
<script setup lang="ts">
import { useVbenForm, useVbenModal } from '@vben/common-ui';
import { CodegenOptionsModalData } from '../codegen.data';
defineOptions({
name: 'CodegenOptionsModal',
});
// 使
const [Form] = useVbenForm({
commonConfig: {
labelWidth: 120,
wrapperClass: 'w-full',
},
schema: CodegenOptionsModalData.formSchema,
// 321
wrapperClass: 'grid-cols-1 md:grid-cols-2',
});
// 使
const [Modal] = useVbenModal({
title: '修改代码生成配置',
class: 'w-[90%] h-[90%]',
onOpenChange(isOpen) {
if (isOpen) {
// TODO:
}
},
});
</script>
<template>
<Modal>
<Form />
</Modal>
</template>

View File

@ -16,13 +16,6 @@ import { CodegenDefaultData } from './codegen.data';
// checked // checked
const checkedStatus = ref<boolean>(false); const checkedStatus = ref<boolean>(false);
/**
* 编辑
*/
const handleEdit = (_row: CodegenApi.CodegenTableRespVO) => {
// console.log('', row);
};
/** /**
* 删除 * 删除
*/ */
@ -145,6 +138,13 @@ const [PreviewCodeModal, previewCodeModalApi] = useVbenModal({
), ),
}); });
// 使
const [CodegenOptionsModal, codegenOptionsModalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./components/codegen-options-modal.vue'),
),
});
/** /**
* 打开导入表弹窗 * 打开导入表弹窗
*/ */
@ -159,6 +159,14 @@ const handleOpenPreviewCodeModal = (row: CodegenApi.CodegenTableRespVO) => {
previewCodeModalApi.setData(row); previewCodeModalApi.setData(row);
previewCodeModalApi.open(); previewCodeModalApi.open();
}; };
/**
* 打开修改代码生成配置弹窗
*/
const handleOpenCodegenOptionsModal = (row: CodegenApi.CodegenTableRespVO) => {
codegenOptionsModalApi.setData(row);
codegenOptionsModalApi.open();
};
</script> </script>
<template> <template>
@ -214,7 +222,7 @@ const handleOpenPreviewCodeModal = (row: CodegenApi.CodegenTableRespVO) => {
type: 'link', type: 'link',
label: '编辑', label: '编辑',
icon: 'ant-design:edit-outlined', icon: 'ant-design:edit-outlined',
onClick: handleEdit.bind(null, row), onClick: handleOpenCodegenOptionsModal.bind(null, row),
}, },
{ {
type: 'link', type: 'link',
@ -241,5 +249,6 @@ const handleOpenPreviewCodeModal = (row: CodegenApi.CodegenTableRespVO) => {
</Grid> </Grid>
<ImportTableModal /> <ImportTableModal />
<PreviewCodeModal /> <PreviewCodeModal />
<CodegenOptionsModal />
</Page> </Page>
</template> </template>

View File

@ -79,9 +79,9 @@ export const modalSchema: VbenFormSchema[] = [
rules: 'required', rules: 'required',
}, },
{ {
component: 'Select', component: 'ApiDict',
componentProps: { componentProps: {
options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), code: DICT_TYPE.COMMON_STATUS,
}, },
fieldName: 'status', fieldName: 'status',
label: '状态', label: '状态',

View File

@ -25,6 +25,10 @@ interface BasicUserInfo {
} }
interface AccessState { interface AccessState {
/**
*
*/
accessMenus: [];
/** /**
* *
*/ */
@ -40,6 +44,9 @@ interface AccessState {
*/ */
export const useUserStore = defineStore('core-user', { export const useUserStore = defineStore('core-user', {
actions: { actions: {
setAccessMenus(menus: []) {
this.accessMenus = menus;
},
setUserInfo(userInfo: BasicUserInfo | null) { setUserInfo(userInfo: BasicUserInfo | null) {
// 设置用户信息 // 设置用户信息
this.userInfo = userInfo; this.userInfo = userInfo;
@ -56,6 +63,7 @@ export const useUserStore = defineStore('core-user', {
pick: ['userInfo', 'userRoles'], pick: ['userInfo', 'userRoles'],
}, },
state: (): AccessState => ({ state: (): AccessState => ({
accessMenus: [],
userInfo: null, userInfo: null,
userRoles: [], userRoles: [],
}), }),