From aa0ffab9276eb67d554ec6db281e8182c8422084 Mon Sep 17 00:00:00 2001 From: XieYongHong <18010623010@163.com> Date: Fri, 27 Oct 2023 14:32:40 +0800 Subject: [PATCH] fix: bug#19167 --- package.json | 2 +- src/components/Layout/BasicLayoutPage.vue | 11 +- src/hook/index.ts | 1 + src/hook/useRequest.ts | 92 +++++++++ src/store/menu.ts | 14 +- src/utils/menu.ts | 195 +----------------- src/utils/request.ts | 6 +- src/views/iframe/index.vue | 24 ++- .../system/Apply/Save/components/EditForm.vue | 20 +- .../system/Apply/componenets/ThirdMenu.vue | 150 ++++++++++++++ src/views/system/Apply/componenets/util.ts | 27 +++ src/views/system/Apply/index.vue | 10 +- src/views/system/Menu/Detail/BasicInfo.vue | 19 +- src/views/system/Menu/index.vue | 26 +-- yarn.lock | 8 +- 15 files changed, 366 insertions(+), 239 deletions(-) create mode 100644 src/hook/index.ts create mode 100644 src/hook/useRequest.ts create mode 100644 src/views/system/Apply/componenets/ThirdMenu.vue create mode 100644 src/views/system/Apply/componenets/util.ts diff --git a/package.json b/package.json index d6fd157d..6976a7c2 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "event-source-polyfill": "^1.0.31", "global": "^4.4.0", "jetlinks-store": "^0.0.3", - "jetlinks-ui-components": "^1.0.34-2", + "jetlinks-ui-components": "^1.0.34-4", "js-cookie": "^3.0.1", "jsencrypt": "^3.3.2", "less": "^4.1.3", diff --git a/src/components/Layout/BasicLayoutPage.vue b/src/components/Layout/BasicLayoutPage.vue index d3be17e0..dbabb304 100644 --- a/src/components/Layout/BasicLayoutPage.vue +++ b/src/components/Layout/BasicLayoutPage.vue @@ -25,9 +25,11 @@ - - - + + + + + @@ -40,6 +42,7 @@ import { clearMenuItem } from 'jetlinks-ui-components/es/ProLayout/util'; import { AccountMenu } from '@/router/menu' import { useSystem } from '@/store/system'; import { storeToRefs } from 'pinia'; +import { useSlots } from 'vue' type StateType = { collapsed: boolean; @@ -55,7 +58,7 @@ const menu = useMenuStore(); const system = useSystem(); const {configInfo,layout, basicLayout} = storeToRefs(system); - +const slots = useSlots() const layoutConf = reactive({ theme: DefaultSetting.layout.theme, siderWidth: layout.value.siderWidth, diff --git a/src/hook/index.ts b/src/hook/index.ts new file mode 100644 index 00000000..f222b03e --- /dev/null +++ b/src/hook/index.ts @@ -0,0 +1 @@ +export * from './useRequest' diff --git a/src/hook/useRequest.ts b/src/hook/useRequest.ts new file mode 100644 index 00000000..6d2d9c03 --- /dev/null +++ b/src/hook/useRequest.ts @@ -0,0 +1,92 @@ +import {onUnmounted, ref} from 'vue' +import type { Ref } from 'vue' +import {isFunction, get, isArray} from 'lodash-es' +import type { AxiosResponseRewrite } from '@/utils/request' + +interface RequestOptions { + immediate: boolean + /** + * 成功回调 + * @param data + * @returns + */ + onSuccess: (data: AxiosResponseRewrite) => S | void + /** + * 返回参数处理 + * @returns + */ + formatName: string | [string] + onError: (e: any) => void + + defaultParams: S | any | any[] + + handleResponse: (data: any) => any +} + +const defaultOptions: any = { + immediate: true, + formatName: 'result' +} + +type Run = (...args: any[]) => void + +export const useRequest = ( + request: (...args: any[]) => Promise>, + options: Partial> = defaultOptions, +): { + data: Ref, + loading: Ref, + run: Run +} => { + const data = ref() + const loading = ref(false) + const _options = { + ...defaultOptions, + ...options + } + + async function run(...arg: any[]) { + if (request && isFunction(request)) { + loading.value = true + try { + // @ts-ignore + const resp = await request.apply(this, arg) + + loading.value = false + + if (resp?.success) { + const successData = await _options.onSuccess?.(resp) + data.value = successData || get(resp, _options.formatName!) + // console.log(data.value) + } else { + _options.onError?.(resp) + } + } catch (e) { + loading.value = false + _options.onError?.(e) + } + } + } + + if (_options.immediate) { // 主动触发 + if (_options.defaultParams) { + isArray(_options.defaultParams) ? run(..._options.defaultParams) : run(_options.defaultParams) + } else { + run() + } + } + + onUnmounted(() => { + // 销毁时,撤销该请求 + if (request && isFunction(request)) { + + } + // request() + }) + + return { + data, + loading, + run + } +} diff --git a/src/store/menu.ts b/src/store/menu.ts index ab33fa91..846f4695 100644 --- a/src/store/menu.ts +++ b/src/store/menu.ts @@ -24,12 +24,12 @@ const defaultOwnParams = [ termType: 'eq', value: 'iot' }, - { - column: 'owner', - termType: 'isnull', - value: '1', - type: 'or' - } + // { + // column: 'owner', + // termType: 'isnull', + // value: '1', + // type: 'or' + // } ] } ] @@ -129,4 +129,4 @@ export const useMenuStore = defineStore({ }) } } -}) \ No newline at end of file +}) diff --git a/src/utils/menu.ts b/src/utils/menu.ts index 53e4ebe4..1d11aabd 100644 --- a/src/utils/menu.ts +++ b/src/utils/menu.ts @@ -1,6 +1,7 @@ import { BlankLayoutPage, BasicLayoutPage } from 'components/Layout' import { isNoCommunity } from '@/utils/utils' import Iframe from '../views/iframe/index.vue' +import { shallowRef, defineAsyncComponent } from 'vue' const pagesComponent = import.meta.glob('../views/**/*.vue'); @@ -155,192 +156,6 @@ const extraRouteObj = { } }; -// -// const resolveComponent = (name: any) => { -// const importPage = pagesComponent[`../views/${name}/index.vue`]; -// console.log(importPage) -// if (!importPage) { -// return undefined -// } else { -// const res = () => importPage() -// return res -// } -// //@ts-ignore -// } -// -// const findChildrenRoute = (code: string, url: string, routes: any[] = []): MenuItem[] => { -// if (extraRouteObj[code]) { -// const extraRoutes = extraRouteObj[code].children.map((route: MenuItem) => { -// return { -// url: `${url}/${route.code}`, -// code: `${code}/${route.code}`, -// name: route.name, -// isShow: false -// } -// }) -// return [...routes, ...extraRoutes] -// } -// return routes -// } -// -// const findDetailRouteItem = (code: string, url: string): Partial | null => { -// const detailComponent = resolveComponent(`${code}/Detail`) -// if (detailComponent) { -// return { -// url: `${url}/detail/:id`, -// code: `${code}/Detail`, -// component: detailComponent, -// name: '详情信息', -// isShow: false -// } -// } -// return null -// } -// -// const findDetailRoutes = (routes: any[]): any[] => { -// const newRoutes: any[] = [] -// routes.forEach((route: any) => { -// newRoutes.push(route) -// const detail = findDetailRouteItem(route.code, route.url) -// if (detail) { -// newRoutes.push(detail) -// } -// }) -// return newRoutes -// } -// -// const filterMenus = ['device/DashBoard'] -// export const filterCommunityMenus = (menuData: any[]) => { -// return menuData.filter(item => { -// if (item.children) { -// item.children = filterCommunityMenus(item.children) -// } -// return !filterMenus.includes(item.code) -// }) -// } -// -// export const findCodeRoute = (asyncRouterMap: any[]) => { -// const routeMeta = {} -// -// function getDetail(code: string, url: string) { -// const detail = findDetailRouteItem(code, url) -// if (!detail) return -// -// routeMeta[(detail as MenuItem).code] = { -// path: detail.url, -// title: detail.name, -// parentName: code, -// buttons: detail.buttons?.map((b: any) => b.id) || [] -// } -// } -// -// function findChildren(data: any[], code: string = '') { -// data.forEach(route => { -// routeMeta[route.code] = { -// path: route.url || route.path, -// title: route.meta?.title || route.name, -// parentName: code, -// buttons: route.buttons?.map((b: any) => b.id) || [] -// } -// const otherRoutes = extraRouteObj[route.code] -// -// if (otherRoutes) { -// otherRoutes.children.map((item: any) => { -// const _code = `${route.code}/${item.code}` -// const url = `${route.url}/${item.code}` -// routeMeta[_code] = { -// path: `${route.url}/${item.code}`, -// title: item.name, -// parentName: route.code, -// buttons: item.buttons?.map((b: any) => b.id) || [] -// } -// getDetail(_code, url) -// }) -// } -// const _code = route.appId ? `/${route.appId}${route.url}` : route.code -// if (!route.appId) { -// getDetail(_code, route.url) -// } else { -// routeMeta[_code] = { -// path: `/${route.appId}${route.url}`, -// title: route.name, -// parentName: code, -// buttons: [] -// } -// } -// if (route.children) { -// findChildren(route.children, _code) -// } -// }) -// } -// -// findChildren(asyncRouterMap) -// -// return routeMeta -// } -// -// export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any } { -// const _asyncRouterMap = cloneDeep(asyncRouterMap) -// const menusData: any[] = [] -// const silderMenus: any[] = [] -// _asyncRouterMap.forEach((route: any) => { -// const hasAppId = route.appId -// const _route: any = { -// path: hasAppId ? `/${route.appId}${route.url}` : `${route.url}`, -// name: hasAppId ? `/${route.appId}${route.url}` : route.code, -// url: hasAppId ? `/${route.appId}${route.url}` : route.url, -// meta: { -// icon: route.icon, -// title: route.name, -// hideInMenu: route.isShow === false, -// buttons: route.buttons?.map((b: any) => b.id) || [], -// isApp: hasAppId, -// }, -// } -// -// const silder = { ..._route } -// // 查看是否有隐藏子路由 -// route.children = findChildrenRoute(route.code, route.url, route.children) -// route.children = findDetailRoutes(route.children) -// if (route.children && route.children.length) { -// // TODO 查看是否具有详情页 -// const { menusData: _menusData, silderMenus: _silderMenus } = filterAsyncRouter(route.children, `${parentCode}/${route.code}`, level + 1) -// _route.children = _menusData -// silder.children = _silderMenus -// const showChildren = _route.children.some((r: any) => !r.meta.hideInMenu) -// -// if (showChildren && _route.children.length) { -// _route.component = level === 1 ? BasicLayoutPage : BlankLayoutPage -// _route.redirect = _route.children[0].url -// } else { -// const myComponent = resolveComponent(route.code) -// // _route.component = myComponent ? myComponent : BlankLayoutPage; -// if (!!myComponent) { -// _route.component = myComponent; -// _route.children.map((r: any) => menusData.push(r)) -// delete _route.children -// } else { -// _route.component = BlankLayoutPage -// } -// } -// } else { -// if (hasAppId) { -// _route.component = route.component || resolveComponent('iframe') -// } else { -// _route.component = route.component || resolveComponent(route.code) || BlankLayoutPage -// } -// } -// menusData.push(_route) -// silderMenus.push(silder) -// }) -// return { -// menusData, -// silderMenus, -// } -// } - -import { shallowRef } from 'vue' - type Buttons = Array<{ id: string }> const hasAppID = (item: { appId?: string, url?: string }): { isApp: boolean, appUrl: string } => { @@ -367,6 +182,12 @@ const handleMeta = (item: MenuItem, isApp: boolean) => { const findComponents = (code: string, level: number, isApp: boolean, components: any) => { const myComponents = components[code] if (level === 1) { // BasicLayoutPage + if (myComponents) { + return h(BasicLayoutPage, {}, () => [h(defineAsyncComponent(() => myComponents()), {})]) + } + if (isApp) { + return h(BasicLayoutPage, {}, () => [h(Iframe, {})]) + } return myComponents ? () => myComponents() : BasicLayoutPage } else if (isApp){ // iframe return Iframe @@ -529,4 +350,4 @@ export const handleAuthMenu = (menuData: any[], cb: (code: any, buttons: any[]) } }) } -} \ No newline at end of file +} diff --git a/src/utils/request.ts b/src/utils/request.ts index 197db378..e2002cf7 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -6,7 +6,7 @@ import { LoginPath } from '@/router/menu' import { cleanToken, getToken, LocalStore } from '@/utils/comm' import type { AxiosInstance, AxiosResponse } from 'axios' -interface AxiosResponseRewrite extends AxiosResponse { +export interface AxiosResponseRewrite extends AxiosResponse { result: T success: boolean } @@ -150,7 +150,7 @@ const showNotification = (message: string, description: string, key?: string, sh * @returns {Promise} */ const errorHandler = (error: any) => { - + if (error.response) { const data = error.response.data const status = error.response.status @@ -257,4 +257,4 @@ export default { remove, getStream, postStream -} \ No newline at end of file +} diff --git a/src/views/iframe/index.vue b/src/views/iframe/index.vue index 677825d7..54b16259 100644 --- a/src/views/iframe/index.vue +++ b/src/views/iframe/index.vue @@ -20,19 +20,29 @@ const handle = async (appId: string, url: string) => { const res = await getAppInfo_api(appId); let menuUrl: any = url; if (res.status === 200) { - if (res.result.page.routeType === 'hash') { - menuUrl = `#${url}`; + const result = res.result + if (result.page.routeType === 'hash') { + menuUrl = url.startsWith('/') ? `#${url}` : `#/${url}`; } - if (res.result.provider === 'internal-standalone') { - const urlStandalone = `${res.result.page.baseUrl}/api/application/sso/${appId}/login?redirect=${menuUrl}?layout=false`; + + if (result.page.parameters) { + const params = new URLSearchParams() + result.page.parameters.forEach((item: any) => { + params.set(item.key,item.value) + }) + menuUrl += `?${params.toString()}` + } + + if (result.provider === 'internal-standalone') { + const urlStandalone = `${result.page.baseUrl}/api/application/sso/${appId}/login?redirect=${menuUrl}?layout=false`; iframeUrl.value = urlStandalone; - } else if (res.result.provider === 'internal-integrated') { + } else if (result.provider === 'internal-integrated') { const tokenUrl = `${ - res.result.page.baseUrl + result.page.baseUrl }/${menuUrl}?layout=false&X-Access-Token=${LocalStore.get(TOKEN_KEY)}`; iframeUrl.value = tokenUrl; } else { - const urlOther = `${res.result.page.baseUrl}/${menuUrl}`; + const urlOther = `${result.page.baseUrl}/${menuUrl}`; iframeUrl.value = urlOther; } } diff --git a/src/views/system/Apply/Save/components/EditForm.vue b/src/views/system/Apply/Save/components/EditForm.vue index 7d47f61d..7d3ca1bf 100644 --- a/src/views/system/Apply/Save/components/EditForm.vue +++ b/src/views/system/Apply/Save/components/EditForm.vue @@ -144,12 +144,7 @@ @@ -1397,12 +1392,20 @@
+
@@ -1420,6 +1423,7 @@ import { import FormLabel from './FormLabel.vue'; import RequestTable from './RequestTable.vue'; import MenuDialog from '../../componenets/MenuDialog.vue'; +import ThirdMenu from '../../componenets/ThirdMenu.vue'; import { getImage, onlyMessage } from '@/utils/comm'; import type { formType, dictType, optionsType, applyType } from '../typing'; import { getRoleList_api } from '@/api/system/user'; @@ -1573,7 +1577,7 @@ const getType = async () => { typeOptions.value = arr; } } - + onMounted(async () => { await getType(); getRoleIdList(); diff --git a/src/views/system/Apply/componenets/ThirdMenu.vue b/src/views/system/Apply/componenets/ThirdMenu.vue new file mode 100644 index 00000000..31993ef6 --- /dev/null +++ b/src/views/system/Apply/componenets/ThirdMenu.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/src/views/system/Apply/componenets/util.ts b/src/views/system/Apply/componenets/util.ts new file mode 100644 index 00000000..fa561e8c --- /dev/null +++ b/src/views/system/Apply/componenets/util.ts @@ -0,0 +1,27 @@ +export const getCheckByTree = (data: any[]): string[] => { + let keys: string[] = [] + if (data.length) { + data.forEach(item => { + if (item.children) { + keys = [...getCheckByTree(item.children), ...keys] + } else { + keys.push(item.code) + } + }) + } + return keys +} + +export const filterTree = (data: any[], ids: string[]) => { + return data?.filter(item => { + delete item.id + item.options = {show: true} + if (ids.includes(item.code)) { + return true + } else if (item.children) { + item.children = filterTree(item.children, ids) + return item.children.length >0 + } + return false + }) || [] +} diff --git a/src/views/system/Apply/index.vue b/src/views/system/Apply/index.vue index bff39a0c..486a395c 100644 --- a/src/views/system/Apply/index.vue +++ b/src/views/system/Apply/index.vue @@ -183,12 +183,19 @@
+
@@ -197,6 +204,7 @@