From 60d513ce403c291e0e54c261bce0b0c76c285714 Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Thu, 10 Oct 2024 11:48:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B7=AF=E7=94=B1=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/router/access.ts | 10 +++ apps/web-antd/src/views/system/menu/data.tsx | 7 +- .../views/演示使用自行删除/query/index.vue | 17 +++++ .../@core/base/typings/src/vue-router.d.ts | 4 ++ packages/effects/access/src/accessible.ts | 10 ++- .../layouts/src/basic/menu/use-navigation.ts | 9 ++- packages/utils/src/helpers/index.ts | 1 + packages/utils/src/helpers/request.ts | 72 +++++++++++++++++++ 8 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 apps/web-antd/src/views/演示使用自行删除/query/index.vue create mode 100644 packages/utils/src/helpers/request.ts diff --git a/apps/web-antd/src/router/access.ts b/apps/web-antd/src/router/access.ts index 1b1c361a..06cf3829 100644 --- a/apps/web-antd/src/router/access.ts +++ b/apps/web-antd/src/router/access.ts @@ -85,6 +85,16 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) { path: menu.path, }; + // 添加路由参数信息 + if (menu.query) { + try { + const query = JSON.parse(menu.query); + vbenRoute.meta && (vbenRoute.meta.query = query); + } catch { + console.error('错误的路由参数类型, 必须为[json]格式'); + } + } + /** * 处理不同组件 */ diff --git a/apps/web-antd/src/views/system/menu/data.tsx b/apps/web-antd/src/views/system/menu/data.tsx index 80803dde..3b320338 100644 --- a/apps/web-antd/src/views/system/menu/data.tsx +++ b/apps/web-antd/src/views/system/menu/data.tsx @@ -325,11 +325,10 @@ export const drawerSchema: FormSchemaGetter = () => [ }, { component: 'Input', - componentProps: () => ({ + componentProps: (model) => ({ // 为链接时组件disabled - // disabled: model.isFrame === '0', - placeholder: '暂未实现功能', - disabled: true, + disabled: model.isFrame === '0', + placeholder: '必须为json字符串格式', }), dependencies: { // 类型为菜单时显示 diff --git a/apps/web-antd/src/views/演示使用自行删除/query/index.vue b/apps/web-antd/src/views/演示使用自行删除/query/index.vue new file mode 100644 index 00000000..6213f29a --- /dev/null +++ b/apps/web-antd/src/views/演示使用自行删除/query/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/packages/@core/base/typings/src/vue-router.d.ts b/packages/@core/base/typings/src/vue-router.d.ts index 87349cd7..e92b34c0 100644 --- a/packages/@core/base/typings/src/vue-router.d.ts +++ b/packages/@core/base/typings/src/vue-router.d.ts @@ -102,6 +102,10 @@ interface RouteMeta { * 用于路由->菜单排序 */ order?: number; + /** + * 路由参数 对象形式 + */ + query?: Record; /** * 标题名称 */ diff --git a/packages/effects/access/src/accessible.ts b/packages/effects/access/src/accessible.ts index c20018cc..5b0ac0a7 100644 --- a/packages/effects/access/src/accessible.ts +++ b/packages/effects/access/src/accessible.ts @@ -10,6 +10,7 @@ import { generateRoutesByBackend, generateRoutesByFrontend, mapTree, + setObjToUrlParams, } from '@vben/utils'; async function generateAccessible( @@ -82,7 +83,14 @@ async function generateRoutes( return route; } - route.redirect = firstChild.path; + // 第一个路由如果有query参数 需要加上参数 + const fistChildQuery = route.children[0]?.meta?.query; + // 根目录菜单固定只有一个children 且path为/ 不需要添加redirect + route.redirect = + fistChildQuery && route.children.length !== 1 && route.path !== '/' + ? setObjToUrlParams(firstChild.path, fistChildQuery) + : firstChild.path; + return route; }); diff --git a/packages/effects/layouts/src/basic/menu/use-navigation.ts b/packages/effects/layouts/src/basic/menu/use-navigation.ts index 5efb3969..d43d479c 100644 --- a/packages/effects/layouts/src/basic/menu/use-navigation.ts +++ b/packages/effects/layouts/src/basic/menu/use-navigation.ts @@ -1,14 +1,21 @@ import { useRouter } from 'vue-router'; -import { isHttpUrl, openWindow } from '@vben/utils'; +import { isHttpUrl, isObject, openWindow } from '@vben/utils'; function useNavigation() { const router = useRouter(); + const allRoutes = router.getRoutes(); const navigation = async (path: string) => { if (isHttpUrl(path)) { openWindow(path, { target: '_blank' }); } else { + // 带路由参数 + const found = allRoutes.find((item) => item.path === path); + if (found && isObject(found.meta.query)) { + await router.push({ path, query: found.meta.query }); + return; + } await router.push(path); } }; diff --git a/packages/utils/src/helpers/index.ts b/packages/utils/src/helpers/index.ts index ae8741de..128df3c0 100644 --- a/packages/utils/src/helpers/index.ts +++ b/packages/utils/src/helpers/index.ts @@ -5,6 +5,7 @@ export * from './generate-routes-frontend'; export * from './get-popup-container'; export * from './merge-route-modules'; export * from './mitt'; +export * from './request'; export * from './reset-routes'; export * from './safe'; export * from './tree'; diff --git a/packages/utils/src/helpers/request.ts b/packages/utils/src/helpers/request.ts new file mode 100644 index 00000000..c5e49342 --- /dev/null +++ b/packages/utils/src/helpers/request.ts @@ -0,0 +1,72 @@ +/** + * 一些发送请求 需要用到的工具 + */ +import { isObject, isString } from '@vben-core/shared/utils'; + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; + +export function joinTimestamp( + join: boolean, + restful: T, +): T extends true ? string : object; + +export function joinTimestamp(join: boolean, restful = false): object | string { + if (!join) { + return restful ? '' : {}; + } + const now = Date.now(); + if (restful) { + return `?_t=${now}`; + } + return { _t: now }; +} + +/** + * @description: Format request parameter time + */ +export function formatRequestDate(params: Record) { + if (Object.prototype.toString.call(params) !== '[object Object]') { + return; + } + + for (const key in params) { + const format = params[key]?.format ?? null; + if (format && typeof format === 'function') { + params[key] = params[key].format(DATE_TIME_FORMAT); + } + if (isString(key)) { + const value = params[key]; + if (value) { + try { + params[key] = isString(value) ? value.trim() : value; + } catch (error: any) { + throw new Error(error); + } + } + } + if (isObject(params[key])) { + formatRequestDate(params[key]); + } + } +} + +/** + * Add the object as a parameter to the URL + * @param baseUrl url + * @param obj + * @returns {string} + * eg: + * let obj = {a: '3', b: '4'} + * setObjToUrlParams('www.baidu.com', obj) + * ==>www.baidu.com?a=3&b=4 + */ +export function setObjToUrlParams(baseUrl: string, obj: any): string { + let parameters = ''; + for (const key in obj) { + parameters += `${key}=${encodeURIComponent(obj[key])}&`; + } + parameters = parameters.replace(/&$/, ''); + return /\?$/.test(baseUrl) + ? baseUrl + parameters + : baseUrl.replace(/\/?$/, '?') + parameters; +}