fix: bug#16459、16434、16453、16452、10936
* fix: bug#16459、16434、16453、16452 * feat: 数据解析添加代码提示 * fix: bug#16451 * fix: 修改子设备绑定 * fix: 北向输出bug修复 * fix: 修改北向输出 * fix: 兼容物模型旧版数据 * fix: 修改订阅通知样式 * fix: 优化物模型规则窗口长度 * fix: 修改告警配置 * fix: providerName * fix: bug#10936 * feat: docker:2.1.0-SNAPSHOT
This commit is contained in:
parent
7a8848360c
commit
9170030d25
4
build.sh
4
build.sh
|
@ -1,3 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
docker build -t registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.1.0-TEST .
|
||||
docker push registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.1.0-TEST
|
||||
docker build -t registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.1.0-SNAPSHOT .
|
||||
docker push registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.1.0-SNAPSHOT
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"event-source-polyfill": "^1.0.31",
|
||||
"global": "^4.4.0",
|
||||
"jetlinks-store": "^0.0.3",
|
||||
"jetlinks-ui-components": "^1.0.24",
|
||||
"jetlinks-ui-components": "^1.0.25",
|
||||
"js-cookie": "^3.0.1",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"less": "^4.1.3",
|
||||
|
|
|
@ -607,3 +607,6 @@ export const saveDeviceVirtualProperty = (productId: string, deviceId: string, d
|
|||
export const queryDeviceVirtualProperty = (productId: string, deviceId: string, propertyId: string) => server.get(`/virtual/property/device/${productId}/${deviceId}/${propertyId}`)
|
||||
|
||||
export const queryByParent = (deviceId: string) => server.get(`/device/gateway/${deviceId}/parent`)
|
||||
|
||||
export const queryCodeTips = (productId: string, deviceId: string) => server.get(`/device/transparent-codec/${productId}/${deviceId}.d.ts`)
|
||||
export const queryProductCodeTips = (productId: string) => server.get(`/device/transparent-codec/${productId}.d.ts`)
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
<div class="box-item" v-for="item in getData" :key="item.id">
|
||||
<slot name="card" v-bind="item"></slot>
|
||||
</div>
|
||||
<div class="box-item">
|
||||
<slot name="add"></slot>
|
||||
</div>
|
||||
<div class="box-btn" v-if="(pageIndex + 1) * showLength < data.length">
|
||||
<div class="box-item-action" @click="onRight">
|
||||
<AIcon type="RightOutlined" />
|
||||
|
@ -63,14 +60,13 @@ const onLeft = () => {
|
|||
.box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 5px 0;
|
||||
margin: 8px 0;
|
||||
.box-item {
|
||||
margin: 0 6px;
|
||||
max-width: 48px;
|
||||
margin: 0 12px;
|
||||
max-width: 60px;
|
||||
}
|
||||
|
||||
.box-btn {
|
||||
margin-right: 12px;
|
||||
.box-item-action {
|
||||
width: 12px;
|
||||
background-color: #F7F8FA;
|
||||
|
@ -79,6 +75,7 @@ const onLeft = () => {
|
|||
font-size: 12px;
|
||||
color: #666666;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: #EFF2FE;
|
||||
color: @primary-color;
|
||||
|
|
|
@ -617,7 +617,9 @@ const onPlatError = (val: any) => {
|
|||
const _validator = (_rule: any, value: string): Promise<any> =>
|
||||
new Promise((resolve, reject) => {
|
||||
const _item = productList.value.find((item) => item.id === value);
|
||||
if (!_item) {
|
||||
if(!modelRef.id || modelRef.id === ':id') {
|
||||
return resolve('');
|
||||
} else if (!_item && value) {
|
||||
return reject('关联产品已被删除,请重新选择');
|
||||
}
|
||||
return resolve('');
|
||||
|
|
|
@ -779,18 +779,19 @@ const onActiveProduct = () => {
|
|||
const _validator = (_rule: any, value: string): Promise<any> =>
|
||||
new Promise((resolve, reject) => {
|
||||
const _item = productList.value.find((item) => item.id === value);
|
||||
if (!_item) {
|
||||
if(!modelRef.id || modelRef.id === ':id') {
|
||||
return resolve('');
|
||||
} else if (!_item && value) {
|
||||
productChange(value);
|
||||
return reject('关联产品已被删除,请重新选择');
|
||||
} else {
|
||||
if (!_item?.state) {
|
||||
_error.value = `当前选择的${_item.name}产品为禁用状态`;
|
||||
// return reject(`当前选择的${_item.name}产品为禁用状态`)
|
||||
} else {
|
||||
_error.value = '';
|
||||
}
|
||||
}
|
||||
return resolve('');
|
||||
}
|
||||
});
|
||||
|
||||
const saveBtn = async () => {
|
||||
|
|
|
@ -105,7 +105,7 @@ const handleSearch = async () => {
|
|||
);
|
||||
});
|
||||
if (_item) {
|
||||
info.value = _item?.providerName
|
||||
info.value = _item?.providerName || _item?.thirdPartyUserId
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -147,15 +147,19 @@ const onSave = (dt: any) => {
|
|||
|
||||
<style lang="less" scoped>
|
||||
.child-item {
|
||||
padding: 5px 20px 0 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-shadow: 0px 1px 0px 0px #e2e2e2;
|
||||
height: 68px;
|
||||
background: linear-gradient(270deg, #ffffff 0%, #f1f6ff 99%);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ebeef3;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.child-item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 24px;
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
|
@ -172,6 +176,7 @@ const onSave = (dt: any) => {
|
|||
|
||||
.child-item-right {
|
||||
display: flex;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -21,10 +21,9 @@
|
|||
<j-collapse-panel
|
||||
v-for="item in dataSource"
|
||||
:key="item.provider"
|
||||
class="custom"
|
||||
:header="item.name"
|
||||
>
|
||||
<div class="child">
|
||||
<div>
|
||||
<template
|
||||
v-for="child in item.children"
|
||||
:key="child.id"
|
||||
|
@ -110,26 +109,32 @@ onMounted(() => {
|
|||
|
||||
<style lang="less" scoped>
|
||||
.alert {
|
||||
height: 40px;
|
||||
padding-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
color: #999999;
|
||||
line-height: 40px;
|
||||
}
|
||||
.custom {
|
||||
background: #F7F8FA;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
color: #333333;
|
||||
}
|
||||
.child {
|
||||
background-color: white;
|
||||
padding-bottom: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.content-collapse {
|
||||
:deep(.ant-collapse-content > .ant-collapse-content-box) {
|
||||
:deep(.ant-collapse) {
|
||||
border-color: #EBEEF3;
|
||||
background-color: #fff;
|
||||
|
||||
.ant-collapse-item {
|
||||
border: 1px solid #EBEEF3;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.ant-collapse-header {
|
||||
background-color: #F7F8FA;
|
||||
height: 42px;
|
||||
}
|
||||
.ant-collapse-content {
|
||||
padding: 17px 21px 7px 21px;
|
||||
}
|
||||
|
||||
.ant-collapse-content-box {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -194,13 +194,22 @@ const handleOk = () => {
|
|||
if (instanceStore.current.accessProvider === 'official-edge-gateway') { // 网关设备
|
||||
queryDeviceMapping(instanceStore.current.id)
|
||||
.then(res => {
|
||||
const arr = bindDeviceRef.value?._dataSource.filter(item => {
|
||||
return !res.result?.[0]?.find(val => val.deviceId === item.id) && _selectedRowKeys.value.includes(item.id);
|
||||
}).map(item => {
|
||||
const arr = bindDeviceRef.value?._dataSource.filter((item: any) => {
|
||||
return _selectedRowKeys.value.includes(item.id);
|
||||
}).map((item: any) => {
|
||||
const _item = res.result?.[0]?.find((val: any) => val.deviceId === item.id)
|
||||
if(_item){
|
||||
return {
|
||||
id: _item.id,
|
||||
deviceId: _item.deviceId,
|
||||
deviceName: _item.deviceName
|
||||
}
|
||||
}else {
|
||||
return {
|
||||
deviceId: item.id,
|
||||
deviceName: item.name
|
||||
}
|
||||
}
|
||||
})
|
||||
return saveDeviceMapping(instanceStore.current.id, {info: arr})
|
||||
}).then(res => {
|
||||
|
|
|
@ -11,35 +11,27 @@
|
|||
编辑
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<j-descriptions-item label="设备ID">{{
|
||||
instanceStore.current?.id
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item v-if='instanceStore.current?.accessProvider === "plugin_gateway"'>
|
||||
<template #label>
|
||||
<div>
|
||||
第三方系统设备ID
|
||||
<j-descriptions-item label="设备ID">
|
||||
<div style="display: flex">
|
||||
<div style="flex: 1">
|
||||
<j-ellipsis> {{ instanceStore.current?.id }} </j-ellipsis>
|
||||
</div>
|
||||
<div v-if='instanceStore.current?.accessProvider === "plugin_gateway"'>
|
||||
<j-tooltip>
|
||||
<template #title>
|
||||
<p>通过调用SDK或HTTP请求的方式接入第三方系统设备数据时,第三方系统与平台当前设备对应的设备ID。</p>
|
||||
如双方ID值一致,则无需填写
|
||||
</template>
|
||||
<a-icon type='QuestionCircleOutlined' />
|
||||
<a v-if="!inklingDeviceId" type='link' @click='giveAnInkling'>
|
||||
未映射
|
||||
</a>
|
||||
<a v-else type='link' @click='inkingVisible = true'>
|
||||
已映射
|
||||
</a>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<j-button v-if='!inklingDeviceId' type="link" @click='giveAnInkling'>映射</j-button>
|
||||
<div v-else style='display: flex;justify-content: space-between;align-items: center;'>
|
||||
<div style='flex: 1 1 auto;'>
|
||||
<j-ellipsis>{{ inklingDeviceId }}</j-ellipsis>
|
||||
</div>
|
||||
<j-button type='link'>
|
||||
<a-icon
|
||||
type='EditOutlined'
|
||||
@click='inkingVisible = true'
|
||||
/>
|
||||
</j-button>
|
||||
</div>
|
||||
</j-descriptions-item>
|
||||
<j-descriptions-item label="产品名称">{{
|
||||
instanceStore.current?.productName
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
style="height: 100%"
|
||||
theme="vs"
|
||||
v-model:modelValue="editorValue"
|
||||
:registrationTypescript="typescriptTip"
|
||||
/>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
|
@ -155,7 +156,7 @@ import {
|
|||
getProtocal,
|
||||
testCode,
|
||||
saveDeviceCode,
|
||||
delDeviceCode,
|
||||
delDeviceCode, queryCodeTips, queryProductCodeTips,
|
||||
} from '@/api/device/instance';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { isBoolean } from 'lodash';
|
||||
|
@ -179,6 +180,11 @@ const loading = ref<boolean>(false);
|
|||
const isTest = ref<boolean>(false);
|
||||
const editorValue = ref<string>('');
|
||||
|
||||
const typescriptTip = reactive({
|
||||
typescript: ''
|
||||
})
|
||||
|
||||
|
||||
const color = computed(() => ({
|
||||
color: readOnly.value ? '#415ed1' : '#a6a6a6',
|
||||
}));
|
||||
|
@ -228,12 +234,24 @@ const getTopic = async () => {
|
|||
topicList.value = item;
|
||||
}
|
||||
};
|
||||
|
||||
const queryCode = () => {
|
||||
queryCodeTips(instanceStore.current.productId,
|
||||
instanceStore.current.id,).then(res => {
|
||||
if (res.success) {
|
||||
typescriptTip.typescript = res.result
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//获取设备解析规则
|
||||
const getDeviceCode = async () => {
|
||||
const res: any = await deviceCode(
|
||||
instanceStore.current.productId,
|
||||
instanceStore.current.id,
|
||||
);
|
||||
|
||||
|
||||
if (res.status === 200) {
|
||||
const item = res.result?.configuration?.script
|
||||
? res.result?.configuration?.script
|
||||
|
@ -261,6 +279,7 @@ const test = async (dataTest: any) => {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//保存设备解析规则
|
||||
const save = async () => {
|
||||
const item = {
|
||||
|
@ -328,6 +347,7 @@ watch(() => instanceStore.current?.id, () => {
|
|||
if (instanceStore.current?.id) {
|
||||
getDeviceCode();
|
||||
getTopic();
|
||||
queryCode()
|
||||
}
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
style="height: 100%"
|
||||
theme="vs"
|
||||
v-model:modelValue="editorValue"
|
||||
:registrationTypescript="typescriptTip"
|
||||
/>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
|
@ -115,7 +116,7 @@ import {
|
|||
productCode,
|
||||
getProtocal,
|
||||
testCode,
|
||||
saveProductCode,
|
||||
saveProductCode, queryProductCodeTips,
|
||||
} from '@/api/device/instance';
|
||||
import { isBoolean } from 'lodash';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
|
@ -135,6 +136,9 @@ const resultValue = ref<any>({});
|
|||
const loading = ref<boolean>(false);
|
||||
const isTest = ref<boolean>(false);
|
||||
const editorValue = ref<string>('');
|
||||
const typescriptTip = reactive({
|
||||
typescript: ''
|
||||
})
|
||||
|
||||
const resStyle = computed(() =>
|
||||
isBoolean(resultValue.value.success)
|
||||
|
@ -168,6 +172,16 @@ const getTopic = async () => {
|
|||
topicList.value = item;
|
||||
}
|
||||
};
|
||||
|
||||
const queryCodeTips = () => {
|
||||
queryProductCodeTips(productStore.current.id).then(res => {
|
||||
if (res.success) {
|
||||
typescriptTip.typescript = res.result
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//获取产品解析规则
|
||||
const getProductCode = async () => {
|
||||
const res: any = await productCode(productStore.current.id);
|
||||
|
@ -248,6 +262,7 @@ const debug = () => {
|
|||
onMounted(() => {
|
||||
getProductCode();
|
||||
getTopic();
|
||||
queryCodeTips()
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -395,19 +395,22 @@ const handleSaveClick = async (next?: Function) => {
|
|||
const virtual: any[] = [];
|
||||
const arr = resp.map((item: any) => {
|
||||
if(item.expands?.virtualRule) {
|
||||
const triggerProperties = item.expands.virtualRule.triggerProperties
|
||||
const rule = omit(item.expands.virtualRule, ['triggerProperties'])
|
||||
virtual.push({
|
||||
...item.expands.virtualRule,
|
||||
triggerProperties,
|
||||
rule,
|
||||
type: rule.type,
|
||||
propertyId: item.id
|
||||
})
|
||||
}
|
||||
// return {
|
||||
// ...item,
|
||||
// expands: {
|
||||
// ...item.expands,
|
||||
// virtualRule: undefined
|
||||
// }
|
||||
// }
|
||||
return item
|
||||
return {
|
||||
...item,
|
||||
expands: {
|
||||
...omit(item.expands, ['virtualRule'])
|
||||
}
|
||||
}
|
||||
// return item
|
||||
})
|
||||
// 保存规则
|
||||
if(virtual.length) {
|
||||
|
|
|
@ -433,26 +433,46 @@ export const useColumns = (type?: MetadataType, target?: 'device' | 'product', n
|
|||
required: true,
|
||||
rules: target !== 'device' ? [
|
||||
{
|
||||
validator: async (_: Record<string, any>, value: any) => {
|
||||
callback: async (rule: any, value: any, dataSource: any[]) => {
|
||||
console.log('value', value)
|
||||
if (value.source) {
|
||||
if(value.source !== 'rule') {
|
||||
if(value.type?.length) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
const field = rule.field.split('.')
|
||||
const fieldIndex = Number(field[1])
|
||||
|
||||
const values = dataSource.find((item, index) => index === fieldIndex)
|
||||
const virtualRule = values.elements?.virtualRule
|
||||
const source = value.source
|
||||
const ids = (noEdit?.value?.id || []) as any[]
|
||||
|
||||
if (source) {
|
||||
if (source !== 'rule' && !value.type?.length) {
|
||||
return Promise.reject('请选择读写类型');
|
||||
}
|
||||
} else {
|
||||
if(value.virtualRule?.rule?.script) {
|
||||
return Promise.resolve();
|
||||
}else {
|
||||
} else if(!ids.includes(values.id) && virtualRule){
|
||||
return Promise.reject('请配置规则');
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
} else {
|
||||
|
||||
return Promise.reject('请选择属性来源');
|
||||
}
|
||||
}
|
||||
// if (value.source) {
|
||||
// if(value.source !== 'rule') {
|
||||
// if(value.type?.length) {
|
||||
// return Promise.resolve();
|
||||
// } else {
|
||||
// return Promise.reject('请选择读写类型');
|
||||
// }
|
||||
// } else {
|
||||
// if(value.virtualRule?.script) {
|
||||
// return Promise.resolve();
|
||||
// }else {
|
||||
// return Promise.reject('请配置规则');
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// return Promise.reject('请选择属性来源');
|
||||
// }
|
||||
// }
|
||||
},
|
||||
]: []
|
||||
},
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<template>
|
||||
<j-select
|
||||
v-model:value="myValue"
|
||||
:options="[
|
||||
{ label: '固定值', value: 'false' },
|
||||
{ label: '范围值', value: 'true' },
|
||||
]"
|
||||
@select="select"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script name="BooleanSelect" setup>
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['update:value'])
|
||||
|
||||
const myValue = ref()
|
||||
const select = (e) => {
|
||||
emit('update:value', {
|
||||
...props.value,
|
||||
range: e === 'true',
|
||||
value: e === 'true' ? [undefined, undefined] : undefined
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => JSON.stringify(props.value), () => {
|
||||
myValue.value = `${props.value?.range}`
|
||||
}, { immediate: true })
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -33,6 +33,7 @@
|
|||
import { defineExpose, provide } from 'vue'
|
||||
import MetricValueItem from './ValueItem.vue'
|
||||
import {validatorConfig} from "@/views/device/components/Metadata/Base/columns";
|
||||
import BooleanSelect from "@/views/device/components/Metadata/Base/components/Properties/Metrics/BooleanSelect.vue";
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
|
@ -107,7 +108,6 @@ const columns: any = [
|
|||
rules: [
|
||||
{
|
||||
validator(_: any, value: any) {
|
||||
console.log('指标配置', value)
|
||||
if (!value) {
|
||||
return Promise.reject('请配置指标')
|
||||
}
|
||||
|
@ -132,17 +132,11 @@ const newColumns = computed(() => {
|
|||
title: '指标值',
|
||||
dataIndex: 'range',
|
||||
width: 120,
|
||||
type: 'booleanSelect',
|
||||
type: 'components',
|
||||
components: {
|
||||
props: {
|
||||
trueText: '范围值',
|
||||
trueValue: true,
|
||||
falseText: '固定值',
|
||||
falseValue: false,
|
||||
}
|
||||
name: BooleanSelect
|
||||
}
|
||||
})
|
||||
console.log(data);
|
||||
return data
|
||||
}
|
||||
return columns
|
||||
|
|
|
@ -10,18 +10,18 @@
|
|||
>
|
||||
<template #content>
|
||||
<j-form ref="formRef" :model="formData">
|
||||
<j-form-item v-if="value.range === 'false'" name="value" :rule="[{ required: true, message: '请输入指标值'}]">
|
||||
<j-form-item v-if="value.range === false" :rules="[{ required: true, message: '请输入指标值'}]" name="value">
|
||||
<Item v-model:value="formData.value" />
|
||||
</j-form-item>
|
||||
<div v-else class="data-table-boolean-item">
|
||||
<div class="data-table-boolean-item--value">
|
||||
<j-form-item :name="['rangeValue', 0]" :rule="[{ required: true, message: '请输入指标值'}]">
|
||||
<j-form-item :name="['rangeValue', 0]" :rules="[{ required: true, message: '请输入指标值'}]">
|
||||
<Item v-model:value="formData.rangeValue[0]" />
|
||||
</j-form-item>
|
||||
</div>
|
||||
<div>-</div>
|
||||
<div class="data-table-boolean-item--value">
|
||||
<j-form-item :name="['rangeValue', 1]" :rule="[{ required: true, message: '请输入指标值'}]">
|
||||
<j-form-item :name="['rangeValue', 1]" :rules="[{ required: true, message: '请输入指标值'}, { validator: validator}]">
|
||||
<Item v-model:value="formData.rangeValue[1]" />
|
||||
</j-form-item>
|
||||
</div>
|
||||
|
@ -38,6 +38,7 @@ import { reactive } from 'vue';
|
|||
import type { PropType } from 'vue';
|
||||
import Item from './item.vue'
|
||||
import {Form} from "jetlinks-ui-components";
|
||||
import {cloneDeep} from "lodash";
|
||||
|
||||
type ValueType = number | Array<number | undefined> | undefined;
|
||||
|
||||
|
@ -56,13 +57,14 @@ const emit = defineEmits<Emit>();
|
|||
const formItemContext = Form.useInjectFormItemContext();
|
||||
|
||||
|
||||
|
||||
const formData = reactive<{
|
||||
value: ValueType;
|
||||
rangeValue: ValueType;
|
||||
}>({
|
||||
value: props.value?.range === false ? props.value?.value : undefined,
|
||||
rangeValue: props.value?.range === true
|
||||
? props.value?.value || [undefined, undefined]
|
||||
? cloneDeep(props.value?.value) || [undefined, undefined]
|
||||
: [undefined, undefined],
|
||||
});
|
||||
|
||||
|
@ -76,6 +78,13 @@ const showText = computed(() => {
|
|||
}
|
||||
})
|
||||
|
||||
const validator = (_: any, value: any) => {
|
||||
if (props.value.range && formData.rangeValue![0] >= formData.rangeValue![1]) {
|
||||
return Promise.reject('需大于左侧数值')
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const confirm = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
formRef.value.validate().then(() => {
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
v-else-if="['int', 'long', 'float', 'double'].includes(type)"
|
||||
v-model:value="myValue"
|
||||
:precision="0"
|
||||
:max="2147483647"
|
||||
:min="-2147483647"
|
||||
style="width: 100%"
|
||||
placeholder="请输入"
|
||||
@change="change"
|
||||
|
@ -31,6 +33,7 @@
|
|||
/>
|
||||
</template>
|
||||
<script setup name="MetricValueItem">
|
||||
import { Form } from 'jetlinks-ui-components'
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
|
@ -40,11 +43,13 @@ const props = defineProps({
|
|||
})
|
||||
|
||||
const emit = defineEmits(['update:value'])
|
||||
const formItemContext = Form.useInjectFormItemContext();
|
||||
|
||||
const type = inject('metricsType')
|
||||
const myValue = ref(props.value)
|
||||
|
||||
const change = () => {
|
||||
// formItemContext.onFieldChange()
|
||||
emit('update:value', myValue.value)
|
||||
}
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@
|
|||
required
|
||||
>
|
||||
<Rule
|
||||
v-model:value="formData.virtualRule.rule.script"
|
||||
:virtualRule="_virtualRule.virtualRule.rule"
|
||||
v-model:value="formData.virtualRule.script"
|
||||
:virtualRule="_virtualRule.virtualRule"
|
||||
:id="value.id"
|
||||
:aggList="aggList"
|
||||
/>
|
||||
|
@ -67,7 +67,7 @@
|
|||
required
|
||||
>
|
||||
<j-select
|
||||
v-model:value="formData.virtualRule.rule.windowType"
|
||||
v-model:value="formData.virtualRule.windowType"
|
||||
:options="[
|
||||
{ label: '无', value: 'undefined' },
|
||||
{ label: '时间窗口', value: 'time' },
|
||||
|
@ -79,26 +79,26 @@
|
|||
/>
|
||||
</j-form-item>
|
||||
<template
|
||||
v-if="formData.virtualRule?.rule?.windowType !== 'undefined'"
|
||||
v-if="formData.virtualRule?.windowType !== 'undefined'"
|
||||
>
|
||||
<j-form-item
|
||||
label="聚合函数"
|
||||
:name="['virtualRule', 'rule', 'aggType']"
|
||||
:name="['virtualRule', 'aggType']"
|
||||
required
|
||||
>
|
||||
<j-select
|
||||
v-model:value="formData.virtualRule.rule.aggType"
|
||||
v-model:value="formData.virtualRule.aggType"
|
||||
:options="aggList"
|
||||
placeholder="请选择聚合函数"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
:label="
|
||||
formData.virtualRule?.rule?.windowType === 'time'
|
||||
formData.virtualRule?.windowType === 'time'
|
||||
? '窗口长度(s)'
|
||||
: '窗口长度(次)'
|
||||
"
|
||||
:name="['virtualRule', 'rule', 'window', 'span']"
|
||||
:name="['virtualRule', 'window', 'span']"
|
||||
required
|
||||
:rules="[
|
||||
{
|
||||
|
@ -112,20 +112,20 @@
|
|||
]"
|
||||
>
|
||||
<j-input-number
|
||||
v-model:value="formData.virtualRule.rule.window.span"
|
||||
placeholder="请输入窗口长度"
|
||||
style="width: 100%"
|
||||
v-model:value="formData.virtualRule.window.span"
|
||||
:max="999999"
|
||||
:min="1"
|
||||
placeholder="请输入窗口长度"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
:label="
|
||||
formData.virtualRule?.rule?.windowType === 'time'
|
||||
formData.virtualRule?.windowType === 'time'
|
||||
? '步长(s)'
|
||||
: '步长(次)'
|
||||
"
|
||||
:name="['virtualRule', 'rule', 'window', 'every']"
|
||||
:name="['virtualRule', 'window', 'every']"
|
||||
required
|
||||
:rules="[
|
||||
{
|
||||
|
@ -140,7 +140,7 @@
|
|||
>
|
||||
<j-input-number
|
||||
style="width: 100%"
|
||||
v-model:value="formData.virtualRule.rule.window.every"
|
||||
v-model:value="formData.virtualRule.window.every"
|
||||
placeholder="请输入步长"
|
||||
:max="999999"
|
||||
:min="1"
|
||||
|
@ -182,7 +182,6 @@ const props = defineProps({
|
|||
|
||||
const initData = {
|
||||
triggerProperties: ['*'],
|
||||
rule: {
|
||||
type: undefined,
|
||||
script: '',
|
||||
isVirtualRule: false,
|
||||
|
@ -192,7 +191,6 @@ const initData = {
|
|||
span: undefined,
|
||||
every: undefined,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const instanceStore = useInstanceStore();
|
||||
|
@ -208,7 +206,6 @@ const formData = reactive<{
|
|||
type: string[];
|
||||
virtualRule?: {
|
||||
triggerProperties: string[];
|
||||
rule: {
|
||||
type: 'script' | 'window' | undefined;
|
||||
script: string | undefined;
|
||||
isVirtualRule: boolean;
|
||||
|
@ -219,7 +216,6 @@ const formData = reactive<{
|
|||
every: number | undefined;
|
||||
};
|
||||
};
|
||||
};
|
||||
}>({
|
||||
type: [],
|
||||
virtualRule: undefined,
|
||||
|
@ -228,7 +224,7 @@ const formData = reactive<{
|
|||
const dataSource = inject<Ref<any[]>>('_dataSource')
|
||||
|
||||
const windowTypeChange = () => {
|
||||
formData.virtualRule!.rule.window = {
|
||||
formData.virtualRule!.window = {
|
||||
span: undefined,
|
||||
every: undefined
|
||||
}
|
||||
|
@ -253,9 +249,11 @@ const options = computed(() => {
|
|||
});
|
||||
|
||||
const setInitVirtualRule = () => {
|
||||
console.log(props.value?.expands?.virtualRule);
|
||||
formData.virtualRule = {
|
||||
...initData,
|
||||
...(props.value?.expands?.virtualRule || {}),
|
||||
triggerProperties: props.value?.expands?.virtualRule?.triggerProperties || ['*'],
|
||||
rule: props.value?.expands?.virtualRule?.rule || initData.rule
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,7 +275,7 @@ const handleSearch = async () => {
|
|||
if (resp && resp.status === 200 && resp.result) {
|
||||
formData.virtualRule = {
|
||||
triggerProperties: resp.result.triggerProperties,
|
||||
rule: resp.result.rule,
|
||||
...resp.result.rule,
|
||||
}
|
||||
} else {
|
||||
setInitVirtualRule()
|
||||
|
@ -308,8 +306,6 @@ watch(
|
|||
() => props.value,
|
||||
() => {
|
||||
formData.type = props.value.expands?.type;
|
||||
if (props.value.virtualRule) {
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
@ -319,7 +315,7 @@ watch(
|
|||
(newVal: SourceType) => {
|
||||
if (newVal === 'rule') {
|
||||
formData.virtualRule = initData;
|
||||
console.log(formData.virtualRule);
|
||||
|
||||
handleSearch();
|
||||
} else {
|
||||
formData.virtualRule = undefined;
|
||||
|
@ -332,16 +328,13 @@ watch(
|
|||
);
|
||||
|
||||
const _virtualRule = computed(() => {
|
||||
const flag = formData?.virtualRule?.rule?.windowType !== 'undefined';
|
||||
const flag = formData?.virtualRule?.windowType !== 'undefined';
|
||||
return {
|
||||
type: formData?.type,
|
||||
virtualRule: {
|
||||
type: flag ? 'window' : 'script',
|
||||
rule: {
|
||||
...formData?.virtualRule?.rule,
|
||||
...formData?.virtualRule,
|
||||
isVirtualRule: flag,
|
||||
type: flag ? 'window' : 'script',
|
||||
},
|
||||
triggerProperties: formData?.virtualRule?.triggerProperties.includes('*')
|
||||
? []
|
||||
: formData?.virtualRule?.triggerProperties,
|
||||
|
|
|
@ -92,7 +92,8 @@ const getCPUEcharts = async (val: any) => {
|
|||
const _cpuXAxis = new Set();
|
||||
if (res.result?.length) {
|
||||
// 根据服务节点来筛选数据
|
||||
const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
|
||||
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
|
||||
const filterArray = res.result
|
||||
filterArray.forEach((item: any) => {
|
||||
const value = item.data.value;
|
||||
const nodeID = item.data.clusterNodeId;
|
||||
|
|
|
@ -90,7 +90,8 @@ const getJVMEcharts = async (val: any) => {
|
|||
const _jvmOptions = {};
|
||||
const _jvmXAxis = new Set();
|
||||
if (res.result?.length) {
|
||||
const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
|
||||
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
|
||||
const filterArray = res.result
|
||||
filterArray.forEach((item: any) => {
|
||||
const value = item.data.value;
|
||||
const memoryJvmHeapFree = value.memoryJvmHeapFree;
|
||||
|
|
|
@ -11,7 +11,27 @@
|
|||
></j-input> </j-form-item
|
||||
></j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item label="类型" name="targetType">
|
||||
<j-form-item name="targetType">
|
||||
<template #label>
|
||||
<j-space>
|
||||
类型
|
||||
<j-tooltip>
|
||||
<template #title>
|
||||
<div>产品:以产品维度告警,某产品下的多个设备异常仅发送一条告警。</div>
|
||||
<div>设备:以设备维度告警,任何设备异常即发送一条告警。</div>
|
||||
<div>组织:以组织维度告警,某组织下的多个设备异常仅发送一条告警。</div>
|
||||
<div>其他:以场景联动维度告警,某场景下的多个设备异常仅发送一条告警。</div>
|
||||
</template>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="
|
||||
color: rgb(136, 136, 136);
|
||||
font-size: 12px;
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</j-space>
|
||||
</template>
|
||||
<j-select
|
||||
:options="options"
|
||||
v-model:value="form.targetType"
|
||||
|
@ -91,13 +111,13 @@ let selectDisable = ref(false);
|
|||
const alarmConfigurationStore = useAlarmConfigurationStore();
|
||||
let { configurationData } = storeToRefs(alarmConfigurationStore);
|
||||
|
||||
const emit = defineEmits(['change'])
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const queryData = () => {
|
||||
if (route.query?.id) {
|
||||
detail(route.query?.id).then((res) => {
|
||||
if (res.status === 200) {
|
||||
emit('change', res?.result?.targetType)
|
||||
emit('change', res?.result?.targetType);
|
||||
form.value = res?.result;
|
||||
// form.level = res?.result?.level;
|
||||
// form.name = res?.result?.name;
|
||||
|
@ -209,7 +229,7 @@ const handleSave = async () => {
|
|||
if (res.status === 200) {
|
||||
onlyMessage('操作成功,请配置关联的场景联动');
|
||||
loading.value = false;
|
||||
emit('change', form.value.targetType)
|
||||
emit('change', form.value.targetType);
|
||||
if (res.result?.id) {
|
||||
menuStory.jumpPage(
|
||||
'rule-engine/Alarm/Configuration/Save',
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
:width="1000"
|
||||
@cancel="closeModal"
|
||||
@ok="saveCorrelation"
|
||||
:maskClosable="false"
|
||||
>
|
||||
<pro-search :columns="columns" @search="handleSearch" />
|
||||
<div style="height: 500px; overflow-y: auto">
|
||||
|
|
|
@ -250,6 +250,7 @@ const getDashBoard = () => {
|
|||
},
|
||||
grid: {
|
||||
top: '2%',
|
||||
left: 40,
|
||||
bottom: 0,
|
||||
},
|
||||
tooltip: {
|
||||
|
@ -428,7 +429,7 @@ const selectChange = () => {
|
|||
.filter((item: any) => item.group === 'alarmTrend')
|
||||
.forEach((item: any) => {
|
||||
xData.push(item.data.timeString);
|
||||
sData.push(item.data.value);
|
||||
sData.push(item.data.value * 100000);
|
||||
});
|
||||
const maxY = sData.sort((a,b)=>{
|
||||
return b-a
|
||||
|
@ -451,7 +452,7 @@ const selectChange = () => {
|
|||
grid: {
|
||||
top: '2%',
|
||||
bottom: '5%',
|
||||
left: maxY > 10000 ? '50px' : '40px',
|
||||
left: maxY < 1000 ? '40px' : maxY.toString().length * 10,
|
||||
right: '48px',
|
||||
},
|
||||
series: [
|
||||
|
|
|
@ -268,7 +268,8 @@ watch(
|
|||
() => props.productDetail,
|
||||
(newVal) => {
|
||||
if (newVal?.id) {
|
||||
if (props.values?.selector === 'fixed') {
|
||||
console.log(props.values)
|
||||
if (props.values?.selector === 'fixed' && props.values?.selectorValues?.length === 1) {
|
||||
const id = props.values?.selectorValues?.[0]?.value;
|
||||
if (id) {
|
||||
detail(id).then((resp) => {
|
||||
|
@ -276,6 +277,7 @@ watch(
|
|||
metadata.value = JSON.parse(
|
||||
resp.result?.metadata || '{}',
|
||||
);
|
||||
console.log(metadata.value, resp.result?.metadata)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ const checkDeviceDelete = async () => {
|
|||
|
||||
if (item!.selectorValues!.length === 1 && hasDevice) {
|
||||
const deviceDetail = deviceResp?.result?.data?.[0]
|
||||
metadata = JSON.parse(deviceDetail?.deriveMetadata || '{}') // 只选中一个设备,以设备物模型为准
|
||||
metadata = JSON.parse(deviceDetail?.deriveMetadata || productDetail?.metadata || '{}') // 只选中一个设备,以设备物模型为准
|
||||
}
|
||||
}
|
||||
if (!hasDevice) { // 某一个设备被删除
|
||||
|
@ -139,9 +139,8 @@ const checkDeviceDelete = async () => {
|
|||
}
|
||||
|
||||
|
||||
if (item!.message!.messageType === 'READ_PROPERTY' && item!.message!.properties && metadata.properties) {
|
||||
if (item!.message!.messageType === 'READ_PROPERTY') {
|
||||
let hasProperties = false
|
||||
console.log('checkDeviceDelete',item!.message!.properties, metadata)
|
||||
if (item!.message!.properties && metadata.properties?.length) {
|
||||
const propertiesKey = item!.message!.properties?.[0]
|
||||
hasProperties = metadata.properties?.some((item: any) => item.id === propertiesKey)
|
||||
|
@ -154,8 +153,7 @@ const checkDeviceDelete = async () => {
|
|||
}
|
||||
|
||||
}
|
||||
console.log('WRITE_PROPERTY',item, metadata)
|
||||
if (item!.message!.messageType === 'WRITE_PROPERTY' && item!.message!.properties && metadata.properties) {
|
||||
if (item!.message!.messageType === 'WRITE_PROPERTY') {
|
||||
let hasProperties = false
|
||||
const propertiesKey = Object.keys(item!.message!.properties!)?.[0]
|
||||
if (item!.message!.properties && metadata.properties?.length) {
|
||||
|
@ -169,7 +167,7 @@ const checkDeviceDelete = async () => {
|
|||
}
|
||||
// 判断值-内置参数
|
||||
const _value = item!.message!.properties?.[propertiesKey]
|
||||
console.log('WRITE_PROPERTY',_value)
|
||||
|
||||
if(_value.source === 'upper') {
|
||||
const _params = {
|
||||
branch: props.thenName,
|
||||
|
@ -248,7 +246,6 @@ const checkNoticeDelete = async () => {
|
|||
const itemType = variableDefinitionsMap.get(variableKey)
|
||||
let hasUser = false
|
||||
|
||||
console.log(itemType, notifyType)
|
||||
if (itemType === 'user') { // 微信用户,钉钉用户
|
||||
let resp = undefined;
|
||||
if (['dingTalk', 'weixin'].includes(notifyType)) {
|
||||
|
@ -319,8 +316,7 @@ const checkNoticeDelete = async () => {
|
|||
}
|
||||
|
||||
const check = () => {
|
||||
const _executor = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name]?.executor
|
||||
console.log('check', _executor)
|
||||
const _executor = _data.value.branches![props.branchesName].then[props.thenName].actions?.[props.name]?.executor
|
||||
if (_executor === 'device' && _data.value.branches![props.branchesName].then[props.thenName].actions[props.name]?.device) { // 设备输出,并且有值
|
||||
checkDeviceDelete()
|
||||
} else if (_executor === 'notify' && _data.value.branches![props.branchesName].then[props.thenName].actions[props.name]?.notify) {
|
||||
|
|
|
@ -536,7 +536,7 @@ const onSave = (data: ActionsType, options: any) => {
|
|||
_data.value.branches![props.branchesName].then[props.thenName].actions.splice(props.name, 1, actionItem)
|
||||
checkItemRef.value?.formTouchOff?.()
|
||||
visible.value = false;
|
||||
EventEmitter.emit(eventEmitterKey.value, data) // 发布消息
|
||||
EventEmitter.emit(key!, data) // 发布消息
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<j-spin :spinning="spinning">
|
||||
<div class="child-item" :class="{ border: !isLast }">
|
||||
<div class="child-item">
|
||||
<div class="child-item-left">
|
||||
<div style="color: #333333">
|
||||
{{ data?.name }}
|
||||
|
@ -14,7 +14,10 @@
|
|||
/>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<div class="child-item-left-auth" :class="{ disabled: !checked }">
|
||||
<div
|
||||
class="child-item-left-auth"
|
||||
:class="{ disabled: !checked }"
|
||||
>
|
||||
<j-tooltip>
|
||||
<template #title>
|
||||
<span v-if="!update">暂无权限,请联系管理员</span>
|
||||
|
@ -27,9 +30,17 @@
|
|||
type="text"
|
||||
@click="onAuth"
|
||||
>
|
||||
<span v-if="!auth.length" class="child-item-left-auth-lock" ><AIcon type="LockFilled" /></span>
|
||||
<span v-else class="child-item-left-auth-key"><AIcon type="KeyOutlined" /></span>
|
||||
<span class="child-item-left-auth-text">权限控制</span>
|
||||
<span
|
||||
v-if="!auth.length"
|
||||
class="child-item-left-auth-lock"
|
||||
><AIcon type="LockFilled"
|
||||
/></span>
|
||||
<span v-else class="child-item-left-auth-key"
|
||||
><AIcon type="KeyOutlined"
|
||||
/></span>
|
||||
<span class="child-item-left-auth-text"
|
||||
>权限控制</span
|
||||
>
|
||||
</j-button>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
|
@ -99,26 +110,16 @@
|
|||
</template>
|
||||
</MCarousel>
|
||||
|
||||
<div class="box-item-add">
|
||||
<div class="box-item-img">
|
||||
<j-tooltip
|
||||
:title="!add ? '暂无权限,请联系管理员' : ''"
|
||||
>
|
||||
<j-tooltip :title="!add ? '暂无权限,请联系管理员' : ''">
|
||||
<j-button
|
||||
class="box-item-add"
|
||||
:disabled="!add"
|
||||
type="text"
|
||||
@click="onAdd"
|
||||
>
|
||||
<AIcon
|
||||
style="font-size: 20px"
|
||||
type="PlusOutlined"
|
||||
/>
|
||||
<AIcon type="PlusOutlined" />
|
||||
</j-button>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<div class="box-item-text"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</j-spin>
|
||||
<Save
|
||||
|
@ -304,12 +305,15 @@ const onAction = (e: boolean) => {
|
|||
role: {
|
||||
idList: [],
|
||||
},
|
||||
permissions: props.provider === 'alarm' ? [
|
||||
permissions:
|
||||
props.provider === 'alarm'
|
||||
? [
|
||||
{
|
||||
id: 'alarm-config',
|
||||
actions: ['query'],
|
||||
},
|
||||
] : [],
|
||||
]
|
||||
: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -406,15 +410,19 @@ const onSave = (_data: any) => {
|
|||
|
||||
<style lang="less" scoped>
|
||||
.child-item {
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 68px;
|
||||
background: linear-gradient(270deg, #ffffff 0%, #f1f6ff 99%);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ebeef3;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.child-item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 80px;
|
||||
margin-left: 24px;
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
|
@ -435,19 +443,20 @@ const onSave = (_data: any) => {
|
|||
color: #666666;
|
||||
}
|
||||
.child-item-left-auth-key {
|
||||
color: #00C800;
|
||||
color: #00c800;
|
||||
font-size: 18px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.child-item-left-auth-lock{
|
||||
.child-item-left-auth-lock {
|
||||
color: @primary-color;
|
||||
font-size: 18px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
.child-item-left-auth-key, .child-item-left-auth-lock {
|
||||
.child-item-left-auth-key,
|
||||
.child-item-left-auth-lock {
|
||||
color: #666666 !important;
|
||||
}
|
||||
}
|
||||
|
@ -460,19 +469,14 @@ const onSave = (_data: any) => {
|
|||
|
||||
.box-item {
|
||||
cursor: pointer;
|
||||
width: 48px;
|
||||
margin: 0 2px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.box-item-img {
|
||||
background-color: #fff;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.box-item-text {
|
||||
|
@ -485,21 +489,27 @@ const onSave = (_data: any) => {
|
|||
|
||||
.box-item-add {
|
||||
cursor: pointer;
|
||||
background-color: #f8f9fc;
|
||||
// width: 54px;
|
||||
background-color: #F7F8FA;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 12px;
|
||||
justify-content: center;
|
||||
color: #666666;
|
||||
border: none;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
margin: 0 16px;
|
||||
|
||||
&:hover {
|
||||
background-color: #eff2fe;
|
||||
color: #2f54eb;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
}
|
||||
|
||||
&.border {
|
||||
box-shadow: 0px 1px 0px 0px #e2e2e2;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -2,7 +2,7 @@
|
|||
<page-container>
|
||||
<FullPage>
|
||||
<div class="content">
|
||||
<div>
|
||||
<div style="margin-bottom: 15px;">
|
||||
<div class="alert">
|
||||
<AIcon type="InfoCircleOutlined" />
|
||||
启用通知类型后,你可以为每种通知类型配置不同的通知方式、通知模板、接收人。
|
||||
|
@ -10,7 +10,7 @@
|
|||
</div>
|
||||
<div class="content-collapse">
|
||||
<j-collapse :bordered="false" v-model:activeKey="activeKey" expand-icon-position="right">
|
||||
<!-- <template #expandIcon="{ isActive }">
|
||||
<template #expandIcon="{ isActive }">
|
||||
<AIcon
|
||||
type="CaretRightOutlined"
|
||||
:style="{
|
||||
|
@ -19,11 +19,10 @@
|
|||
}deg)`,
|
||||
}"
|
||||
/>
|
||||
</template> -->
|
||||
</template>
|
||||
<j-collapse-panel
|
||||
v-for="item in dataSource"
|
||||
:key="item.provider"
|
||||
class="custom"
|
||||
>
|
||||
<template #header>
|
||||
<div>
|
||||
|
@ -31,7 +30,7 @@
|
|||
<span style="margin-left: 10px;" class="alert" v-if="item.provider === 'alarm'">注意:接收人需要有告警配置页面查询权限,才能收到告警类通知</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="child">
|
||||
<div>
|
||||
<template
|
||||
v-for="(child, index) in item.children"
|
||||
:key="child.provider"
|
||||
|
@ -142,7 +141,6 @@ onMounted(() => {
|
|||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// height: 100%;
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
|
||||
|
@ -153,27 +151,31 @@ onMounted(() => {
|
|||
}
|
||||
}
|
||||
.alert {
|
||||
height: 40px;
|
||||
padding-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
color: rgba(0, 0, 0, 0.55);
|
||||
line-height: 40px;
|
||||
// background-color: #f6f6f6;
|
||||
}
|
||||
.custom {
|
||||
background: #F7F8FA;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
color: #333333;
|
||||
}
|
||||
.child {
|
||||
background-color: white;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.content-collapse {
|
||||
:deep(.ant-collapse-content > .ant-collapse-content-box) {
|
||||
:deep(.ant-collapse) {
|
||||
border-color: #EBEEF3;
|
||||
background-color: #fff;
|
||||
|
||||
.ant-collapse-item {
|
||||
border: 1px solid #EBEEF3;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.ant-collapse-header {
|
||||
background-color: #F7F8FA;
|
||||
height: 42px;
|
||||
}
|
||||
.ant-collapse-content {
|
||||
padding: 17px 21px 7px 21px;
|
||||
}
|
||||
|
||||
.ant-collapse-content-box {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -3835,10 +3835,10 @@ jetlinks-ui-components@^1.0.23:
|
|||
lodash-es "^4.17.21"
|
||||
monaco-editor "^0.35.0"
|
||||
|
||||
jetlinks-ui-components@^1.0.24:
|
||||
version "1.0.24"
|
||||
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.24.tgz#e15551fb114e4cb8752db962423b3ca17d9389c1"
|
||||
integrity sha512-TGyQ9SmdkoNkZScfYvfBF1/P1oBzXkxMuzR+DiNnof6CbSlYfPrkRsJIpOIZUjqg2o/6dyKLDK8gOxbxWm8wjA==
|
||||
jetlinks-ui-components@^1.0.25:
|
||||
version "1.0.25"
|
||||
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.25.tgz#b783da3fe05c1420b2ee5707868a67baa90559f7"
|
||||
integrity sha512-4HJM9Wi8gFfBgYFPjCO7JpmEAXVtDUf5u5lnXTQUt1QkGh0QCzFSBGBIStFs6HE5oY3oIIS3ZWoAjvXElpnNZg==
|
||||
dependencies:
|
||||
"@vueuse/core" "^9.12.0"
|
||||
"@vueuse/router" "^9.13.0"
|
||||
|
|
Loading…
Reference in New Issue