feat: 新增IEC104协议;修复自定义采集频率不生效;修复MODBUS_TCP新建通道主机IP和端口未保存到后端的bug等
* feat: 新增IEC104协议 * fix: 修复自定义采集频率不生效 * fix: bug#21712、21711 * fix: 修复MODBUS_TCP新建通道主机IP和端口未保存到后端的bug * fix: 修复产品“物模型映射”目标属性下拉框无选项的bug * fix: bug#21958 * fix: bug#21338 * fix: bug#21262 * fix: bug#22074 * fix: 场景联动条件修改
This commit is contained in:
parent
aaa0e78343
commit
fd37264925
|
@ -32,7 +32,7 @@ const handleTermsArr = (queryTerms: any, data: any[], parentKey?: string) => {
|
|||
handleTermsArr(queryTerms, item, `${key}`)
|
||||
} else if (isObject(item)) {
|
||||
handleTermsObject(queryTerms, item, `${key}`)
|
||||
} else {
|
||||
} else{
|
||||
queryTerms[key] = item
|
||||
}
|
||||
})
|
||||
|
@ -40,8 +40,10 @@ const handleTermsArr = (queryTerms: any, data: any[], parentKey?: string) => {
|
|||
const handleTermsObject = (queryTerms: any, data: any, parentKey?: string) => {
|
||||
Object.keys(data).forEach(k => {
|
||||
const key = `${parentKey}.${k}`
|
||||
console.log(key, data[k], isObject(data[k]), isArray(data[k]))
|
||||
if (isArray(data[k])) {
|
||||
console.log(key, data[k], isObject(data[k]), isArray(data[k]),k)
|
||||
if( k === 'value' && isArray(data[k])){
|
||||
queryTerms[key] = data[k].join(',')
|
||||
}else if (isArray(data[k])) {
|
||||
handleTermsArr(queryTerms, data[k], `${key}`)
|
||||
} else if (isObject(data[k])) {
|
||||
handleTermsObject(queryTerms, data[k], `${key}`)
|
||||
|
|
|
@ -249,7 +249,7 @@ const handleOk = async () => {
|
|||
params.configuration={
|
||||
connect : false
|
||||
}
|
||||
} else {
|
||||
} else if (params?.provider === 'iec104') {
|
||||
params.configuration = {}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
:key="item.property"
|
||||
>
|
||||
<template #label>
|
||||
<Ellipsis style="margin-right: 5px;">
|
||||
<Ellipsis style="margin-right: 5px">
|
||||
{{ item.name }}
|
||||
<j-tooltip
|
||||
v-if="item.description"
|
||||
|
@ -69,11 +69,13 @@
|
|||
>
|
||||
<span v-else-if="item.type.type === 'enum'">
|
||||
<Ellipsis>{{
|
||||
item.type.elements?.find((i)=>
|
||||
i.value === instanceStore.current?.configuration?.[
|
||||
item.property
|
||||
]
|
||||
)?.text || ''
|
||||
item.type.elements?.find(
|
||||
(i) =>
|
||||
i.value ===
|
||||
instanceStore.current?.configuration?.[
|
||||
item.property
|
||||
],
|
||||
)?.text || ''
|
||||
}}</Ellipsis>
|
||||
<j-tooltip
|
||||
v-if="isExit(item.property)"
|
||||
|
@ -85,9 +87,24 @@
|
|||
><AIcon type="QuestionCircleOutlined"
|
||||
/></j-tooltip>
|
||||
</span>
|
||||
<span v-else-if="item.type.type === 'boolean'">
|
||||
<Ellipsis>{{
|
||||
[
|
||||
{
|
||||
label: item?.type?.falseText,
|
||||
value: item?.type?.falseValue,
|
||||
},
|
||||
{
|
||||
label: item?.type?.trueText,
|
||||
value: item?.type?.trueValue,
|
||||
}
|
||||
].find((i) => i.value ===
|
||||
instanceStore.current?.configuration?.[item.property] )?.label || ''
|
||||
}}</Ellipsis>
|
||||
</span>
|
||||
<span v-else>
|
||||
<Ellipsis>{{
|
||||
instanceStore.current?.configuration?.[item.property] ||
|
||||
instanceStore.current?.configuration?.[item.property] ||
|
||||
''
|
||||
}}</Ellipsis>
|
||||
<j-tooltip
|
||||
|
@ -172,4 +189,4 @@ const saveBtn = () => {
|
|||
instanceStore.refresh(instanceStore.current.id);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -140,7 +140,7 @@ import { useProductStore } from '@/store/product';
|
|||
import { detail as queryPluginAccessDetail } from '@/api/link/accessConfig';
|
||||
import { getPluginData, getProductByPluginId } from '@/api/link/plugin';
|
||||
import { getImage, onlyMessage } from '@/utils/comm';
|
||||
import { getMetadataMapById, metadataMapById } from '@/api/device/instance';
|
||||
import { getMetadataMapById, metadataMapById, getProtocolMetadata } from '@/api/device/instance';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
const productStore = useProductStore();
|
||||
|
@ -242,7 +242,7 @@ const onSearch = () => {
|
|||
const getDefaultMetadata = async () => {
|
||||
const metadata = JSON.parse(productDetail.value?.metadata || '{}');
|
||||
const properties = metadata.properties;
|
||||
const pluginMetadata = await getPluginMetadata();
|
||||
const pluginMetadata = await getMetadata();
|
||||
const pluginProperties = pluginMetadata?.properties || [];
|
||||
const metadataMap: any = await getMetadataMapData();
|
||||
pluginOptions.value = pluginProperties.map((item) => ({
|
||||
|
@ -309,6 +309,19 @@ const getPluginMetadata = (): Promise<{ properties: any[] }> => {
|
|||
);
|
||||
});
|
||||
};
|
||||
const getMetadata = (): Promise<{ properties: any[] }> => {
|
||||
return new Promise((resolve) => {
|
||||
const transport = productDetail.value?.transportProtocol;
|
||||
getProtocolMetadata(productDetail.value?.messageProtocol || '', transport).then(
|
||||
(res: any) => {
|
||||
if (res.success) {
|
||||
resolve(JSON.parse(res?.result || '{}'));
|
||||
}
|
||||
resolve({ properties: [] });
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const onMapData = async (arr: any[], flag?: boolean) => {
|
||||
const res = await metadataMapById('product', productDetail.value?.id, arr);
|
||||
|
|
|
@ -39,7 +39,8 @@ export const testType = (data:any,index:number,isArray?:boolean,isObject?:boolea
|
|||
}
|
||||
}
|
||||
if(data.type === 'object' && !isArray && !isObject){
|
||||
if(data?.valueType?.properties?.length > 0){
|
||||
console.log(data,'data123')
|
||||
if(data?.properties?.length > 0){
|
||||
return testObject(data.properties,index)
|
||||
}else{
|
||||
onlyMessage(`方法定义inputs第${index+1}个数组ValueType中缺失properties属性`,'error')
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
<j-radio-button value="hour">
|
||||
最近1小时
|
||||
</j-radio-button>
|
||||
<j-radio-button value="day"> 最近24小时 </j-radio-button>
|
||||
<j-radio-button value="day">
|
||||
最近24小时
|
||||
</j-radio-button>
|
||||
<j-radio-button value="week"> 近一周 </j-radio-button>
|
||||
</j-radio-group>
|
||||
<j-range-picker
|
||||
|
@ -48,20 +50,18 @@
|
|||
v-if="isEmpty"
|
||||
style="height: 250px; margin-top: 100px"
|
||||
/>
|
||||
<template v-else>
|
||||
<div style="height: 300px">
|
||||
<Echarts
|
||||
:options="echartsOptions"
|
||||
/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<div style="height: 300px">
|
||||
<Echarts :options="echartsOptions" />
|
||||
</div>
|
||||
|
||||
<ServerList
|
||||
v-if="serverOptions.length > 1"
|
||||
v-model:value="serverActive"
|
||||
:options="serverOptions"
|
||||
color="#979AFF"
|
||||
/>
|
||||
</template>
|
||||
<ServerList
|
||||
v-if="serverOptions.length > 1"
|
||||
v-model:value="serverActive"
|
||||
:options="serverOptions"
|
||||
color="#979AFF"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</j-spin>
|
||||
|
@ -70,23 +70,24 @@
|
|||
<script lang="ts" setup name="Network">
|
||||
import { dashboard } from '@/api/link/dashboard';
|
||||
import {
|
||||
getTimeByType,
|
||||
typeDataLine,
|
||||
areaStyle,
|
||||
colorNetwork,
|
||||
networkParams, arrayReverse,
|
||||
getTimeByType,
|
||||
typeDataLine,
|
||||
areaStyle,
|
||||
colorNetwork,
|
||||
networkParams,
|
||||
arrayReverse,
|
||||
} from './tool.ts';
|
||||
import dayjs from 'dayjs';
|
||||
import { DataType } from '../typings.d';
|
||||
import ServerList from './ServerList.vue'
|
||||
import Echarts from './echarts.vue'
|
||||
import ServerList from './ServerList.vue';
|
||||
import Echarts from './echarts.vue';
|
||||
|
||||
const props = defineProps({
|
||||
serviceId: {
|
||||
type: String,
|
||||
default: undefined
|
||||
}
|
||||
})
|
||||
serviceId: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const chartRef = ref<Record<string, any>>({});
|
||||
const loading = ref(false);
|
||||
|
@ -98,20 +99,20 @@ const data = ref<DataType>({
|
|||
},
|
||||
});
|
||||
const isEmpty = ref(false);
|
||||
const serverActive = ref<string[]>([])
|
||||
const serverOptions = ref<string[]>([])
|
||||
const serverActive = ref<string[]>([]);
|
||||
const serverOptions = ref<string[]>([]);
|
||||
const serverData = reactive({
|
||||
xAxis: [],
|
||||
data: []
|
||||
})
|
||||
xAxis: [],
|
||||
data: [],
|
||||
});
|
||||
|
||||
const pickerTimeChange = (value: any) => {
|
||||
data.value.time.type = undefined;
|
||||
getNetworkEcharts(data.value);
|
||||
};
|
||||
const changeType = (value:any) =>{
|
||||
const changeType = (value: any) => {
|
||||
getNetworkEcharts(data.value);
|
||||
}
|
||||
};
|
||||
const getNetworkEcharts = async (val: any) => {
|
||||
loading.value = true;
|
||||
const resp: any = await dashboard(networkParams(val));
|
||||
|
@ -119,10 +120,10 @@ const getNetworkEcharts = async (val: any) => {
|
|||
const _networkOptions = {};
|
||||
const _networkXAxis = new Set();
|
||||
if (resp.result.length) {
|
||||
isEmpty.value = false;
|
||||
const filterArray = resp.result
|
||||
// const filterArray = resp.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId)
|
||||
filterArray.forEach((item: any) => {
|
||||
isEmpty.value = false;
|
||||
const filterArray = resp.result;
|
||||
// const filterArray = resp.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId)
|
||||
filterArray.forEach((item: any) => {
|
||||
const value = item.data.value;
|
||||
const _data: Array<any> = [];
|
||||
const nodeID = item.data.clusterNodeId;
|
||||
|
@ -149,9 +150,9 @@ const getNetworkEcharts = async (val: any) => {
|
|||
|
||||
const formatterData = (value: any) => {
|
||||
let _data = '';
|
||||
const kb = 1024
|
||||
const mb = kb**2
|
||||
const gb = kb**3
|
||||
const kb = 1024;
|
||||
const mb = kb ** 2;
|
||||
const gb = kb ** 3;
|
||||
|
||||
if (value >= kb && value < mb) {
|
||||
_data = `${Number((value / kb).toFixed(2))}KB`;
|
||||
|
@ -166,10 +167,24 @@ const formatterData = (value: any) => {
|
|||
};
|
||||
|
||||
const networkValueRender = (obj: any) => {
|
||||
const { value } = obj;
|
||||
return `${obj?.axisValueLabel}<br />${obj?.marker}${
|
||||
obj?.seriesName
|
||||
} ${formatterData(value)}`;
|
||||
// const { value } = obj;
|
||||
let data: any = '';
|
||||
obj.forEach((item: any, index: number) => {
|
||||
const { value } = item;
|
||||
if (index === 0) {
|
||||
data += `${item?.axisValueLabel}<br />${item?.marker}${
|
||||
item?.seriesName
|
||||
} ${formatterData(value)}<br />`;
|
||||
}else{
|
||||
data += `${item?.marker}${
|
||||
item?.seriesName
|
||||
} ${formatterData(value)}<br />`;
|
||||
}
|
||||
});
|
||||
return data;
|
||||
// return `${obj?.axisValueLabel}<br />${obj?.marker}${
|
||||
// obj?.seriesName
|
||||
// } ${formatterData(value)}`;
|
||||
};
|
||||
|
||||
const setOptions = (data: any, key: string) => ({
|
||||
|
@ -181,43 +196,43 @@ const setOptions = (data: any, key: string) => ({
|
|||
});
|
||||
|
||||
const handleNetworkOptions = (optionsData: any, xAxis: any) => {
|
||||
const dataKeys = Object.keys(optionsData);
|
||||
serverActive.value = dataKeys
|
||||
serverOptions.value = dataKeys
|
||||
serverData.xAxis = xAxis
|
||||
serverData.data = optionsData
|
||||
const dataKeys = Object.keys(optionsData);
|
||||
serverActive.value = dataKeys;
|
||||
serverOptions.value = dataKeys;
|
||||
serverData.xAxis = xAxis;
|
||||
serverData.data = optionsData;
|
||||
};
|
||||
|
||||
const echartsOptions = computed(() => {
|
||||
const series = serverActive.value.length
|
||||
? serverActive.value.map((key) => setOptions(serverData.data, key))
|
||||
: typeDataLine
|
||||
return {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: serverData.xAxis,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: (_value: any) => formatterData(_value),
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: '70px',
|
||||
right: data.value.time.type === 'week' ? 50 :10,
|
||||
bottom: '24px',
|
||||
top: 24
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (_value: any) => networkValueRender(_value[0]),
|
||||
},
|
||||
color: colorNetwork,
|
||||
series: series
|
||||
};
|
||||
})
|
||||
const series = serverActive.value.length
|
||||
? serverActive.value.map((key) => setOptions(serverData.data, key))
|
||||
: typeDataLine;
|
||||
return {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: serverData.xAxis,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: (_value: any) => formatterData(_value),
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: '70px',
|
||||
right: data.value.time.type === 'week' ? 50 : 10,
|
||||
bottom: '24px',
|
||||
top: 24,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (_value: any) => networkValueRender(_value),
|
||||
},
|
||||
color: colorNetwork,
|
||||
series: series,
|
||||
};
|
||||
});
|
||||
|
||||
watch(
|
||||
() => data.value.time.type,
|
||||
|
@ -231,7 +246,6 @@ watch(
|
|||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
v-model:value='paramsValue.termType'
|
||||
@select='termsTypeSelect'
|
||||
/>
|
||||
<div v-if="!['notnull','isnull'].includes(paramsValue.termType)">
|
||||
<DoubleParamsDropdown
|
||||
v-if='showDouble'
|
||||
icon='icon-canshu'
|
||||
|
@ -60,7 +59,6 @@
|
|||
v-model:source='paramsValue.value.source'
|
||||
@select='valueSelect'
|
||||
/>
|
||||
</div>
|
||||
<j-popconfirm title='确认删除?' @confirm='onDelete' :overlayStyle='{minWidth: "180px"}'>
|
||||
<div v-show='showDelete' class='button-delete'> <AIcon type='CloseOutlined' /></div>
|
||||
</j-popconfirm>
|
||||
|
@ -84,12 +82,12 @@ import { ContextKey, arrayParamsKey, timeTypeKeys } from './util'
|
|||
import { useSceneStore } from 'store/scene'
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { Form } from 'jetlinks-ui-components'
|
||||
import {indexOf, isArray, isObject, isString, pick} from 'lodash-es'
|
||||
import {cloneDeep} from "lodash";
|
||||
import {indexOf, isArray, isObject, isString, pick , cloneDeep } from 'lodash-es'
|
||||
|
||||
const sceneStore = useSceneStore()
|
||||
const { data: formModel } = storeToRefs(sceneStore)
|
||||
const formItemContext = Form.useInjectFormItemContext();
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:value', data: TermsType): void
|
||||
}
|
||||
|
@ -330,21 +328,15 @@ const termsTypeSelect = (e: { key: string, name: string }) => {
|
|||
newValue.value = undefined
|
||||
}
|
||||
}
|
||||
if(
|
||||
['isnull','notull'].includes(e.key)
|
||||
){
|
||||
newValue.value.value = 1
|
||||
}
|
||||
paramsValue.value = newValue
|
||||
|
||||
emit('update:value', { ...paramsValue })
|
||||
formItemContext.onFieldChange()
|
||||
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName][1] = e.name
|
||||
|
||||
|
||||
}
|
||||
|
||||
const valueSelect = (v: any, label: string, labelObj: Record<number, any>, option: any) => {
|
||||
console.log(labelObj,option,paramsValue.value,'____123')
|
||||
if (paramsValue.value?.source === 'metric') {
|
||||
paramsValue.value.metric = option?.id
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue