mirror of
https://github.com/m-xlsea/ruoyi-plus-soybean.git
synced 2025-09-24 07:49:47 +08:00
feat(projects): add menu route field
This commit is contained in:
@ -1,12 +1,20 @@
|
||||
<script setup lang="tsx">
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import type { SelectOption } from 'naive-ui';
|
||||
import type { LastLevelRouteKey } from '@elegant-router/types';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
import { $t } from '@/locales';
|
||||
import { enableStatusOptions, menuIconTypeOptions, menuTypeOptions } from '@/constants/business';
|
||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||
import { getLocalIcons } from '@/utils/icon';
|
||||
import { getLayoutAndPage, transformLayoutAndPageToComponent } from './shared';
|
||||
import { fetchGetAllRoles } from '@/service/api';
|
||||
import {
|
||||
getLayoutAndPage,
|
||||
transformLayoutAndPageToComponent,
|
||||
transformToKeyValuePairs,
|
||||
transformToQueryObject
|
||||
} from './shared';
|
||||
|
||||
defineOptions({
|
||||
name: 'MenuOperateDrawer'
|
||||
@ -51,6 +59,7 @@ type Model = Pick<
|
||||
Api.SystemManage.Menu,
|
||||
| 'menuType'
|
||||
| 'menuName'
|
||||
| 'i18nKey'
|
||||
| 'icon'
|
||||
| 'iconType'
|
||||
| 'routeName'
|
||||
@ -58,8 +67,17 @@ type Model = Pick<
|
||||
| 'component'
|
||||
| 'status'
|
||||
| 'hideInMenu'
|
||||
| 'activeMenu'
|
||||
| 'order'
|
||||
| 'parentId'
|
||||
| 'constant'
|
||||
| 'keepAlive'
|
||||
| 'href'
|
||||
| 'multiTab'
|
||||
| 'fixedIndexInTab'
|
||||
| 'roles'
|
||||
| 'buttons'
|
||||
| 'query'
|
||||
> & {
|
||||
layout: string;
|
||||
page: string;
|
||||
@ -71,16 +89,26 @@ function createDefaultModel(): Model {
|
||||
return {
|
||||
menuType: '1',
|
||||
menuName: '',
|
||||
i18nKey: '' as App.I18n.I18nKey,
|
||||
icon: '',
|
||||
iconType: '1',
|
||||
routeName: '',
|
||||
routePath: '',
|
||||
layout: '',
|
||||
page: '',
|
||||
status: null,
|
||||
status: '1',
|
||||
hideInMenu: false,
|
||||
activeMenu: '' as LastLevelRouteKey,
|
||||
order: 0,
|
||||
parentId: 0
|
||||
parentId: 0,
|
||||
constant: false,
|
||||
keepAlive: false,
|
||||
href: '',
|
||||
multiTab: false,
|
||||
fixedIndexInTab: 0,
|
||||
roles: [],
|
||||
buttons: [],
|
||||
query: {}
|
||||
};
|
||||
}
|
||||
|
||||
@ -136,6 +164,29 @@ const layoutOptions: CommonType.Option[] = [
|
||||
}
|
||||
];
|
||||
|
||||
const dynamicQueryKeyValuePairs: Ref<Record<string, string>[]> = ref([
|
||||
{
|
||||
key: '',
|
||||
value: ''
|
||||
}
|
||||
]);
|
||||
|
||||
/** the enabled role options */
|
||||
const roleOptions = ref<CommonType.Option<string>[]>([]);
|
||||
|
||||
async function getRoleOptions() {
|
||||
const { error, data } = await fetchGetAllRoles();
|
||||
|
||||
if (!error) {
|
||||
const options = data.map(item => ({
|
||||
label: item.roleName,
|
||||
value: item.roleCode
|
||||
}));
|
||||
|
||||
roleOptions.value = [...options];
|
||||
}
|
||||
}
|
||||
|
||||
function handleUpdateModel() {
|
||||
if (props.operateType === 'add') {
|
||||
Object.assign(model, createDefaultModel());
|
||||
@ -150,11 +201,12 @@ function handleUpdateModel() {
|
||||
}
|
||||
|
||||
if (props.operateType === 'edit' && props.rowData) {
|
||||
const { component, ...rest } = props.rowData;
|
||||
const { component, query, ...rest } = props.rowData;
|
||||
|
||||
const { layout, page } = getLayoutAndPage(component);
|
||||
|
||||
Object.assign(model, rest, { layout, page });
|
||||
dynamicQueryKeyValuePairs.value = transformToKeyValuePairs(query);
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,6 +218,12 @@ async function handleSubmit() {
|
||||
await validate();
|
||||
|
||||
model.component = transformLayoutAndPageToComponent(model.layout, model.page);
|
||||
model.query = transformToQueryObject(dynamicQueryKeyValuePairs.value);
|
||||
|
||||
// model.buttons = [];
|
||||
// Need: Get buttons based on roles
|
||||
|
||||
console.log('model:', model);
|
||||
|
||||
// request
|
||||
window.$message?.success($t('common.updateSuccess'));
|
||||
@ -177,73 +235,154 @@ watch(visible, () => {
|
||||
if (visible.value) {
|
||||
handleUpdateModel();
|
||||
restoreValidation();
|
||||
getRoleOptions();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="360">
|
||||
<NDrawer v-model:show="visible" display-directive="show" :width="400">
|
||||
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
||||
<NForm ref="formRef" :model="model" :rules="rules" label-placement="left" :label-width="80">
|
||||
<NFormItem :label="$t('page.manage.menu.menuType')" path="menuType">
|
||||
<NRadioGroup v-model:value="model.menuType" :disabled="disabledMenuType">
|
||||
<NRadio v-for="item in menuTypeOptions" :key="item.value" :value="item.value" :label="$t(item.label)" />
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.manage.menu.menuName')" path="menuName">
|
||||
<NInput v-model:value="model.menuName" :placeholder="$t('page.manage.menu.form.menuName')" />
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.manage.menu.iconTypeTitle')" path="iconType">
|
||||
<NRadioGroup v-model:value="model.iconType">
|
||||
<NRadio v-for="item in menuIconTypeOptions" :key="item.value" :value="item.value" :label="$t(item.label)" />
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.manage.menu.icon')" path="icon">
|
||||
<template v-if="model.iconType === '1'">
|
||||
<NInput v-model:value="model.icon" :placeholder="$t('page.manage.menu.form.icon')" class="flex-1">
|
||||
<template #suffix>
|
||||
<SvgIcon v-if="model.icon" :icon="model.icon" class="text-icon" />
|
||||
</template>
|
||||
</NInput>
|
||||
</template>
|
||||
<template v-if="model.iconType === '2'">
|
||||
<NSelect
|
||||
v-model:value="model.icon"
|
||||
:placeholder="$t('page.manage.menu.form.localIcon')"
|
||||
:options="localIconOptions"
|
||||
<NGrid>
|
||||
<NFormItemGi span="12" :label="$t('page.manage.menu.menuType')" path="menuType">
|
||||
<NRadioGroup v-model:value="model.menuType" :disabled="disabledMenuType">
|
||||
<NRadio v-for="item in menuTypeOptions" :key="item.value" :value="item.value" :label="$t(item.label)" />
|
||||
</NRadioGroup>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="12" :label="$t('page.manage.menu.order')" path="order">
|
||||
<NInputNumber v-model:value="model.order" :placeholder="$t('page.manage.menu.form.order')" />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.menuName')" path="menuName">
|
||||
<NInput v-model:value="model.menuName" :placeholder="$t('page.manage.menu.form.menuName')" />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.i18nKey')" path="i18nKey">
|
||||
<NInput v-model:value="model.i18nKey" :placeholder="$t('page.manage.menu.form.i18nKey')" />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="12" :label="$t('page.manage.menu.menuStatus')" path="status">
|
||||
<NRadioGroup v-model:value="model.status">
|
||||
<NRadio
|
||||
v-for="item in enableStatusOptions"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="$t(item.label)"
|
||||
/>
|
||||
</NRadioGroup>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="12" :label="$t('page.manage.menu.hideInMenu')" path="hideInMenu">
|
||||
<NRadioGroup v-model:value="model.hideInMenu">
|
||||
<NRadio value :label="$t('common.yesOrNo.yes')" />
|
||||
<NRadio :value="false" :label="$t('common.yesOrNo.no')" />
|
||||
</NRadioGroup>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="12" :label="$t('page.manage.menu.keepAlive')" path="keepAlive">
|
||||
<NRadioGroup v-model:value="model.keepAlive">
|
||||
<NRadio value :label="$t('common.yesOrNo.yes')" />
|
||||
<NRadio :value="false" :label="$t('common.yesOrNo.no')" />
|
||||
</NRadioGroup>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="12" :label="$t('page.manage.menu.constant')" path="constant">
|
||||
<NRadioGroup v-model:value="model.constant">
|
||||
<NRadio value :label="$t('common.yesOrNo.yes')" />
|
||||
<NRadio :value="false" :label="$t('common.yesOrNo.no')" />
|
||||
</NRadioGroup>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="12" :label="$t('page.manage.menu.multiTab')" path="multiTab">
|
||||
<NRadioGroup v-model:value="model.multiTab">
|
||||
<NRadio value :label="$t('common.yesOrNo.yes')" />
|
||||
<NRadio :value="false" :label="$t('common.yesOrNo.no')" />
|
||||
</NRadioGroup>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="12" :label="$t('page.manage.menu.fixedIndexInTab')" path="fixedIndexInTab">
|
||||
<NInputNumber
|
||||
v-model:value="model.fixedIndexInTab"
|
||||
:placeholder="$t('page.manage.menu.form.fixedIndexInTab')"
|
||||
/>
|
||||
</template>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.manage.menu.routeName')" path="routeName">
|
||||
<NInput v-model:value="model.routeName" :placeholder="$t('page.manage.menu.form.routeName')" />
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.manage.menu.routePath')" path="routePath">
|
||||
<NInput v-model:value="model.routePath" :placeholder="$t('page.manage.menu.form.routePath')" />
|
||||
</NFormItem>
|
||||
<NFormItem v-if="showLayout" :label="$t('page.manage.menu.layout')" path="layout">
|
||||
<NSelect
|
||||
v-model:value="model.layout"
|
||||
:options="layoutOptions"
|
||||
:placeholder="$t('page.manage.menu.form.layout')"
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem v-if="showPage" :label="$t('page.manage.menu.page')" path="page">
|
||||
<NSelect v-model:value="model.page" :options="pageOptions" :placeholder="$t('page.manage.menu.form.page')" />
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.manage.menu.menuStatus')" path="status">
|
||||
<NRadioGroup v-model:value="model.status">
|
||||
<NRadio v-for="item in enableStatusOptions" :key="item.value" :value="item.value" :label="$t(item.label)" />
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.manage.menu.hideInMenu')" path="hideInMenu">
|
||||
<NRadioGroup v-model:value="model.hideInMenu">
|
||||
<NRadio value :label="$t('common.yesOrNo.yes')" />
|
||||
<NRadio :value="false" :label="$t('common.yesOrNo.no')" />
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.manage.menu.order')" path="order">
|
||||
<NInputNumber v-model:value="model.order" :placeholder="$t('page.manage.menu.form.order')" />
|
||||
</NFormItem>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.iconTypeTitle')" path="iconType">
|
||||
<NRadioGroup v-model:value="model.iconType">
|
||||
<NRadio
|
||||
v-for="item in menuIconTypeOptions"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="$t(item.label)"
|
||||
/>
|
||||
</NRadioGroup>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.icon')" path="icon">
|
||||
<template v-if="model.iconType === '1'">
|
||||
<NInput v-model:value="model.icon" :placeholder="$t('page.manage.menu.form.icon')" class="flex-1">
|
||||
<template #suffix>
|
||||
<SvgIcon v-if="model.icon" :icon="model.icon" class="text-icon" />
|
||||
</template>
|
||||
</NInput>
|
||||
</template>
|
||||
<template v-if="model.iconType === '2'">
|
||||
<NSelect
|
||||
v-model:value="model.icon"
|
||||
:placeholder="$t('page.manage.menu.form.localIcon')"
|
||||
:options="localIconOptions"
|
||||
/>
|
||||
</template>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.routeName')" path="routeName">
|
||||
<NInput v-model:value="model.routeName" :placeholder="$t('page.manage.menu.form.routeName')" />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.routePath')" path="routePath">
|
||||
<NInput v-model:value="model.routePath" :placeholder="$t('page.manage.menu.form.routePath')" />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi v-if="showLayout" span="24" :label="$t('page.manage.menu.layout')" path="layout">
|
||||
<NSelect
|
||||
v-model:value="model.layout"
|
||||
:options="layoutOptions"
|
||||
:placeholder="$t('page.manage.menu.form.layout')"
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi v-if="showPage" span="24" :label="$t('page.manage.menu.page')" path="page">
|
||||
<NSelect
|
||||
v-model:value="model.page"
|
||||
:options="pageOptions"
|
||||
:placeholder="$t('page.manage.menu.form.page')"
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi v-if="showPage" span="24" :label="$t('page.manage.menu.activeMenu')" path="activeMenu">
|
||||
<NSelect
|
||||
v-model:value="model.activeMenu"
|
||||
:options="pageOptions"
|
||||
:placeholder="$t('page.manage.menu.form.activeMenu')"
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.href')" path="href">
|
||||
<NInput v-model:value="model.href" :placeholder="$t('page.manage.menu.form.href')" />
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.roles')" path="roles">
|
||||
<NSelect
|
||||
v-model:value="model.roles"
|
||||
multiple
|
||||
:options="roleOptions"
|
||||
:placeholder="$t('page.manage.menu.form.roles')"
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span="24" :label="$t('page.manage.menu.query')">
|
||||
<NDynamicInput
|
||||
v-model:value="dynamicQueryKeyValuePairs"
|
||||
preset="pair"
|
||||
:key-placeholder="$t('page.manage.menu.form.queryKey')"
|
||||
:value-placeholder="$t('page.manage.menu.form.queryValue')"
|
||||
>
|
||||
<template #action="{ index, create, remove }">
|
||||
<NSpace class="ml-2">
|
||||
<NButton size="medium" @click="() => create(index)">
|
||||
<icon-ic:round-plus class="text-icon" />
|
||||
</NButton>
|
||||
<NButton size="medium" @click="() => remove(index)">
|
||||
<icon-ic-round-remove class="text-icon" />
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</template>
|
||||
</NDynamicInput>
|
||||
</NFormItemGi>
|
||||
</NGrid>
|
||||
</NForm>
|
||||
<template #footer>
|
||||
<NSpace :size="16">
|
||||
|
@ -40,3 +40,21 @@ export function transformLayoutAndPageToComponent(layout: string, page: string)
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function transformToQueryObject(data: Record<string, string>[]) {
|
||||
const query: Record<string, string> = {};
|
||||
data.forEach(pair => {
|
||||
if (pair.key && pair.value) {
|
||||
query[pair.key] = pair.value;
|
||||
}
|
||||
});
|
||||
return query;
|
||||
}
|
||||
|
||||
export function transformToKeyValuePairs(query?: Record<string, string>) {
|
||||
const safeQuery = query || {};
|
||||
return Object.entries(safeQuery).map(([key, value]) => ({
|
||||
key,
|
||||
value
|
||||
}));
|
||||
}
|
||||
|
Reference in New Issue
Block a user