Merge branch 'dev' into dev-dictionary
# Conflicts: # package.json # src/store/menu.ts # src/utils/menu.ts # src/views/device/Instance/Detail/components/BindParentDevice/index.vue # src/views/system/Menu/Detail/BasicInfo.vue # src/views/system/Menu/index.vue # yarn.lock
This commit is contained in:
commit
2abc3362c8
|
@ -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-3",
|
||||
"jetlinks-ui-components": "^1.0.34-4",
|
||||
"js-cookie": "^3.0.1",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"less": "^4.1.3",
|
||||
|
|
|
@ -25,9 +25,11 @@
|
|||
<UserInfo />
|
||||
</div>
|
||||
</template>
|
||||
<router-view v-slot="{ Component }">
|
||||
<component :is="components || Component" />
|
||||
</router-view>
|
||||
<slot>
|
||||
<router-view v-slot="{ Component }">
|
||||
<component :is="components || Component" />
|
||||
</router-view>
|
||||
</slot>
|
||||
</j-pro-layout>
|
||||
</template>
|
||||
|
||||
|
@ -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,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from './useRequest'
|
|
@ -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<T, S> {
|
||||
immediate: boolean
|
||||
/**
|
||||
* 成功回调
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
onSuccess: (data: AxiosResponseRewrite<S>) => 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 = <T = any, S = any>(
|
||||
request: (...args: any[]) => Promise<AxiosResponseRewrite<T>>,
|
||||
options: Partial<RequestOptions<T, S>> = defaultOptions,
|
||||
): {
|
||||
data: Ref<S | undefined>,
|
||||
loading: Ref<boolean>,
|
||||
run: Run
|
||||
} => {
|
||||
const data = ref<S>()
|
||||
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
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import router from '@/router'
|
|||
import { onlyMessage } from '@/utils/comm'
|
||||
import { AccountMenu, NotificationRecordCode, NotificationSubscriptionCode } from '@/router/menu'
|
||||
import { USER_CENTER_MENU_CODE } from '@/utils/consts'
|
||||
import { isNoCommunity } from "@/utils/utils";
|
||||
import {isNoCommunity} from "@/utils/utils";
|
||||
|
||||
const defaultOwnParams = [
|
||||
{
|
||||
|
@ -139,4 +139,4 @@ export const useMenuStore = defineStore({
|
|||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { BlankLayoutPage, BasicLayoutPage, SinglePage } from 'components/Layout'
|
||||
import { isNoCommunity } from '@/utils/utils'
|
||||
import Iframe from '../views/iframe/index.vue'
|
||||
import { h } from 'vue'
|
||||
import { shallowRef, defineAsyncComponent, h } from 'vue'
|
||||
|
||||
const pagesComponent = import.meta.glob('../views/**/*.vue');
|
||||
|
||||
|
@ -156,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<MenuItem> | 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: any): { isApp: boolean, appUrl: string } => {
|
||||
|
@ -370,6 +184,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
|
||||
|
@ -536,4 +356,4 @@ export const handleAuthMenu = (menuData: any[], cb: (code: any, buttons: any[])
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import { LoginPath } from '@/router/menu'
|
|||
import { cleanToken, getToken, LocalStore } from '@/utils/comm'
|
||||
import type { AxiosInstance, AxiosResponse } from 'axios'
|
||||
|
||||
interface AxiosResponseRewrite<T = any[]> extends AxiosResponse<T, any> {
|
||||
export interface AxiosResponseRewrite<T = any[]> extends AxiosResponse<T, any> {
|
||||
result: T
|
||||
success: boolean
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
{{ TypeStringMap[data.record.valueType?.type] }}
|
||||
</template>
|
||||
<template #config="{ data }">
|
||||
<!-- <OtherConfigInfo :value="data.record.valueType"></OtherConfigInfo>-->
|
||||
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
||||
</template>
|
||||
</DataTableObject>
|
||||
|
@ -54,7 +53,7 @@
|
|||
|
||||
<script setup lang="ts" name="MetadataDataType">
|
||||
import { getUnit } from '@/api/device/instance';
|
||||
import { ValueObject } from '../components'
|
||||
import {DataType, ValueObject} from '../components'
|
||||
import {
|
||||
DataTableTypeSelect,
|
||||
DataTableArray,
|
||||
|
@ -68,7 +67,7 @@ import {
|
|||
DataTableObject,
|
||||
} from 'jetlinks-ui-components';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import {handleTypeValue, typeSelectChange, TypeStringMap, useUnit} from '../columns'
|
||||
import {handleTypeValue, typeSelectChange, TypeStringMap, useUnit, validatorConfig} from '../columns'
|
||||
import ConfigModal from './ConfigModal.vue'
|
||||
import { Form } from 'jetlinks-ui-components'
|
||||
|
||||
|
@ -137,7 +136,6 @@ const columns = [{
|
|||
required: true,
|
||||
rules: [{
|
||||
validator(_: any, value: any) {
|
||||
console.log('validator',value)
|
||||
if (!value?.type) {
|
||||
return Promise.reject('请选择数据类型')
|
||||
}
|
||||
|
@ -150,7 +148,23 @@ const columns = [{
|
|||
{
|
||||
title: '其他配置',
|
||||
dataIndex: 'config',
|
||||
width: 100
|
||||
width: 100,
|
||||
// components: {
|
||||
// name: ConfigModal,
|
||||
// props: {
|
||||
// showOther: false
|
||||
// }
|
||||
// },
|
||||
form: {
|
||||
rules: [{
|
||||
callback(rule: any, value: any, dataSource: any[]) {
|
||||
const field = rule.field.split('.')
|
||||
const fieldIndex = Number(field[1])
|
||||
const values = dataSource.find((item, index) => index === fieldIndex)
|
||||
return validatorConfig(values?.valueType)
|
||||
}
|
||||
}]
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
|
|
|
@ -30,19 +30,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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,12 +144,7 @@
|
|||
|
||||
<RequestTable
|
||||
v-model:value="form.data.page.parameters"
|
||||
value-type="select"
|
||||
:value-options="[
|
||||
{ label: '用户ID', value: '用户ID' },
|
||||
{ label: '用户名', value: '用户名' },
|
||||
{ label: 'token', value: 'token' },
|
||||
]"
|
||||
value-type="input"
|
||||
/>
|
||||
</j-form-item>
|
||||
</template>
|
||||
|
@ -1397,12 +1392,20 @@
|
|||
|
||||
<div class="dialog">
|
||||
<MenuDialog
|
||||
v-if="dialog.visible"
|
||||
v-if="dialog.visible && dialog.current.provider !== 'third-party'"
|
||||
v-model:visible="dialog.visible"
|
||||
:data="dialog.current"
|
||||
:mode="routeQuery.id ? 'edit' : 'add'"
|
||||
@refresh="menuStory.jumpPage('system/Apply')"
|
||||
/>
|
||||
<ThirdMenu
|
||||
v-if="dialog.visible && dialog.current.provider === 'third-party'"
|
||||
:data="dialog.current"
|
||||
:mode="routeQuery.id ? 'edit' : 'add'"
|
||||
mode="add"
|
||||
@cancel="dialog.visible = false"
|
||||
@ok="menuStory.jumpPage('system/Apply')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -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();
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<template>
|
||||
<j-modal
|
||||
:confirmLoading="loading"
|
||||
class="edit-dialog-container"
|
||||
title="集成菜单"
|
||||
visible
|
||||
width="600px"
|
||||
@cancel="cancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<p>
|
||||
当前集成菜单
|
||||
</p>
|
||||
<j-tree
|
||||
v-if="menuTree.length"
|
||||
v-model:checkedKeys="menuState.checkedMenu"
|
||||
v-model:expandedKeys="menuState.expandedKeys"
|
||||
:fieldNames="{ key: 'code', title: 'name' }"
|
||||
:height="300"
|
||||
:tree-data="menuTree"
|
||||
checkable
|
||||
/>
|
||||
<j-empty
|
||||
v-else
|
||||
/>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script name="ThirdMenu" setup>
|
||||
import {getMenuTree_api, queryOwnThree} from '@/api/system/menu';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import { useRequest } from '@/hook'
|
||||
import {filterTree, getCheckByTree} from "@/views/system/Apply/componenets/util";
|
||||
import {
|
||||
saveOwnerMenu_api,
|
||||
updateApp_api,
|
||||
} from '@/api/system/apply';
|
||||
|
||||
const props = defineProps({
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'add'
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const loading = ref(false)
|
||||
const emit = defineEmits(['ok', 'cancel']);
|
||||
const menuState = reactive({
|
||||
checkedMenu: [],
|
||||
expandedKeys: [],
|
||||
menuTree: ''
|
||||
})
|
||||
|
||||
const menuTree = computed(() => {
|
||||
try {
|
||||
return JSON.parse(menuState.menuTree || '[]')
|
||||
} catch (e) {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
useRequest(queryOwnThree,
|
||||
{
|
||||
defaultParams: { terms: [{ column: 'owner', termType: 'isnull', value: 0 }]},
|
||||
onSuccess(res) {
|
||||
menuState.menuTree = JSON.stringify(res.result)
|
||||
return res
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const { run } = useRequest(getMenuTree_api, {
|
||||
immediate: false,
|
||||
onSuccess(res) {
|
||||
menuState.checkedMenu = getCheckByTree(res.result)
|
||||
return res
|
||||
}
|
||||
}) // 获取应用绑定的菜单
|
||||
|
||||
const cancel = () => {
|
||||
if (props.mode === 'add') {
|
||||
menuStory.jumpPage('system/Apply/Save', {}, { id: props.data?.id })
|
||||
}
|
||||
emit('cancel')
|
||||
}
|
||||
|
||||
const handleOk = async () => {
|
||||
if (!menuState.checkedMenu.length) {
|
||||
onlyMessage('请勾选配置菜单', 'warning')
|
||||
return
|
||||
}
|
||||
const id = props.data.id
|
||||
const cloneData = JSON.parse(menuState.menuTree)
|
||||
const filterData = filterTree(cloneData, menuState.checkedMenu)
|
||||
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
const resp = await saveOwnerMenu_api('iot', id, filterData)
|
||||
await updateApp_api(id, {
|
||||
...props.data,
|
||||
integrationModes: props.data?.integrationModes?.map((item) => item?.value || item),
|
||||
page: {
|
||||
...props.data?.page,
|
||||
configuration: {
|
||||
checkedSystem: props.data?.page?.configuration?.checkedSystem
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (resp.success) {
|
||||
// 保存集成菜单
|
||||
onlyMessage('操作成功');
|
||||
emit('ok')
|
||||
}
|
||||
loading.value = false
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const getBindMenuData = () => {
|
||||
const id = props.data.id
|
||||
|
||||
run({
|
||||
terms: [
|
||||
{
|
||||
column: 'appId',
|
||||
value: id,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
if (props.data?.id) {
|
||||
getBindMenuData()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -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
|
||||
}) || []
|
||||
}
|
|
@ -183,12 +183,19 @@
|
|||
</div>
|
||||
<div class="dialogs">
|
||||
<MenuDialog
|
||||
v-if="dialogVisible"
|
||||
v-if="dialogVisible && current.provider !== 'third-party'"
|
||||
v-model:visible="dialogVisible"
|
||||
mode="edit"
|
||||
:data="current"
|
||||
@refresh="table.refresh"
|
||||
/>
|
||||
<ThirdMenu
|
||||
v-if="dialogVisible && current.provider === 'third-party'"
|
||||
:data="current"
|
||||
mode="edit"
|
||||
@cancel="dialogVisible = false"
|
||||
@ok="() => { dialogVisible = false; table.refresh}"
|
||||
/>
|
||||
</div>
|
||||
<Add v-if="visible" @close="visible = false" />
|
||||
</page-container>
|
||||
|
@ -197,6 +204,7 @@
|
|||
<script setup lang="ts" name="Apply">
|
||||
import PermissionButton from '@/components/PermissionButton/index.vue';
|
||||
import MenuDialog from './componenets/MenuDialog.vue';
|
||||
import ThirdMenu from './componenets/ThirdMenu.vue'
|
||||
import {
|
||||
getApplyList_api,
|
||||
changeApplyStatus_api,
|
||||
|
|
|
@ -129,6 +129,20 @@
|
|||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="所属应用"
|
||||
name="owner"
|
||||
>
|
||||
<j-select
|
||||
v-model:value="form.data.owner"
|
||||
:options="[{ label: 'Iot', value: 'iot' }]"
|
||||
allowClear
|
||||
placeholder="请选择所属应用"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</div>
|
||||
|
||||
|
@ -371,9 +385,8 @@ const form = reactive({
|
|||
const accessSupportValue = form.data.accessSupport;
|
||||
const params = {
|
||||
...form.data,
|
||||
options:{
|
||||
show:true
|
||||
},
|
||||
owner: form.data?.owner ?? null,
|
||||
options: { show: true },
|
||||
accessSupport: {
|
||||
value: accessSupportValue,
|
||||
label:
|
||||
|
@ -383,7 +396,6 @@ const form = reactive({
|
|||
? '支持'
|
||||
: '间接控制',
|
||||
},
|
||||
owner: 'iot',
|
||||
};
|
||||
api(params)
|
||||
.then((resp: any) => {
|
||||
|
@ -454,7 +466,7 @@ type assetType = {
|
|||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 5px px;
|
||||
top: 5px;
|
||||
left: 0;
|
||||
width: 4px;
|
||||
height: calc(100% - 10px);
|
||||
|
|
|
@ -3738,10 +3738,10 @@ jetlinks-store@^0.0.3:
|
|||
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
||||
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
||||
|
||||
jetlinks-ui-components@^1.0.34-3:
|
||||
version "1.0.34-3"
|
||||
resolved "https://registry.npmjs.org/jetlinks-ui-components/-/jetlinks-ui-components-1.0.34-3.tgz#c4f8182ce7419db40ed6d937ab0a7040bfb1549a"
|
||||
integrity sha512-9jzzGOIR5ICCBdCVYfQoWyZCIFcauLuvIF+WN/djR1glC4lsBdegN06HpzxcGMfsJlWODxzjRXEq+UDNqiL4zg==
|
||||
jetlinks-ui-components@^1.0.34-4:
|
||||
version "1.0.34-4"
|
||||
resolved "https://registry.npmjs.org/jetlinks-ui-components/-/jetlinks-ui-components-1.0.34-4.tgz#92cfc6be685988385a489f3e924383c4831f3ed5"
|
||||
integrity sha512-td+RgaBC5lQxRuDsHkCg9UEzCcSy4XikufnabVGz5IxU+UmXu+PJUjz2wo9vDe8sPSctyk/5jQU+N6GBPlp8JA==
|
||||
dependencies:
|
||||
"@vueuse/core" "^9.12.0"
|
||||
"@vueuse/router" "^9.13.0"
|
||||
|
|
Loading…
Reference in New Issue