Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
0c4c93c386
|
@ -48,7 +48,7 @@ export const category = (data: any) => server.post('/device/category/_tree', dat
|
||||||
/**
|
/**
|
||||||
* 获取网关类型
|
* 获取网关类型
|
||||||
*/
|
*/
|
||||||
export const getProviders = () => server.get('/gateway/device/providers')
|
export const getProviders = (terms?:any) => server.get('/gateway/device/providers',terms)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询所属部门
|
* 查询所属部门
|
||||||
|
|
|
@ -10,4 +10,7 @@ export const addRelation_api = (data: object) => server.post(`/relation`, data);
|
||||||
// 保存关系
|
// 保存关系
|
||||||
export const editRelation_api = (data: object) => server.patch(`/relation`, data);
|
export const editRelation_api = (data: object) => server.patch(`/relation`, data);
|
||||||
// 删除关系
|
// 删除关系
|
||||||
export const delRelation_api = (id: string) => server.remove(`/relation/${id}`);
|
export const delRelation_api = (id: string) => server.remove(`/relation/${id}`);
|
||||||
|
|
||||||
|
// 验证标识唯一性
|
||||||
|
export const validateField = (params: any) => server.get<any>(`/relation/_validate`, params);
|
|
@ -75,11 +75,9 @@ const handleMenuClick = (e: any) => {
|
||||||
if(!(val?.popConfirm || val?.onClick)){
|
if(!(val?.popConfirm || val?.onClick)){
|
||||||
emits('update:isCheck', true);
|
emits('update:isCheck', true);
|
||||||
emits('change', true);
|
emits('change', true);
|
||||||
}
|
|
||||||
if (val?.popConfirm) {
|
|
||||||
visible.value = false;
|
|
||||||
} else {
|
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
|
} else {
|
||||||
|
visible.value = false;
|
||||||
}
|
}
|
||||||
_item.value = (val || {}) as any;
|
_item.value = (val || {}) as any;
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
>
|
>
|
||||||
{{ slotProps.route.breadcrumbName }}
|
{{ slotProps.route.breadcrumbName }}
|
||||||
</a>
|
</a>
|
||||||
<span v-else style='cursor: pointer' >{{ slotProps.route.breadcrumbName }}</span>
|
<span v-else style='cursor: default' >{{ slotProps.route.breadcrumbName }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #rightContentRender>
|
<template #rightContentRender>
|
||||||
<div class="right-content">
|
<div class="right-content">
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
type DepartmentStateType = {
|
||||||
|
productId: string;
|
||||||
|
optType: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useDepartmentStore = defineStore({
|
||||||
|
id: 'department',
|
||||||
|
state: (): DepartmentStateType => ({
|
||||||
|
productId: '',
|
||||||
|
// 设备资产分配弹窗操作类型:
|
||||||
|
// 1. optType === 'handle': 手动点击资产分配按钮;
|
||||||
|
// 2. optType === ': 产品资产分配后, 自动弹出设备资产分配
|
||||||
|
optType: ''
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
setProductId(value: string) {
|
||||||
|
this.productId = value
|
||||||
|
},
|
||||||
|
setType(value: string | undefined) {
|
||||||
|
this.optType = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -32,14 +32,20 @@ export const defaultBranches = [
|
||||||
{
|
{
|
||||||
terms: [
|
terms: [
|
||||||
{
|
{
|
||||||
column: undefined,
|
terms: [
|
||||||
value: {
|
{
|
||||||
source: 'fixed',
|
column: undefined,
|
||||||
value: undefined
|
value: {
|
||||||
},
|
source: 'fixed',
|
||||||
termType: undefined,
|
value: undefined
|
||||||
key: 'params_1',
|
},
|
||||||
|
termType: undefined,
|
||||||
|
key: 'params_1',
|
||||||
|
type: 'and',
|
||||||
|
},
|
||||||
|
],
|
||||||
type: 'and',
|
type: 'and',
|
||||||
|
key: 'terms_1_terms_1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
type: 'and',
|
type: 'and',
|
||||||
|
@ -79,9 +85,22 @@ export const useSceneStore = defineStore('scene', () => {
|
||||||
name: '',
|
name: '',
|
||||||
id: undefined
|
id: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
const productCache = {}
|
const productCache = {}
|
||||||
|
|
||||||
|
const refresh = () => {
|
||||||
|
data.value = {
|
||||||
|
trigger: { type: ''},
|
||||||
|
options: cloneDeep(defaultOptions),
|
||||||
|
branches: cloneDeep(defaultBranches),
|
||||||
|
description: '',
|
||||||
|
name: '',
|
||||||
|
id: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const getDetail = async (id: string) => {
|
const getDetail = async (id: string) => {
|
||||||
|
refresh()
|
||||||
const resp = await detail(id)
|
const resp = await detail(id)
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
const result = resp.result as any
|
const result = resp.result as any
|
||||||
|
@ -109,22 +128,11 @@ export const useSceneStore = defineStore('scene', () => {
|
||||||
...result,
|
...result,
|
||||||
trigger: result.trigger || {},
|
trigger: result.trigger || {},
|
||||||
branches: cloneDeep(assignmentKey(branches)),
|
branches: cloneDeep(assignmentKey(branches)),
|
||||||
options: result.options ? {...defaultOptions, ...result.options } : defaultOptions,
|
options: result.options ? {...cloneDeep(defaultOptions), ...result.options } : cloneDeep(defaultOptions),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const refresh = () => {
|
|
||||||
data.value = {
|
|
||||||
trigger: { type: ''},
|
|
||||||
options: cloneDeep(defaultOptions),
|
|
||||||
branches: cloneDeep(defaultBranches),
|
|
||||||
description: '',
|
|
||||||
name: '',
|
|
||||||
id: undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data,
|
data,
|
||||||
productCache,
|
productCache,
|
||||||
|
|
|
@ -108,4 +108,29 @@ export const onlyMessage = (msg: string, type: 'success' | 'error' | 'warning' =
|
||||||
content: msg,
|
content: msg,
|
||||||
key: type
|
key: type
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchItemData {
|
||||||
|
column: any;
|
||||||
|
value: any;
|
||||||
|
termType: string;
|
||||||
|
type?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handleParamsToString = (terms:SearchItemData[] = []) => {
|
||||||
|
const _terms: any[] = [
|
||||||
|
{ terms: [null,null,null]},
|
||||||
|
{ terms: [null,null,null]}
|
||||||
|
]
|
||||||
|
let termsIndex = 0
|
||||||
|
let termsStar = 0
|
||||||
|
terms.forEach((item, index) => {
|
||||||
|
if (index > 2) {
|
||||||
|
termsIndex = 1
|
||||||
|
termsStar = 4
|
||||||
|
}
|
||||||
|
_terms[termsIndex].terms[index - termsStar ] = item
|
||||||
|
})
|
||||||
|
|
||||||
|
return JSON.stringify({ terms: _terms})
|
||||||
}
|
}
|
|
@ -148,6 +148,9 @@ const extraRouteObj = {
|
||||||
'edge/Device': {
|
'edge/Device': {
|
||||||
children: [{ code: 'Remote', name: '远程控制' }],
|
children: [{ code: 'Remote', name: '远程控制' }],
|
||||||
},
|
},
|
||||||
|
'rule-engine/Alarm/Log': {
|
||||||
|
children: [{ code: 'Record', name: '处理记录' }]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,7 +209,7 @@ const findDetailRoutes = (routes: any[]): any[] => {
|
||||||
export const findCodeRoute = (asyncRouterMap: any[]) => {
|
export const findCodeRoute = (asyncRouterMap: any[]) => {
|
||||||
const routeMeta = {}
|
const routeMeta = {}
|
||||||
|
|
||||||
function getDetail( code: string, url: string) {
|
function getDetail(code: string, url: string) {
|
||||||
const detail = findDetailRouteItem(code, url)
|
const detail = findDetailRouteItem(code, url)
|
||||||
if (!detail) return
|
if (!detail) return
|
||||||
routeMeta[(detail as MenuItem).code] = {
|
routeMeta[(detail as MenuItem).code] = {
|
||||||
|
@ -217,7 +220,7 @@ export const findCodeRoute = (asyncRouterMap: any[]) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findChildren (data: any[], code: string = '') {
|
function findChildren(data: any[], code: string = '') {
|
||||||
data.forEach(route => {
|
data.forEach(route => {
|
||||||
routeMeta[route.code] = {
|
routeMeta[route.code] = {
|
||||||
path: route.url || route.path,
|
path: route.url || route.path,
|
||||||
|
@ -254,7 +257,7 @@ export const findCodeRoute = (asyncRouterMap: any[]) => {
|
||||||
return routeMeta
|
return routeMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any} {
|
export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level = 1): { menusData: any, silderMenus: any } {
|
||||||
const _asyncRouterMap = cloneDeep(asyncRouterMap)
|
const _asyncRouterMap = cloneDeep(asyncRouterMap)
|
||||||
const menusData: any[] = []
|
const menusData: any[] = []
|
||||||
const silderMenus: any[] = []
|
const silderMenus: any[] = []
|
||||||
|
@ -270,7 +273,7 @@ export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level =
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const silder = {..._route}
|
const silder = { ..._route }
|
||||||
|
|
||||||
// 查看是否有隐藏子路由
|
// 查看是否有隐藏子路由
|
||||||
route.children = findChildrenRoute(route.code, route.url, route.children)
|
route.children = findChildrenRoute(route.code, route.url, route.children)
|
||||||
|
|
|
@ -118,6 +118,16 @@ export const postStream = function(url: string, data={}, params = {}) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showNotification = ( message: string, description: string, key?: string, show: boolean = true ) => {
|
||||||
|
if (show) {
|
||||||
|
Notification.error({
|
||||||
|
key,
|
||||||
|
message,
|
||||||
|
description
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异常拦截处理器
|
* 异常拦截处理器
|
||||||
* @param {Object} error
|
* @param {Object} error
|
||||||
|
@ -128,47 +138,20 @@ const errorHandler = (error: any) => {
|
||||||
const data = error.response.data
|
const data = error.response.data
|
||||||
const status = error.response.status
|
const status = error.response.status
|
||||||
if (status === 403) {
|
if (status === 403) {
|
||||||
Notification.error({
|
showNotification( 'Forbidden', (data.message + '').substr(0, 90), '403')
|
||||||
key: '403',
|
|
||||||
message: 'Forbidden',
|
|
||||||
description: (data.message + '').substr(0, 90)
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
router.push({
|
|
||||||
name: 'Exception403'
|
|
||||||
})
|
|
||||||
}, 0)
|
|
||||||
} else if (status === 500) {
|
} else if (status === 500) {
|
||||||
Notification.error({
|
showNotification( 'Server Side Error', (data.message + '').substr(0, 90), '500')
|
||||||
key: '500',
|
|
||||||
message: 'Server Side Error',
|
|
||||||
description: (data.message + '').substr(0, 90)
|
|
||||||
})
|
|
||||||
} else if (status === 400) {
|
} else if (status === 400) {
|
||||||
Notification.error({
|
showNotification( 'Request Error', (data.message + '').substr(0, 90), '400')
|
||||||
key: '400',
|
|
||||||
message: 'Request Error',
|
|
||||||
description: (data.message + '').substr(0, 90)
|
|
||||||
})
|
|
||||||
} else if (status === 401) {
|
} else if (status === 401) {
|
||||||
Notification.error({
|
showNotification( 'Unauthorized', '用户未登录', '401')
|
||||||
key: '401',
|
console.log('showNotification')
|
||||||
message: 'Unauthorized',
|
|
||||||
description: '用户未登录'
|
|
||||||
})
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
debugger
|
location.href = `/#${LoginPath}`
|
||||||
router.push({
|
|
||||||
path: LoginPath
|
|
||||||
})
|
|
||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
} else if (error.response === undefined) {
|
} else if (error.response === undefined) {
|
||||||
Notification.error({
|
showNotification( error.message, (error.stack + '').substr(0, 90), undefined)
|
||||||
message: error.message,
|
|
||||||
description: (error.stack + '').substr(0, 90)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
|
@ -180,10 +163,13 @@ request.interceptors.request.use(config => {
|
||||||
const token = LocalStore.get(TOKEN_KEY)
|
const token = LocalStore.get(TOKEN_KEY)
|
||||||
// const token = store.$state.tokenAlias
|
// const token = store.$state.tokenAlias
|
||||||
if (!token) {
|
if (!token) {
|
||||||
|
// setTimeout(() => {
|
||||||
|
// router.replace({
|
||||||
|
// path: LoginPath
|
||||||
|
// })
|
||||||
|
// }, 0)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
router.replace({
|
location.href = `/#${LoginPath}`
|
||||||
path: LoginPath
|
|
||||||
})
|
|
||||||
}, 0)
|
}, 0)
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
:status="getState(slotProps).value"
|
:status="getState(slotProps).value"
|
||||||
:statusText="getState(slotProps).text"
|
:statusText="getState(slotProps).text"
|
||||||
:statusNames="StatusColorEnum"
|
:statusNames="StatusColorEnum"
|
||||||
|
@click="handlEye(slotProps.id)"
|
||||||
>
|
>
|
||||||
<template #img>
|
<template #img>
|
||||||
<slot name="img">
|
<slot name="img">
|
||||||
|
@ -48,8 +49,9 @@
|
||||||
<Ellipsis style="width: calc(100% - 100px)">
|
<Ellipsis style="width: calc(100% - 100px)">
|
||||||
<span
|
<span
|
||||||
style="
|
style="
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 800;
|
||||||
|
line-height: 22px;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ slotProps.name }}
|
{{ slotProps.name }}
|
||||||
|
@ -276,6 +278,9 @@ const handlEdit = (data: object) => {
|
||||||
current.value = _.cloneDeep(data);
|
current.value = _.cloneDeep(data);
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
};
|
};
|
||||||
|
const handlEye = (id: string) => {
|
||||||
|
menuStory.jumpPage(`DataCollect/Collector`, {}, { channelId: id });
|
||||||
|
};
|
||||||
const saveChange = (value: object) => {
|
const saveChange = (value: object) => {
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
current.value = {};
|
current.value = {};
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
? '正常的采集器不能删除'
|
? '正常的采集器不能删除'
|
||||||
: '删除',
|
: '删除',
|
||||||
}"
|
}"
|
||||||
|
:danger="data?.state?.value === 'disabled'"
|
||||||
hasPermission="DataCollect/Collector:delete"
|
hasPermission="DataCollect/Collector:delete"
|
||||||
:popConfirm="{
|
:popConfirm="{
|
||||||
title: `该操作将会删除下属点位,确定删除?`,
|
title: `该操作将会删除下属点位,确定删除?`,
|
||||||
|
@ -253,7 +254,7 @@ watch(
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.tree-container {
|
.tree-container {
|
||||||
padding-right: 24px;
|
padding-right: 24px;
|
||||||
width: 300px;
|
width: 350px;
|
||||||
.add-btn {
|
.add-btn {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ const changeTree = (row: any) => {
|
||||||
min-height: calc(100vh - 180px);
|
min-height: calc(100vh - 180px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.left {
|
.left {
|
||||||
width: 300px;
|
width: 350px;
|
||||||
border-right: 1px #eeeeee solid;
|
border-right: 1px #eeeeee solid;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,6 +265,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
|
|
||||||
const column = {
|
const column = {
|
||||||
username: 'context.username',
|
username: 'context.username',
|
||||||
|
description: 'action',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,10 +31,11 @@
|
||||||
<script setup lang="ts" name="FileUpload">
|
<script setup lang="ts" name="FileUpload">
|
||||||
import { LocalStore } from '@/utils/comm';
|
import { LocalStore } from '@/utils/comm';
|
||||||
import { TOKEN_KEY } from '@/utils/variable';
|
import { TOKEN_KEY } from '@/utils/variable';
|
||||||
import { FIRMWARE_UPLOAD, querySystemApi } from '@/api/device/firmware';
|
import { FIRMWARE_UPLOAD } from '@/api/device/firmware';
|
||||||
import { onlyMessage } from '@/utils/comm';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
import type { UploadChangeParam } from 'ant-design-vue';
|
import type { UploadChangeParam } from 'ant-design-vue';
|
||||||
import { notification as Notification } from 'ant-design-vue';
|
import { notification as Notification } from 'ant-design-vue';
|
||||||
|
import { useSystem } from '@/store/system';
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'update:extraValue', 'change']);
|
const emit = defineEmits(['update:modelValue', 'update:extraValue', 'change']);
|
||||||
|
|
||||||
|
@ -45,6 +46,10 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paths: string = useSystem().$state.configInfo.paths?.[
|
||||||
|
'base-path'
|
||||||
|
] as string;
|
||||||
|
|
||||||
const fileValue = ref(props.modelValue);
|
const fileValue = ref(props.modelValue);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
@ -53,11 +58,9 @@ const handleChange = async (info: UploadChangeParam) => {
|
||||||
if (info.file.status === 'done') {
|
if (info.file.status === 'done') {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
const result = info.file.response?.result;
|
const result = info.file.response?.result;
|
||||||
const api: any = await querySystemApi(['paths']); // todo base-path在pinia获取系统配置的
|
const f = `${paths || ''}/file/${result.id}?accessKey=${
|
||||||
const path = api.result[0]?.properties
|
result.others.accessKey
|
||||||
? api.result[0]?.properties['base-path']
|
}`;
|
||||||
: '';
|
|
||||||
const f = `${path}/file/${result.id}?accessKey=${result.others.accessKey}`;
|
|
||||||
onlyMessage('上传成功!', 'success');
|
onlyMessage('上传成功!', 'success');
|
||||||
fileValue.value = f;
|
fileValue.value = f;
|
||||||
emit('update:modelValue', f);
|
emit('update:modelValue', f);
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
selectedRowKeys: _selectedRowKeys,
|
selectedRowKeys: _selectedRowKeys,
|
||||||
onSelect: onSelectChange,
|
onSelect: onSelectChange,
|
||||||
onSelectAll: onSelectAllChange,
|
onSelectAll: onSelectAllChange,
|
||||||
|
onChange: onChange,
|
||||||
}"
|
}"
|
||||||
@cancelSelect="cancelSelect"
|
|
||||||
:params="params"
|
:params="params"
|
||||||
>
|
>
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
|
@ -125,7 +125,7 @@ const defaultParams = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const statusMap = new Map();
|
const statusMap = new Map();
|
||||||
statusMap.set('online', 'success');
|
statusMap.set('online', 'processing');
|
||||||
statusMap.set('offline', 'error');
|
statusMap.set('offline', 'error');
|
||||||
statusMap.set('notActive', 'warning');
|
statusMap.set('notActive', 'warning');
|
||||||
|
|
||||||
|
@ -223,8 +223,10 @@ const getSelectedRowsKey = (selectedRows: T[]) =>
|
||||||
const getSetRowKey = (selectedRows: T[]) =>
|
const getSetRowKey = (selectedRows: T[]) =>
|
||||||
new Set([..._selectedRowKeys.value, ...getSelectedRowsKey(selectedRows)]);
|
new Set([..._selectedRowKeys.value, ...getSelectedRowsKey(selectedRows)]);
|
||||||
|
|
||||||
const cancelSelect = () => {
|
const onChange = (selectedRowKeys: T[]) => {
|
||||||
_selectedRowKeys.value = [];
|
if (selectedRowKeys.length === 0) {
|
||||||
|
_selectedRowKeys.value = [];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = () => {
|
const handleOk = () => {
|
||||||
|
@ -249,7 +251,7 @@ const onVisible = () => {
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
cancelSelect();
|
_selectedRowKeys.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
style="padding: 0px"
|
style="padding: 0px"
|
||||||
@click="i.onClick"
|
@click="i.onClick"
|
||||||
type="link"
|
type="link"
|
||||||
|
:danger="i.key === 'delete'"
|
||||||
:hasPermission="'device/Firmware:' + i.key"
|
:hasPermission="'device/Firmware:' + i.key"
|
||||||
>
|
>
|
||||||
<template #icon
|
<template #icon
|
||||||
|
@ -68,7 +69,6 @@
|
||||||
<script lang="ts" setup name="FirmwarePage">
|
<script lang="ts" setup name="FirmwarePage">
|
||||||
import type { ActionsType } from '@/components/Table/index';
|
import type { ActionsType } from '@/components/Table/index';
|
||||||
import { query, queryProduct, remove } from '@/api/device/firmware';
|
import { query, queryProduct, remove } from '@/api/device/firmware';
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import Save from './Save/index.vue';
|
import Save from './Save/index.vue';
|
||||||
|
|
|
@ -162,7 +162,7 @@ import {
|
||||||
} from '@/api/device/instance';
|
} from '@/api/device/instance';
|
||||||
import MSelect from './MSelect.vue';
|
import MSelect from './MSelect.vue';
|
||||||
import PatchMapping from './PatchMapping.vue';
|
import PatchMapping from './PatchMapping.vue';
|
||||||
import { message } from 'ant-design-vue/es';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
|
@ -280,7 +280,7 @@ const unbind = async (id: string) => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
onlyMessage('操作成功!', 'success');
|
||||||
handleSearch();
|
handleSearch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,7 +313,7 @@ const onSave = () => {
|
||||||
submitData,
|
submitData,
|
||||||
);
|
);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
onlyMessage('操作成功!', 'success');
|
||||||
handleSearch();
|
handleSearch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ const onAction = async (record: any) => {
|
||||||
submitData,
|
submitData,
|
||||||
);
|
);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
onlyMessage('操作成功!', 'success');
|
||||||
handleSearch();
|
handleSearch();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
<j-image :src="value?.formatValue" />
|
<j-image :src="value?.formatValue" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="['.flv', '.m3u8', '.mp4'].includes(type)">
|
<template v-else-if="['.flv', '.m3u8', '.mp4'].includes(type)">
|
||||||
|
<LivePlayer :url="value?.formatValue" autoplay />
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<JsonViewer
|
<JsonViewer
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import JsonViewer from 'vue-json-viewer';
|
import JsonViewer from 'vue-json-viewer';
|
||||||
|
import LivePlayer from '@/components/Player/index.vue';
|
||||||
|
|
||||||
const _data = defineProps({
|
const _data = defineProps({
|
||||||
type: {
|
type: {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p>{{ type === 'active' ? '启用' : '同步' }}成功:{{ count }}条</p>
|
<p>{{ type === 'active' ? '启用' : '同步' }}成功:{{ count }}条</p>
|
||||||
<p v-if="type === 'active'">启用失败:{{ errCount }}条<j-tooltip title="实例信息页面中的配置项未完善"><AIcon type="QuestionCircleOutlined" /></j-tooltip></p>
|
<p v-if="type === 'active'">启用失败:{{ errCount }}条<j-tooltip title="实例信息页面中的配置项未完善"><AIcon style="margin-left: 5px" type="QuestionCircleOutlined" /></j-tooltip></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
@ -56,13 +56,13 @@ const getData = (api: string) => {
|
||||||
source.value = _source;
|
source.value = _source;
|
||||||
_source.onmessage = (e: any) => {
|
_source.onmessage = (e: any) => {
|
||||||
const res = JSON.parse(e.data);
|
const res = JSON.parse(e.data);
|
||||||
// console.log(res)
|
|
||||||
switch (props.type) {
|
switch (props.type) {
|
||||||
case 'active':
|
case 'active':
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
_source.close();
|
_source.close();
|
||||||
dt += res.total;
|
dt += res.total;
|
||||||
count.value = dt;
|
count.value = dt;
|
||||||
|
flag.value = false;
|
||||||
} else {
|
} else {
|
||||||
if (res.source) {
|
if (res.source) {
|
||||||
errCount.value = 1
|
errCount.value = 1
|
||||||
|
@ -76,6 +76,7 @@ const getData = (api: string) => {
|
||||||
case 'sync':
|
case 'sync':
|
||||||
dt += res;
|
dt += res;
|
||||||
count.value = dt;
|
count.value = dt;
|
||||||
|
flag.value = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -328,6 +328,7 @@ const columns = [
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
key: 'id',
|
key: 'id',
|
||||||
|
ellipsis: true,
|
||||||
search: {
|
search: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
defaultTermType: 'eq',
|
defaultTermType: 'eq',
|
||||||
|
@ -337,6 +338,7 @@ const columns = [
|
||||||
title: '设备名称',
|
title: '设备名称',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
|
ellipsis: true,
|
||||||
search: {
|
search: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
first: true,
|
first: true,
|
||||||
|
@ -346,6 +348,7 @@ const columns = [
|
||||||
title: '产品名称',
|
title: '产品名称',
|
||||||
dataIndex: 'productName',
|
dataIndex: 'productName',
|
||||||
key: 'productName',
|
key: 'productName',
|
||||||
|
ellipsis: true,
|
||||||
search: {
|
search: {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
rename: 'productId',
|
rename: 'productId',
|
||||||
|
@ -367,6 +370,7 @@ const columns = [
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
key: 'createTime',
|
key: 'createTime',
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
|
width: 200,
|
||||||
search: {
|
search: {
|
||||||
type: 'date',
|
type: 'date',
|
||||||
},
|
},
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<j-button
|
<j-button
|
||||||
style="margin: 0 0 0 20px"
|
class="changeBtn"
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="
|
:disabled="
|
||||||
productStore.current?.count &&
|
productStore.current?.count &&
|
||||||
|
@ -418,6 +418,8 @@ import { marked } from 'marked';
|
||||||
import type { TableColumnType } from 'ant-design-vue';
|
import type { TableColumnType } from 'ant-design-vue';
|
||||||
import { useMenuStore } from '@/store/menu';
|
import { useMenuStore } from '@/store/menu';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import encodeQuery from '@/utils/encodeQuery';
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const menuStore = useMenuStore();
|
const menuStore = useMenuStore();
|
||||||
|
@ -501,14 +503,15 @@ const query = reactive({
|
||||||
return new Promise((res) => {
|
return new Promise((res) => {
|
||||||
getProviders().then((resp: any) => {
|
getProviders().then((resp: any) => {
|
||||||
listData.value = [];
|
listData.value = [];
|
||||||
console.log(description.value);
|
|
||||||
if (isNoCommunity) {
|
if (isNoCommunity) {
|
||||||
listData.value = (resp?.result || []).map(
|
(resp?.result || []).map((item: any) => {
|
||||||
(item: any) => ({
|
if (item.id != 'plugin_gateway') {
|
||||||
label: item.name,
|
listData.value.push({
|
||||||
value: item.id,
|
label: item.name,
|
||||||
}),
|
value: item.id,
|
||||||
);
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
listData.value = (resp?.result || [])
|
listData.value = (resp?.result || [])
|
||||||
.filter((i: any) =>
|
.filter((i: any) =>
|
||||||
|
@ -568,17 +571,7 @@ const query = reactive({
|
||||||
});
|
});
|
||||||
const param = ref<Record<string, any>>({
|
const param = ref<Record<string, any>>({
|
||||||
pageSize: 4,
|
pageSize: 4,
|
||||||
terms: [
|
terms: [],
|
||||||
{
|
|
||||||
terms: [
|
|
||||||
{
|
|
||||||
column: 'channel',
|
|
||||||
termType: 'nin',
|
|
||||||
value: 'plugin',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
const queryParams = ref<Record<string, any>>({});
|
const queryParams = ref<Record<string, any>>({});
|
||||||
/**
|
/**
|
||||||
|
@ -1085,4 +1078,10 @@ nextTick(() => {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
.changeBtn {
|
||||||
|
margin: 0 0 0 20px;
|
||||||
|
color: #315efb;
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #315efb;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<page-container
|
<page-container
|
||||||
:tabList="list"
|
:tabList="list"
|
||||||
@back="onBack"
|
|
||||||
:tabActiveKey="productStore.tabActiveKey"
|
:tabActiveKey="productStore.tabActiveKey"
|
||||||
@tabChange="onTabChange"
|
@tabChange="onTabChange"
|
||||||
showBack="true"
|
showBack="true"
|
||||||
|
@ -49,9 +48,21 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #content>
|
||||||
<div style="padding-top: 10px">
|
<div style="padding-top: 10px">
|
||||||
<j-descriptions size="small" :column="4">
|
<j-descriptions size="small" :column="4">
|
||||||
<j-descriptions-item label="设备数量"
|
<j-descriptions-item
|
||||||
|
label="设备数量"
|
||||||
|
:labelStyle="{
|
||||||
|
fontSize: '14px',
|
||||||
|
opacity: 0.55,
|
||||||
|
}"
|
||||||
|
:contentStyle="{
|
||||||
|
fontSize: '14px',
|
||||||
|
color: '#092EE7',
|
||||||
|
cursor: 'pointer',
|
||||||
|
}"
|
||||||
><span @click="jumpDevice">{{
|
><span @click="jumpDevice">{{
|
||||||
productStore.current?.count
|
productStore.current?.count
|
||||||
? productStore.current?.count
|
? productStore.current?.count
|
||||||
|
@ -62,18 +73,6 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<!-- <j-popconfirm
|
|
||||||
title="确认应用配置"
|
|
||||||
@confirm="handleCofig"
|
|
||||||
okText="确定"
|
|
||||||
cancelText="取消"
|
|
||||||
>
|
|
||||||
<j-button
|
|
||||||
:disabled="productStore.current.state === 0"
|
|
||||||
type="primary"
|
|
||||||
>应用配置</j-button
|
|
||||||
>
|
|
||||||
</j-popconfirm> -->
|
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
type="primary"
|
type="primary"
|
||||||
:popConfirm="{
|
:popConfirm="{
|
||||||
|
@ -112,7 +111,7 @@ import {
|
||||||
getProtocolDetail,
|
getProtocolDetail,
|
||||||
} from '@/api/device/product';
|
} from '@/api/device/product';
|
||||||
import { message } from 'jetlinks-ui-components';
|
import { message } from 'jetlinks-ui-components';
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage, handleParamsToString } from '@/utils/comm'
|
||||||
import encodeQuery from '@/utils/encodeQuery';
|
import encodeQuery from '@/utils/encodeQuery';
|
||||||
import { useMenuStore } from '@/store/menu';
|
import { useMenuStore } from '@/store/menu';
|
||||||
|
|
||||||
|
@ -172,7 +171,9 @@ watch(
|
||||||
getProtocol();
|
getProtocol();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const onBack = () => {};
|
const onBack = () => {
|
||||||
|
history.back();
|
||||||
|
};
|
||||||
|
|
||||||
const onTabChange = (e: string) => {
|
const onTabChange = (e: string) => {
|
||||||
productStore.tabActiveKey = e;
|
productStore.tabActiveKey = e;
|
||||||
|
@ -250,7 +251,7 @@ const getProtocol = async () => {
|
||||||
tab: '数据解析',
|
tab: '数据解析',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}else{
|
} else {
|
||||||
list.value = [
|
list.value = [
|
||||||
{
|
{
|
||||||
key: 'Info',
|
key: 'Info',
|
||||||
|
@ -264,7 +265,8 @@ const getProtocol = async () => {
|
||||||
{
|
{
|
||||||
key: 'Device',
|
key: 'Device',
|
||||||
tab: '设备接入',
|
tab: '设备接入',
|
||||||
},]
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,7 +286,7 @@ const jumpDevice = () => {
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
target: 'device-instance',
|
target: 'device-instance',
|
||||||
q: JSON.stringify({ terms: [{ terms: [{ searchParams }] }] }),
|
q: handleParamsToString([searchParams]),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
>
|
>
|
||||||
<template #title="item">
|
<template #title="item">
|
||||||
<span>{{ item.title }}</span>
|
<span>{{ item.title }}</span>
|
||||||
<a-tooltip :title="item"
|
<a-tooltip :title="item.option.tooltip"
|
||||||
><AIcon
|
><AIcon
|
||||||
type="QuestionCircleOutlined"
|
type="QuestionCircleOutlined"
|
||||||
style="margin-left: 2px"
|
style="margin-left: 2px"
|
||||||
|
|
|
@ -447,12 +447,14 @@ const query = reactive({
|
||||||
listData.value = [];
|
listData.value = [];
|
||||||
// const list = () => {
|
// const list = () => {
|
||||||
if (isNoCommunity) {
|
if (isNoCommunity) {
|
||||||
listData.value = (resp?.result || []).map(
|
(resp?.result || []).map((item: any) => {
|
||||||
(item: any) => ({
|
if (item.id != 'plugin_gateway') {
|
||||||
label: item.name,
|
listData.value.push({
|
||||||
value: item.id,
|
label: item.name,
|
||||||
}),
|
value: item.id,
|
||||||
);
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
listData.value = (resp?.result || [])
|
listData.value = (resp?.result || [])
|
||||||
.filter((i: any) =>
|
.filter((i: any) =>
|
||||||
|
|
|
@ -267,26 +267,26 @@ const columns = [
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
key: 'productId$product-info',
|
// key: 'productId$product-info',
|
||||||
dataIndex: 'productId$product-info',
|
// dataIndex: 'productId$product-info',
|
||||||
title: '接入方式',
|
// title: '接入方式',
|
||||||
hideInTable: true,
|
// hideInTable: true,
|
||||||
search: {
|
// search: {
|
||||||
type: 'select',
|
// type: 'select',
|
||||||
options: () =>
|
// options: () =>
|
||||||
new Promise((resolve) => {
|
// new Promise((resolve) => {
|
||||||
queryGatewayList({}).then((resp: any) => {
|
// queryGatewayList({}).then((resp: any) => {
|
||||||
resolve(
|
// resolve(
|
||||||
resp.result.map((item: any) => ({
|
// resp.result.map((item: any) => ({
|
||||||
label: item.name,
|
// label: item.name,
|
||||||
value: `accessId is ${item.id}`,
|
// value: `accessId is ${item.id}`,
|
||||||
})),
|
// })),
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
}),
|
// }),
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
dataIndex: 'deviceType',
|
dataIndex: 'deviceType',
|
||||||
title: '设备类型',
|
title: '设备类型',
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<j-col :span="8">已下发数量:{{ countErr + count }}</j-col>
|
<j-col :span="8">已下发数量:{{ countErr + count }}</j-col>
|
||||||
</j-row>
|
</j-row>
|
||||||
<div v-if="!flag">
|
<div v-if="!flag">
|
||||||
<j-textarea :rows="20" :value="JSON.stringify(errMessage)" />
|
<j-textarea :rows="10" :value="JSON.stringify(errMessage)" />
|
||||||
</div>
|
</div>
|
||||||
</j-modal>
|
</j-modal>
|
||||||
</template>
|
</template>
|
||||||
|
@ -86,7 +86,7 @@ const getData = () => {
|
||||||
et += 1;
|
et += 1;
|
||||||
countErr.value = et;
|
countErr.value = et;
|
||||||
flag.value = false;
|
flag.value = false;
|
||||||
if (errMessages.length <= 5) {
|
if (errMessages.length < 5) {
|
||||||
errMessages.push({ ...res });
|
errMessages.push({ ...res });
|
||||||
errMessage.value = [...errMessages];
|
errMessage.value = [...errMessages];
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,8 @@ const onCancel = () => {
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.search {
|
.search {
|
||||||
padding: 0 0 0 24px;
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
}
|
}
|
||||||
.alert {
|
.alert {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<template>
|
<template>
|
||||||
<j-form layout="vertical" :model="form" ref="formBasicRef">
|
<j-form layout="vertical" :model="form" ref="formBasicRef">
|
||||||
<j-row :span="24" :gutter="24">
|
<j-row :span="24" :gutter="24">
|
||||||
<j-col :span="10">
|
<j-col :span="12">
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="系统名称"
|
label="系统名称"
|
||||||
name="title"
|
name="title"
|
||||||
|
@ -193,7 +193,7 @@
|
||||||
</j-col>
|
</j-col>
|
||||||
</j-row>
|
</j-row>
|
||||||
</j-col>
|
</j-col>
|
||||||
<j-col :span="14">
|
<j-col :span="12">
|
||||||
<j-form-item label="登录背景图">
|
<j-form-item label="登录背景图">
|
||||||
<div class="upload-image-warp-back">
|
<div class="upload-image-warp-back">
|
||||||
<div class="upload-image-border-back">
|
<div class="upload-image-border-back">
|
||||||
|
|
|
@ -183,6 +183,7 @@ defineExpose({
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.role-item-content {
|
.role-item-content {
|
||||||
|
|
|
@ -572,7 +572,7 @@ const columns = [
|
||||||
search: {
|
search: {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
options: [
|
options: [
|
||||||
{ label: '正常', value: 'using' },
|
{ label: '激活', value: 'using' },
|
||||||
{ label: '未激活', value: 'toBeActivated' },
|
{ label: '未激活', value: 'toBeActivated' },
|
||||||
{ label: '停机', value: 'deactivate' },
|
{ label: '停机', value: 'deactivate' },
|
||||||
{ label: '其它', value: 'using,toBeActivated,deactivate' },
|
{ label: '其它', value: 'using,toBeActivated,deactivate' },
|
||||||
|
|
|
@ -482,6 +482,7 @@
|
||||||
type="primary"
|
type="primary"
|
||||||
style="margin-right: 8px"
|
style="margin-right: 8px"
|
||||||
@click="saveData"
|
@click="saveData"
|
||||||
|
:loading="loading"
|
||||||
:hasPermission="`link/AccessConfig:${
|
:hasPermission="`link/AccessConfig:${
|
||||||
id === ':id' ? 'add' : 'update'
|
id === ':id' ? 'add' : 'update'
|
||||||
}`"
|
}`"
|
||||||
|
@ -534,7 +535,7 @@ const props = defineProps({
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const view = route.query.view as string;
|
const view = route.query.view as string;
|
||||||
const id = route.params.id as string;
|
const id = route.params.id as string;
|
||||||
|
const loading = ref(false);
|
||||||
const activeKey: any = ref([]);
|
const activeKey: any = ref([]);
|
||||||
const clientHeight = document.body.clientHeight;
|
const clientHeight = document.body.clientHeight;
|
||||||
|
|
||||||
|
@ -638,10 +639,17 @@ const saveData = () => {
|
||||||
transport: 'SIP',
|
transport: 'SIP',
|
||||||
channel: 'gb28181',
|
channel: 'gb28181',
|
||||||
};
|
};
|
||||||
params.configuration.sipId = Number(params.configuration?.sipId);
|
loading.value = true;
|
||||||
const resp =
|
const resp =
|
||||||
id === ':id' ? await save(params) : await update({ ...params, id });
|
id === ':id'
|
||||||
if (resp.status === 200) {
|
? await save(params).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
})
|
||||||
|
: await update({ ...params, id }).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (resp?.status === 200) {
|
||||||
onlyMessage('操作成功', 'success');
|
onlyMessage('操作成功', 'success');
|
||||||
history.back();
|
history.back();
|
||||||
}
|
}
|
||||||
|
@ -667,12 +675,14 @@ const next = async () => {
|
||||||
...data1,
|
...data1,
|
||||||
...data2,
|
...data2,
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
return onlyMessage('请新增或完善配置', 'error');
|
||||||
}
|
}
|
||||||
current.value = current.value + 1;
|
current.value = current.value + 1;
|
||||||
params.configuration = data1;
|
params.configuration = data1;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
err.errorFields.forEach((item: any) => {
|
err.errorFields?.forEach((item: any) => {
|
||||||
const activeId: any =
|
const activeId: any =
|
||||||
dynamicValidateForm.cluster[item.name[1]].id;
|
dynamicValidateForm.cluster[item.name[1]].id;
|
||||||
if (!activeKey.value.includes(activeId)) {
|
if (!activeKey.value.includes(activeId)) {
|
||||||
|
@ -680,10 +690,24 @@ const next = async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
current.value = current.value + 1;
|
||||||
|
params.configuration = data1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const prev = () => {
|
const prev = () => {
|
||||||
current.value = current.value - 1;
|
current.value = current.value - 1;
|
||||||
|
develop();
|
||||||
|
};
|
||||||
|
|
||||||
|
const develop = () => {
|
||||||
|
if (dynamicValidateForm.cluster.length !== 0) {
|
||||||
|
dynamicValidateForm.cluster.forEach((item) => {
|
||||||
|
const id: any = JSON.stringify(Date.now() + Math.random());
|
||||||
|
item.id = id;
|
||||||
|
activeKey.value.push(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -723,21 +747,13 @@ onMounted(() => {
|
||||||
const { configuration, name, description = '' } = props.data;
|
const { configuration, name, description = '' } = props.data;
|
||||||
formData.value = { name, description };
|
formData.value = { name, description };
|
||||||
|
|
||||||
if (configuration?.shareCluster) {
|
formState.value = {
|
||||||
formState.value = {
|
...formState.value,
|
||||||
...formState.value,
|
...props.data.configuration,
|
||||||
...props.data.configuration,
|
};
|
||||||
};
|
if (!configuration?.shareCluster) {
|
||||||
} else {
|
|
||||||
formState.value = {
|
|
||||||
...formState.value,
|
|
||||||
...props.data.configuration,
|
|
||||||
};
|
|
||||||
dynamicValidateForm.cluster = configuration.cluster;
|
dynamicValidateForm.cluster = configuration.cluster;
|
||||||
if (dynamicValidateForm.cluster.length === 1) {
|
develop();
|
||||||
activeKey.value = ['1'];
|
|
||||||
dynamicValidateForm.cluster[0].id = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,6 +13,17 @@
|
||||||
:request="list"
|
:request="list"
|
||||||
:defaultParams="{
|
:defaultParams="{
|
||||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
termType: 'nin',
|
||||||
|
column: 'provider',
|
||||||
|
value: 'plugin_gateway', //todo 暂时不做插件接入
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
}"
|
}"
|
||||||
gridColumn="2"
|
gridColumn="2"
|
||||||
:gridColumns="[1, 2]"
|
:gridColumns="[1, 2]"
|
||||||
|
@ -40,6 +51,7 @@
|
||||||
enabled: 'processing',
|
enabled: 'processing',
|
||||||
disabled: 'error',
|
disabled: 'error',
|
||||||
}"
|
}"
|
||||||
|
@click="handlEye(slotProps.id)"
|
||||||
>
|
>
|
||||||
<template #img>
|
<template #img>
|
||||||
<slot name="img">
|
<slot name="img">
|
||||||
|
@ -52,13 +64,9 @@
|
||||||
style="
|
style="
|
||||||
width: calc(100% - 100px);
|
width: calc(100% - 100px);
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
color: #2f54eb;
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span
|
<span class="card-title">
|
||||||
class="card-title"
|
|
||||||
@click.stop="handlEye(slotProps.id)"
|
|
||||||
>
|
|
||||||
{{ slotProps.name }}
|
{{ slotProps.name }}
|
||||||
</span>
|
</span>
|
||||||
</Ellipsis>
|
</Ellipsis>
|
||||||
|
@ -310,10 +318,12 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
const getProvidersList = async () => {
|
const getProvidersList = async () => {
|
||||||
const res: any = await getProviders();
|
const res: any = await getProviders();
|
||||||
providersList.value = res.result;
|
providersList.value = res.result;
|
||||||
providersOptions.value = (res?.result || [])?.map((item: any) => ({
|
providersOptions.value = (res?.result || [])
|
||||||
label: item.name,
|
?.map((item: any) => ({
|
||||||
value: item.id,
|
label: item.name,
|
||||||
}));
|
value: item.id,
|
||||||
|
}))
|
||||||
|
.filter((item: any) => item.value !== 'plugin_gateway'); // todo 暂时不做插件接入
|
||||||
};
|
};
|
||||||
getProvidersList();
|
getProvidersList();
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<CertificateFile
|
<CertificateFile
|
||||||
name="cert"
|
name="cert"
|
||||||
v-model:modelValue="formData.configs.cert"
|
v-model:modelValue="formData.configs.cert"
|
||||||
placeholder='证书格式以"-----BEGIN CERTIFICATE-----"开头,以"-----END CERTIFICATE-----"结尾"'
|
placeholder="请输入证书文件"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
<CertificateFile
|
<CertificateFile
|
||||||
name="key"
|
name="key"
|
||||||
v-model:modelValue="formData.configs.key"
|
v-model:modelValue="formData.configs.key"
|
||||||
placeholder='证书私钥格式以"-----BEGIN (RSA|EC) PRIVATE KEY-----"开头,以"-----END(RSA|EC) PRIVATE KEY-----"结尾。'
|
placeholder="请输入证书私钥"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item label="说明" name="description">
|
<j-form-item label="说明" name="description">
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
style="padding: 0px"
|
style="padding: 0px"
|
||||||
@click="i.onClick"
|
@click="i.onClick"
|
||||||
type="link"
|
type="link"
|
||||||
|
:danger="i.key === 'delete'"
|
||||||
:hasPermission="'link/Certificate:' + i.key"
|
:hasPermission="'link/Certificate:' + i.key"
|
||||||
>
|
>
|
||||||
<template #icon
|
<template #icon
|
||||||
|
@ -96,6 +97,7 @@ const columns = [
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
search: {
|
search: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
first: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,8 +75,6 @@ const pickerTimeChange = () => {
|
||||||
|
|
||||||
const getCPUEcharts = async (val: any) => {
|
const getCPUEcharts = async (val: any) => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
console.log(224, val);
|
|
||||||
|
|
||||||
const res: any = await dashboard(defulteParamsData('cpu', val));
|
const res: any = await dashboard(defulteParamsData('cpu', val));
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
const _cpuOptions = {};
|
const _cpuOptions = {};
|
||||||
|
|
|
@ -114,8 +114,8 @@ const getNetworkEcharts = async (val: any) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
};
|
||||||
const networkValueRender = (obj: any) => {
|
|
||||||
const { value } = obj;
|
const formatterData = (value: any) => {
|
||||||
let _data = '';
|
let _data = '';
|
||||||
if (value >= 1024 && value < 1024 * 1024) {
|
if (value >= 1024 && value < 1024 * 1024) {
|
||||||
_data = `${Number((value / 1024).toFixed(2))}KB`;
|
_data = `${Number((value / 1024).toFixed(2))}KB`;
|
||||||
|
@ -124,7 +124,14 @@ const networkValueRender = (obj: any) => {
|
||||||
} else {
|
} else {
|
||||||
_data = `${value}B`;
|
_data = `${value}B`;
|
||||||
}
|
}
|
||||||
return `${obj?.axisValueLabel}<br />${obj?.marker}${obj?.seriesName}: ${_data}`;
|
return _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const networkValueRender = (obj: any) => {
|
||||||
|
const { value } = obj;
|
||||||
|
return `${obj?.axisValueLabel}<br />${obj?.marker}${
|
||||||
|
obj?.seriesName
|
||||||
|
} ${formatterData(value)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setOptions = (data: any, key: string) => ({
|
const setOptions = (data: any, key: string) => ({
|
||||||
|
@ -149,9 +156,12 @@ const handleNetworkOptions = (optionsData: any, xAxis: any) => {
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: (_value: any) => formatterData(_value),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
left: '100px',
|
left: '70px',
|
||||||
right: '50px',
|
right: '50px',
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
|
|
|
@ -27,10 +27,11 @@
|
||||||
<script setup lang="ts" name="FileUpload">
|
<script setup lang="ts" name="FileUpload">
|
||||||
import { LocalStore } from '@/utils/comm';
|
import { LocalStore } from '@/utils/comm';
|
||||||
import { TOKEN_KEY } from '@/utils/variable';
|
import { TOKEN_KEY } from '@/utils/variable';
|
||||||
import { PROTOCOL_UPLOAD, querySystemApi } from '@/api/link/protocol';
|
import { PROTOCOL_UPLOAD } from '@/api/link/protocol';
|
||||||
import { onlyMessage } from '@/utils/comm';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
import type { UploadChangeParam, UploadProps } from 'ant-design-vue';
|
import type { UploadChangeParam, UploadProps } from 'ant-design-vue';
|
||||||
import { notification as Notification } from 'ant-design-vue';
|
import { notification as Notification } from 'ant-design-vue';
|
||||||
|
import { useSystem } from '@/store/system';
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'change']);
|
const emit = defineEmits(['update:modelValue', 'change']);
|
||||||
|
|
||||||
|
@ -41,6 +42,10 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paths: string = useSystem().$state.configInfo.paths?.[
|
||||||
|
'base-path'
|
||||||
|
] as string;
|
||||||
|
|
||||||
const value = ref(props.modelValue);
|
const value = ref(props.modelValue);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
@ -58,11 +63,9 @@ const handleChange = async (info: UploadChangeParam) => {
|
||||||
if (info.file.status === 'done') {
|
if (info.file.status === 'done') {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
const result = info.file.response?.result;
|
const result = info.file.response?.result;
|
||||||
const api: any = await querySystemApi(['paths']); // todo base-path在pinia获取系统配置的
|
const f = `${paths || ''}/file/${result.id}?accessKey=${
|
||||||
const path = api.result[0]?.properties
|
result.others.accessKey
|
||||||
? api.result[0]?.properties['base-path']
|
}`;
|
||||||
: '';
|
|
||||||
const f = `${path}/file/${result.id}?accessKey=${result.others.accessKey}`;
|
|
||||||
onlyMessage('上传成功!', 'success');
|
onlyMessage('上传成功!', 'success');
|
||||||
value.value = f;
|
value.value = f;
|
||||||
emit('update:modelValue', f);
|
emit('update:modelValue', f);
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
:disabled="!!id"
|
:disabled="!!id"
|
||||||
v-model:value="formData.type"
|
v-model:value="formData.type"
|
||||||
:options="options"
|
:options="options"
|
||||||
|
:column="2"
|
||||||
@change="changeType"
|
@change="changeType"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
|
|
@ -103,18 +103,6 @@
|
||||||
:key="cluster.id"
|
:key="cluster.id"
|
||||||
:show-arrow="!formData.shareCluster"
|
:show-arrow="!formData.shareCluster"
|
||||||
>
|
>
|
||||||
<!-- <j-collapse-panel
|
|
||||||
:key="cluster.id"
|
|
||||||
:header="
|
|
||||||
cluster.serverId
|
|
||||||
? cluster.serverId
|
|
||||||
: !formData.shareCluster
|
|
||||||
? `#${index + 1}.配置信息`
|
|
||||||
: ''
|
|
||||||
"
|
|
||||||
collapsible="header"
|
|
||||||
:show-arrow="!formData.shareCluster"
|
|
||||||
> -->
|
|
||||||
<template #header v-if="!shareCluster">
|
<template #header v-if="!shareCluster">
|
||||||
<div class="collapse-header">
|
<div class="collapse-header">
|
||||||
{{
|
{{
|
||||||
|
@ -1136,10 +1124,6 @@ const filterConfigByType = (data: any, type: string) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeheader = (value: string) => {
|
|
||||||
console.log(22, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getPortOptions = (portOptions: object, index = 0) => {
|
const getPortOptions = (portOptions: object, index = 0) => {
|
||||||
if (!portOptions) return;
|
if (!portOptions) return;
|
||||||
const type = formData.value.type;
|
const type = formData.value.type;
|
||||||
|
@ -1224,6 +1208,10 @@ const saveData = async () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!formRef2Data?.cluster) {
|
||||||
|
return onlyMessage('请新增或完善配置', 'error');
|
||||||
|
}
|
||||||
|
|
||||||
const { configuration } = formRef2Data?.cluster[0];
|
const { configuration } = formRef2Data?.cluster[0];
|
||||||
const params = shareCluster.value
|
const params = shareCluster.value
|
||||||
? { ...formData.value, configuration }
|
? { ...formData.value, configuration }
|
||||||
|
@ -1418,5 +1406,6 @@ watch(
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border: 1px solid #e50012;
|
border: 1px solid #e50012;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -113,6 +113,19 @@ export const Validator = {
|
||||||
regOnlyNumber: new RegExp(/^\d+$/),
|
regOnlyNumber: new RegExp(/^\d+$/),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const validateAddress = (_rule: any, value: string): Promise<any> =>
|
||||||
|
new Promise(async (resolve, reject) => {
|
||||||
|
if (
|
||||||
|
Validator.regIpv4.test(value) ||
|
||||||
|
Validator.regIPv6.test(value) ||
|
||||||
|
Validator.regDomain.test(value)
|
||||||
|
) {
|
||||||
|
return resolve('');
|
||||||
|
} else {
|
||||||
|
return reject('请输入正确的IP地址或者域名');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const Rules = {
|
export const Rules = {
|
||||||
name: [
|
name: [
|
||||||
{
|
{
|
||||||
|
@ -160,10 +173,14 @@ export const Rules = {
|
||||||
message: '请输入公网地址',
|
message: '请输入公网地址',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern:
|
validator: validateAddress,
|
||||||
Validator.regIpv4 || Validator.regIPv6 || Validator.regDomain,
|
message: '请输入正确的IP地址或者域名',
|
||||||
message: '请输入正确格式的域名或ip',
|
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// pattern:
|
||||||
|
// Validator.regIpv4 || Validator.regIPv6 || Validator.regDomain,
|
||||||
|
// message: '请输入正确格式的域名或ip',
|
||||||
|
// },
|
||||||
],
|
],
|
||||||
publicPort: [
|
publicPort: [
|
||||||
{
|
{
|
||||||
|
@ -181,9 +198,7 @@ export const Rules = {
|
||||||
message: '请输入远程地址',
|
message: '请输入远程地址',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern:
|
validator: validateAddress,
|
||||||
Validator.regIpv4 || Validator.regIPv6 || Validator.regDomain,
|
|
||||||
|
|
||||||
message: '请输入正确格式的域名或ip',
|
message: '请输入正确格式的域名或ip',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
enabled: 'processing',
|
enabled: 'processing',
|
||||||
disabled: 'error',
|
disabled: 'error',
|
||||||
}"
|
}"
|
||||||
|
@click="handlEye(slotProps.id)"
|
||||||
>
|
>
|
||||||
<template #img>
|
<template #img>
|
||||||
<slot name="img">
|
<slot name="img">
|
||||||
|
@ -51,15 +52,14 @@
|
||||||
style="
|
style="
|
||||||
width: calc(100% - 100px);
|
width: calc(100% - 100px);
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
color: #2f54eb;
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
style="
|
style="
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 800;
|
||||||
|
line-height: 22px;
|
||||||
"
|
"
|
||||||
@click.stop="handlEye(slotProps.id)"
|
|
||||||
>
|
>
|
||||||
{{ slotProps.name }}
|
{{ slotProps.name }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -136,6 +136,7 @@
|
||||||
style="padding: 0px"
|
style="padding: 0px"
|
||||||
@click="i.onClick"
|
@click="i.onClick"
|
||||||
type="link"
|
type="link"
|
||||||
|
:danger="i.key === 'delete'"
|
||||||
:hasPermission="'link/Type:' + i.key"
|
:hasPermission="'link/Type:' + i.key"
|
||||||
>
|
>
|
||||||
<template #icon
|
<template #icon
|
||||||
|
|
|
@ -76,10 +76,7 @@
|
||||||
message: '请输入API Host',
|
message: '请输入API Host',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern:
|
validator: validateAddress,
|
||||||
Validator.regIpv4 ||
|
|
||||||
Validator.regIPv6 ||
|
|
||||||
Validator.regDomain,
|
|
||||||
message: '请输入正确的IP地址或者域名',
|
message: '请输入正确的IP地址或者域名',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
@ -133,10 +130,7 @@
|
||||||
message: '请输入RTP IP',
|
message: '请输入RTP IP',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern:
|
validator: validateAddress,
|
||||||
Validator.regIpv4 ||
|
|
||||||
Validator.regIPv6 ||
|
|
||||||
Validator.regDomain,
|
|
||||||
message: '请输入正确的IP地址或者域名',
|
message: '请输入正确的IP地址或者域名',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
@ -197,15 +191,8 @@
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:min="1"
|
:min="1"
|
||||||
:max="
|
:max="
|
||||||
Number(
|
formData.configuration
|
||||||
formData.configuration
|
.dynamicRtpPortRange1 || 65535
|
||||||
.dynamicRtpPortRange1,
|
|
||||||
) < 65535
|
|
||||||
? Number(
|
|
||||||
formData.configuration
|
|
||||||
.dynamicRtpPortRange1,
|
|
||||||
)
|
|
||||||
: 65535
|
|
||||||
"
|
"
|
||||||
:precision="0"
|
:precision="0"
|
||||||
placeholder="起始端口"
|
placeholder="起始端口"
|
||||||
|
@ -231,7 +218,8 @@
|
||||||
<j-input-number
|
<j-input-number
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:min="
|
:min="
|
||||||
formData.configuration.dynamicRtpPortRange0
|
formData.configuration
|
||||||
|
.dynamicRtpPortRange0 || 1
|
||||||
"
|
"
|
||||||
:max="65535"
|
:max="65535"
|
||||||
:precision="0"
|
:precision="0"
|
||||||
|
@ -305,6 +293,19 @@ const Validator = {
|
||||||
regOnlyNumber: new RegExp(/^\d+$/),
|
regOnlyNumber: new RegExp(/^\d+$/),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const validateAddress = (_rule: any, value: string): Promise<any> =>
|
||||||
|
new Promise(async (resolve, reject) => {
|
||||||
|
if (
|
||||||
|
Validator.regIpv4.test(value) ||
|
||||||
|
Validator.regIPv6.test(value) ||
|
||||||
|
Validator.regDomain.test(value)
|
||||||
|
) {
|
||||||
|
return resolve('');
|
||||||
|
} else {
|
||||||
|
return reject('请输入正确的IP地址或者域名');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const formData = ref<FormDataType>({
|
const formData = ref<FormDataType>({
|
||||||
name: '',
|
name: '',
|
||||||
provider: undefined,
|
provider: undefined,
|
||||||
|
|
|
@ -38,9 +38,10 @@
|
||||||
:status="slotProps.state.value"
|
:status="slotProps.state.value"
|
||||||
:statusText="slotProps.state.text"
|
:statusText="slotProps.state.text"
|
||||||
:statusNames="{
|
:statusNames="{
|
||||||
enabled: 'success',
|
enabled: 'processing',
|
||||||
disabled: 'error',
|
disabled: 'error',
|
||||||
}"
|
}"
|
||||||
|
@click="handlEye(slotProps.id)"
|
||||||
>
|
>
|
||||||
<template #img>
|
<template #img>
|
||||||
<slot name="img">
|
<slot name="img">
|
||||||
|
@ -53,15 +54,14 @@
|
||||||
style="
|
style="
|
||||||
width: calc(100% - 100px);
|
width: calc(100% - 100px);
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: #2f54eb;
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
style="
|
style="
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 800;
|
||||||
|
line-height: 22px;
|
||||||
"
|
"
|
||||||
@click.stop="handlEye(slotProps.id)"
|
|
||||||
>
|
>
|
||||||
{{ slotProps.name }}
|
{{ slotProps.name }}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
</j-col>
|
</j-col>
|
||||||
</j-row>
|
</j-row>
|
||||||
<j-form-item label="级别" name="level">
|
<j-form-item label="级别" name="level">
|
||||||
<j-radio-group v-model:value="form.level">
|
<j-radio-group v-model:value="form.level" class="levelSelect">
|
||||||
<j-radio-button
|
<j-radio-button
|
||||||
v-for="(item, index) in levelOption"
|
v-for="(item, index) in levelOption"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
@ -199,7 +199,11 @@ queryData();
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.ant-radio-button-wrapper {
|
.ant-radio-button-wrapper {
|
||||||
margin: 10px 15px 0 0;
|
margin: 10px 15px 0 0;
|
||||||
width: 125px;
|
width: 20%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
.levelSelect{
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,13 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<j-modal
|
<page-container>
|
||||||
visible
|
|
||||||
title="处理记录"
|
|
||||||
:width="1200"
|
|
||||||
cancelText="取消"
|
|
||||||
okText="确定"
|
|
||||||
@ok="clsoeModal"
|
|
||||||
@cancel="clsoeModal"
|
|
||||||
>
|
|
||||||
<pro-search
|
<pro-search
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
target="bind-channel"
|
target="bind-channel"
|
||||||
|
@ -30,7 +22,7 @@
|
||||||
<span>
|
<span>
|
||||||
{{
|
{{
|
||||||
dayjs(slotsProps.handleTime).format(
|
dayjs(slotsProps.handleTime).format(
|
||||||
'YYYY-MM-DD HH:mm:ss'
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
|
@ -41,29 +33,25 @@
|
||||||
<template #alarmTime="slotProps">
|
<template #alarmTime="slotProps">
|
||||||
<span>
|
<span>
|
||||||
{{
|
{{
|
||||||
dayjs(slotProps.alarmTime).format(
|
dayjs(slotProps.alarmTime).format('YYYY-MM-DD HH:mm:ss')
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)
|
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</JProTable>
|
</JProTable>
|
||||||
</j-modal>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { queryHandleHistory } from '@/api/rule-engine/log';
|
import { queryHandleHistory } from '@/api/rule-engine/log';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
const props = defineProps({
|
import { useRoute } from 'vue-router';
|
||||||
data: {
|
const route = useRoute();
|
||||||
type: Object,
|
const id = route.query?.id;
|
||||||
},
|
|
||||||
});
|
|
||||||
const terms = [
|
const terms = [
|
||||||
{
|
{
|
||||||
column: 'alarmRecordId',
|
column: 'alarmRecordId',
|
||||||
termType: 'eq',
|
termType: 'eq',
|
||||||
value: props.data.id,
|
value: id,
|
||||||
type: 'and',
|
type: 'and',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -119,9 +107,6 @@ const emit = defineEmits(['closeLog']);
|
||||||
/**
|
/**
|
||||||
* 关闭弹窗
|
* 关闭弹窗
|
||||||
*/
|
*/
|
||||||
const clsoeModal = () => {
|
|
||||||
emit('closeLog');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearch = (e: any) => {
|
const handleSearch = (e: any) => {
|
||||||
params.value = e;
|
params.value = e;
|
|
@ -62,8 +62,8 @@
|
||||||
</span>
|
</span>
|
||||||
</Ellipsis>
|
</Ellipsis>
|
||||||
<j-row :gutter="24">
|
<j-row :gutter="24">
|
||||||
<j-col :span="8">
|
<j-col :span="8" class="content-left">
|
||||||
<div class="content-des-title">
|
<div class="content-left-title">
|
||||||
{{ titleMap.get(slotProps.targetType) }}
|
{{ titleMap.get(slotProps.targetType) }}
|
||||||
</div>
|
</div>
|
||||||
<Ellipsis
|
<Ellipsis
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
>
|
>
|
||||||
</j-col>
|
</j-col>
|
||||||
<j-col :span="8">
|
<j-col :span="8">
|
||||||
<div class="content-des-title">
|
<div class="content-right-title">
|
||||||
最近告警时间
|
最近告警时间
|
||||||
</div>
|
</div>
|
||||||
<Ellipsis
|
<Ellipsis
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
>
|
>
|
||||||
</j-col>
|
</j-col>
|
||||||
<j-col :span="8">
|
<j-col :span="8">
|
||||||
<div class="content-des-title">状态</div>
|
<div class="content-right-title">状态</div>
|
||||||
<BadgeStatus
|
<BadgeStatus
|
||||||
:status="slotProps.state.value"
|
:status="slotProps.state.value"
|
||||||
:statusName="{
|
:statusName="{
|
||||||
|
@ -136,11 +136,6 @@
|
||||||
v-if="data.solveVisible"
|
v-if="data.solveVisible"
|
||||||
@closeSolve="closeSolve"
|
@closeSolve="closeSolve"
|
||||||
/>
|
/>
|
||||||
<SolveLog
|
|
||||||
:data="data.current"
|
|
||||||
v-if="data.logVisible"
|
|
||||||
@closeLog="closeLog"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -292,7 +287,7 @@ const orgCol = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let params = ref({
|
let params:any = ref({
|
||||||
sorts: [{ name: 'alarmTime', order: 'desc' }],
|
sorts: [{ name: 'alarmTime', order: 'desc' }],
|
||||||
terms: [],
|
terms: [],
|
||||||
});
|
});
|
||||||
|
@ -412,8 +407,11 @@ const getActions = (
|
||||||
},
|
},
|
||||||
icon: 'FileTextOutlined',
|
icon: 'FileTextOutlined',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
data.value.current = currentData;
|
menuStory.jumpPage(
|
||||||
data.value.logVisible = true;
|
'rule-engine/Alarm/Log/Record',
|
||||||
|
{},
|
||||||
|
{ id: currentData.id },
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -434,4 +432,14 @@ const closeLog = () => {
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
.content-left{
|
||||||
|
border-right: .2px solid rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.content-right-title{
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
|
.content-left-title{
|
||||||
|
font-size: 18px
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -188,11 +188,18 @@ const handOptionByColumn = (option: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
watch(() => [columnOptions.value, paramsValue.column], () => {
|
||||||
if (!props.value.error && props.value.column) { // 新增不查找option
|
if (paramsValue.column) {
|
||||||
const option = getOption(columnOptions.value, paramsValue.column, 'id')
|
const option = getOption(columnOptions.value, paramsValue.column, 'id')
|
||||||
if (option) {
|
if (option && Object.keys(option).length) {
|
||||||
handOptionByColumn(option)
|
handOptionByColumn(option)
|
||||||
|
if (props.value.error) {
|
||||||
|
emit('update:value', {
|
||||||
|
...props.value,
|
||||||
|
error: false
|
||||||
|
})
|
||||||
|
formItemContext.onFieldChange()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
emit('update:value', {
|
emit('update:value', {
|
||||||
...props.value,
|
...props.value,
|
||||||
|
|
|
@ -213,7 +213,7 @@ const rules = [
|
||||||
return Promise.reject(new Error('请选择操作符'))
|
return Promise.reject(new Error('请选择操作符'))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v.value === undefined) {
|
if (v.value.value === undefined) {
|
||||||
return Promise.reject(new Error('请选择或输入参数值'))
|
return Promise.reject(new Error('请选择或输入参数值'))
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
<div class='actions-terms-list-content'>
|
<div class='actions-terms-list-content'>
|
||||||
<template v-if='showWhen'>
|
<template v-if='showWhen'>
|
||||||
<TermsItem
|
<WhenItem
|
||||||
v-for='(item, index) in whenData'
|
v-for='(item, index) in whenData'
|
||||||
:key='item.key'
|
:key='item.key'
|
||||||
:name='index'
|
:name='index'
|
||||||
|
@ -37,9 +37,7 @@
|
||||||
:isFirst='index === 0'
|
:isFirst='index === 0'
|
||||||
:isLast='index === whenData.length -1'
|
:isLast='index === whenData.length -1'
|
||||||
:branchName='name'
|
:branchName='name'
|
||||||
:whenName='index'
|
|
||||||
:data='item'
|
:data='item'
|
||||||
:isFrist='index === 0'
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<span v-else class='when-add' @click='addWhen' :style='{ padding: isFirst ? "16px 0" : 0 }'>
|
<span v-else class='when-add' @click='addWhen' :style='{ padding: isFirst ? "16px 0" : 0 }'>
|
||||||
|
@ -67,10 +65,11 @@
|
||||||
<script lang='ts' setup name='Branches'>
|
<script lang='ts' setup name='Branches'>
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { ActionBranchesProps } from '@/views/rule-engine/Scene/typings'
|
import type { ActionBranchesProps } from '@/views/rule-engine/Scene/typings'
|
||||||
import TermsItem from './TermsItem.vue'
|
import WhenItem from './WhenItem.vue'
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useSceneStore } from 'store/scene'
|
import { useSceneStore } from 'store/scene'
|
||||||
import Action from '../../action/index.vue'
|
import Action from '../../action/index.vue'
|
||||||
|
import { randomString } from '@/utils/utils'
|
||||||
|
|
||||||
const sceneStore = useSceneStore()
|
const sceneStore = useSceneStore()
|
||||||
const { data: FormModel } = storeToRefs(sceneStore)
|
const { data: FormModel } = storeToRefs(sceneStore)
|
||||||
|
@ -110,7 +109,11 @@ const whenData = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const onDelete = () => {
|
const onDelete = () => {
|
||||||
FormModel.value.branches?.splice(props.name, 1)
|
if (FormModel.value.branches?.length == 2) {
|
||||||
|
FormModel.value.branches?.splice(props.name, 1, null)
|
||||||
|
} else {
|
||||||
|
FormModel.value.branches?.splice(props.name, 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDeleteAll = () => {
|
const onDeleteAll = () => {
|
||||||
|
@ -133,24 +136,31 @@ const mouseout = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const addWhen = () => {
|
const addWhen = () => {
|
||||||
const whenItem = {
|
const terms = {
|
||||||
key: `when_${new Date().getTime()}`,
|
|
||||||
type: 'and',
|
type: 'and',
|
||||||
terms: [
|
terms: [
|
||||||
{
|
{
|
||||||
column: undefined,
|
terms: [
|
||||||
value: {
|
{
|
||||||
source: 'fixed',
|
column: undefined,
|
||||||
value: undefined
|
value: {
|
||||||
},
|
source: 'fixed',
|
||||||
termType: undefined,
|
value: undefined
|
||||||
key: 'params_1',
|
},
|
||||||
|
termType: undefined,
|
||||||
|
key: `params_${randomString()}`,
|
||||||
|
type: 'and',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
key: `terms_2_${randomString()}`,
|
||||||
type: 'and',
|
type: 'and',
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
key: `terms_${randomString()}`
|
||||||
}
|
}
|
||||||
FormModel.value.branches?.[props.name].when.push(whenItem)
|
FormModel.value.branches?.[props.name].when?.push(terms)
|
||||||
FormModel.value.branches?.push(null)
|
FormModel.value.branches?.push(null as any)
|
||||||
|
FormModel.value.options!.when[props.name]?.terms.push({ termType: '并且', terms: [['','eq','','and']]})
|
||||||
}
|
}
|
||||||
|
|
||||||
const optionsClass = computed(() => {
|
const optionsClass = computed(() => {
|
||||||
|
|
|
@ -81,6 +81,7 @@ import { ContextKey } from './util'
|
||||||
import { useSceneStore } from 'store/scene'
|
import { useSceneStore } from 'store/scene'
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { Form } from 'jetlinks-ui-components'
|
import { Form } from 'jetlinks-ui-components'
|
||||||
|
import { pick } from 'lodash-es'
|
||||||
|
|
||||||
const sceneStore = useSceneStore()
|
const sceneStore = useSceneStore()
|
||||||
const { data: formModel } = storeToRefs(sceneStore)
|
const { data: formModel } = storeToRefs(sceneStore)
|
||||||
|
@ -187,11 +188,18 @@ const handOptionByColumn = (option: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
watch(() => [columnOptions.value, paramsValue.column], () => {
|
||||||
if (!props.value.error && props.value.column) { // 新增不查找option
|
if (paramsValue.column) {
|
||||||
const option = getOption(columnOptions.value, paramsValue.column, 'column')
|
const option = getOption(columnOptions.value, paramsValue.column, 'column')
|
||||||
if (option) {
|
if (option && Object.keys(option).length) {
|
||||||
handOptionByColumn(option)
|
handOptionByColumn(option)
|
||||||
|
if (props.value.error) {
|
||||||
|
emit('update:value', {
|
||||||
|
...props.value,
|
||||||
|
error: false
|
||||||
|
})
|
||||||
|
formItemContext.onFieldChange()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
emit('update:value', {
|
emit('update:value', {
|
||||||
...props.value,
|
...props.value,
|
||||||
|
@ -200,7 +208,7 @@ watchEffect(() => {
|
||||||
formItemContext.onFieldChange()
|
formItemContext.onFieldChange()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}, { immediate: true, deep: true })
|
||||||
|
|
||||||
const showDouble = computed(() => {
|
const showDouble = computed(() => {
|
||||||
const isRange = paramsValue.termType ? arrayParamsKey.includes(paramsValue.termType) : false
|
const isRange = paramsValue.termType ? arrayParamsKey.includes(paramsValue.termType) : false
|
||||||
|
@ -225,15 +233,18 @@ const mouseout = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const columnSelect = (option: any) => {
|
const columnSelect = (option: any) => {
|
||||||
paramsValue.termType = 'eq'
|
const termTypes = option.termTypes
|
||||||
|
paramsValue.termType = termTypes?.length ? termTypes[0].id : 'eq'
|
||||||
paramsValue.value = {
|
paramsValue.value = {
|
||||||
source: tabsOptions.value[0].key,
|
source: tabsOptions.value[0].key,
|
||||||
value: undefined
|
value: undefined
|
||||||
}
|
}
|
||||||
|
handOptionByColumn(option)
|
||||||
emit('update:value', { ...paramsValue })
|
emit('update:value', { ...paramsValue })
|
||||||
formItemContext.onFieldChange()
|
formItemContext.onFieldChange()
|
||||||
formModel.value.options!.when[props.whenName].terms[props.termsName].terms[props.name][0] = option.name
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.name][0] = option.name
|
||||||
formModel.value.options!.when[props.whenName].terms[props.termsName].terms[props.name][1] = paramsValue.termType
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.name][1] = paramsValue.termType
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const termsTypeSelect = (e: { key: string, name: string }) => {
|
const termsTypeSelect = (e: { key: string, name: string }) => {
|
||||||
|
@ -244,16 +255,18 @@ const termsTypeSelect = (e: { key: string, name: string }) => {
|
||||||
}
|
}
|
||||||
emit('update:value', { ...paramsValue })
|
emit('update:value', { ...paramsValue })
|
||||||
formItemContext.onFieldChange()
|
formItemContext.onFieldChange()
|
||||||
formModel.value.options!.when[props.whenName].terms[props.termsName].terms[props.name][1] = e.name
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.name][1] = e.name
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const valueSelect = (_: any, label: string, labelObj: Record<number, any>) => {
|
const valueSelect = (_: any, label: string, labelObj: Record<number, any>) => {
|
||||||
|
emit('update:value', { ...paramsValue })
|
||||||
formItemContext.onFieldChange()
|
formItemContext.onFieldChange()
|
||||||
formModel.value.options!.when[props.whenName].terms[props.termsName].terms[props.name][2] = labelObj
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.name][2] = labelObj
|
||||||
}
|
}
|
||||||
|
|
||||||
const typeSelect = (e: any) => {
|
const typeSelect = (e: any) => {
|
||||||
formModel.value.options!.when[props.whenName].terms[props.termsName].terms[props.name][3] = e.label
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.name][3] = e.label
|
||||||
}
|
}
|
||||||
|
|
||||||
const termAdd = () => {
|
const termAdd = () => {
|
||||||
|
@ -267,17 +280,17 @@ const termAdd = () => {
|
||||||
type: 'and',
|
type: 'and',
|
||||||
key: `params_${new Date().getTime()}`
|
key: `params_${new Date().getTime()}`
|
||||||
}
|
}
|
||||||
formModel.value.branches?.[props.branchName]?.when?.[props.whenName]?.terms?.push(terms)
|
formModel.value.branches?.[props.branchName]?.when?.[props.whenName]?.terms?.[props.termsName]?.terms?.push(terms)
|
||||||
formModel.value.options!.when[props.whenName].terms[props.termsName].terms[props.name].push(['', '', '', '并且'])
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName].push(['', '', '', '并且'])
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDelete = () => {
|
const onDelete = () => {
|
||||||
formModel.value.branches?.[props.branchName]?.when?.[props.whenName]?.terms?.splice(props.name, 1)
|
formModel.value.branches?.[props.branchName]?.when?.[props.whenName]?.terms?.[props.termsName]?.terms?.splice(props.name, 1)
|
||||||
formModel.value.options!.when[props.whenName].terms[props.termsName].terms.splice(props.name, 1)
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms.splice(props.name, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
Object.assign(paramsValue, props.value)
|
Object.assign(paramsValue, pick(props.value, ['column', 'options', 'termType', 'terms', 'type', 'value']))
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,67 +1,46 @@
|
||||||
<template>
|
<template>
|
||||||
<div class='terms-params'>
|
<div
|
||||||
<div class='terms-params-warp'>
|
class='terms-params-content'
|
||||||
<div v-if='!isFirst' class='term-type-warp'>
|
@mouseover='mouseover'
|
||||||
<DropdownButton
|
@mouseout='mouseout'
|
||||||
:options='[
|
>
|
||||||
{ label: "并且", value: "and" },
|
<j-popconfirm
|
||||||
{ label: "或者", value: "or" },
|
title='确认删除?'
|
||||||
]'
|
@confirm='onDelete'
|
||||||
type='type'
|
>
|
||||||
v-model:value='formModel.branches[branchName].when[whenName].type'
|
<div v-show='showDelete' class='terms-params-delete'>
|
||||||
@select='typeChange'
|
<AIcon type='CloseOutlined' />
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
</j-popconfirm>
|
||||||
class='terms-params-content'
|
|
||||||
@mouseover='mouseover'
|
|
||||||
@mouseout='mouseout'
|
|
||||||
>
|
|
||||||
<j-popconfirm
|
|
||||||
title='确认删除?'
|
|
||||||
@confirm='onDelete'
|
|
||||||
>
|
|
||||||
<div v-show='showDelete' class='terms-params-delete'>
|
|
||||||
<AIcon type='CloseOutlined' />
|
|
||||||
</div>
|
|
||||||
</j-popconfirm>
|
|
||||||
|
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-for='(item, index) in termsData'
|
v-for='(item, index) in termsData'
|
||||||
:key='item.key'
|
:key='item.key'
|
||||||
:name='["branches", branchName, "when", whenName, "terms", index]'
|
:name='["branches", branchName, "when", whenName, "terms", props.name, "terms", index]'
|
||||||
:rules='rules'
|
:rules='rules'
|
||||||
>
|
>
|
||||||
<ParamsItem
|
<ParamsItem
|
||||||
v-model:value='formModel.branches[branchName].when[whenName].terms[index]'
|
v-model:value='formModel.branches[branchName].when[whenName].terms[props.name].terms[index]'
|
||||||
:isFirst='index === 0'
|
:isFirst='index === 0'
|
||||||
:isLast='index === termsData.length - 1'
|
:isLast='index === termsData.length - 1'
|
||||||
:showDeleteBtn='termsData.length !== 1'
|
:showDeleteBtn='termsData.length !== 1'
|
||||||
:name='index'
|
:name='index'
|
||||||
:termsName='name'
|
:termsName='name'
|
||||||
:whenName='whenName'
|
:whenName='whenName'
|
||||||
:branchName='branchName'
|
:branchName='branchName'
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</div>
|
|
||||||
<div class='terms-group-add' @click='addTerms' v-if='isLast'>
|
|
||||||
<div class='terms-content'>
|
|
||||||
<AIcon type='PlusOutlined' />
|
|
||||||
<span>分组</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts' name='TermsItem'>
|
<script setup lang='ts' name='TermsItem'>
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { TermsType } from '@/views/rule-engine/Scene/typings'
|
import type { TermsType } from '@/views/rule-engine/Scene/typings'
|
||||||
import DropdownButton from '../DropdownButton'
|
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useSceneStore } from 'store/scene'
|
import { useSceneStore } from 'store/scene'
|
||||||
import ParamsItem from './ParamsItem.vue'
|
import ParamsItem from './ParamsItem.vue'
|
||||||
import { isArray } from 'lodash-es'
|
import { isArray } from 'lodash-es'
|
||||||
|
import { randomString } from '@/utils/utils'
|
||||||
|
|
||||||
const sceneStore = useSceneStore()
|
const sceneStore = useSceneStore()
|
||||||
const { data: formModel } = storeToRefs(sceneStore)
|
const { data: formModel } = storeToRefs(sceneStore)
|
||||||
|
@ -107,7 +86,7 @@ const props = defineProps({
|
||||||
|
|
||||||
const rules = [
|
const rules = [
|
||||||
{
|
{
|
||||||
validator(_: any, v: any) {
|
validator: async (_: any, v: any) => {
|
||||||
if (v !== undefined && !v.error) {
|
if (v !== undefined && !v.error) {
|
||||||
if (!Object.keys(v).length) {
|
if (!Object.keys(v).length) {
|
||||||
return Promise.reject(new Error('该数据已发生变更,请重新配置'));
|
return Promise.reject(new Error('该数据已发生变更,请重新配置'));
|
||||||
|
@ -115,22 +94,17 @@ const rules = [
|
||||||
if (!v.column) {
|
if (!v.column) {
|
||||||
return Promise.reject(new Error('请选择参数'));
|
return Promise.reject(new Error('请选择参数'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!v.termType) {
|
if (!v.termType) {
|
||||||
return Promise.reject(new Error('请选择操作符'));
|
return Promise.reject(new Error('请选择操作符'));
|
||||||
}
|
}
|
||||||
|
if (!v.value?.value) {
|
||||||
if (v.value === undefined) {
|
return Promise.reject(new Error('请选择或输入参数值'));
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
isArray(v.value.value) &&
|
||||||
|
v.value.value.some((_v: any) => _v === undefined)
|
||||||
|
) {
|
||||||
return Promise.reject(new Error('请选择或输入参数值'));
|
return Promise.reject(new Error('请选择或输入参数值'));
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
isArray(v.value.value) &&
|
|
||||||
v.value.value.some((_v: any) => _v === undefined)
|
|
||||||
) {
|
|
||||||
return Promise.reject(new Error('请选择或输入参数值'));
|
|
||||||
} else if (v.value.value === undefined) {
|
|
||||||
return Promise.reject(new Error('请选择或输入参数值'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(new Error('请选择参数'));
|
return Promise.reject(new Error('请选择参数'));
|
||||||
|
@ -159,12 +133,8 @@ const mouseout = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDelete = () => {
|
const onDelete = () => {
|
||||||
formModel.value.branches?.[props.branchName]?.when?.splice(props.name, 1)
|
formModel.value.branches?.[props.branchName]?.when?.splice(props.whenName, 1)
|
||||||
formModel.value.options!.when[props.whenName].terms.splice(props.name, 1)
|
formModel.value.options!.when[props.branchName].terms.splice(props.whenName, 1)
|
||||||
}
|
|
||||||
|
|
||||||
const typeChange = (e: any) => {
|
|
||||||
formModel.value.options!.when[props.whenName].terms[props.name].termType = e.label
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const addTerms = () => {
|
const addTerms = () => {
|
||||||
|
@ -178,16 +148,14 @@ const addTerms = () => {
|
||||||
value: undefined
|
value: undefined
|
||||||
},
|
},
|
||||||
termType: undefined,
|
termType: undefined,
|
||||||
key: 'params_1',
|
key: `params_${randomString()}`,
|
||||||
type: 'and',
|
type: 'and',
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
key: `terms_${new Date().getTime()}`
|
key: `terms_${randomString()}`
|
||||||
}
|
}
|
||||||
formModel.value.branches?.[props.branchName]?.when?.push(terms)
|
formModel.value.branches?.[props.branchName]?.when?.[props.whenName].terms?.push(terms)
|
||||||
formModel.value.options!.when[props.whenName].push({
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms.push(['','eq','','and'])
|
||||||
terms: [{ termType: '并且', terms: [['','eq','','and']]}]
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
<template>
|
||||||
|
<div class='terms-params'>
|
||||||
|
<div class='terms-params-warp'>
|
||||||
|
<div v-if='!isFirst' class='term-type-warp'>
|
||||||
|
<DropdownButton
|
||||||
|
:options='[
|
||||||
|
{ label: "并且", value: "and" },
|
||||||
|
{ label: "或者", value: "or" },
|
||||||
|
]'
|
||||||
|
type='type'
|
||||||
|
v-model:value='formModel.branches[branchName].when[name].type'
|
||||||
|
@select='typeChange'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<TermsItem
|
||||||
|
v-for='(item, index) in termsData'
|
||||||
|
:key='item.key'
|
||||||
|
:branchName='branchName'
|
||||||
|
:whenName='props.name'
|
||||||
|
:name='index'
|
||||||
|
:showDeleteBtn='showDeleteBtn'
|
||||||
|
:isFirst='index === 0'
|
||||||
|
:isLast='index === termsData.length -1'
|
||||||
|
:data='item'
|
||||||
|
/>
|
||||||
|
<div class='terms-group-add' @click='addWhen' v-if='isLast'>
|
||||||
|
<div class='terms-content'>
|
||||||
|
<AIcon type='PlusOutlined' />
|
||||||
|
<span>分组</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang='ts' name='WhenItem'>
|
||||||
|
import type { PropType } from 'vue'
|
||||||
|
import TermsItem from './TermsItem.vue'
|
||||||
|
import { TermsType } from '@/views/rule-engine/Scene/typings'
|
||||||
|
import { useSceneStore } from 'store/scene'
|
||||||
|
import DropdownButton from '../DropdownButton'
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { randomString } from '@/utils/utils'
|
||||||
|
|
||||||
|
const sceneStore = useSceneStore()
|
||||||
|
const { data: formModel } = storeToRefs(sceneStore)
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
isFirst: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object as PropType<TermsType>,
|
||||||
|
default: () => ({
|
||||||
|
when: [],
|
||||||
|
shakeLimit: {},
|
||||||
|
then: []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
showDeleteBtn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
class: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
branchName: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
isLast: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const termsData = computed(() => {
|
||||||
|
return props.data.terms
|
||||||
|
})
|
||||||
|
|
||||||
|
const typeChange = (e: any) => {
|
||||||
|
formModel.value.options!.when[props.name].terms[props.name].termType = e.label
|
||||||
|
}
|
||||||
|
|
||||||
|
const addWhen = () => {
|
||||||
|
const terms = {
|
||||||
|
type: 'and',
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
column: undefined,
|
||||||
|
value: {
|
||||||
|
source: 'fixed',
|
||||||
|
value: undefined
|
||||||
|
},
|
||||||
|
termType: undefined,
|
||||||
|
key: `params_${randomString()}`,
|
||||||
|
type: 'and',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
key: `terms_2_${randomString()}`,
|
||||||
|
type: 'and',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
key: `terms_${randomString()}`
|
||||||
|
}
|
||||||
|
formModel.value.branches?.[props.branchName]?.when?.push(terms)
|
||||||
|
formModel.value.options?.when?.[props.branchName]?.terms.push({ termType: '并且', terms: [['','eq','','and']]})
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -113,6 +113,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.terms-params {
|
.terms-params {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,8 @@ const save = async () => {
|
||||||
const formData = await sceneForm.value.validateFields()
|
const formData = await sceneForm.value.validateFields()
|
||||||
if (formData) {
|
if (formData) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const resp = await modify(data.value.id!, data.value).then(res => res)
|
const branches = data.value.branches?.filter(item => item)
|
||||||
|
const resp = await modify(data.value.id!, { ...data.value, branches }).then(res => res)
|
||||||
loading.value = false
|
loading.value = false
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
menuStore.jumpPage('rule-engine/Scene')
|
menuStore.jumpPage('rule-engine/Scene')
|
||||||
|
|
|
@ -311,7 +311,7 @@ const getActions = (
|
||||||
},
|
},
|
||||||
icon: 'LikeOutlined',
|
icon: 'LikeOutlined',
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: '',
|
title: '确认手动触发?',
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
const resp = await _execute(data.id);
|
const resp = await _execute(data.id);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
|
|
|
@ -143,6 +143,9 @@ import {
|
||||||
} from '@/api/system/department';
|
} from '@/api/system/department';
|
||||||
import { message } from 'jetlinks-ui-components';
|
import { message } from 'jetlinks-ui-components';
|
||||||
import { dictType } from '../typing';
|
import { dictType } from '../typing';
|
||||||
|
import { useDepartmentStore } from '@/store/department';
|
||||||
|
|
||||||
|
const departmentStore = useDepartmentStore();
|
||||||
|
|
||||||
const emits = defineEmits(['confirm', 'update:visible']);
|
const emits = defineEmits(['confirm', 'update:visible']);
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -154,6 +157,9 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
// 弹窗相关
|
// 弹窗相关
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
// 资产咨询次数, 产品分配后自动进入的设备资产, 第一次需要带上产品id查询
|
||||||
|
const queryCount = ref(0);
|
||||||
|
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
if (table.selectedRows.length < 1) {
|
if (table.selectedRows.length < 1) {
|
||||||
return message.warning('请先勾选数据');
|
return message.warning('请先勾选数据');
|
||||||
|
@ -167,6 +173,11 @@ const confirm = () => {
|
||||||
permission: item.selectPermissions,
|
permission: item.selectPermissions,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (params.length === 1) {
|
||||||
|
// 只选择一个产品资产分配时, 分配之后, 进入设备资产分配需查出对应产品下的设备
|
||||||
|
departmentStore.setProductId(params[0].assetIdList[0]);
|
||||||
|
}
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
bindDeviceOrProductList_api(props.assetType, params)
|
bindDeviceOrProductList_api(props.assetType, params)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -259,8 +270,10 @@ const table: any = {
|
||||||
// 选中
|
// 选中
|
||||||
onSelectChange: (row: any) => {
|
onSelectChange: (row: any) => {
|
||||||
// 若该项的可选权限中没有分享权限,则不支持任何操作
|
// 若该项的可选权限中没有分享权限,则不支持任何操作
|
||||||
if (!row.permissionList.find((item: any) => item.value === 'share'))
|
if (!row.permissionList.find((item: any) => item.value === 'share')) {
|
||||||
|
message.warning('该资产不支持共享');
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
const selectedRowKeys = table._selectedRowKeys.value;
|
const selectedRowKeys = table._selectedRowKeys.value;
|
||||||
const index = selectedRowKeys.indexOf(row.id);
|
const index = selectedRowKeys.indexOf(row.id);
|
||||||
|
|
||||||
|
@ -330,7 +343,9 @@ const table: any = {
|
||||||
resolve({
|
resolve({
|
||||||
code: 200,
|
code: 200,
|
||||||
result: {
|
result: {
|
||||||
data: data.sort((a, b) => a.createTime - b.createTime),
|
data: data.sort(
|
||||||
|
(a, b) => a.createTime - b.createTime,
|
||||||
|
),
|
||||||
pageIndex,
|
pageIndex,
|
||||||
pageSize,
|
pageSize,
|
||||||
total,
|
total,
|
||||||
|
@ -394,6 +409,7 @@ const table: any = {
|
||||||
}),
|
}),
|
||||||
// 整理参数并获取数据
|
// 整理参数并获取数据
|
||||||
requestFun: async (oParams: any) => {
|
requestFun: async (oParams: any) => {
|
||||||
|
queryCount.value += 1;
|
||||||
if (props.parentId) {
|
if (props.parentId) {
|
||||||
const terms = [
|
const terms = [
|
||||||
{
|
{
|
||||||
|
@ -411,9 +427,24 @@ const table: any = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
column: 'productId$product-info',
|
||||||
|
type: 'and',
|
||||||
|
value: `id is ${departmentStore.productId}`,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (
|
||||||
|
props.assetType !== 'device' ||
|
||||||
|
!departmentStore.productId ||
|
||||||
|
queryCount.value > 1 ||
|
||||||
|
departmentStore.optType === 'handle'
|
||||||
|
) {
|
||||||
|
// 非设备|产品id不存在|有其他查询操作(queryCount+1)|设备页面手动点击资产分配, 均删除产品带入的id
|
||||||
|
terms[0].terms.pop();
|
||||||
|
}
|
||||||
if (oParams.terms && oParams.terms.length > 0)
|
if (oParams.terms && oParams.terms.length > 0)
|
||||||
terms.unshift({ terms: oParams.terms });
|
terms.unshift({ terms: oParams.terms });
|
||||||
const params = {
|
const params = {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
placeholder="请选择上级组织"
|
placeholder="请选择上级组织"
|
||||||
:tree-data="treeData"
|
:tree-data="treeData"
|
||||||
:field-names="{ value: 'id' }"
|
:field-names="{ value: 'id' }"
|
||||||
|
@change="handleTreeSelectChange"
|
||||||
>
|
>
|
||||||
<template #title="{ name }"> {{ name }} </template>
|
<template #title="{ name }"> {{ name }} </template>
|
||||||
</j-tree-select>
|
</j-tree-select>
|
||||||
|
@ -60,6 +61,21 @@ import {
|
||||||
updateDepartment_api,
|
updateDepartment_api,
|
||||||
} from '@/api/system/department';
|
} from '@/api/system/department';
|
||||||
|
|
||||||
|
type treeType = {
|
||||||
|
id: string;
|
||||||
|
parentId?: string;
|
||||||
|
name: string;
|
||||||
|
sortIndex: string | number;
|
||||||
|
children?: treeType[];
|
||||||
|
disabled?: boolean;
|
||||||
|
};
|
||||||
|
type formType = {
|
||||||
|
id?: string;
|
||||||
|
parentId?: string;
|
||||||
|
name: string;
|
||||||
|
sortIndex: string | number;
|
||||||
|
};
|
||||||
|
|
||||||
const emits = defineEmits(['refresh', 'update:visible']);
|
const emits = defineEmits(['refresh', 'update:visible']);
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
treeData: any[];
|
treeData: any[];
|
||||||
|
@ -91,8 +107,8 @@ const treeData = computed(() => {
|
||||||
});
|
});
|
||||||
/**
|
/**
|
||||||
* 在给定的树中通过id匹配
|
* 在给定的树中通过id匹配
|
||||||
* @param node
|
* @param node
|
||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
const findItemById = (node: treeType[], id: string): treeType | null => {
|
const findItemById = (node: treeType[], id: string): treeType | null => {
|
||||||
let result = null;
|
let result = null;
|
||||||
|
@ -107,7 +123,7 @@ const findItemById = (node: treeType[], id: string): treeType | null => {
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* 将此树下的所有节点禁用
|
* 将此树下的所有节点禁用
|
||||||
* @param treeNode
|
* @param treeNode
|
||||||
*/
|
*/
|
||||||
const filterTree = (treeNode: treeType[]) => {
|
const filterTree = (treeNode: treeType[]) => {
|
||||||
if (treeNode.length < 1) return;
|
if (treeNode.length < 1) return;
|
||||||
|
@ -160,18 +176,15 @@ const form = reactive({
|
||||||
});
|
});
|
||||||
form.init();
|
form.init();
|
||||||
|
|
||||||
type treeType = {
|
/**
|
||||||
id: string;
|
* 上级组织选择改变
|
||||||
parentId?: string;
|
*/
|
||||||
name: string;
|
const handleTreeSelectChange = () => {
|
||||||
sortIndex: string | number;
|
// 上级组织
|
||||||
children?: treeType[];
|
const parent = treeData.value.find((f: any) => f.id === form.data.parentId);
|
||||||
disabled?: boolean;
|
// 当前编辑的组织排序, 为选择上级组织的最大排序+1, 如上级组织没有自组织, 则默认为1
|
||||||
};
|
form.data.sortIndex = parent?.children
|
||||||
type formType = {
|
? parent.children[parent.children.length - 1].sortIndex + 1
|
||||||
id?: string;
|
: 1;
|
||||||
parentId?: string;
|
|
||||||
name: string;
|
|
||||||
sortIndex: string | number;
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -8,7 +8,12 @@
|
||||||
visible
|
visible
|
||||||
@cancel="emits('update:visible', false)"
|
@cancel="emits('update:visible', false)"
|
||||||
>
|
>
|
||||||
<div>
|
<a-alert
|
||||||
|
message="只能分配有'共享'权限的资产数据"
|
||||||
|
type="warning"
|
||||||
|
show-icon
|
||||||
|
/>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
<span>资产权限:</span>
|
<span>资产权限:</span>
|
||||||
<j-checkbox-group
|
<j-checkbox-group
|
||||||
v-model:value="form.permission"
|
v-model:value="form.permission"
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
v-if="treeData.length > 0"
|
v-if="treeData.length > 0"
|
||||||
:tree-data="treeData"
|
:tree-data="treeData"
|
||||||
v-model:selected-keys="selectedKeys"
|
v-model:selected-keys="selectedKeys"
|
||||||
|
v-model:expandedKeys="expandedKeys"
|
||||||
:fieldNames="{ key: 'id' }"
|
:fieldNames="{ key: 'id' }"
|
||||||
>
|
>
|
||||||
<template #title="{ name, data }">
|
<template #title="{ name, data }">
|
||||||
|
@ -105,6 +106,7 @@ const sourceTree = ref<any[]>([]); // 源数据
|
||||||
const treeMap = new Map(); // 数据的map版本
|
const treeMap = new Map(); // 数据的map版本
|
||||||
const treeData = ref<any[]>([]); // 展示的数据
|
const treeData = ref<any[]>([]); // 展示的数据
|
||||||
const selectedKeys = ref<string[]>([]); // 当前选中的项
|
const selectedKeys = ref<string[]>([]); // 当前选中的项
|
||||||
|
const expandedKeys = ref<string[] | number[]>([]);
|
||||||
|
|
||||||
function getTree(cb?: Function) {
|
function getTree(cb?: Function) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
@ -149,6 +151,7 @@ const search = debounce(() => {
|
||||||
treeData.value = ArrayToTree(cloneDeep([...treeArray.values()]));
|
treeData.value = ArrayToTree(cloneDeep([...treeArray.values()]));
|
||||||
} else {
|
} else {
|
||||||
treeData.value = ArrayToTree(cloneDeep([...treeMap.values()]));
|
treeData.value = ArrayToTree(cloneDeep([...treeMap.values()]));
|
||||||
|
expandedKeys.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function dig(_data: any[]): any {
|
function dig(_data: any[]): any {
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
:hasPermission="`${permission}:assert`"
|
:hasPermission="`${permission}:assert`"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="table.clickAdd"
|
@click="table.clickAdd('handle')"
|
||||||
>
|
>
|
||||||
<AIcon type="PlusOutlined" />资产分配
|
<AIcon type="PlusOutlined" />资产分配
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
|
@ -211,6 +211,9 @@ import { intersection } from 'lodash-es';
|
||||||
|
|
||||||
import type { dictType, optionsType } from '../typing';
|
import type { dictType, optionsType } from '../typing';
|
||||||
import { message } from 'jetlinks-ui-components';
|
import { message } from 'jetlinks-ui-components';
|
||||||
|
import { useDepartmentStore } from '@/store/department';
|
||||||
|
|
||||||
|
const departmentStore = useDepartmentStore();
|
||||||
|
|
||||||
const permission = 'system/Department';
|
const permission = 'system/Department';
|
||||||
|
|
||||||
|
@ -248,7 +251,7 @@ const columns = [
|
||||||
rename: 'productId$product-info',
|
rename: 'productId$product-info',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
handleValue(value: string) {
|
handleValue(value: string) {
|
||||||
return `id is ${value}`
|
return `id is ${value}`;
|
||||||
},
|
},
|
||||||
options: () =>
|
options: () =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
|
@ -291,9 +294,9 @@ const columns = [
|
||||||
search: {
|
search: {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
options: [
|
options: [
|
||||||
{ label: '禁用', value: 'notActive' },
|
{ label: '禁用', value: 'notActive' },
|
||||||
{ label: '离线', value: 'offline' },
|
{ label: '离线', value: 'offline' },
|
||||||
{ label: '在线', value: 'online' },
|
{ label: '在线', value: 'online' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
|
@ -465,7 +468,9 @@ const table = {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
clickAdd: () => {
|
clickAdd: (type?: string) => {
|
||||||
|
// 设备资产分配弹窗操作类型: type = 'handle': 手动点击资产分配按钮, !type产品资产分配后, 自动弹出设备资产分配
|
||||||
|
departmentStore.setType(type)
|
||||||
dialogs.addShow = true;
|
dialogs.addShow = true;
|
||||||
},
|
},
|
||||||
clickEdit: (row?: any) => {
|
clickEdit: (row?: any) => {
|
||||||
|
@ -518,7 +523,7 @@ const dialogs = reactive({
|
||||||
});
|
});
|
||||||
|
|
||||||
table.init();
|
table.init();
|
||||||
nextTick(() => {
|
watchEffect(() => {
|
||||||
props.bindBool && table.clickAdd();
|
props.bindBool && table.clickAdd();
|
||||||
emits('update:bindBool', false);
|
emits('update:bindBool', false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,8 +27,13 @@
|
||||||
@cancelSelect="table.cancelSelect"
|
@cancelSelect="table.cancelSelect"
|
||||||
model="TABLE"
|
model="TABLE"
|
||||||
:defaultParams="{
|
:defaultParams="{
|
||||||
|
pageSize: 10,
|
||||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
}"
|
}"
|
||||||
|
:pagination="{
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100'],
|
||||||
|
}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</j-modal>
|
</j-modal>
|
||||||
|
|
|
@ -16,6 +16,13 @@
|
||||||
}"
|
}"
|
||||||
@cancelSelect="table.cancelSelect"
|
@cancelSelect="table.cancelSelect"
|
||||||
model="TABLE"
|
model="TABLE"
|
||||||
|
:defaultParams="{
|
||||||
|
pageSize: 10,
|
||||||
|
}"
|
||||||
|
:pagination="{
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100'],
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请上传图标',
|
message: '请上传图标',
|
||||||
|
trigger: 'change',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
style="flex: 0 0 186px"
|
style="flex: 0 0 186px"
|
||||||
|
@ -45,11 +46,22 @@
|
||||||
label="名称"
|
label="名称"
|
||||||
name="name"
|
name="name"
|
||||||
:rules="[
|
:rules="[
|
||||||
{ required: true, message: '请输入名称',trigger: 'change', },
|
{
|
||||||
{ max: 64, message: '最多可输入64个字符', trigger: 'change', },
|
required: true,
|
||||||
|
message: '请输入名称',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多可输入64个字符',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<j-input v-model:value="form.data.name" />
|
<j-input
|
||||||
|
v-model:value="form.data.name"
|
||||||
|
placeholder="请输入名称"
|
||||||
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-col>
|
</j-col>
|
||||||
<j-col :span="12">
|
<j-col :span="12">
|
||||||
|
@ -57,15 +69,26 @@
|
||||||
label="编码"
|
label="编码"
|
||||||
name="code"
|
name="code"
|
||||||
:rules="[
|
:rules="[
|
||||||
{ required: true, message: '请输入编码', trigger: 'change', },
|
{
|
||||||
{ max: 64, message: '最多可输入64个字符', trigger: 'change', },
|
required: true,
|
||||||
|
message: '请输入编码',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多可输入64个字符',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
validator: form.checkCode,
|
validator: form.checkCode,
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<j-input v-model:value="form.data.code" />
|
<j-input
|
||||||
|
v-model:value="form.data.code"
|
||||||
|
placeholder="请输入编码"
|
||||||
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-col>
|
</j-col>
|
||||||
<j-col :span="12">
|
<j-col :span="12">
|
||||||
|
@ -80,7 +103,10 @@
|
||||||
{ max: 128, message: '最多可输入128字符' },
|
{ max: 128, message: '最多可输入128字符' },
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<j-input v-model:value="form.data.url" />
|
<j-input
|
||||||
|
v-model:value="form.data.url"
|
||||||
|
placeholder="请输入页面地址"
|
||||||
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-col>
|
</j-col>
|
||||||
<j-col :span="12">
|
<j-col :span="12">
|
||||||
|
@ -94,7 +120,11 @@
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<j-input v-model:value="form.data.sortIndex" />
|
<j-input-number
|
||||||
|
v-model:value="form.data.sortIndex"
|
||||||
|
placeholder="请输入排序"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-col>
|
</j-col>
|
||||||
</j-row>
|
</j-row>
|
||||||
|
@ -104,6 +134,8 @@
|
||||||
<j-textarea
|
<j-textarea
|
||||||
v-model:value="form.data.describe"
|
v-model:value="form.data.describe"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
|
show-count
|
||||||
|
:maxlength="200"
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
@ -277,7 +309,7 @@ const form = reactive({
|
||||||
accessSupport:
|
accessSupport:
|
||||||
resp.result?.accessSupport?.value || 'unsupported',
|
resp.result?.accessSupport?.value || 'unsupported',
|
||||||
};
|
};
|
||||||
form.sourceCode = resp.result.code
|
form.sourceCode = resp.result.code;
|
||||||
});
|
});
|
||||||
// 获取关联菜单
|
// 获取关联菜单
|
||||||
getMenuTree_api({ paging: false }).then((resp: any) => {
|
getMenuTree_api({ paging: false }).then((resp: any) => {
|
||||||
|
@ -292,10 +324,11 @@ const form = reactive({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
checkCode: async (_rule: Rule, value: string): Promise<any> => {
|
checkCode: async (_rule: Rule, value: string): Promise<any> => {
|
||||||
if (!value) return Promise.reject('请输入编码');
|
if (!value) return Promise.reject('');
|
||||||
else if (value.length > 64) return Promise.reject('最多可输入64个字符');
|
else if (value.length > 64) return Promise.reject('最多可输入64个字符');
|
||||||
// 编辑时不校验原本的编码
|
// 编辑时不校验原本的编码
|
||||||
else if (routeParams.id && value === form.sourceCode) return Promise.resolve('');
|
else if (routeParams.id && value === form.sourceCode)
|
||||||
|
return Promise.resolve('');
|
||||||
else {
|
else {
|
||||||
const resp: any = await validCode_api({
|
const resp: any = await validCode_api({
|
||||||
code: value,
|
code: value,
|
||||||
|
@ -372,6 +405,13 @@ type assetType = {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => form.data.icon,
|
||||||
|
() => {
|
||||||
|
basicFormRef.value?.validate();
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -32,9 +32,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template #createTime="slotProps">
|
<template #createTime="slotProps">
|
||||||
{{
|
{{
|
||||||
moment(slotProps.createTime).format(
|
dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)
|
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
<template #action="slotProps">
|
<template #action="slotProps">
|
||||||
|
@ -81,7 +79,7 @@ import PermissionButton from '@/components/PermissionButton/index.vue';
|
||||||
|
|
||||||
import { getMenuTree_api, delMenuInfo_api } from '@/api/system/menu';
|
import { getMenuTree_api, delMenuInfo_api } from '@/api/system/menu';
|
||||||
import { message } from 'jetlinks-ui-components';
|
import { message } from 'jetlinks-ui-components';
|
||||||
import moment from 'moment';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
const permission = 'system/Menu';
|
const permission = 'system/Menu';
|
||||||
|
|
||||||
|
@ -143,6 +141,7 @@ const columns = [
|
||||||
type: 'date',
|
type: 'date',
|
||||||
},
|
},
|
||||||
width: 180,
|
width: 180,
|
||||||
|
scopedSlots: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
|
|
@ -13,7 +13,14 @@
|
||||||
:request="getPermission_api"
|
:request="getPermission_api"
|
||||||
model="TABLE"
|
model="TABLE"
|
||||||
:params="queryParams"
|
:params="queryParams"
|
||||||
:defaultParams="{ sorts: [{ name: 'id', order: 'asc' }] }"
|
:defaultParams="{
|
||||||
|
pageSize: 10,
|
||||||
|
sorts: [{ name: 'id', order: 'asc' }],
|
||||||
|
}"
|
||||||
|
:pagination="{
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100'],
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
:dataSource="paramsTable"
|
:dataSource="paramsTable"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
size="small"
|
size="small"
|
||||||
|
bordered
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record, index }">
|
<template #bodyCell="{ column, record, index }">
|
||||||
<template v-if="column.key === 'name'">
|
<template v-if="column.key === 'name'">
|
||||||
|
@ -65,8 +66,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'action'">
|
<template v-else-if="column.key === 'action'">
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
type="link"
|
type="text"
|
||||||
:hasPermission="`{permission}:delete`"
|
|
||||||
:popConfirm="{
|
:popConfirm="{
|
||||||
title: `确定删除`,
|
title: `确定删除`,
|
||||||
onConfirm: () =>
|
onConfirm: () =>
|
||||||
|
@ -80,16 +80,35 @@
|
||||||
</j-table>
|
</j-table>
|
||||||
</j-form>
|
</j-form>
|
||||||
|
|
||||||
<j-pagination
|
<div
|
||||||
:pageSize="requestBody.pageSize"
|
class="pager"
|
||||||
v-model:current="requestBody.pageNum"
|
v-if="
|
||||||
:total="requestBody.params.paramsTable.length"
|
requestBody.params.paramsTable.length &&
|
||||||
hideOnSinglePage
|
requestBody.pageSize
|
||||||
style="text-align: center"
|
"
|
||||||
/>
|
>
|
||||||
|
<j-select
|
||||||
|
v-model:value="requestBody.pageNum"
|
||||||
|
style="width: 60px"
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
v-for="(val, i) in pageArr"
|
||||||
|
:value="i + 1"
|
||||||
|
>{{ i + 1 }}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
<j-pagination
|
||||||
|
:pageSize="requestBody.pageSize"
|
||||||
|
v-model:current="requestBody.pageNum"
|
||||||
|
:total="requestBody.params.paramsTable.length"
|
||||||
|
hideOnSinglePage
|
||||||
|
style="text-align: center"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<j-button
|
<j-button
|
||||||
|
type="dashed"
|
||||||
@click="requestBody.addRow"
|
@click="requestBody.addRow"
|
||||||
style="width: 100%; text-align: center"
|
style="width: 100%; text-align: center; margin-top: 5px"
|
||||||
>
|
>
|
||||||
<AIcon type="PlusOutlined" />新增
|
<AIcon type="PlusOutlined" />新增
|
||||||
</j-button>
|
</j-button>
|
||||||
|
@ -250,6 +269,12 @@ type requestObj = {
|
||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
|
const pageArr = computed(() => {
|
||||||
|
const maxPageNum = Math.ceil(
|
||||||
|
requestBody.params.paramsTable.length / requestBody.pageSize,
|
||||||
|
);
|
||||||
|
return new Array(maxPageNum).fill(1);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -305,10 +330,25 @@ type requestObj = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.table {
|
.table {
|
||||||
|
margin-bottom: 22px;
|
||||||
:deep(.ant-table-cell) {
|
:deep(.ant-table-cell) {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
}
|
}
|
||||||
|
.pager {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 8px 0;
|
||||||
|
.ant-pagination {
|
||||||
|
margin-left: 8px;
|
||||||
|
:deep(.ant-pagination-item) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.ant-form-item) {
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,9 +77,12 @@ const rowSelection = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onChange: (keys: string[]) => {
|
||||||
|
rowSelection.selectedRowKeys.value = keys;
|
||||||
|
},
|
||||||
selectedRowKeys: ref<string[]>([]),
|
selectedRowKeys: ref<string[]>([]),
|
||||||
};
|
};
|
||||||
const save = () => {
|
const save = async () => {
|
||||||
const keys = props.selectedRowKeys;
|
const keys = props.selectedRowKeys;
|
||||||
|
|
||||||
const removeKeys = props.sourceKeys.filter((key) => !keys.includes(key));
|
const removeKeys = props.sourceKeys.filter((key) => !keys.includes(key));
|
||||||
|
@ -87,13 +90,20 @@ const save = () => {
|
||||||
|
|
||||||
if (props.mode === 'api') {
|
if (props.mode === 'api') {
|
||||||
// 此时是api配置
|
// 此时是api配置
|
||||||
removeKeys.length &&
|
// removeKeys.length &&
|
||||||
delOperations_api(removeKeys)
|
// delOperations_api(removeKeys)
|
||||||
.finally(() => addOperations_api(addKeys))
|
// .finally(() => addOperations_api(addKeys))
|
||||||
.then(() => {
|
// .then(() => {
|
||||||
message.success('操作成功');
|
// message.success('操作成功');
|
||||||
emits('refresh')
|
// emits('refresh');
|
||||||
});
|
// });
|
||||||
|
// fix: bug#10829
|
||||||
|
removeKeys.length && (await delOperations_api(removeKeys));
|
||||||
|
const res = await addOperations_api(addKeys);
|
||||||
|
if (res.success) {
|
||||||
|
message.success('操作成功');
|
||||||
|
emits('refresh');
|
||||||
|
}
|
||||||
} else if (props.mode === 'appManger') {
|
} else if (props.mode === 'appManger') {
|
||||||
const removeItems = removeKeys.map((key) => ({
|
const removeItems = removeKeys.map((key) => ({
|
||||||
id: key,
|
id: key,
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
<template>
|
<template>
|
||||||
<j-tree
|
<j-spin :spinning="spinning">
|
||||||
:tree-data="treeData"
|
<template #indicator>
|
||||||
@select="clickSelectItem"
|
<AIcon type="LoadingOutlined" />
|
||||||
v-model:selected-keys="selectedKeys"
|
|
||||||
showLine
|
|
||||||
class="left-tree-container"
|
|
||||||
>
|
|
||||||
<template #title="{ name }">
|
|
||||||
{{ name }}
|
|
||||||
</template>
|
</template>
|
||||||
</j-tree>
|
<j-tree
|
||||||
|
:tree-data="treeData"
|
||||||
|
@select="clickSelectItem"
|
||||||
|
v-model:selected-keys="selectedKeys"
|
||||||
|
showLine
|
||||||
|
class="left-tree-container"
|
||||||
|
>
|
||||||
|
<template #title="{ name }">
|
||||||
|
{{ name }}
|
||||||
|
</template>
|
||||||
|
</j-tree>
|
||||||
|
</j-spin>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -32,8 +37,10 @@ const props = defineProps<{
|
||||||
|
|
||||||
const treeData = ref<TreeProps['treeData']>([]);
|
const treeData = ref<TreeProps['treeData']>([]);
|
||||||
const selectedKeys = ref<string[]>([]);
|
const selectedKeys = ref<string[]>([]);
|
||||||
|
const spinning = ref(false);
|
||||||
const getTreeData = () => {
|
const getTreeData = () => {
|
||||||
let tree: treeNodeTpye[] = [];
|
let tree: treeNodeTpye[] = [];
|
||||||
|
spinning.value = true;
|
||||||
getTreeOne_api().then((resp: any) => {
|
getTreeOne_api().then((resp: any) => {
|
||||||
tree = resp.urls.map((item: any) => ({
|
tree = resp.urls.map((item: any) => ({
|
||||||
...item,
|
...item,
|
||||||
|
@ -44,32 +51,36 @@ const getTreeData = () => {
|
||||||
if (props.mode === 'appManger') allPromise.push(apiOperations_api());
|
if (props.mode === 'appManger') allPromise.push(apiOperations_api());
|
||||||
else if (props.mode === 'home')
|
else if (props.mode === 'home')
|
||||||
allPromise.push(getApiGranted_api(props.code as string));
|
allPromise.push(getApiGranted_api(props.code as string));
|
||||||
Promise.all(allPromise).then((values) => {
|
Promise.all(allPromise)
|
||||||
values.forEach((item: any, i) => {
|
.then((values) => {
|
||||||
if (props.mode === 'api') {
|
values.forEach((item: any, i) => {
|
||||||
tree[i].schemas = item.components.schemas;
|
if (props.mode === 'api') {
|
||||||
tree[i].children = combData(item.paths);
|
tree[i].schemas = item.components.schemas;
|
||||||
} else if (i < values.length - 2) {
|
tree[i].children = combData(item.paths);
|
||||||
const paths = filterPath(
|
} else if (i < values.length - 2) {
|
||||||
item.paths,
|
const paths = filterPath(
|
||||||
values[values.length - 1].result as string[],
|
item.paths,
|
||||||
);
|
values[values.length - 1].result as string[],
|
||||||
tree[i].children = combData(paths);
|
);
|
||||||
tree[i].schemas = item.components.schemas;
|
tree[i].children = combData(paths);
|
||||||
}
|
tree[i].schemas = item.components.schemas;
|
||||||
});
|
}
|
||||||
if (props.hasHome) {
|
|
||||||
tree.unshift({
|
|
||||||
key: 'home',
|
|
||||||
name: '首页',
|
|
||||||
schemas: {},
|
|
||||||
children: [],
|
|
||||||
});
|
});
|
||||||
selectedKeys.value = ['home'];
|
if (props.hasHome) {
|
||||||
}
|
tree.unshift({
|
||||||
|
key: 'home',
|
||||||
|
name: '首页',
|
||||||
|
schemas: {},
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
selectedKeys.value = ['home'];
|
||||||
|
}
|
||||||
|
|
||||||
treeData.value = tree;
|
treeData.value = tree;
|
||||||
});
|
})
|
||||||
|
.finally(() => {
|
||||||
|
spinning.value = false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const clickSelectItem: TreeProps['onSelect'] = (key: any[], node: any) => {
|
const clickSelectItem: TreeProps['onSelect'] = (key: any[], node: any) => {
|
||||||
|
|
|
@ -49,13 +49,14 @@
|
||||||
<j-select
|
<j-select
|
||||||
v-model:value="form.data.objectType"
|
v-model:value="form.data.objectType"
|
||||||
:disabled="!!form.data.id"
|
:disabled="!!form.data.id"
|
||||||
@change="() => (form.data.targetType = undefined)"
|
@change="form.handleObjectTypeChange"
|
||||||
|
placeholder="请选择关联方"
|
||||||
>
|
>
|
||||||
<j-select-option
|
<j-select-option
|
||||||
v-for="item in form.objectList"
|
v-for="item in form.objectList"
|
||||||
:value="item.id"
|
:value="item.id"
|
||||||
>
|
>
|
||||||
{{ item.name }}.
|
{{ item.name }}
|
||||||
</j-select-option>
|
</j-select-option>
|
||||||
</j-select>
|
</j-select>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
@ -69,6 +70,8 @@
|
||||||
<j-select
|
<j-select
|
||||||
v-model:value="form.data.targetType"
|
v-model:value="form.data.targetType"
|
||||||
:disabled="!!form.data.id"
|
:disabled="!!form.data.id"
|
||||||
|
@change="form.rules.checkUnique"
|
||||||
|
placeholder="请选择关联方"
|
||||||
>
|
>
|
||||||
<j-select-option
|
<j-select-option
|
||||||
v-for="item in targetList"
|
v-for="item in targetList"
|
||||||
|
@ -100,6 +103,7 @@ import {
|
||||||
getObjectList_api,
|
getObjectList_api,
|
||||||
addRelation_api,
|
addRelation_api,
|
||||||
editRelation_api,
|
editRelation_api,
|
||||||
|
validateField,
|
||||||
} from '@/api/system/relationship';
|
} from '@/api/system/relationship';
|
||||||
import { dictItemType } from '../../DataSource/typing';
|
import { dictItemType } from '../../DataSource/typing';
|
||||||
|
|
||||||
|
@ -130,15 +134,44 @@ const formRef = ref<FormInstance>();
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
data: props.data,
|
data: props.data,
|
||||||
rules: {
|
rules: {
|
||||||
checkRelation: (_rule: Rule, value: string): any => {
|
/**
|
||||||
if (!value) return Promise.reject('');
|
* 验证标识
|
||||||
else if (value.length > 64) return Promise.reject('');
|
* @param _rule
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
checkRelation: async (_rule: Rule, value: string) => {
|
||||||
const reg = new RegExp('^[0-9a-zA-Z_\\\\-]+$');
|
const reg = new RegExp('^[0-9a-zA-Z_\\\\-]+$');
|
||||||
|
if (!value) return Promise.reject('');
|
||||||
return reg.test(value)
|
if (!reg.test(value))
|
||||||
? Promise.resolve()
|
return Promise.reject(
|
||||||
: Promise.reject('标识只能由数字、字母、下划线、中划线组成');
|
'标识只能由数字、字母、下划线、中划线组成',
|
||||||
|
);
|
||||||
|
return form.rules.checkUnique();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 验证标识唯一性
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
checkUnique: () => {
|
||||||
|
if (
|
||||||
|
!form.data.relation ||
|
||||||
|
!form.data.objectType ||
|
||||||
|
!form.data.targetType
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const { result } = await validateField({
|
||||||
|
relation: form.data.relation,
|
||||||
|
objectType: form.data.objectType,
|
||||||
|
targetType: form.data.targetType,
|
||||||
|
});
|
||||||
|
result.passed ? resolve('') : reject(result.reason);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
handleObjectTypeChange: () => {
|
||||||
|
form.data.targetType = undefined;
|
||||||
|
form.rules.checkUnique();
|
||||||
},
|
},
|
||||||
objectList: [] as any[],
|
objectList: [] as any[],
|
||||||
|
|
||||||
|
@ -169,7 +202,7 @@ form.getObjectList();
|
||||||
type formType = {
|
type formType = {
|
||||||
name: string;
|
name: string;
|
||||||
relation: string;
|
relation: string;
|
||||||
objectType: string;
|
objectType: string | undefined;
|
||||||
targetType: string | undefined;
|
targetType: string | undefined;
|
||||||
description: string;
|
description: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
|
|
|
@ -14,8 +14,13 @@
|
||||||
model="TABLE"
|
model="TABLE"
|
||||||
:params="queryParams"
|
:params="queryParams"
|
||||||
:defaultParams="{
|
:defaultParams="{
|
||||||
|
pageSize: 10,
|
||||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
}"
|
}"
|
||||||
|
:pagination="{
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100'],
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
|
|
@ -78,12 +78,16 @@ const form = reactive({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
clickSave: () => {
|
clickSave: () => {
|
||||||
const updateRole = updateRole_api(form.data);
|
formRef.value?.validate().then(() => {
|
||||||
const updateTree = updatePrimissTree_api(roleId, { menus: form.menus });
|
const updateRole = updateRole_api(form.data);
|
||||||
|
const updateTree = updatePrimissTree_api(roleId, {
|
||||||
|
menus: form.menus,
|
||||||
|
});
|
||||||
|
|
||||||
Promise.all([updateRole, updateTree]).then((resp) => {
|
Promise.all([updateRole, updateTree]).then((resp) => {
|
||||||
message.success('操作成功');
|
message.success('操作成功');
|
||||||
router.push('/system/Role');
|
router.push('/system/Role');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -123,7 +127,7 @@ form.getForm();
|
||||||
:deep(.ant-form-item-required) {
|
:deep(.ant-form-item-required) {
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
|
|
||||||
&::before{
|
&::before {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,13 @@
|
||||||
}"
|
}"
|
||||||
@cancelSelect="selectedRowKeys = []"
|
@cancelSelect="selectedRowKeys = []"
|
||||||
size="small"
|
size="small"
|
||||||
|
:defaultParams="{
|
||||||
|
pageSize: 10,
|
||||||
|
}"
|
||||||
|
:pagination="{
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100'],
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<j-button type="primary" @click="dialogVisible = true">
|
<j-button type="primary" @click="dialogVisible = true">
|
||||||
|
@ -35,6 +42,9 @@
|
||||||
}"
|
}"
|
||||||
></BadgeStatus>
|
></BadgeStatus>
|
||||||
</template>
|
</template>
|
||||||
|
<template #createTime="slotProps">
|
||||||
|
{{ dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #action="slotProps">
|
<template #action="slotProps">
|
||||||
<j-space :size="16">
|
<j-space :size="16">
|
||||||
|
@ -66,6 +76,7 @@ import PermissionButton from '@/components/PermissionButton/index.vue';
|
||||||
import AddUserDialog from '../components/AddUserDialog.vue';
|
import AddUserDialog from '../components/AddUserDialog.vue';
|
||||||
import { getUserByRole_api, unbindUser_api } from '@/api/system/role';
|
import { getUserByRole_api, unbindUser_api } from '@/api/system/role';
|
||||||
import { message } from 'jetlinks-ui-components';
|
import { message } from 'jetlinks-ui-components';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
const roleId = useRoute().params.id as string;
|
const roleId = useRoute().params.id as string;
|
||||||
|
|
||||||
|
@ -93,6 +104,7 @@ const columns = [
|
||||||
search: {
|
search: {
|
||||||
type: 'date',
|
type: 'date',
|
||||||
},
|
},
|
||||||
|
scopedSlots: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
allow-clear
|
allow-clear
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
|
show-count
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-form>
|
</j-form>
|
||||||
|
|
|
@ -14,11 +14,16 @@
|
||||||
model="TABLE"
|
model="TABLE"
|
||||||
:params="queryParams"
|
:params="queryParams"
|
||||||
:defaultParams="{
|
:defaultParams="{
|
||||||
|
pageSize: 10,
|
||||||
sorts: [
|
sorts: [
|
||||||
{ name: 'createTime', order: 'desc' },
|
{ name: 'createTime', order: 'desc' },
|
||||||
{ name: 'id', order: 'desc' },
|
{ name: 'id', order: 'desc' },
|
||||||
],
|
],
|
||||||
}"
|
}"
|
||||||
|
:pagination="{
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100'],
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
@ -99,7 +104,7 @@ const columns = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '描述',
|
title: '说明',
|
||||||
key: 'description',
|
key: 'description',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
dataIndex: 'description',
|
dataIndex: 'description',
|
||||||
|
|
|
@ -93,7 +93,7 @@ export default defineConfig(({ mode}) => {
|
||||||
// target: 'http://192.168.33.22:8800',
|
// target: 'http://192.168.33.22:8800',
|
||||||
// target: 'http://192.168.32.244:8881',
|
// target: 'http://192.168.32.244:8881',
|
||||||
target: 'http://120.77.179.54:8844', // 120测试
|
target: 'http://120.77.179.54:8844', // 120测试
|
||||||
// target: 'http://192.168.33.46:8844', // 本地开发环境
|
// target: 'http://192.168.33.46:8844', // 本地开发环境
|
||||||
ws: 'ws://192.168.33.46:8844',
|
ws: 'ws://192.168.33.46:8844',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, '')
|
rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
|
|
|
@ -3700,8 +3700,8 @@ jetlinks-store@^0.0.3:
|
||||||
|
|
||||||
jetlinks-ui-components@^1.0.5:
|
jetlinks-ui-components@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#77bd58156212d793fdebe41fc8864eeed5db7182"
|
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#8cb5c9e68e46e6e7eebc0d96b1cdaab24828779f"
|
||||||
integrity sha512-VXuCMJlMV/bbmBhPtBzY/BUBIvGebQbguLPE06xps79i5Pjq46+HBW8VPsJ9MwvyMhYkhzPlQJu9Ft7v5uo+yA==
|
integrity sha512-yIbmplK+twekevr7n+dGMvO8tvyIqguC60TWeJCmx2mUqpwv8dEnr/cwwpJee4PBLWohvGPywsYgmm7KxVBbcw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/core" "^9.12.0"
|
"@vueuse/core" "^9.12.0"
|
||||||
ant-design-vue "^3.2.15"
|
ant-design-vue "^3.2.15"
|
||||||
|
|
Loading…
Reference in New Issue