fix: bug#21601、20621、21711、21712
* fix: bug#21601、#20621 * fix: bug#21711 * fix: bug#21712
This commit is contained in:
parent
8600bbee98
commit
aaa0e78343
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
|
@ -58,4 +58,5 @@ export const protocolList = [
|
||||||
{ label: 'MODBUS_TCP', value: 'MODBUS_TCP', alias: 'Modbus/TCP' },
|
{ label: 'MODBUS_TCP', value: 'MODBUS_TCP', alias: 'Modbus/TCP' },
|
||||||
{ label: 'COLLECTOR_GATEWAY', value: 'COLLECTOR_GATEWAY', alias: 'GATEWAY' },
|
{ label: 'COLLECTOR_GATEWAY', value: 'COLLECTOR_GATEWAY', alias: 'GATEWAY' },
|
||||||
{ label: 'S7', value: 'snap7', alias: 'snap7' },
|
{ label: 'S7', value: 'snap7', alias: 'snap7' },
|
||||||
|
{ label: 'IEC104', value: 'iec104', alias: 'IEC104' }
|
||||||
]
|
]
|
||||||
|
|
|
@ -249,6 +249,8 @@ const handleOk = async () => {
|
||||||
params.configuration={
|
params.configuration={
|
||||||
connect : false
|
connect : false
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
params.configuration = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
params.circuitBreaker = {
|
params.circuitBreaker = {
|
||||||
|
@ -316,7 +318,7 @@ const getProvidersList = async () => {
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const arr = resp.result
|
const arr = resp.result
|
||||||
.filter(
|
.filter(
|
||||||
(item: any) => ['GATEWAY', 'Modbus/TCP', 'opc-ua','snap7'].includes(item.name),
|
(item: any) => ['GATEWAY', 'Modbus/TCP', 'opc-ua','snap7', 'IEC104'].includes(item.name),
|
||||||
)
|
)
|
||||||
.map((it: any) => it.name);
|
.map((it: any) => it.name);
|
||||||
const providers: any = protocolList.filter((item: any) =>
|
const providers: any = protocolList.filter((item: any) =>
|
||||||
|
|
|
@ -67,9 +67,9 @@
|
||||||
<div class="card-item-content-text">
|
<div class="card-item-content-text">
|
||||||
<j-tooltip>
|
<j-tooltip>
|
||||||
<template #title>{{
|
<template #title>{{
|
||||||
slotProps.provider
|
protocolList.find(item => item.value === slotProps.provider)?.label
|
||||||
}}</template>
|
}}</template>
|
||||||
{{ slotProps.provider }}
|
{{ protocolList.find(item => item.value === slotProps.provider)?.label }}
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</j-col>
|
</j-col>
|
||||||
|
@ -103,9 +103,11 @@
|
||||||
<div class="card-item-content-text">
|
<div class="card-item-content-text">
|
||||||
说明
|
说明
|
||||||
</div>
|
</div>
|
||||||
<div class="card-item-content-text">
|
<j-ellipsis>
|
||||||
<j-ellipsis>{{slotProps.description}}</j-ellipsis>
|
<div class="explain">
|
||||||
</div>
|
{{slotProps.description}}
|
||||||
|
</div>
|
||||||
|
</j-ellipsis>
|
||||||
</j-col>
|
</j-col>
|
||||||
</j-row>
|
</j-row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -161,10 +163,12 @@ const opcImage = getImage('/DataCollect/device-opcua.png');
|
||||||
const modbusImage = getImage('/DataCollect/device-modbus.png');
|
const modbusImage = getImage('/DataCollect/device-modbus.png');
|
||||||
const s7Image = getImage('/DataCollect/s7.png')
|
const s7Image = getImage('/DataCollect/s7.png')
|
||||||
const gatewayImage = getImage('/DataCollect/gateway.png')
|
const gatewayImage = getImage('/DataCollect/gateway.png')
|
||||||
|
const iecImage = getImage('/DataCollect/IEC104.png')
|
||||||
const ImageMap = new Map()
|
const ImageMap = new Map()
|
||||||
ImageMap.set('OPC_UA',opcImage)
|
ImageMap.set('OPC_UA',opcImage)
|
||||||
ImageMap.set('MODBUS_TCP',modbusImage)
|
ImageMap.set('MODBUS_TCP',modbusImage)
|
||||||
ImageMap.set('snap7',s7Image)
|
ImageMap.set('snap7',s7Image)
|
||||||
|
ImageMap.set('iec104',iecImage)
|
||||||
ImageMap.set('COLLECTOR_GATEWAY',gatewayImage)
|
ImageMap.set('COLLECTOR_GATEWAY',gatewayImage)
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,6 +371,9 @@ const handleSearch = (e: any) => {
|
||||||
text-overflow: ellipsis; //溢出用省略号显示
|
text-overflow: ellipsis; //溢出用省略号显示
|
||||||
white-space: nowrap; //溢出不换行
|
white-space: nowrap; //溢出不换行
|
||||||
}
|
}
|
||||||
|
.explain {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.details-text {
|
.details-text {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
|
|
@ -0,0 +1,263 @@
|
||||||
|
<template>
|
||||||
|
<j-modal :title="data.id ? '编辑' : '新增'" visible @cancel="handleCancel">
|
||||||
|
<j-form :model="formData" layout="vertical" ref="formRef">
|
||||||
|
<j-form-item
|
||||||
|
label="点位名称"
|
||||||
|
name="name"
|
||||||
|
:rules="rules.name"
|
||||||
|
>
|
||||||
|
<j-input
|
||||||
|
placeholder="请输入点位名称"
|
||||||
|
v-model:value="formData.name"
|
||||||
|
:maxlength="64"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item
|
||||||
|
label="类型标识"
|
||||||
|
:name="['configuration', 'typeIdentifierName']"
|
||||||
|
:rules="rules.configuration.typeIdentifierName"
|
||||||
|
>
|
||||||
|
<j-select
|
||||||
|
v-model:value="formData.configuration.typeIdentifierName"
|
||||||
|
:options="dataTypeList"
|
||||||
|
placeholder="请选择类型标识"
|
||||||
|
allowClear
|
||||||
|
show-search
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item
|
||||||
|
label="地址"
|
||||||
|
:name="['configuration', 'pointAddress']"
|
||||||
|
:rules="rules.configuration.pointAddress"
|
||||||
|
>
|
||||||
|
<j-input
|
||||||
|
v-model:value="formData.configuration.pointAddress"
|
||||||
|
placeholder="请输入地址"
|
||||||
|
:min="1"
|
||||||
|
:max="65535"
|
||||||
|
:precision="0"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item
|
||||||
|
label="访问类型"
|
||||||
|
name="accessModes"
|
||||||
|
:rules="rules.accessModes"
|
||||||
|
>
|
||||||
|
<j-card-select
|
||||||
|
multiple
|
||||||
|
:showImage="false"
|
||||||
|
v-model:value="formData.accessModes"
|
||||||
|
:options="[
|
||||||
|
{ label: '读', value: 'read' },
|
||||||
|
{ label: '写', value: 'write' },
|
||||||
|
{ label: '订阅', value: 'subscribe' },
|
||||||
|
]"
|
||||||
|
:column="3"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item :name="['configuration', 'terms']" :rules="[{
|
||||||
|
validator: Area,
|
||||||
|
trigger: 'change',
|
||||||
|
}]">
|
||||||
|
<template #label>
|
||||||
|
<j-space>
|
||||||
|
<span>点位死区</span><span class="explain">点位死区范围内的异常数据将被过滤(请勿配置非数值类型)</span>
|
||||||
|
</j-space>
|
||||||
|
</template>
|
||||||
|
<DeathArea v-model:value="formData.configuration.terms" />
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item label="轮询任务" :name="['configuration', 'interval']" :rules="rules.configuration.interval">
|
||||||
|
<p>
|
||||||
|
采集频率<span
|
||||||
|
style="
|
||||||
|
margin-left: 5px;
|
||||||
|
color: #9d9ea1;
|
||||||
|
font-size: 12px;
|
||||||
|
"
|
||||||
|
>采集频率为0时不执行轮询任务</span
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<j-input-number
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入采集频率"
|
||||||
|
v-model:value="formData.configuration.interval"
|
||||||
|
addon-after="ms"
|
||||||
|
:max="2147483648"
|
||||||
|
:min="0"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item name="features">
|
||||||
|
<j-checkbox-group v-model:value="formData.features">
|
||||||
|
<j-checkbox value="changedOnly"
|
||||||
|
>只推送变化的数据</j-checkbox
|
||||||
|
>
|
||||||
|
</j-checkbox-group>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item label="说明" name="description">
|
||||||
|
<j-textarea
|
||||||
|
placeholder="请输入说明"
|
||||||
|
v-model:value="formData.description"
|
||||||
|
:maxlength="200"
|
||||||
|
:rows="3"
|
||||||
|
showCount
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-form>
|
||||||
|
<template #footer>
|
||||||
|
<j-button @click="handleCancel">取消</j-button>
|
||||||
|
<PermissionButton
|
||||||
|
key="submit"
|
||||||
|
type="primary"
|
||||||
|
:loading="loading"
|
||||||
|
@click="handleOk"
|
||||||
|
style="margin-left: 8px"
|
||||||
|
:hasPermission="`DataCollect/Collector:${
|
||||||
|
data.id ? 'update' : 'add'
|
||||||
|
}`"
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</j-modal>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
savePoint,
|
||||||
|
updatePoint,
|
||||||
|
} from '@/api/data-collect/collector';
|
||||||
|
import { randomString } from '@/utils/utils';
|
||||||
|
import DeathArea from './DeathArea.vue';
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const formRef = ref()
|
||||||
|
const dataTypeList = ref([
|
||||||
|
{ label: '单点开关量', value: 'onePointTelecontrol' },
|
||||||
|
{ label: '双点开关量', value: 'twoPointTelecontrol' },
|
||||||
|
{ label: '归一化值', value: 'prefabActivationOneParameter' },
|
||||||
|
]);
|
||||||
|
const formData = ref({
|
||||||
|
name: props.data.name,
|
||||||
|
configuration: props.data.configuration || {
|
||||||
|
typeIdentifierName: undefined,
|
||||||
|
pointAddress: '',
|
||||||
|
interval: 3000,
|
||||||
|
},
|
||||||
|
accessModes: [],
|
||||||
|
features: [],
|
||||||
|
description: props.data.description || '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
name: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入名称',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
configuration: {
|
||||||
|
typeIdentifierName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入类型标识',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pointAddress: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入地址',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
interval: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入采集频率',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
accessModes: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择访问类型',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const Area = (_: any, value: any): Promise<any> =>
|
||||||
|
new Promise(async (resolve, reject) => {
|
||||||
|
if (!value) {
|
||||||
|
return resolve('')
|
||||||
|
}
|
||||||
|
if (value?.length === 0) {
|
||||||
|
return resolve('')
|
||||||
|
} else if (value?.length === 1) {
|
||||||
|
return value[0].value && value[0].termType ? resolve('') : reject('请配置点位死区');
|
||||||
|
} else {
|
||||||
|
if (value?.[0].column === 'currentValue') {
|
||||||
|
// value.forEach((item:any) => {
|
||||||
|
// if(item.termType && item.value){
|
||||||
|
// return resolve('')
|
||||||
|
// }else{
|
||||||
|
// return reject('请配置点位死区')
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
const pass = value.every((item: any) => item.termType && item.value)
|
||||||
|
return pass ? resolve('') : reject('请配置点位死区')
|
||||||
|
} else {
|
||||||
|
value.forEach((item: any) => {
|
||||||
|
if (item.column === `this['currentValue'] - this['lastValue']*init/100`) {
|
||||||
|
return reject('请配置点位死区')
|
||||||
|
} else {
|
||||||
|
return resolve('')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
const res: any = await formRef.value?.validate();
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
...res,
|
||||||
|
configuration: {
|
||||||
|
...res.configuration,
|
||||||
|
},
|
||||||
|
inheritBreaker: true,
|
||||||
|
pointKey: props.data.pointKey || randomString(9),
|
||||||
|
provider: props.data.provider,
|
||||||
|
collectorId: props.data.collectorId,
|
||||||
|
accessModes: res?.accessModes.filter((item: any) => item)
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
const response = !props.data.id
|
||||||
|
? await savePoint(params).catch(() => { })
|
||||||
|
: await updatePoint(props.data.id, { ...props.data, ...params }).catch(() => { });
|
||||||
|
emit('change', response?.status === 200);
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('change', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
formData.value.features = props.data.features?.map((item: any) => item.value)
|
||||||
|
if (props.data.accessModes?.length !== 0) {
|
||||||
|
formData.value.accessModes = props.data.accessModes?.map((item: any) => item.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -97,20 +97,14 @@
|
||||||
<p>
|
<p>
|
||||||
采集频率<span style="margin-left: 5px; color: #9d9ea1; font-size: 12px">采集频率为0时不执行轮询任务</span>
|
采集频率<span style="margin-left: 5px; color: #9d9ea1; font-size: 12px">采集频率为0时不执行轮询任务</span>
|
||||||
</p>
|
</p>
|
||||||
<j-radio-group v-model:value="form.configuration.interval">
|
<j-input-number
|
||||||
<j-space>
|
style="width: 100%"
|
||||||
<j-radio-button :value="3000">3000ms</j-radio-button>
|
placeholder="请输入采集频率"
|
||||||
<j-radio-button :value="6000">6000ms</j-radio-button>
|
v-model:value="form.configuration.interval"
|
||||||
<j-radio-button :value="9000">9000ms</j-radio-button>
|
addon-after="ms"
|
||||||
<j-radio-button :value="Number(form.configuration.interval)" @click="intervalRef.visible = true">
|
:max="2147483648"
|
||||||
{{
|
:min="0"
|
||||||
![3000, 6000, 9000].includes(form.configuration.interval)
|
/>
|
||||||
? form.configuration.interval + 'ms'
|
|
||||||
: '自定义'
|
|
||||||
}}
|
|
||||||
</j-radio-button>
|
|
||||||
</j-space>
|
|
||||||
</j-radio-group>
|
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item name="features">
|
<j-form-item name="features">
|
||||||
<j-checkbox-group v-model:value="form.features">
|
<j-checkbox-group v-model:value="form.features">
|
||||||
|
@ -121,17 +115,6 @@
|
||||||
<j-textarea placeholder="请输入说明" v-model:value="form.description" :maxlength="200" :rows="3" showCount />
|
<j-textarea placeholder="请输入说明" v-model:value="form.description" :maxlength="200" :rows="3" showCount />
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</j-form>
|
</j-form>
|
||||||
<j-modal title="采集频率" :visible="intervalRef.visible" @cancel="handleCancelInterval" @ok="handleInterval">
|
|
||||||
<j-form ref="formRef2" name="virtual-form" layout="vertical" :model="intervalRef">
|
|
||||||
<j-form-item label="采集频率" name="interval" :rules="[
|
|
||||||
{ required: true, message: '请输入采集频率' },
|
|
||||||
]">
|
|
||||||
<j-input-number type="tel" addonAfter="ms" v-model:value="intervalRef.interval" placeholder="请输入采集频率"
|
|
||||||
:controls="false" :precision="0" :maxlength="64" />
|
|
||||||
</j-form-item>
|
|
||||||
</j-form>
|
|
||||||
</j-modal>
|
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<j-button key="back" @click="handleCancel">取消</j-button>
|
<j-button key="back" @click="handleCancel">取消</j-button>
|
||||||
<PermissionButton key="submit" type="primary" :loading="loading" @click="handleOk" style="margin-left: 8px"
|
<PermissionButton key="submit" type="primary" :loading="loading" @click="handleOk" style="margin-left: 8px"
|
||||||
|
@ -181,8 +164,7 @@ const dataAreaFilter = {
|
||||||
const emit = defineEmits(['change']);
|
const emit = defineEmits(['change']);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
const formRef2 = ref<FormInstance>();
|
const deviceType = ref<string>(props. data.deviceType);
|
||||||
const deviceType = ref<string>(props.data.deviceType);
|
|
||||||
const dataTypesList = ref<any[]>([]);
|
const dataTypesList = ref<any[]>([]);
|
||||||
const daveAreaList = ref<any>([]);
|
const daveAreaList = ref<any>([]);
|
||||||
|
|
||||||
|
@ -203,10 +185,6 @@ const form = ref<any>({
|
||||||
// inheritBreaker: true,
|
// inheritBreaker: true,
|
||||||
// pointKey: randomString(9)
|
// pointKey: randomString(9)
|
||||||
});
|
});
|
||||||
const intervalRef = reactive({
|
|
||||||
visible: false,
|
|
||||||
interval: 3000,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
/**选择S7点位数据类型 */
|
/**选择S7点位数据类型 */
|
||||||
|
@ -259,19 +237,6 @@ const dataAreaFilterList = computed(() => {
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleInterval = async () => {
|
|
||||||
const res = await formRef2.value?.validate()
|
|
||||||
if (res) {
|
|
||||||
form.value.configuration.interval = res.interval
|
|
||||||
intervalRef.visible = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const handleCancelInterval = () => {
|
|
||||||
intervalRef.visible = false
|
|
||||||
intervalRef.interval = 3000
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
const res: any = await formRef.value?.validate();
|
const res: any = await formRef.value?.validate();
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<j-space>
|
<j-space>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
v-if="['MODBUS_TCP', 'COLLECTOR_GATEWAY','snap7'].includes(data?.provider)"
|
v-if="['MODBUS_TCP', 'COLLECTOR_GATEWAY','snap7', 'iec104'].includes(data?.provider)"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handlAdd"
|
@click="handlAdd"
|
||||||
hasPermission="DataCollect/Collector:add"
|
hasPermission="DataCollect/Collector:add"
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
新增点位
|
新增点位
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
v-if="['MODBUS_TCP', 'COLLECTOR_GATEWAY','snap7'].includes(data?.provider)"
|
v-if="['MODBUS_TCP', 'COLLECTOR_GATEWAY','snap7', 'iec104'].includes(data?.provider)"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleImport"
|
@click="handleImport"
|
||||||
hasPermission="DataCollect/Collector:add"
|
hasPermission="DataCollect/Collector:add"
|
||||||
|
@ -324,6 +324,7 @@
|
||||||
@change="saveChange"
|
@change="saveChange"
|
||||||
/>
|
/>
|
||||||
<SaveS7 v-if="visible.saveS7" :data="current" @change="saveChange"/>
|
<SaveS7 v-if="visible.saveS7" :data="current" @change="saveChange"/>
|
||||||
|
<SaveIEC104 v-if="visible.saveIEC104" :data="current" @change="saveChange"/>
|
||||||
<Scan v-if="visible.scan" :data="current" @change="saveChange" />
|
<Scan v-if="visible.scan" :data="current" @change="saveChange" />
|
||||||
<Import v-if="visible.import" :data="current" @close-import="closeImport"/>
|
<Import v-if="visible.import" :data="current" @close-import="closeImport"/>
|
||||||
</j-spin>
|
</j-spin>
|
||||||
|
@ -352,6 +353,7 @@ import { map } from 'rxjs/operators';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { responsiveArray } from 'ant-design-vue/lib/_util/responsiveObserve';
|
import { responsiveArray } from 'ant-design-vue/lib/_util/responsiveObserve';
|
||||||
import SaveS7 from './Save/SaveS7.vue';
|
import SaveS7 from './Save/SaveS7.vue';
|
||||||
|
import SaveIEC104 from './Save/SaveIEC104.vue';
|
||||||
import Import from './components/Import/index.vue'
|
import Import from './components/Import/index.vue'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
@ -366,10 +368,12 @@ const opcImage = getImage('/DataCollect/device-opcua.png');
|
||||||
const modbusImage = getImage('/DataCollect/device-modbus.png');
|
const modbusImage = getImage('/DataCollect/device-modbus.png');
|
||||||
const s7Image = getImage('/DataCollect/s7.png')
|
const s7Image = getImage('/DataCollect/s7.png')
|
||||||
const gatewayImage = getImage('/DataCollect/gateway.png')
|
const gatewayImage = getImage('/DataCollect/gateway.png')
|
||||||
|
const iecImage = getImage('/DataCollect/IEC104.png')
|
||||||
const ImageMap = new Map()
|
const ImageMap = new Map()
|
||||||
ImageMap.set('OPC_UA',opcImage)
|
ImageMap.set('OPC_UA',opcImage)
|
||||||
ImageMap.set('MODBUS_TCP',modbusImage)
|
ImageMap.set('MODBUS_TCP',modbusImage)
|
||||||
ImageMap.set('snap7',s7Image)
|
ImageMap.set('snap7',s7Image)
|
||||||
|
ImageMap.set('iec104',iecImage)
|
||||||
ImageMap.set('COLLECTOR_GATEWAY',gatewayImage)
|
ImageMap.set('COLLECTOR_GATEWAY',gatewayImage)
|
||||||
|
|
||||||
|
|
||||||
|
@ -380,7 +384,8 @@ const visible = reactive({
|
||||||
batchUpdate: false,
|
batchUpdate: false,
|
||||||
scan: false,
|
scan: false,
|
||||||
saveS7:false,
|
saveS7:false,
|
||||||
import:false
|
import:false,
|
||||||
|
saveIEC104: false
|
||||||
});
|
});
|
||||||
const current: any = ref({});
|
const current: any = ref({});
|
||||||
const accessModesOption = ref();
|
const accessModesOption = ref();
|
||||||
|
@ -500,7 +505,13 @@ const handlAdd = () => {
|
||||||
provider: props.data?.provider,
|
provider: props.data?.provider,
|
||||||
deviceType:props.data?.configuration.type,
|
deviceType:props.data?.configuration.type,
|
||||||
}
|
}
|
||||||
}else{
|
}else if (props.data?.provider === 'iec104'){
|
||||||
|
visible.saveIEC104 = true;
|
||||||
|
current.value = {
|
||||||
|
collectorId: props.data?.id,
|
||||||
|
provider: props.data?.provider,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
visible.saveModBus = true;
|
visible.saveModBus = true;
|
||||||
current.value = {
|
current.value = {
|
||||||
collectorId: props.data?.id,
|
collectorId: props.data?.id,
|
||||||
|
@ -514,7 +525,9 @@ const handlEdit = (data: any) => {
|
||||||
visible.saveOPCUA = true;
|
visible.saveOPCUA = true;
|
||||||
} else if(data?.provider === 'snap7'){
|
} else if(data?.provider === 'snap7'){
|
||||||
visible.saveS7 = true
|
visible.saveS7 = true
|
||||||
}else{
|
} else if(data?.provider === 'iec104') {
|
||||||
|
visible.saveIEC104 = true
|
||||||
|
} else {
|
||||||
visible.saveModBus = true;
|
visible.saveModBus = true;
|
||||||
}
|
}
|
||||||
current.value = cloneDeep({
|
current.value = cloneDeep({
|
||||||
|
|
|
@ -67,6 +67,20 @@
|
||||||
<j-radio-button :value="true">串行</j-radio-button>
|
<j-radio-button :value="true">串行</j-radio-button>
|
||||||
</j-radio-group>
|
</j-radio-group>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
<template v-if="provider === 'iec104'">
|
||||||
|
<j-form-item label="从机地址" :name="['configuration', 'host']" :rules="LeftTreeRules.host">
|
||||||
|
<j-input v-model:value="formData.configuration.host" autocomplete="off" placeholder="请输入" :disabled="false"/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item label="从机端口" :name="['configuration', 'port']" >
|
||||||
|
<j-input-number style="width: 100%" v-model:value="formData.configuration.port" :precision="0" autocomplete="off" placeholder="请输入从机端口"/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item label="分组地址" :name="['configuration', 'terminnalAddress']" :rules="LeftTreeRules.terminnalAddress">
|
||||||
|
<j-input-number style="width: 100%" :min="0" :max="65535" :precision="0" v-model:value="formData.configuration.terminnalAddress" autocomplete="off" placeholder="请输入分组地址"></j-input-number>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item label="确认帧数量" :name="['configuration', 'frameAmountMax']" :rules="LeftTreeRules.frameAmountMax">
|
||||||
|
<j-input-number style="width: 100%" v-model:value="formData.configuration.frameAmountMax" placeholder="请输入确认帧数量" :min="1" :maxlength="16" :precision="0"></j-input-number>
|
||||||
|
</j-form-item>
|
||||||
|
</template>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-if="provider === 'COLLECTOR_GATEWAY'"
|
v-if="provider === 'COLLECTOR_GATEWAY'"
|
||||||
label="通讯协议"
|
label="通讯协议"
|
||||||
|
|
|
@ -271,6 +271,8 @@ export const LeftTreeRules = {
|
||||||
timeout: [{ required: true, trigger: 'blur', validator: validator4 }],
|
timeout: [{ required: true, trigger: 'blur', validator: validator4 }],
|
||||||
type: [{required: true, trigger: 'change', message: '请选择型号'}],
|
type: [{required: true, trigger: 'change', message: '请选择型号'}],
|
||||||
serializable: [{required: true, trigger: 'change', message: '请选择型号'}],
|
serializable: [{required: true, trigger: 'change', message: '请选择型号'}],
|
||||||
|
terminnalAddress: [{required: true, trigger: 'blur', message: '请输入分组地址'}],
|
||||||
|
frameAmountMax: [{required: true, message: '请输入确认帧数量', trigger: 'blur'}],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FormTableColumns = [
|
export const FormTableColumns = [
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<j-spin :spinning="spinning">
|
<j-spin :spinning="spinning">
|
||||||
<Point v-if="data || data === undefined" :data="data" />
|
<Point v-if="data" :data="data" />
|
||||||
<j-empty style="margin-top: 20%" v-else />
|
<j-empty style="margin-top: 20%" v-else />
|
||||||
</j-spin>
|
</j-spin>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -113,10 +113,11 @@
|
||||||
<j-scrollbar>
|
<j-scrollbar>
|
||||||
<div class="title">功能说明</div>
|
<div class="title">功能说明</div>
|
||||||
<p>
|
<p>
|
||||||
该功能用于将插件中的
|
该功能用于将插件/协议包中的
|
||||||
<b>物模型属性标识</b>与
|
<b>物模型属性标识</b>与
|
||||||
<b>平台物模型属性标识</b
|
<b>平台物模型属性标识</b
|
||||||
>进行映射,当两方属性标识不一致时,可在当前页面直接修改映射管理,系统将以映射后的物模型属性进行数据处理。
|
>进行映射,当两方属性标识不一致时,可在当前页面直接修改映射管理,系统将以
|
||||||
|
<b>映射后</b>的<b>物模型属性</b>进行数据处理。
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
未完成映射的属性标识“目标属性”列数据为空,代表该属性值来源以在平台配置的来源为准。
|
未完成映射的属性标识“目标属性”列数据为空,代表该属性值来源以在平台配置的来源为准。
|
||||||
|
|
|
@ -315,7 +315,9 @@ const getProtocol = async () => {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (productStore.current?.accessProvider === 'plugin_gateway') {
|
//当前设备接入选择的协议
|
||||||
|
const protocol = res.result?.transports.find(item => item.id === productStore.current.transportProtocol);
|
||||||
|
if(protocol?.features.find(item => item.id === 'diffMetadataSameProduct')){
|
||||||
list.value.push({ key: 'MetadataMap', tab: '物模型映射'})
|
list.value.push({ key: 'MetadataMap', tab: '物模型映射'})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
:label="item?.name"
|
:label="item?.name"
|
||||||
v-for="(item, index) in variableDefinitions"
|
v-for="(item, index) in variableDefinitions"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:required="getType(item) !== 'file' ? true : false"
|
:required="!['file', 'user', 'org', 'tag'].includes(getType(item)) ? true : false"
|
||||||
:rules="[
|
:rules="[
|
||||||
{
|
{
|
||||||
validator: (_rule, value) => checkValue(_rule, value, item),
|
validator: (_rule, value) => checkValue(_rule, value, item),
|
||||||
|
@ -62,6 +62,7 @@ import Tag from './variableItem/Tag.vue';
|
||||||
import InputFile from './variableItem/InputFile.vue';
|
import InputFile from './variableItem/InputFile.vue';
|
||||||
import User from './variableItem/User.vue';
|
import User from './variableItem/User.vue';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
variableDefinitions: {
|
variableDefinitions: {
|
||||||
|
@ -209,6 +210,13 @@ const onChange = (val: any, type: any, index: number, options?: string) => {
|
||||||
|
|
||||||
const onSave = () =>
|
const onSave = () =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
|
const pass = props.variableDefinitions.filter(item => ['user', 'org', 'tag'].includes(getType(item))).some(item => {
|
||||||
|
return modelRef[item.id]
|
||||||
|
})
|
||||||
|
if(!pass) {
|
||||||
|
onlyMessage('收信人,收信人部门,收信人标签至少填写一个', 'warning')
|
||||||
|
return reject(false)
|
||||||
|
}
|
||||||
formRef.value?.validate().then((_data: any) => {
|
formRef.value?.validate().then((_data: any) => {
|
||||||
resolve(_data);
|
resolve(_data);
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
|
Loading…
Reference in New Issue