fix: 优化monaco-editor编辑;修改我的订阅;修复运维管理仪表盘在暂无数据情况下切换导致无数据展示问题
* fix: 优化菜单跳转 * fix: 优化菜单跳转 * fix: bug#16693 * feat: task#2572 * fix: 优化物模型映射保存请求异常 * fix: 修复运维管理仪表盘在暂无数据情况下切换导致无数据展示问题 * fix: 修改订阅管理文字提示 * fix: totalFlow * fix: 修改我的订阅 * fix: 优化monaco-editor编辑
This commit is contained in:
parent
143144a64e
commit
49cf7c5594
|
@ -25,7 +25,7 @@
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
"global": "^4.4.0",
|
"global": "^4.4.0",
|
||||||
"jetlinks-store": "^0.0.3",
|
"jetlinks-store": "^0.0.3",
|
||||||
"jetlinks-ui-components": "^1.0.26",
|
"jetlinks-ui-components": "^1.0.27",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<ConfigProvider :locale='zhCN'>
|
<ConfigProvider :locale='zhCN'>
|
||||||
<!-- <router-view v-slot="{ Component }">-->
|
|
||||||
<!-- <keep-alive>-->
|
|
||||||
<!-- <component :is="Component" />-->
|
|
||||||
<!-- </keep-alive>-->
|
|
||||||
<!-- </router-view>-->
|
|
||||||
<router-view />
|
<router-view />
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,6 +3,9 @@ import server from '@/utils/request';
|
||||||
export const queryCollector = (data: any) =>
|
export const queryCollector = (data: any) =>
|
||||||
server.post(`/data-collect/collector/_query/no-paging?paging=false`, data);
|
server.post(`/data-collect/collector/_query/no-paging?paging=false`, data);
|
||||||
|
|
||||||
|
export const queryCollectorTree = (data: any) =>
|
||||||
|
server.post(`/data-collect/collector/_detail/no-paging?paging=false`, data);
|
||||||
|
|
||||||
export const queryChannelNoPaging = () =>
|
export const queryChannelNoPaging = () =>
|
||||||
server.post(`/data-collect/channel/_query/no-paging`, {
|
server.post(`/data-collect/channel/_query/no-paging`, {
|
||||||
paging: false,
|
paging: false,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<j-pro-layout
|
<j-pro-layout
|
||||||
v-bind="layoutConf"
|
v-bind="layoutConf"
|
||||||
v-model:openKeys="state.openKeys"
|
v-model:collapsed="basicLayout.collapsed"
|
||||||
v-model:collapsed="state.collapsed"
|
v-model:openKeys="basicLayout.openKeys"
|
||||||
v-model:selectedKeys="state.selectedKeys"
|
:selectedKeys="basicLayout.selectedKeys"
|
||||||
:headerHeight='layout.headerHeight'
|
:headerHeight='layout.headerHeight'
|
||||||
:pure="state.pure"
|
:breadcrumb="{ routes: breadcrumbs }"
|
||||||
:breadcrumb="{ routes: breadcrumb }"
|
:pure="basicLayout.pure"
|
||||||
@backClick='routerBack'
|
@backClick='routerBack'
|
||||||
>
|
>
|
||||||
<template #breadcrumbRender="slotProps">
|
<template #breadcrumbRender="slotProps">
|
||||||
|
@ -25,9 +25,9 @@
|
||||||
<UserInfo />
|
<UserInfo />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
<component :is="Component" />
|
<component :is="components || Component" />
|
||||||
</router-view>
|
</router-view>
|
||||||
</j-pro-layout>
|
</j-pro-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -54,14 +54,14 @@ const route = useRoute();
|
||||||
const menu = useMenuStore();
|
const menu = useMenuStore();
|
||||||
|
|
||||||
const system = useSystem();
|
const system = useSystem();
|
||||||
const {configInfo,layout} = storeToRefs(system);
|
const {configInfo,layout, basicLayout} = storeToRefs(system);
|
||||||
|
|
||||||
const layoutConf = reactive({
|
const layoutConf = reactive({
|
||||||
theme: DefaultSetting.layout.theme,
|
theme: DefaultSetting.layout.theme,
|
||||||
siderWidth: layout.value.siderWidth,
|
siderWidth: layout.value.siderWidth,
|
||||||
logo: DefaultSetting.layout.logo,
|
logo: DefaultSetting.layout.logo,
|
||||||
title: DefaultSetting.layout.title,
|
title: DefaultSetting.layout.title,
|
||||||
menuData: [...clearMenuItem(menu.siderMenus), AccountMenu],
|
menuData: [...menu.siderMenus, AccountMenu],
|
||||||
// menuData: menu.siderMenus,
|
// menuData: menu.siderMenus,
|
||||||
splitMenus: true,
|
splitMenus: true,
|
||||||
});
|
});
|
||||||
|
@ -72,87 +72,51 @@ watchEffect(() => {
|
||||||
layoutConf.logo = configInfo.value.front?.logo || DefaultSetting.layout.logo;
|
layoutConf.logo = configInfo.value.front?.logo || DefaultSetting.layout.logo;
|
||||||
})
|
})
|
||||||
|
|
||||||
const state = reactive<StateType>({
|
const components = computed(() => {
|
||||||
pure: false,
|
const componentName = route.matched[route.matched.length - 1]?.components?.default?.name
|
||||||
collapsed: false, // default value
|
if (componentName !== 'BasicLayoutPage') {
|
||||||
openKeys: [],
|
return route.matched[route.matched.length - 1]?.components?.default
|
||||||
selectedKeys: [],
|
}
|
||||||
});
|
return undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 面包屑
|
||||||
|
*/
|
||||||
|
const breadcrumbs = computed(() =>
|
||||||
|
{
|
||||||
|
const paths = router.currentRoute.value.matched
|
||||||
|
|
||||||
|
return paths.map((item, index) => {
|
||||||
|
return {
|
||||||
|
index,
|
||||||
|
isLast: index === (paths.length -1),
|
||||||
|
path: item.path,
|
||||||
|
breadcrumbName: (item.meta as any).title || '',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const routerBack = () => {
|
const routerBack = () => {
|
||||||
router.go(-1)
|
router.go(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const findRouteMeta = (code: string) => {
|
|
||||||
let meta = []
|
|
||||||
let menuItem: any = menu.menus[code]
|
|
||||||
while (menuItem) {
|
|
||||||
meta.unshift(menuItem)
|
|
||||||
if (menuItem.parentName) {
|
|
||||||
menuItem = menu.menus[menuItem.parentName]
|
|
||||||
} else {
|
|
||||||
menuItem = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return meta
|
|
||||||
}
|
|
||||||
|
|
||||||
const jump = (item: any) => {
|
const jump = (item: any) => {
|
||||||
let path = history.state.back
|
router.push(item.path)
|
||||||
if (path) {
|
|
||||||
// 包含query参数,清除?参数
|
|
||||||
if (path.includes('?')) {
|
|
||||||
const _path = path.split('?')[0]
|
|
||||||
path = _path === item.path ? path : item.path
|
|
||||||
} else if (path !== item.path) {
|
|
||||||
path = item.path
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
path = item.path
|
|
||||||
}
|
|
||||||
|
|
||||||
// jumpPage(slotProps.route.path)
|
|
||||||
router.push(path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const breadcrumb = computed(() =>
|
|
||||||
{
|
|
||||||
const paths = router.currentRoute.value.name as string
|
|
||||||
|
|
||||||
const metas = findRouteMeta(paths)
|
|
||||||
return metas.map((item, index) => {
|
watchEffect(() => {
|
||||||
return {
|
if (router.currentRoute) {
|
||||||
index,
|
const paths = router.currentRoute.value.matched
|
||||||
isLast: index === (metas.length - 1),
|
basicLayout.value.selectedKeys = paths.map(item => item.path)
|
||||||
path: item.path,
|
basicLayout.value.openKeys = paths.map(item => item.path)
|
||||||
breadcrumbName: item.title || '',
|
console.log(paths) //
|
||||||
};
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
);
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
if (router.currentRoute) {
|
|
||||||
const paths = router.currentRoute.value.name as string
|
|
||||||
if (paths) {
|
|
||||||
const _metas = findRouteMeta(paths)
|
|
||||||
state.selectedKeys = _metas.map(item => item.path)
|
|
||||||
state.openKeys = _metas.filter((r) => r !== router.currentRoute.value.path).map(item => item.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
if (
|
|
||||||
route.query &&
|
|
||||||
'layout' in route.query &&
|
|
||||||
route.query.layout === 'false'
|
|
||||||
) {
|
|
||||||
state.pure = true;
|
|
||||||
} else {
|
|
||||||
state.pure = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const toDoc = () => window.open('http://doc.v2.jetlinks.cn/');
|
const toDoc = () => window.open('http://doc.v2.jetlinks.cn/');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<router-view />
|
<router-view v-slot="Component">
|
||||||
|
<component :is="components || Component" />
|
||||||
|
</router-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script name="BlankLayoutPage" setup>
|
||||||
export default {
|
|
||||||
name: 'BlankLayoutPage'
|
const route = useRoute()
|
||||||
}
|
|
||||||
|
const components = computed(() => {
|
||||||
|
const componentName = route.matched[route.matched.length - 1]?.components?.default?.name
|
||||||
|
if (componentName !== 'BlankLayoutPage') {
|
||||||
|
return route.matched[route.matched.length - 1]?.components?.default
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { queryOwnThree } from '@/api/system/menu'
|
import { queryOwnThree } from '@/api/system/menu'
|
||||||
import {filterAsyncRouter, filterCommunityMenus, findCodeRoute, MenuItem} from '@/utils/menu'
|
import {
|
||||||
|
handleMenus,
|
||||||
|
MenuItem,
|
||||||
|
handleSiderMenu,
|
||||||
|
getAsyncRoutesMap, handleMenusMap
|
||||||
|
} from '@/utils/menu'
|
||||||
import { cloneDeep, isArray } from 'lodash-es'
|
import { cloneDeep, isArray } from 'lodash-es'
|
||||||
import { usePermissionStore } from './permission'
|
import { usePermissionStore } from './permission'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
@ -32,14 +37,7 @@ const defaultOwnParams = [
|
||||||
]
|
]
|
||||||
|
|
||||||
type MenuStateType = {
|
type MenuStateType = {
|
||||||
menus: {
|
menus: any
|
||||||
[key: string]: {
|
|
||||||
buttons?: string[]
|
|
||||||
title: string
|
|
||||||
parentName: string
|
|
||||||
path: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
siderMenus: MenuItem[]
|
siderMenus: MenuItem[]
|
||||||
params: Record<string, any>
|
params: Record<string, any>
|
||||||
}
|
}
|
||||||
|
@ -96,6 +94,10 @@ export const useMenuStore = defineStore({
|
||||||
name, params, query, state: { params }
|
name, params, query, state: { params }
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleMenusMapById(item: { code: string, path: string}) {
|
||||||
|
const { name, path } = item
|
||||||
|
this.menus[name] = {path}
|
||||||
|
},
|
||||||
queryMenuTree(isCommunity = false): Promise<any[]> {
|
queryMenuTree(isCommunity = false): Promise<any[]> {
|
||||||
return new Promise(async (res) => {
|
return new Promise(async (res) => {
|
||||||
//过滤非集成的菜单
|
//过滤非集成的菜单
|
||||||
|
@ -106,18 +108,12 @@ export const useMenuStore = defineStore({
|
||||||
// if (!isNoCommunity) {
|
// if (!isNoCommunity) {
|
||||||
// resultData = filterCommunityMenus(resultData)
|
// resultData = filterCommunityMenus(resultData)
|
||||||
// }
|
// }
|
||||||
permission.permissions = {}
|
const components = getAsyncRoutesMap()
|
||||||
const { menusData, silderMenus } = filterAsyncRouter(resultData)
|
const menusData = handleMenus(cloneDeep(resultData), components)
|
||||||
|
permission.handlePermission(resultData)
|
||||||
|
const silderMenus = handleSiderMenu(cloneDeep(resultData))
|
||||||
this.menus = findCodeRoute([...resultData]) // AccountMenu
|
// const { menusData, silderMenus } = filterAsyncRouter(resultData)
|
||||||
Object.keys(this.menus).forEach((item) => {
|
handleMenusMap(cloneDeep(menusData), this.handleMenusMapById)
|
||||||
const _item = this.menus[item]
|
|
||||||
if (_item.buttons?.length) {
|
|
||||||
permission.permissions[item] = _item.buttons
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
menusData.push({
|
menusData.push({
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: menusData[0]?.path,
|
redirect: menusData[0]?.path,
|
||||||
|
@ -125,6 +121,7 @@ export const useMenuStore = defineStore({
|
||||||
hideInMenu: true
|
hideInMenu: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// console.log(menusData)
|
||||||
// menusData.push(AccountMenu)
|
// menusData.push(AccountMenu)
|
||||||
this.siderMenus = silderMenus.filter((item: { name: string }) => ![USER_CENTER_MENU_CODE, NotificationRecordCode, NotificationSubscriptionCode].includes(item.name))
|
this.siderMenus = silderMenus.filter((item: { name: string }) => ![USER_CENTER_MENU_CODE, NotificationRecordCode, NotificationSubscriptionCode].includes(item.name))
|
||||||
res(menusData)
|
res(menusData)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
import {handleAuthMenu} from "@/utils/menu";
|
||||||
|
|
||||||
export const usePermissionStore = defineStore({
|
export const usePermissionStore = defineStore({
|
||||||
id: 'permission',
|
id: 'permission',
|
||||||
|
@ -39,5 +40,17 @@ export const usePermissionStore = defineStore({
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setPermission(code: string, buttons: string[]) {
|
||||||
|
this.permissions[code] = buttons
|
||||||
|
},
|
||||||
|
cleanPermission() {
|
||||||
|
this.permissions = {}
|
||||||
|
},
|
||||||
|
handlePermission(data: any) {
|
||||||
|
this.cleanPermission()
|
||||||
|
handleAuthMenu(data, this.setPermission)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -13,6 +13,12 @@ type SystemStateType = {
|
||||||
siderWidth: string | number | undefined; // 左侧菜单栏宽度
|
siderWidth: string | number | undefined; // 左侧菜单栏宽度
|
||||||
headerHeight: string | number | undefined; // 头部高度
|
headerHeight: string | number | undefined; // 头部高度
|
||||||
collapsedWidth: string | number | undefined;
|
collapsedWidth: string | number | undefined;
|
||||||
|
},
|
||||||
|
basicLayout: {
|
||||||
|
selectedKeys: string[],
|
||||||
|
openKeys: string[],
|
||||||
|
collapsed: boolean
|
||||||
|
pure: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +31,12 @@ export const useSystem = defineStore('system', {
|
||||||
siderWidth: 208, // 左侧菜单栏宽度
|
siderWidth: 208, // 左侧菜单栏宽度
|
||||||
headerHeight: 60, // 头部高度
|
headerHeight: 60, // 头部高度
|
||||||
collapsedWidth: 48,
|
collapsedWidth: 48,
|
||||||
|
},
|
||||||
|
basicLayout: {
|
||||||
|
selectedKeys: [],
|
||||||
|
openKeys: [],
|
||||||
|
collapsed: false,
|
||||||
|
pure: false
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
import { BlankLayoutPage, BasicLayoutPage } from 'components/Layout'
|
import { BlankLayoutPage, BasicLayoutPage } from 'components/Layout'
|
||||||
import { isNoCommunity } from '@/utils/utils'
|
import { isNoCommunity } from '@/utils/utils'
|
||||||
|
import Iframe from '../views/iframe/index.vue'
|
||||||
|
|
||||||
const pagesComponent = import.meta.glob('../views/**/*.vue');
|
const pagesComponent = import.meta.glob('../views/**/*.vue');
|
||||||
|
|
||||||
|
@ -155,185 +155,363 @@ 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,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const resolveComponent = (name: any) => {
|
import { shallowRef } from 'vue'
|
||||||
const importPage = pagesComponent[`../views/${name}/index.vue`];
|
|
||||||
if (!importPage) {
|
type Buttons = Array<{ id: string }>
|
||||||
return undefined
|
|
||||||
} else {
|
const hasAppID = (item: { appId?: string, url?: string }): { isApp: boolean, appUrl: string } => {
|
||||||
const res = () => importPage()
|
return {
|
||||||
return res
|
isApp: !!item.appId,
|
||||||
|
appUrl: `/${item.appId}${item.url}`
|
||||||
}
|
}
|
||||||
//@ts-ignore
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const findChildrenRoute = (code: string, url: string, routes: any[] = []): MenuItem[] => {
|
const handleButtons = (buttons?: Buttons) => {
|
||||||
if (extraRouteObj[code]) {
|
return buttons?.map((b) => b.id) || []
|
||||||
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 handleMeta = (item: MenuItem, isApp: boolean) => {
|
||||||
const detailComponent = resolveComponent(`${code}/Detail`)
|
return {
|
||||||
|
icon: item.icon,
|
||||||
|
title: item.name,
|
||||||
|
hideInMenu: item.isShow === false,
|
||||||
|
buttons: handleButtons(item.buttons),
|
||||||
|
isApp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const findComponents = (code: string, level: number, isApp: boolean, components: any) => {
|
||||||
|
const myComponents = components[code]
|
||||||
|
if (level === 1) { // BasicLayoutPage
|
||||||
|
return myComponents ? () => myComponents() : BasicLayoutPage
|
||||||
|
} else if (level === 2) { // BlankLayoutPage or components
|
||||||
|
return myComponents ? () => myComponents() : BlankLayoutPage
|
||||||
|
} else if (isApp){ // iframe
|
||||||
|
return () => Iframe
|
||||||
|
} else if(myComponents) { // components
|
||||||
|
return () => myComponents()
|
||||||
|
}
|
||||||
|
// return components['demo'] // 开发测试用
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasExtraChildren = (item: MenuItem, extraMenus: any ) => {
|
||||||
|
const extraItem = extraMenus[item.code]
|
||||||
|
if (extraItem) {
|
||||||
|
return extraItem.children.map(e => ({
|
||||||
|
...e,
|
||||||
|
url: `${item.url}${e.url}`,
|
||||||
|
isShow: false
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAsyncRoutesMap = () => {
|
||||||
|
const modules = {}
|
||||||
|
Object.keys(pagesComponent).forEach(item => {
|
||||||
|
const code = item.replace('../views/', '').replace('/index.vue', '')
|
||||||
|
modules[code] = pagesComponent[item]
|
||||||
|
})
|
||||||
|
return modules
|
||||||
|
}
|
||||||
|
|
||||||
|
const findDetailRouteItem = (item: any, components: any) => {
|
||||||
|
const { code, url } = item
|
||||||
|
const detailComponent = components[`${item.code}/Detail`]
|
||||||
if (detailComponent) {
|
if (detailComponent) {
|
||||||
return {
|
return [{
|
||||||
url: `${url}/detail/:id`,
|
url: `${url}/detail/:id`,
|
||||||
code: `${code}/Detail`,
|
code: `${code}/Detail`,
|
||||||
component: detailComponent,
|
component: detailComponent,
|
||||||
name: '详情信息',
|
name: '详情信息',
|
||||||
isShow: false
|
isShow: false
|
||||||
}
|
}]
|
||||||
}
|
}
|
||||||
return null
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const findDetailRoutes = (routes: any[]): any[] => {
|
export const handleMenus = (menuData: any[], components: any, level: number = 1) => {
|
||||||
const newRoutes: any[] = []
|
if (menuData && menuData.length) {
|
||||||
routes.forEach((route: any) => {
|
return menuData.map(item => {
|
||||||
newRoutes.push(route)
|
const { isApp, appUrl } = hasAppID(item) // 是否为第三方程序
|
||||||
const detail = findDetailRouteItem(route.code, route.url)
|
const meta = handleMeta(item, isApp)
|
||||||
if (detail) {
|
const route: any = {
|
||||||
newRoutes.push(detail)
|
path: isApp ? appUrl : `${item.url}`,
|
||||||
}
|
name: isApp ? appUrl : item.code,
|
||||||
})
|
url: isApp ? appUrl : item.url,
|
||||||
return newRoutes
|
meta: meta,
|
||||||
}
|
children: item.children
|
||||||
|
|
||||||
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) {
|
route.component = findComponents(item.code, level, isApp, components)
|
||||||
otherRoutes.children.map((item: any) => {
|
const extraRoute = hasExtraChildren(item, extraRouteObj)
|
||||||
const _code = `${route.code}/${item.code}`
|
const detail_components = findDetailRouteItem(item, components)
|
||||||
const url = `${route.url}/${item.code}`
|
|
||||||
routeMeta[_code] = {
|
|
||||||
path: `${route.url}/${item.code}`,
|
if (extraRoute && !isApp) { // 包含额外的子路由
|
||||||
title: item.name,
|
route.children = route.children ? [...route.children, ...extraRoute] : extraRoute
|
||||||
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) {
|
if (detail_components.length) {
|
||||||
getDetail(_code, route.url)
|
route.children = route.children ? route.children.concat(detail_components) : detail_components
|
||||||
} else {
|
|
||||||
routeMeta[_code] = {
|
|
||||||
path: `/${route.appId}${route.url}`,
|
|
||||||
title: route.name,
|
|
||||||
parentName: code,
|
|
||||||
buttons: []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (route.children) {
|
|
||||||
findChildren(route.children, _code)
|
if (route.children && route.children.length) {
|
||||||
|
route.children = handleMenus(route.children, components, level + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showChildren = route.children?.filter(r => !r.meta?.hideInMenu) || []
|
||||||
|
|
||||||
|
if (route.children && route.children.length && showChildren.length) {
|
||||||
|
route.redirect = showChildren[0].path
|
||||||
|
}
|
||||||
|
|
||||||
|
return route
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
findChildren(asyncRouterMap)
|
return []
|
||||||
|
|
||||||
return routeMeta
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any } {
|
export const handleMenusMap = (menuData: any[], cb: (data: any) => void) => {
|
||||||
const _asyncRouterMap = cloneDeep(asyncRouterMap)
|
if (menuData && menuData.length) {
|
||||||
const menusData: any[] = []
|
menuData.forEach(item => {
|
||||||
const silderMenus: any[] = []
|
cb(item)
|
||||||
_asyncRouterMap.forEach((route: any) => {
|
if (item.children) {
|
||||||
const hasAppId = route.appId
|
handleMenusMap(item.children, cb)
|
||||||
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
|
const hideInMenu = (code: string) => {
|
||||||
}
|
return ['account-center', 'message-subscribe'].includes(code)
|
||||||
}
|
}
|
||||||
menusData.push(_route)
|
|
||||||
silderMenus.push(silder)
|
export const handleSiderMenu = (menuData: any[]) => {
|
||||||
})
|
if (menuData && menuData.length) {
|
||||||
return {
|
return menuData.map(item => {
|
||||||
menusData,
|
const { isApp, appUrl } = hasAppID(item) // 是否为第三方程序
|
||||||
silderMenus,
|
const meta = handleMeta(item, isApp)
|
||||||
|
const route: any = {
|
||||||
|
path: isApp ? appUrl : `${item.url}`,
|
||||||
|
name: isApp ? appUrl : item.code,
|
||||||
|
url: isApp ? appUrl : item.url,
|
||||||
|
meta: meta,
|
||||||
|
children: item.children
|
||||||
|
}
|
||||||
|
|
||||||
|
if (route.children && route.children.length) {
|
||||||
|
route.children = handleSiderMenu(route.children)
|
||||||
|
}
|
||||||
|
|
||||||
|
route.meta.hideInMenu = hideInMenu(item.code)
|
||||||
|
|
||||||
|
return route
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const handleAuthMenu = (menuData: any[], cb: (code: any, buttons: any[]) => void) => {
|
||||||
|
if (menuData && menuData.length) {
|
||||||
|
return menuData.forEach(item => {
|
||||||
|
const { code, buttons, children} = item
|
||||||
|
|
||||||
|
if (buttons) {
|
||||||
|
cb(code, buttons.map(a => a.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children) {
|
||||||
|
handleAuthMenu(children, cb)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -54,13 +54,13 @@
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
:name="['circuitBreaker', 'type']"
|
:name="['configuration', 'inheritBreakerSpec', 'type']"
|
||||||
:rules="LeftTreeRules.type"
|
:rules="LeftTreeRules.type"
|
||||||
label="故障处理"
|
label="点位熔断处理"
|
||||||
>
|
>
|
||||||
<j-card-select
|
<j-card-select
|
||||||
:showImage="false"
|
:showImage="false"
|
||||||
v-model:value="formData.circuitBreaker.type"
|
v-model:value="formData.configuration.inheritBreakerSpec.type"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '降频', value: 'LowerFrequency' },
|
{ label: '降频', value: 'LowerFrequency' },
|
||||||
{ label: '断开', value: 'Break' },
|
{ label: '断开', value: 'Break' },
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<p style="color: #616161">
|
<p style="color: #616161">
|
||||||
{{ getTypeTooltip(formData.circuitBreaker.type) }}
|
{{ getTypeTooltip(formData.configuration.inheritBreakerSpec.type) }}
|
||||||
</p>
|
</p>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="双字高低位切换"
|
label="双字高低位切换"
|
||||||
|
@ -158,6 +158,7 @@
|
||||||
import { save, update } from '@/api/data-collect/collector';
|
import { save, update } from '@/api/data-collect/collector';
|
||||||
import { LeftTreeRules } from '../../data';
|
import { LeftTreeRules } from '../../data';
|
||||||
import type { FormInstance } from 'ant-design-vue';
|
import type { FormInstance } from 'ant-design-vue';
|
||||||
|
import {cloneDeep} from "lodash-es";
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const visibleEndian = ref(false);
|
const visibleEndian = ref(false);
|
||||||
|
@ -214,9 +215,13 @@ const formData = ref({
|
||||||
endian: 'BIG',
|
endian: 'BIG',
|
||||||
endianIn: 'BIG',
|
endianIn: 'BIG',
|
||||||
requsetTimeout: 2000,
|
requsetTimeout: 2000,
|
||||||
|
inheritBreakerSpec: {
|
||||||
|
type: 'LowerFrequency',
|
||||||
|
}
|
||||||
},
|
},
|
||||||
circuitBreaker: {
|
circuitBreaker: {
|
||||||
type: 'LowerFrequency',
|
// type: 'LowerFrequency',
|
||||||
|
type: 'Ignore'
|
||||||
},
|
},
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
@ -243,19 +248,21 @@ const handleOk = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTypeTooltip = (value: string) =>
|
const getTypeTooltip = (value: string) => {
|
||||||
value === 'LowerFrequency'
|
switch (value) {
|
||||||
? '连续20次采集异常后,降低采集频率至设定频率的1/10,故障处理后,采集频率将恢复至设定频率。'
|
case 'LowerFrequency': return '连续20次采集异常后,降低采集频率至设定频率的1/10,故障处理后,采集频率将恢复至设定频率。';
|
||||||
: value === 'Break'
|
// case 'Break': return '连续10分钟异常,停止采集数据进入断开状态,设备重新启用后恢复采集状态。'
|
||||||
? '连续10分钟异常,停止采集数据进入断开状态,设备重新启用后恢复采集状态。'
|
case 'Break': return '连续20次采集异常后,降低采集频率至设定频率的1/10,10分钟内未排除故障,将停止采集。'
|
||||||
: '忽略异常,保持原采集频率超时时间为5s。';
|
default: return '忽略异常,保持设定采集频率。';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
emit('change', false);
|
emit('change', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeCardSelectType = (value: Array<string>) => {
|
const changeCardSelectType = (value: Array<string>) => {
|
||||||
formData.value.circuitBreaker.type = value[0];
|
formData.value.configuration.inheritBreakerSpec.type = value[0];
|
||||||
};
|
};
|
||||||
const changeCardSelectEndian = (value: Array<string>) => {
|
const changeCardSelectEndian = (value: Array<string>) => {
|
||||||
formData.value.configuration.endian = value[0];
|
formData.value.configuration.endian = value[0];
|
||||||
|
@ -281,7 +288,19 @@ watch(
|
||||||
watch(
|
watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value.id) formData.value = value;
|
if (value.id) {
|
||||||
|
let copyValue = cloneDeep(value)
|
||||||
|
if (!copyValue?.configuration?.inheritBreakerSpec) {
|
||||||
|
copyValue.configuration = {
|
||||||
|
...copyValue.configuration,
|
||||||
|
inheritBreakerSpec: {
|
||||||
|
type: value.circuitBreaker.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copyValue.circuitBreaker.type = 'Ignore'
|
||||||
|
}
|
||||||
|
formData.value = copyValue
|
||||||
|
};
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
);
|
);
|
||||||
|
|
|
@ -39,8 +39,16 @@
|
||||||
<j-tag
|
<j-tag
|
||||||
class="tree-left-tag"
|
class="tree-left-tag"
|
||||||
v-if="data.id !== '*'"
|
v-if="data.id !== '*'"
|
||||||
:color="colorMap.get(data?.runningState?.value)"
|
:color="
|
||||||
>{{ data?.runningState?.text }}</j-tag
|
data?.uniformState?.value === 'normal' || data?.state?.value === 'disabled' ?
|
||||||
|
colorMap.get(data?.runningState?.value) :
|
||||||
|
colorMap.get(data?.uniformState?.value)
|
||||||
|
"
|
||||||
|
>{{
|
||||||
|
data?.uniformState?.value === 'normal' || data?.state?.value === 'disabled' ?
|
||||||
|
data?.runningState?.text :
|
||||||
|
data?.uniformState?.text
|
||||||
|
}}</j-tag
|
||||||
>
|
>
|
||||||
<j-tag
|
<j-tag
|
||||||
class="tree-left-tag2"
|
class="tree-left-tag2"
|
||||||
|
@ -117,7 +125,7 @@
|
||||||
|
|
||||||
<script setup lang="ts" name="TreePage">
|
<script setup lang="ts" name="TreePage">
|
||||||
import {
|
import {
|
||||||
queryCollector,
|
queryCollectorTree,
|
||||||
queryChannelNoPaging,
|
queryChannelNoPaging,
|
||||||
update,
|
update,
|
||||||
remove,
|
remove,
|
||||||
|
@ -245,7 +253,7 @@ const handleSearch = async (value: any) => {
|
||||||
!!value && (params.value = value);
|
!!value && (params.value = value);
|
||||||
}
|
}
|
||||||
spinning.value = true;
|
spinning.value = true;
|
||||||
const res: any = await queryCollector(params.value);
|
const res: any = await queryCollectorTree(params.value);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
if (clickSearch) {
|
if (clickSearch) {
|
||||||
defualtDataSource.value = res.result;
|
defualtDataSource.value = res.result;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
export const colorMap = new Map();
|
export const colorMap = new Map();
|
||||||
colorMap.set('running', 'success');
|
colorMap.set('running', 'success');
|
||||||
colorMap.set('partialError', 'warning');
|
colorMap.set('partialError', 'warning');
|
||||||
|
colorMap.set('partError', 'warning'); // 部分错误
|
||||||
colorMap.set('failed', 'error');
|
colorMap.set('failed', 'error');
|
||||||
|
colorMap.set('allError', 'error'); // 全部错误
|
||||||
colorMap.set('stopped', 'default');
|
colorMap.set('stopped', 'default');
|
||||||
colorMap.set('processing', '#cccccc');
|
colorMap.set('processing', '#cccccc');
|
||||||
colorMap.set('enabled', 'processing');
|
colorMap.set('enabled', 'processing');
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
width="770px"
|
width="770px"
|
||||||
@cancel="emits('close')"
|
@cancel="emits('close')"
|
||||||
:confirmLoading="loading"
|
:confirmLoading="loading"
|
||||||
|
:zIndex="1100"
|
||||||
|
:maskClosable='false'
|
||||||
>
|
>
|
||||||
<j-form :model="form" layout="vertical" ref="formRef">
|
<j-form :model="form" layout="vertical" ref="formRef">
|
||||||
<j-row :gutter="24">
|
<j-row :gutter="24">
|
||||||
|
@ -66,7 +68,7 @@
|
||||||
:rules="[
|
:rules="[
|
||||||
{
|
{
|
||||||
pattern: /^1[3456789]\d{9}$/,
|
pattern: /^1[3456789]\d{9}$/,
|
||||||
message: '请输入正确手机号',
|
message: '请输入正确的手机号',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<j-modal :width="'900px'" visible @cancel="emit('close')" :zIndex="1100">
|
<j-modal :maskClosable='false' :width="'900px'" visible @cancel="emit('close')" :zIndex="1100">
|
||||||
<template v-if="getType === 'notifier-weixin'">
|
<template v-if="getType === 'notifier-weixin'">
|
||||||
<j-spin :spinning="loading">
|
<j-spin :spinning="loading">
|
||||||
<div class="code" style="height: 450px">
|
<div class="code" style="height: 450px">
|
||||||
|
|
|
@ -28,11 +28,14 @@
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<Detail
|
<Detail
|
||||||
@unsubscribe="onUnSubscribe"
|
@unsubscribe="onUnSubscribe"
|
||||||
@save="onSave"
|
v-if="
|
||||||
v-if="current?.channelProvider !== 'inside-mail' && popoverVisible"
|
current?.channelProvider !== 'inside-mail' &&
|
||||||
|
popoverVisible
|
||||||
|
"
|
||||||
:current="current"
|
:current="current"
|
||||||
:data="props.data"
|
:data="data"
|
||||||
@close="popoverVisible = false"
|
@bindChange="onChange('bind')"
|
||||||
|
@infoChange="onChange('info')"
|
||||||
/>
|
/>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
v-else
|
v-else
|
||||||
|
@ -51,12 +54,28 @@
|
||||||
{{ current?.name }}
|
{{ current?.name }}
|
||||||
</j-ellipsis>
|
</j-ellipsis>
|
||||||
</div>
|
</div>
|
||||||
|
<EditInfo
|
||||||
|
v-if="editInfoVisible"
|
||||||
|
:data="user.userInfos"
|
||||||
|
@close="editInfoVisible = false"
|
||||||
|
@save="onSave"
|
||||||
|
/>
|
||||||
|
<Bind
|
||||||
|
@close="visible = false"
|
||||||
|
v-if="visible"
|
||||||
|
:data="data"
|
||||||
|
:current="current"
|
||||||
|
@save="onBindSave"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import Detail from './Detail.vue';
|
import Detail from './Detail.vue';
|
||||||
|
import { useUserInfo } from '@/store/userInfo';
|
||||||
|
import EditInfo from '../../EditInfo/index.vue';
|
||||||
|
import Bind from './Bind.vue';
|
||||||
|
|
||||||
const iconMap = new Map();
|
const iconMap = new Map();
|
||||||
iconMap.set('notifier-dingTalk', getImage('/notice-rule/dingtalk.png'));
|
iconMap.set('notifier-dingTalk', getImage('/notice-rule/dingtalk.png'));
|
||||||
|
@ -81,19 +100,44 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
notifyChannels: {
|
notifyChannels: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => [],
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
const user = useUserInfo();
|
||||||
const popoverVisible = ref<boolean>(false);
|
const popoverVisible = ref<boolean>(false);
|
||||||
|
|
||||||
|
const editInfoVisible = ref<boolean>(false);
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
|
|
||||||
|
const onChange = (type: 'bind' | 'info') => {
|
||||||
|
if(type === 'bind'){
|
||||||
|
editInfoVisible.value = true
|
||||||
|
} else {
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSave = () => {
|
||||||
|
editInfoVisible.value = false;
|
||||||
|
user.getUserInfo();
|
||||||
|
emit('save', props.current);
|
||||||
|
popoverVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onBindSave = () => {
|
||||||
|
visible.value = false
|
||||||
|
emit('save', props.current);
|
||||||
|
popoverVisible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
const onUnSubscribe = (dt: any) => {
|
const onUnSubscribe = (dt: any) => {
|
||||||
emit('unsubscribe', dt);
|
emit('unsubscribe', dt);
|
||||||
popoverVisible.value = false
|
popoverVisible.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCheckChange = (dt: any) => {
|
const onCheckChange = (dt: any) => {
|
||||||
emit('save', dt)
|
emit('save', dt);
|
||||||
popoverVisible.value = false
|
popoverVisible.value = false;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -21,29 +21,14 @@
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<EditInfo
|
|
||||||
v-if="editInfoVisible"
|
|
||||||
:data="user.userInfos"
|
|
||||||
@close="editInfoVisible = false"
|
|
||||||
@save="onSave"
|
|
||||||
/>
|
|
||||||
<Bind
|
|
||||||
@close="visible = false"
|
|
||||||
v-if="visible"
|
|
||||||
:data="props.data"
|
|
||||||
:current="current"
|
|
||||||
@save="onBindSave"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getIsBindThird } from '@/api/account/notificationSubscription';
|
import { getIsBindThird } from '@/api/account/notificationSubscription';
|
||||||
import { useUserInfo } from '@/store/userInfo';
|
import { useUserInfo } from '@/store/userInfo';
|
||||||
import EditInfo from '../../EditInfo/index.vue';
|
|
||||||
import Bind from './Bind.vue';
|
|
||||||
|
|
||||||
const user = useUserInfo();
|
const user = useUserInfo();
|
||||||
const emit = defineEmits(['save', 'unsubscribe', 'close']);
|
const emit = defineEmits(['infoChange', 'unsubscribe', 'bindChange']);
|
||||||
const info = ref<any>(null);
|
const info = ref<any>(null);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
@ -58,39 +43,23 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const editInfoVisible = ref<boolean>(false);
|
|
||||||
const visible = ref<boolean>(false);
|
|
||||||
|
|
||||||
const getType = computed(() => {
|
const getType = computed(() => {
|
||||||
return props.current?.channelProvider;
|
return props.current?.channelProvider;
|
||||||
});
|
});
|
||||||
|
|
||||||
const onBind = () => {
|
const onBind = () => {
|
||||||
if (
|
if (
|
||||||
['notifier-voice', 'notifier-sms', 'notifier-email'].includes(
|
!['notifier-voice', 'notifier-sms', 'notifier-email'].includes(
|
||||||
props.current?.channelProvider,
|
props.current?.channelProvider,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
editInfoVisible.value = true;
|
emit('infoChange')
|
||||||
} else {
|
} else {
|
||||||
visible.value = true
|
emit('bindChange')
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSave = () => {
|
|
||||||
editInfoVisible.value = false;
|
|
||||||
user.getUserInfo();
|
|
||||||
emit('save', props.current);
|
|
||||||
emit('close')
|
|
||||||
};
|
|
||||||
|
|
||||||
const onBindSave = () => {
|
|
||||||
visible.value = false
|
|
||||||
emit('save', props.current);
|
|
||||||
emit('close')
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
if (
|
if (
|
||||||
!['notifier-voice', 'notifier-sms', 'notifier-email'].includes(
|
!['notifier-voice', 'notifier-sms', 'notifier-email'].includes(
|
||||||
|
@ -114,16 +83,6 @@ onMounted(() => {
|
||||||
handleSearch()
|
handleSearch()
|
||||||
})
|
})
|
||||||
|
|
||||||
// watch(
|
|
||||||
// () => props.current,
|
|
||||||
// () => {
|
|
||||||
// handleSearch();
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// immediate: true,
|
|
||||||
// deep: true,
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<j-modal :width="'384px'" visible @cancel="emit('close')" :footer="null">
|
<j-modal :maskClosable='false' :width="'384px'" visible @cancel="emit('close')" :footer="null">
|
||||||
<template v-if="getType === 'notifier-dingTalk'">
|
<template v-if="getType === 'notifier-dingTalk'">
|
||||||
<div class="tip">请先绑定钉钉账号</div>
|
<div class="tip">请先绑定钉钉账号</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -358,7 +358,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (_delTag.value) {
|
if (_delTag.value && dataSourceCache.value) {
|
||||||
// 保存数据
|
// 保存数据
|
||||||
const arr = dataSourceCache.value.filter((i: any) => i?.original).map((item: any) => {
|
const arr = dataSourceCache.value.filter((i: any) => i?.original).map((item: any) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -277,7 +277,7 @@ const initPage = async (newId: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeRouteUpdate((to: any) => {
|
onBeforeRouteUpdate((to: any) => {
|
||||||
if (to.params?.id!==instanceStore.current.id) {
|
if (to.params?.id!==instanceStore.current.id && to.name === 'device/Instance/Detail') {
|
||||||
initPage(to.params?.id)
|
initPage(to.params?.id)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -354,7 +354,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (_delTag.value) {
|
if (_delTag.value && dataSourceCache.value.length) {
|
||||||
// 保存数据
|
// 保存数据
|
||||||
const arr = dataSourceCache.value.filter((i: any) => i?.plugin).map((item: any) => {
|
const arr = dataSourceCache.value.filter((i: any) => i?.plugin).map((item: any) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -164,7 +164,7 @@ const deviceList = ref([
|
||||||
label: '网关子设备',
|
label: '网关子设备',
|
||||||
value: 'childrenDevice',
|
value: 'childrenDevice',
|
||||||
iconUrl: getImage('/device-type-2.png'),
|
iconUrl: getImage('/device-type-2.png'),
|
||||||
tooltip: '作为网关的子设备,有网关代理连接到物联网平台',
|
tooltip: '作为网关的子设备,由网关代理连接到物联网平台',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '网关设备',
|
label: '网关设备',
|
||||||
|
|
|
@ -20,30 +20,58 @@
|
||||||
<j-scrollbar v-if='deviceList.length'>
|
<j-scrollbar v-if='deviceList.length'>
|
||||||
<j-spin :spinning='deviceSpinning'>
|
<j-spin :spinning='deviceSpinning'>
|
||||||
<div class='device-list-items'>
|
<div class='device-list-items'>
|
||||||
<div
|
<template v-for='item in deviceList'>
|
||||||
v-for='item in deviceList'
|
|
||||||
:class='{
|
|
||||||
"device-list-item": true,
|
|
||||||
"active": checkKeys.includes(item.id),
|
|
||||||
"disabled": disabledKeys.includes(item.id)
|
|
||||||
}'
|
|
||||||
@click='() => deviceClick(item.id, item)'
|
|
||||||
>
|
|
||||||
<template v-if='disabledKeys.includes(item.id)'>
|
<template v-if='disabledKeys.includes(item.id)'>
|
||||||
<j-tooltip
|
<j-tooltip
|
||||||
title='该设备已绑定平台设备'
|
title='该设备已绑定平台设备'
|
||||||
>
|
>
|
||||||
<span class='item-title'>{{ item.id }}</span>
|
<div
|
||||||
|
:class='{
|
||||||
|
"device-list-item": true,
|
||||||
|
"active": checkKeys.includes(item.id),
|
||||||
|
"disabled": disabledKeys.includes(item.id)
|
||||||
|
}'
|
||||||
|
@click='() => deviceClick(item.id, item)'
|
||||||
|
>
|
||||||
|
<div class='item-title'>
|
||||||
|
<span class="title-name no-tooltip">
|
||||||
|
{{item.name}}
|
||||||
|
</span>
|
||||||
|
<span class="title-id">
|
||||||
|
({{ item.id }})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<span v-else class='item-title'>
|
<div
|
||||||
{{ item.id }}
|
v-else
|
||||||
</span>
|
:class='{
|
||||||
<a-icon
|
"device-list-item": true,
|
||||||
v-if='checkKeys.includes(item.id)'
|
"active": checkKeys.includes(item.id),
|
||||||
type='CheckOutlined'
|
"disabled": disabledKeys.includes(item.id)
|
||||||
/>
|
}'
|
||||||
</div>
|
@click='() => deviceClick(item.id, item)'
|
||||||
|
>
|
||||||
|
|
||||||
|
<div class='item-title'>
|
||||||
|
<span class="title-name">
|
||||||
|
<j-ellipsis>
|
||||||
|
{{item.name}}
|
||||||
|
</j-ellipsis>
|
||||||
|
</span>
|
||||||
|
<span class="title-id">
|
||||||
|
<j-ellipsis>
|
||||||
|
({{ item.id }})
|
||||||
|
</j-ellipsis>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<a-icon
|
||||||
|
v-if='checkKeys.includes(item.id)'
|
||||||
|
type='CheckOutlined'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</j-spin>
|
</j-spin>
|
||||||
</j-scrollbar>
|
</j-scrollbar>
|
||||||
|
@ -278,7 +306,31 @@ onMounted(() => {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
> .item-title {
|
> .item-title {
|
||||||
flex: 1 1 auto;
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.title-name {
|
||||||
|
max-width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-tooltip {
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: bottom;
|
||||||
|
cursor: pointer;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
word-break: break-all;
|
||||||
|
max-height: 380px;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-id {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
color: #a3a3a3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -288,6 +340,10 @@ onMounted(() => {
|
||||||
&.active {
|
&.active {
|
||||||
background-color: rgba(153, 153, 153, 0.06);
|
background-color: rgba(153, 153, 153, 0.06);
|
||||||
color: @primary-color;
|
color: @primary-color;
|
||||||
|
.title-id {
|
||||||
|
color: @primary-color;
|
||||||
|
opacity: .8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
|
|
|
@ -192,7 +192,7 @@ import type {
|
||||||
ProductItem,
|
ProductItem,
|
||||||
} from '@/views/device/Product/typings';
|
} from '@/views/device/Product/typings';
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
import { onBeforeRouteLeave } from 'vue-router'
|
import {useRouter, onBeforeRouteUpdate} from 'vue-router'
|
||||||
import { useMetadata, useOperateLimits } from './hooks';
|
import { useMetadata, useOperateLimits } from './hooks';
|
||||||
import {TypeStringMap, useColumns} from './columns';
|
import {TypeStringMap, useColumns} from './columns';
|
||||||
import { levelMap, sourceMap, expandsType, limitsMap } from './utils';
|
import { levelMap, sourceMap, expandsType, limitsMap } from './utils';
|
||||||
|
@ -211,6 +211,8 @@ import { Modal } from 'jetlinks-ui-components'
|
||||||
import {EventEmitter} from "@/utils/utils";
|
import {EventEmitter} from "@/utils/utils";
|
||||||
import {watch} from "vue";
|
import {watch} from "vue";
|
||||||
import {cloneDeep} from "lodash";
|
import {cloneDeep} from "lodash";
|
||||||
|
import {useSystem} from "store/system";
|
||||||
|
import {storeToRefs} from "pinia";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
target: {
|
target: {
|
||||||
|
@ -229,6 +231,10 @@ const props = defineProps({
|
||||||
|
|
||||||
const _target = inject<'device' | 'product'>('_metadataType', props.target);
|
const _target = inject<'device' | 'product'>('_metadataType', props.target);
|
||||||
|
|
||||||
|
const system = useSystem();
|
||||||
|
const {basicLayout} = storeToRefs(system);
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const { data: metadata, noEdit, productNoEdit } = useMetadata(_target, props.type);
|
const { data: metadata, noEdit, productNoEdit } = useMetadata(_target, props.type);
|
||||||
const { hasOperate } = useOperateLimits(_target);
|
const { hasOperate } = useOperateLimits(_target);
|
||||||
|
|
||||||
|
@ -337,28 +343,11 @@ const handleAddClick = async (_data?: any, index?: number) => {
|
||||||
|
|
||||||
const newObject = _data || getDataByType()
|
const newObject = _data || getDataByType()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const data = [...dataSource.value];
|
|
||||||
//
|
|
||||||
// if (index !== undefined) {
|
|
||||||
// // 校验
|
|
||||||
// const _data = await tableRef.value.getData()
|
|
||||||
// console.log(_data)
|
|
||||||
// if (_data) {
|
|
||||||
// data.splice(index + 1, 0, newObject);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// data.push(newObject);
|
|
||||||
// }
|
|
||||||
// dataSource.value = data
|
|
||||||
const _addData = await tableRef.value.addItem(newObject, index)
|
const _addData = await tableRef.value.addItem(newObject, index)
|
||||||
if (_addData.length === 1) {
|
if (_addData.length === 1) {
|
||||||
showLastDelete.value = true
|
showLastDelete.value = true
|
||||||
}
|
}
|
||||||
showSave.value = true
|
showSave.value = true
|
||||||
// const _index = index !== undefined ? index + 1 : 0
|
|
||||||
// tableRef.value?.addItemAll?.(_index)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyItem = (record: any, index: number) => {
|
const copyItem = (record: any, index: number) => {
|
||||||
|
@ -452,16 +441,24 @@ const tabsChange = inject('tabsChange')
|
||||||
|
|
||||||
const parentTabsChange = (next?: Function) => {
|
const parentTabsChange = (next?: Function) => {
|
||||||
if (editStatus.value) {
|
if (editStatus.value) {
|
||||||
Modal.confirm({
|
const modal = Modal.confirm({
|
||||||
content: '页面改动数据未保存',
|
content: '页面改动数据未保存',
|
||||||
okText: '保存',
|
okText: '保存',
|
||||||
cancelText: '不保存',
|
cancelText: '不保存',
|
||||||
zIndex: 1400,
|
zIndex: 1400,
|
||||||
|
closable: true,
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
handleSaveClick(next as Function)
|
handleSaveClick(next as Function)
|
||||||
},
|
},
|
||||||
onCancel: () => {
|
onCancel: (e: any) => {
|
||||||
(next as Function)?.()
|
if (!e.triggerCancel) { // 取消按钮
|
||||||
|
modal.destroy();
|
||||||
|
(next as Function)?.()
|
||||||
|
} else {// 右上角取消按钮
|
||||||
|
const paths = router.currentRoute.value.matched
|
||||||
|
// basicLayout.value.selectedKeys = paths.map(item => item.path)
|
||||||
|
basicLayout.value.openKeys = paths.map(item => item.path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -479,7 +476,7 @@ watch(() => metadata.value, () => {
|
||||||
dataSource.value = metadata.value
|
dataSource.value = metadata.value
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
onBeforeRouteLeave((to, from, next) => {
|
onBeforeRouteUpdate((to, from, next) => {
|
||||||
parentTabsChange(next as Function)
|
parentTabsChange(next as Function)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -302,22 +302,22 @@ export const useColumns = (type?: MetadataType, target?: 'device' | 'product', n
|
||||||
title: '输入参数',
|
title: '输入参数',
|
||||||
dataIndex: 'inputs',
|
dataIndex: 'inputs',
|
||||||
width: 120,
|
width: 120,
|
||||||
form: {
|
// form: {
|
||||||
required: true,
|
// required: true,
|
||||||
rules: [{
|
// rules: [{
|
||||||
callback(rule:any,value: any, dataSource: any[]) {
|
// callback(rule:any,value: any, dataSource: any[]) {
|
||||||
const field = rule.field.split('.')
|
// const field = rule.field.split('.')
|
||||||
const fieldIndex = Number(field[1])
|
// const fieldIndex = Number(field[1])
|
||||||
|
//
|
||||||
const values = dataSource.find((item, index) => index === fieldIndex)
|
// const values = dataSource.find((item, index) => index === fieldIndex)
|
||||||
|
//
|
||||||
return validatorConfig({
|
// return validatorConfig({
|
||||||
type: 'object',
|
// type: 'object',
|
||||||
properties: values.inputs
|
// properties: values.inputs
|
||||||
}, true)
|
// }, true)
|
||||||
}
|
// }
|
||||||
}]
|
// }]
|
||||||
},
|
// },
|
||||||
control(newValue, oldValue) {
|
control(newValue, oldValue) {
|
||||||
if (newValue && !oldValue) {
|
if (newValue && !oldValue) {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -193,11 +193,11 @@
|
||||||
<div class="progress-text">
|
<div class="progress-text">
|
||||||
<div>
|
<div>
|
||||||
{{
|
{{
|
||||||
(
|
slotProps.totalFlow ? (
|
||||||
(slotProps.usedFlow /
|
(slotProps.usedFlow /
|
||||||
slotProps.totalFlow) *
|
slotProps.totalFlow) *
|
||||||
100
|
100
|
||||||
).toFixed(2)
|
).toFixed(2) : '0.00'
|
||||||
}}
|
}}
|
||||||
%
|
%
|
||||||
</div>
|
</div>
|
||||||
|
@ -209,9 +209,9 @@
|
||||||
:strokeColor="'#ADC6FF'"
|
:strokeColor="'#ADC6FF'"
|
||||||
:showInfo="false"
|
:showInfo="false"
|
||||||
:percent="
|
:percent="
|
||||||
(slotProps.usedFlow /
|
slotProps.totalFlow ? (slotProps.usedFlow /
|
||||||
slotProps.totalFlow) *
|
slotProps.totalFlow) *
|
||||||
100
|
100 : 0
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -139,6 +139,7 @@ const getCPUEcharts = async (val: any) => {
|
||||||
const _cpuOptions = {};
|
const _cpuOptions = {};
|
||||||
const _cpuXAxis = new Set();
|
const _cpuXAxis = new Set();
|
||||||
if (res.result?.length) {
|
if (res.result?.length) {
|
||||||
|
isEmpty.value = false;
|
||||||
// 根据服务节点来筛选数据
|
// 根据服务节点来筛选数据
|
||||||
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
|
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
|
||||||
const filterArray = res.result
|
const filterArray = res.result
|
||||||
|
|
|
@ -103,6 +103,7 @@ const getJVMEcharts = async (val: any) => {
|
||||||
const _jvmOptions = {};
|
const _jvmOptions = {};
|
||||||
const _jvmXAxis = new Set();
|
const _jvmXAxis = new Set();
|
||||||
if (res.result?.length) {
|
if (res.result?.length) {
|
||||||
|
isEmpty.value = false;
|
||||||
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
|
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
|
||||||
const filterArray = res.result
|
const filterArray = res.result
|
||||||
filterArray.forEach((item: any) => {
|
filterArray.forEach((item: any) => {
|
||||||
|
|
|
@ -114,6 +114,7 @@ const getNetworkEcharts = async (val: any) => {
|
||||||
const _networkOptions = {};
|
const _networkOptions = {};
|
||||||
const _networkXAxis = new Set();
|
const _networkXAxis = new Set();
|
||||||
if (resp.result.length) {
|
if (resp.result.length) {
|
||||||
|
isEmpty.value = false;
|
||||||
const filterArray = resp.result
|
const filterArray = resp.result
|
||||||
// const filterArray = resp.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId)
|
// const filterArray = resp.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId)
|
||||||
filterArray.forEach((item: any) => {
|
filterArray.forEach((item: any) => {
|
||||||
|
|
|
@ -44,7 +44,7 @@ watch(() => props.options, () => {
|
||||||
echartsRender()
|
echartsRender()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, { deep: true })
|
}, { immediate: true, deep: true })
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
@cancel="emit('close')"
|
@cancel="emit('close')"
|
||||||
@ok="onSave"
|
@ok="onSave"
|
||||||
>
|
>
|
||||||
|
<div class="alert">
|
||||||
|
<AIcon type="InfoCircleOutlined" />
|
||||||
|
通过角色控制【{{ name }}】的所有的通知方式可被哪些用户订阅。
|
||||||
|
</div>
|
||||||
<Role v-model="_selectedRowKeys" :gridColumn="2" />
|
<Role v-model="_selectedRowKeys" :gridColumn="2" />
|
||||||
</j-modal>
|
</j-modal>
|
||||||
</template>
|
</template>
|
||||||
|
@ -20,6 +24,10 @@ const props = defineProps({
|
||||||
type: Array as PropType<string[]>,
|
type: Array as PropType<string[]>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const _selectedRowKeys = ref<string[]>([]);
|
const _selectedRowKeys = ref<string[]>([]);
|
||||||
|
@ -32,3 +40,14 @@ const onSave = () => {
|
||||||
emit('save', _selectedRowKeys.value);
|
emit('save', _selectedRowKeys.value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.alert {
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 20px 0 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: rgba(0, 0, 0, 0.55);
|
||||||
|
line-height: 40px;
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -22,7 +22,7 @@
|
||||||
<template #title>
|
<template #title>
|
||||||
<span v-if="!update">暂无权限,请联系管理员</span>
|
<span v-if="!update">暂无权限,请联系管理员</span>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
用于配制外层权限<br />未配置外层权限将执行通知方式中配置的权限<br />配置外层权限后将覆盖所有通知方式中配置的权限
|
通过角色控制【{{ data.name }}】的所有的通知方式可被哪些用户订阅。
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<j-button
|
<j-button
|
||||||
|
@ -129,6 +129,7 @@
|
||||||
@save="onSave"
|
@save="onSave"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
|
:name="data.name"
|
||||||
/>
|
/>
|
||||||
<Detail
|
<Detail
|
||||||
:data="current"
|
:data="current"
|
||||||
|
@ -140,6 +141,7 @@
|
||||||
:data="data?.grant?.role?.idList"
|
:data="data?.grant?.role?.idList"
|
||||||
@close="authVisible = false"
|
@close="authVisible = false"
|
||||||
@save="onAuthSave"
|
@save="onAuthSave"
|
||||||
|
:name="data.name"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -346,49 +348,53 @@ const onSwitchChange = (e: boolean) => {
|
||||||
if (_checked) {
|
if (_checked) {
|
||||||
onAction(e);
|
onAction(e);
|
||||||
} else {
|
} else {
|
||||||
Modal.confirm({
|
if (e) {
|
||||||
title: e
|
onAction(e);
|
||||||
? '开启后默认平台所有用户都能接收到该通知'
|
} else {
|
||||||
: '关闭后平台所有用户都不能接收到该通知',
|
Modal.confirm({
|
||||||
cancelText: '取消',
|
title: e
|
||||||
okText: e ? '确认开启' : '确认关闭',
|
? '开启后默认平台所有用户都能接收到该通知'
|
||||||
content: h(
|
: '关闭后平台所有用户都不能接收到该通知',
|
||||||
'div',
|
cancelText: '取消',
|
||||||
{
|
okText: e ? '确认开启' : '确认关闭',
|
||||||
style: {
|
content: h(
|
||||||
display: 'flex',
|
'div',
|
||||||
justifyContent: 'flex-end',
|
{
|
||||||
marginTop: '20px',
|
style: {
|
||||||
},
|
display: 'flex',
|
||||||
},
|
justifyContent: 'flex-end',
|
||||||
[
|
marginTop: '20px',
|
||||||
h(
|
|
||||||
Checkbox,
|
|
||||||
{
|
|
||||||
onChange: (_e: any) => {
|
|
||||||
LocalStore.set(
|
|
||||||
user.userInfos?.username,
|
|
||||||
e
|
|
||||||
? {
|
|
||||||
..._value,
|
|
||||||
open: _e.target?.checked,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
..._value,
|
|
||||||
close: _e.target?.checked,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'不再提示',
|
},
|
||||||
),
|
[
|
||||||
],
|
h(
|
||||||
),
|
Checkbox,
|
||||||
onOk() {
|
{
|
||||||
onAction(e);
|
onChange: (_e: any) => {
|
||||||
},
|
LocalStore.set(
|
||||||
onCancel() {},
|
user.userInfos?.username,
|
||||||
});
|
e
|
||||||
|
? {
|
||||||
|
..._value,
|
||||||
|
open: _e.target?.checked,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
..._value,
|
||||||
|
close: _e.target?.checked,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'不再提示',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onOk() {
|
||||||
|
onAction(e);
|
||||||
|
},
|
||||||
|
onCancel() {},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -489,7 +495,7 @@ const onSave = (_data: any) => {
|
||||||
|
|
||||||
.box-item-add {
|
.box-item-add {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: #F7F8FA;
|
background-color: #f7f8fa;
|
||||||
width: 54px;
|
width: 54px;
|
||||||
height: 54px;
|
height: 54px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
</j-alert>
|
</j-alert>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<j-scrollbar height="400px">
|
<j-scrollbar :height="gridColumn <= 2 ? '320px' : '250px'">
|
||||||
<j-pro-table
|
<j-pro-table
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<AIcon type="InfoCircleOutlined" />
|
<AIcon type="InfoCircleOutlined" />
|
||||||
钉钉群机器人类型的配置在当前页面将被过滤
|
钉钉群机器人类型的配置在当前页面将被过滤
|
||||||
</div>
|
</div>
|
||||||
<div style="height: 400px; overflow-y: auto">
|
<div style="max-height: 400px; overflow-y: auto">
|
||||||
<JProTable
|
<JProTable
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:request="query"
|
:request="query"
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<AIcon type="InfoCircleOutlined" />
|
<AIcon type="InfoCircleOutlined" />
|
||||||
已规定固定收信人的模板在当前页面将被过滤
|
已规定固定收信人的模板在当前页面将被过滤
|
||||||
</div>
|
</div>
|
||||||
<div style="height: 400px; overflow-y: auto">
|
<div style="max-height: 400px; overflow-y: auto">
|
||||||
<JProTable
|
<JProTable
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:request="(e) => handleData(e)"
|
:request="(e) => handleData(e)"
|
||||||
|
|
|
@ -69,10 +69,12 @@ onMounted(() => {
|
||||||
iconUrl: iconMap.get(item.id),
|
iconUrl: iconMap.get(item.id),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
emit('update:value', options.value?.[0]?.value);
|
||||||
|
emit('update:name', options.value?.[0]?.label);
|
||||||
|
emit('change', {label: options.value?.[0]?.label, value: options.value?.[0]?.value});
|
||||||
}
|
}
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
notifyType.value = props.value;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,12 @@
|
||||||
<j-step v-for="(item, index) in stepList" :key="item">
|
<j-step v-for="(item, index) in stepList" :key="item">
|
||||||
<template #title>
|
<template #title>
|
||||||
{{ item
|
{{ item
|
||||||
}}<j-tooltip
|
}}<j-tooltip v-if="index === 4">
|
||||||
v-if="index === 4"
|
|
||||||
>
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<span>内层权限配置<br />外层权限已配置的情况下,将取外层权限与当前页面分配权限的交集,向对应角色发送通知。<br />外层权限未配置的情况下,将按此处配置的权限发送通知。</span>
|
<span>
|
||||||
|
通过角色控制【{{ name }}】下的【{{ showName }}通知】可被哪些用户订阅。<br />
|
||||||
|
注意:当前配置会被外层【{{ name }}】中的权限控制覆盖。
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<AIcon type="QuestionCircleOutlined"
|
<AIcon type="QuestionCircleOutlined"
|
||||||
/></j-tooltip>
|
/></j-tooltip>
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
<template v-if="current === 0">
|
<template v-if="current === 0">
|
||||||
<NotifyWay
|
<NotifyWay
|
||||||
:value="formModel.channelProvider"
|
:value="formModel.channelProvider"
|
||||||
|
v-model:name="showName"
|
||||||
@change="onWayChange"
|
@change="onWayChange"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -161,6 +163,10 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const stepList = [
|
const stepList = [
|
||||||
|
@ -190,14 +196,15 @@ const formModel = reactive<{
|
||||||
});
|
});
|
||||||
const variableRef = ref();
|
const variableRef = ref();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
|
const showName = ref<string>('钉钉')
|
||||||
|
|
||||||
const _getType = computed(() => {
|
const _getType = computed(() => {
|
||||||
if(['notifier-dingTalk'].includes(props.data?.channelProvider)) {
|
if (['notifier-dingTalk'].includes(props.data?.channelProvider)) {
|
||||||
return ['user', 'tag']
|
return ['user', 'tag'];
|
||||||
} else {
|
} else {
|
||||||
return ['user', 'org', 'tag']
|
return ['user', 'org', 'tag'];
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
const _variableDefinitions = computed(() => {
|
const _variableDefinitions = computed(() => {
|
||||||
return variable.value.filter((item: any) => {
|
return variable.value.filter((item: any) => {
|
||||||
|
|
17
yarn.lock
17
yarn.lock
|
@ -3738,7 +3738,7 @@ jetlinks-store@^0.0.3:
|
||||||
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
||||||
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
||||||
|
|
||||||
jetlinks-ui-components@^1.0.23, jetlinks-ui-components@^1.0.26:
|
jetlinks-ui-components@^1.0.23:
|
||||||
version "1.0.26"
|
version "1.0.26"
|
||||||
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.26.tgz#26896c578396b09d49649ac87c3943491af3a9ae"
|
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.26.tgz#26896c578396b09d49649ac87c3943491af3a9ae"
|
||||||
integrity sha512-HkLk52C6pDKe/Ca9O4w34h1/PrC7GdBUheiicPOX2V/Lc49N+WzI9wmrCd82XBm8MocPM4gAOJxNaTxY20EO9w==
|
integrity sha512-HkLk52C6pDKe/Ca9O4w34h1/PrC7GdBUheiicPOX2V/Lc49N+WzI9wmrCd82XBm8MocPM4gAOJxNaTxY20EO9w==
|
||||||
|
@ -3753,6 +3753,21 @@ jetlinks-ui-components@^1.0.23, jetlinks-ui-components@^1.0.26:
|
||||||
sortablejs "^1.15.0"
|
sortablejs "^1.15.0"
|
||||||
vuedraggable "^4.1.0"
|
vuedraggable "^4.1.0"
|
||||||
|
|
||||||
|
jetlinks-ui-components@^1.0.27:
|
||||||
|
version "1.0.27"
|
||||||
|
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.27.tgz#c2e62ebf26d9465aed5489fdde37297738d57f2b"
|
||||||
|
integrity sha512-IVWCPfC5awTIIMQ5t6V5KTHLjfENj0owb6HsHxqRLrHebz7FaDng6oNfebvn17P+gHGVwwMemTCF7b8PpWFiwg==
|
||||||
|
dependencies:
|
||||||
|
"@vueuse/core" "^9.12.0"
|
||||||
|
"@vueuse/router" "^9.13.0"
|
||||||
|
ant-design-vue "^3.2.15"
|
||||||
|
colorpicker-v3 "^2.10.2"
|
||||||
|
jetlinks-ui-components "^1.0.23"
|
||||||
|
lodash-es "^4.17.21"
|
||||||
|
monaco-editor "^0.40.0"
|
||||||
|
sortablejs "^1.15.0"
|
||||||
|
vuedraggable "^4.1.0"
|
||||||
|
|
||||||
js-cookie@^3.0.1:
|
js-cookie@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz"
|
resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz"
|
||||||
|
|
Loading…
Reference in New Issue