diff --git a/.env b/.env index 324f0f7b..1c0c09b4 100644 --- a/.env +++ b/.env @@ -12,7 +12,7 @@ VITE_ICON_PREFIX=icon VITE_ICON_LOCAL_PREFIX=icon-local # auth route mode: static | dynamic -VITE_AUTH_ROUTE_MODE=static +VITE_AUTH_ROUTE_MODE=dynamic # static auth route home VITE_ROUTE_HOME=home diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b72f2d1..4292e953 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -202,9 +202,6 @@ importers: packages/materials: dependencies: - '@sa/hooks': - specifier: workspace:* - version: link:../hooks '@sa/utils': specifier: workspace:* version: link:../utils diff --git a/src/constants/business.ts b/src/constants/business.ts index d11cc3ce..75b1d219 100644 --- a/src/constants/business.ts +++ b/src/constants/business.ts @@ -17,6 +17,15 @@ export const menuTypeRecord: Record = { export const menuTypeOptions = transformRecordToOption(menuTypeRecord); +/** menu is frame */ +export const menuIsFrameRecord: Record = { + '0': '缓存', + '1': '不缓存', + '2': 'iframe' +}; + +export const menuIsFrameOptions = transformRecordToOption(menuIsFrameRecord); + /** menu icon type */ export const menuIconTypeRecord: Record = { '1': 'iconify', diff --git a/src/store/modules/route/index.ts b/src/store/modules/route/index.ts index 2849459b..fb79d5dd 100644 --- a/src/store/modules/route/index.ts +++ b/src/store/modules/route/index.ts @@ -93,7 +93,9 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => { function parseRouter(route: ElegantConstRoute, parent?: ElegantConstRoute) { if (authRouteMode.value === 'dynamic') { - route.path = route.path.substring(1); + // @ts-expect-error no query field + const query = route.query ? String(route.query) : undefined; + route.path = route.path.startsWith('//') ? route.path.substring(1) : route.path; const name = humpToLine(route.path.substring(1).replace('/', '_')); route.name = parent ? `${parent.name}_${name}` : name; @@ -116,10 +118,17 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => { } if (route.component.endsWith('iframe-page')) { - route.meta.href = String(route.meta.link); - route.path = '/iframe-page/123'; - route.name = 'iframe_page'; route.component = 'view.iframe-page'; + if (query) { + route.props = { + url: query + }; + } else { + route.meta.href = String(route.meta.link); + const randomValue = Math.random().toString(36).slice(2, 12); + route.path = `/iframe-page/${randomValue}`; + route.name = `iframe_page_${randomValue}`; + } } delete route.meta.link; diff --git a/src/typings/api/system.api.d.ts b/src/typings/api/system.api.d.ts index c5b9b2b5..c3e1346b 100644 --- a/src/typings/api/system.api.d.ts +++ b/src/typings/api/system.api.d.ts @@ -150,6 +150,15 @@ declare namespace Api { */ type MenuType = 'M' | 'C' | 'F'; + /** + * 是否外链 + * + * - "0": "是" + * - "1": "否" + * - "2": "iframe" + */ + type IsMenuFrame = '0' | '1' | '2'; + type Menu = Common.CommonRecord<{ /** 菜单 ID */ menuId?: CommonType.IdType; @@ -165,8 +174,8 @@ declare namespace Api { component?: string; /** 路由参数 */ queryParam?: string; - /** 是否为外链(0是 1否) */ - isFrame?: Common.YesOrNoStatus; + /** 是否为外链(0是 1否 2iframe) */ + isFrame?: IsMenuFrame; /** 是否缓存(0缓存 1不缓存) */ isCache?: Common.YesOrNoStatus; /** 菜单类型(M目录 C菜单 F按钮) */ diff --git a/src/typings/elegant-router.d.ts b/src/typings/elegant-router.d.ts index 15c63960..5279b28a 100644 --- a/src/typings/elegant-router.d.ts +++ b/src/typings/elegant-router.d.ts @@ -161,7 +161,7 @@ declare module "@elegant-router/types" { component: `view.${K}`; } : never; - + /** * the center level route */ @@ -184,7 +184,7 @@ declare module "@elegant-router/types" { children: (CenterLevelRoute> | LastLevelRoute>)[]; } : never; - + /** * the custom first level route */ diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue index dc0ef3ff..6e4672d4 100644 --- a/src/views/system/menu/index.vue +++ b/src/views/system/menu/index.vue @@ -6,7 +6,7 @@ import { NButton, NIcon, NInput, NPopconfirm, NTooltip } from 'naive-ui'; import { fetchDeleteMenu, fetchGetMenuList } from '@/service/api'; import SvgIcon from '@/components/custom/svg-icon.vue'; import { useAppStore } from '@/store/modules/app'; -import { menuTypeRecord } from '@/constants/business'; +import { menuIsFrameRecord, menuTypeRecord } from '@/constants/business'; import ButtonIcon from '@/components/custom/button-icon.vue'; import { $t } from '@/locales'; import { handleMenuTree } from '@/utils/ruoyi'; @@ -133,9 +133,10 @@ function handleClickTree(option: Array) { getBtnMenuList(); } -const tagMap: Record = { +const tagMap: Record<'0' | '1' | '2', NaiveUI.ThemeColor> = { '0': 'success', - '1': 'warning' + '1': 'warning', + '2': 'primary' }; async function getBtnMenuList() { @@ -291,6 +292,7 @@ const { record: showHideRecord } = useDict('sys_show_hide'); v-model:checked-keys="checkedKeys" v-model:expanded-keys="expandedKeys" :cancelable="false" + show-line :data="treeData as []" :default-expanded-keys="[0]" :show-irrelevant-nodes="false" @@ -379,7 +381,9 @@ const { record: showHideRecord } = useDict('sys_show_hide'); {{ currentMenu.perms }} - + + {{ menuIsFrameRecord[currentMenu.isFrame] }} + @@ -395,7 +399,7 @@ const { record: showHideRecord } = useDict('sys_show_hide'); - diff --git a/src/views/system/menu/modules/menu-operate-drawer.vue b/src/views/system/menu/modules/menu-operate-drawer.vue index 82f5f6b1..5a865ced 100644 --- a/src/views/system/menu/modules/menu-operate-drawer.vue +++ b/src/views/system/menu/modules/menu-operate-drawer.vue @@ -5,7 +5,7 @@ import { NTooltip } from 'naive-ui'; import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { $t } from '@/locales'; import { fetchCreateMenu, fetchUpdateMenu } from '@/service/api'; -import { menuIconTypeOptions, menuTypeOptions } from '@/constants/business'; +import { menuIconTypeOptions, menuIsFrameOptions, menuTypeOptions } from '@/constants/business'; import SvgIcon from '@/components/custom/svg-icon.vue'; import { getLocalMenuIcons } from '@/utils/icon'; import { humpToLine, isNotNull } from '@/utils/common'; @@ -109,8 +109,11 @@ function handleInitModel() { Object.assign(model, props.rowData); model.component = model.component?.replaceAll('_', '/'); iconType.value = model.icon?.startsWith('icon-') ? '2' : '1'; - const queryObj: { [key: string]: string } = JSON.parse(model.queryParam || '{}'); - queryList.value = Object.keys(queryObj).map(item => ({ key: item, value: queryObj[item] })); + + if (model.isFrame !== '2') { + const queryObj: { [key: string]: string } = JSON.parse(model.queryParam || '{}'); + queryList.value = Object.keys(queryObj).map(item => ({ key: item, value: queryObj[item] })); + } } } @@ -121,10 +124,6 @@ function closeDrawer() { async function handleSubmit() { await validate(); - const queryObj: { [key: string]: string } = {}; - queryList.value.forEach(item => (queryObj[item.key] = item.value)); - model.queryParam = JSON.stringify(queryObj); - const { menuId, parentId, @@ -140,9 +139,10 @@ async function handleSubmit() { remark } = model; - let path = model.path; - if (model.isFrame === '1') { - path = !model.path?.startsWith('/') ? `/${model.path}` : model.path; + if (isFrame !== '2' && queryList.value.length) { + const queryObj: { [key: string]: string } = {}; + queryList.value.forEach(item => (queryObj[item.key] = item.value)); + model.queryParam = JSON.stringify(queryObj); } let icon; @@ -150,18 +150,15 @@ async function handleSubmit() { icon = iconType.value === '1' ? model.icon : model.icon?.replace('menu-', 'icon-'); } + let path = model.path; let component = model.component; - - if (model.menuType === 'C') { - component = humpToLine(model.component?.replaceAll('/', '_') || ''); - } - - if (model.menuType === 'M') { - component = model.parentId === 0 ? 'layout.base' : undefined; - } - - if (model.isFrame === '0') { + if (isFrame !== '0') { component = 'iframe-page'; + path = !model.path?.startsWith('/') ? `/${model.path}` : model.path; + } else if (model.menuType === 'C') { + component = humpToLine(model.component?.replaceAll('/', '_') || ''); + } else if (model.menuType === 'M') { + component = model.parentId === 0 ? 'layout.base' : undefined; } // request @@ -276,8 +273,7 @@ const FormTipComponent = defineComponent({
- 路由地址 + {{ model.isFrame !== '0' ? '路由地址' : '外链地址' }}
- +