feat: 采集器 OPCUA扫描全部功能
This commit is contained in:
parent
4e51d021eb
commit
721409dfb0
|
@ -42,3 +42,13 @@ export const readPoint = (collectorId: string, data: string[]) =>
|
|||
|
||||
export const writePoint = (collectorId: string, data: string[]) =>
|
||||
server.post(`/data-collect/collector/${collectorId}/points/_write`, data);
|
||||
|
||||
export const queryPointNoPaging = () =>
|
||||
server.post(`/data-collect/point/_query/no-paging`, { paging: false });
|
||||
|
||||
export const scanOpcUAList = (data: any) =>
|
||||
server.get(
|
||||
`/data-collect/opc/channel/${data.id}/nodes?nodeId=${
|
||||
data?.nodeId || ''
|
||||
}`,
|
||||
);
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
<template>
|
||||
<j-form style="width: 80%" ref="formTableRef" :model="modelRef">
|
||||
<j-table
|
||||
:dataSource="modelRef.dataSource"
|
||||
:columns="FormTableColumns"
|
||||
:scroll="{ x: 1100, y: 500 }"
|
||||
>
|
||||
<template #bodyCell="{ column: { dataIndex }, record, index }">
|
||||
<template v-if="dataIndex === 'name'">
|
||||
<a-form-item
|
||||
:name="['dataSource', index, 'name']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="record[dataIndex]"
|
||||
placeholder="请输入"
|
||||
allowClear
|
||||
></j-input>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<template v-if="dataIndex === 'id'">
|
||||
<a-form-item :name="['dataSource', index, 'id']">
|
||||
<j-input v-model:value="record[dataIndex]" disabled>
|
||||
</j-input>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="dataIndex === 'accessModes'">
|
||||
<a-form-item
|
||||
class="form-item"
|
||||
:name="['dataSource', index, 'accessModes', 'value']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<j-select
|
||||
style="width: 75%"
|
||||
v-model:value="record[dataIndex].value"
|
||||
placeholder="请选择"
|
||||
allowClear
|
||||
mode="multiple"
|
||||
:filter-option="filterOption"
|
||||
:options="[
|
||||
{ label: '读', value: 'read' },
|
||||
{ label: '写', value: 'write' },
|
||||
{ label: '订阅', value: 'subscribe' },
|
||||
]"
|
||||
:disabled="index !== 0 && record[dataIndex].check"
|
||||
@change="changeValue(index, dataIndex)"
|
||||
>
|
||||
</j-select>
|
||||
<j-checkbox
|
||||
style="margin-left: 5px"
|
||||
v-if="index !== 0"
|
||||
v-model:checked="record[dataIndex].check"
|
||||
@click="changeCheckbox(index, dataIndex)"
|
||||
>同上</j-checkbox
|
||||
>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<template v-if="dataIndex === 'interval'">
|
||||
<a-form-item
|
||||
class="form-item"
|
||||
:name="[
|
||||
'dataSource',
|
||||
index,
|
||||
'configuration',
|
||||
'interval',
|
||||
'value',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
style="width: 70%"
|
||||
v-model:value="
|
||||
record.configuration[dataIndex].value
|
||||
"
|
||||
placeholder="请输入"
|
||||
allowClear
|
||||
addon-after="ms"
|
||||
:disabled="
|
||||
index !== 0 &&
|
||||
record.configuration[dataIndex].check
|
||||
"
|
||||
@blur="changeValue(index, dataIndex)"
|
||||
></j-input>
|
||||
<j-checkbox
|
||||
style="margin-left: 5px"
|
||||
v-show="index !== 0"
|
||||
v-model:checked="
|
||||
record.configuration[dataIndex].check
|
||||
"
|
||||
@click="changeCheckbox(index, dataIndex)"
|
||||
>同上</j-checkbox
|
||||
>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<template v-if="dataIndex === 'features'">
|
||||
<a-form-item
|
||||
class="form-item"
|
||||
:name="['dataSource', index, 'features', 'value']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请选择',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<j-select
|
||||
style="width: 50%"
|
||||
v-model:value="record[dataIndex].value"
|
||||
placeholder="请选择"
|
||||
allowClear
|
||||
:filter-option="filterOption"
|
||||
:options="[
|
||||
{
|
||||
label: '是',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: '否',
|
||||
value: false,
|
||||
},
|
||||
]"
|
||||
:disabled="index !== 0 && record[dataIndex].check"
|
||||
@change="changeValue(index, dataIndex)"
|
||||
>
|
||||
</j-select>
|
||||
|
||||
<j-checkbox
|
||||
style="margin-left: 5px"
|
||||
v-show="index !== 0"
|
||||
v-model:checked="record[dataIndex].check"
|
||||
@click="changeCheckbox(index, dataIndex)"
|
||||
>同上</j-checkbox
|
||||
>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="dataIndex === 'action'">
|
||||
<a-tooltip title="删除">
|
||||
<a-popconfirm
|
||||
title="确认删除"
|
||||
@confirm="clickDelete(record.id)"
|
||||
>
|
||||
<AIcon type="DeleteOutlined" />
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</template>
|
||||
</j-table>
|
||||
</j-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { FormTableColumns } from '../../data';
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['change']);
|
||||
|
||||
const formTableRef = ref();
|
||||
const defaultType = ['accessModes', 'interval', 'features'];
|
||||
const modelRef = reactive({
|
||||
dataSource: [],
|
||||
});
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
const clickDelete = (value: string) => {
|
||||
emits('change', value);
|
||||
};
|
||||
|
||||
const getTargetData = (index: number, type: string) => {
|
||||
const { dataSource } = modelRef;
|
||||
const Interval = type === 'interval';
|
||||
return !Interval
|
||||
? dataSource[index][type]
|
||||
: dataSource[index].configuration[type];
|
||||
};
|
||||
|
||||
const changeValue = (index: number, type: string) => {
|
||||
const { dataSource } = modelRef;
|
||||
const originData = getTargetData(index, type);
|
||||
for (let i = index + 1; i < dataSource.length; i++) {
|
||||
const targetType = getTargetData(i, type);
|
||||
if (!targetType.check) return;
|
||||
targetType.value = originData.value;
|
||||
}
|
||||
};
|
||||
|
||||
const changeCheckbox = (index: number, type: string) => {
|
||||
// console.log(1, getTargetData(index, type).check,getTargetData(index, type));
|
||||
//如果不使用setTimeout,会导致值更新不及时
|
||||
setTimeout(() => {
|
||||
// console.log(2, getTargetData(index, type).check,getTargetData(index, type));
|
||||
let startIndex = 0;
|
||||
const { dataSource } = modelRef;
|
||||
const currentCheck = getTargetData(index, type).check;
|
||||
if (!currentCheck) return;
|
||||
for (let i = index; i >= 0; i--) {
|
||||
const preDatCheck = getTargetData(i, type).check;
|
||||
if (!preDatCheck) {
|
||||
startIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const originData = getTargetData(startIndex, type);
|
||||
for (let i = startIndex; i < dataSource.length - 1; i++) {
|
||||
const targetType = getTargetData(i + 1, type);
|
||||
if (!targetType.check) return;
|
||||
targetType.value = originData.value;
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const validate = () => {
|
||||
return new Promise((res, rej) => {
|
||||
formTableRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
res(modelRef.dataSource);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
rej(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
defineExpose({
|
||||
validate,
|
||||
});
|
||||
watch(
|
||||
() => props.data,
|
||||
(value, preValue) => {
|
||||
modelRef.dataSource = value;
|
||||
|
||||
// 有新增时同上数据
|
||||
const vlength = value.length,
|
||||
plength = preValue.length;
|
||||
if (plength !== 0 && plength < vlength) {
|
||||
defaultType.forEach((type) => {
|
||||
vlength === 2
|
||||
? changeValue(0, type)
|
||||
: changeCheckbox(vlength - 1, type);
|
||||
});
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.form-item {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,240 @@
|
|||
<template>
|
||||
<div class="tree-content">
|
||||
<div class="tree-header">
|
||||
<div>数据源</div>
|
||||
<j-checkbox v-model:checked="isSelected">隐藏已有节点</j-checkbox>
|
||||
</div>
|
||||
<j-spin :spinning="spinning">
|
||||
<a-tree
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
:tree-data="treeData"
|
||||
default-expand-all
|
||||
checkable
|
||||
@check="onCheck"
|
||||
:height="600"
|
||||
>
|
||||
<!-- <a-tree
|
||||
:load-data="onLoadData"
|
||||
:tree-data="treeData"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
checkable
|
||||
@check="onCheck"
|
||||
> -->
|
||||
<template #title="{ name, key }">
|
||||
<span
|
||||
:class="[
|
||||
selectKeys.includes(key)
|
||||
? 'tree-selected'
|
||||
: 'tree-title',
|
||||
]"
|
||||
>
|
||||
{{ name }}
|
||||
</span>
|
||||
</template>
|
||||
</a-tree>
|
||||
</j-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { TreeProps } from 'ant-design-vue';
|
||||
import {
|
||||
scanOpcUAList,
|
||||
queryPointNoPaging,
|
||||
} from '@/api/data-collect/collector';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
unSelectKeys: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['change']);
|
||||
|
||||
// const channelId = '1610517801347788800'; //测试
|
||||
const channelId = props.data?.channelId;
|
||||
|
||||
const checkedKeys = ref<string[]>([]);
|
||||
const selectKeys = ref<string[]>([]);
|
||||
const spinning = ref(false);
|
||||
|
||||
const isSelected = ref(false);
|
||||
const treeData = ref<TreeProps['treeData']>();
|
||||
const treeAllData = ref<TreeProps['treeData']>();
|
||||
|
||||
const onLoadData = (node: any) =>
|
||||
new Promise<void>(async (resolve) => {
|
||||
if ((node?.children && node.children?.length) || !node?.folder) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const resp = await scanOpcUAList({
|
||||
id: channelId,
|
||||
nodeId: node.key,
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
const list = resp.result.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
key: item.id,
|
||||
title: item.name,
|
||||
disabled: item?.folder,
|
||||
isLeaf: !item?.folder,
|
||||
};
|
||||
});
|
||||
|
||||
treeAllData.value = updateTreeData(
|
||||
cloneDeep(treeAllData.value),
|
||||
node.key,
|
||||
[...list],
|
||||
);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
|
||||
const handleData = (arr: any[]): any[] => {
|
||||
const data = arr.filter((item) => {
|
||||
return (
|
||||
(isSelected && !selectKeys.value.includes(item.id)) || !isSelected
|
||||
);
|
||||
});
|
||||
return data.map((item) => {
|
||||
if (item.children && item.children?.length) {
|
||||
return {
|
||||
...item,
|
||||
children: handleData(item.children),
|
||||
};
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onCheck = (checkedKeys, info) => {
|
||||
const one: any = { ...info.node };
|
||||
const list: any = [];
|
||||
const last: any = list.length ? list[list.length - 1] : undefined;
|
||||
if (list.map((i: any) => i?.id).includes(one.id)) {
|
||||
return;
|
||||
}
|
||||
const item = {
|
||||
features: {
|
||||
value: last
|
||||
? last?.features?.value
|
||||
: (one?.features || []).includes('changedOnly'),
|
||||
check: true,
|
||||
},
|
||||
id: one?.id || '',
|
||||
name: one?.name || '',
|
||||
accessModes: {
|
||||
value: last ? last?.accessModes?.value : one?.accessModes || [],
|
||||
check: true,
|
||||
},
|
||||
configuration: {
|
||||
...one?.configuration,
|
||||
interval: {
|
||||
value: last
|
||||
? last?.configuration?.interval?.value
|
||||
: one?.configuration?.interval || 3000,
|
||||
check: true,
|
||||
},
|
||||
nodeId: one?.id,
|
||||
},
|
||||
};
|
||||
emits('change', item, info.checked);
|
||||
};
|
||||
|
||||
const updateTreeData = (list: any[], key: string, children: any[]): any[] => {
|
||||
const arr = list.map((node) => {
|
||||
if (node.key === key) {
|
||||
return {
|
||||
...node,
|
||||
children,
|
||||
};
|
||||
}
|
||||
if (node?.children && node?.children?.length) {
|
||||
return {
|
||||
...node,
|
||||
children: updateTreeData(node.children, key, children),
|
||||
};
|
||||
}
|
||||
return node;
|
||||
});
|
||||
return arr;
|
||||
};
|
||||
|
||||
const getPoint = async () => {
|
||||
spinning.value = true;
|
||||
const res = await queryPointNoPaging();
|
||||
if (res.status === 200) {
|
||||
selectKeys.value = res.result.map((item: any) => item.pointKey);
|
||||
}
|
||||
spinning.value = false;
|
||||
};
|
||||
getPoint();
|
||||
|
||||
const getScanOpcUAList = async () => {
|
||||
const res = await scanOpcUAList({ id: channelId });
|
||||
treeAllData.value = res.result.map((item: any) => ({
|
||||
...item,
|
||||
key: item.id,
|
||||
title: item.name,
|
||||
disabled: item?.folder || false,
|
||||
}));
|
||||
};
|
||||
getScanOpcUAList();
|
||||
|
||||
watch(
|
||||
() => isSelected.value,
|
||||
(value) => {
|
||||
if (value) {
|
||||
treeData.value = handleData(treeAllData.value);
|
||||
} else {
|
||||
treeData.value = treeAllData.value;
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
watch(
|
||||
() => treeAllData.value,
|
||||
(value) => {
|
||||
if (isSelected.value) {
|
||||
treeData.value = handleData(value);
|
||||
} else {
|
||||
treeData.value = value;
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.unSelectKeys,
|
||||
(value) => {
|
||||
checkedKeys.value = checkedKeys.value.filter((i) => i !== value);
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tree-content {
|
||||
padding: 16px;
|
||||
padding-left: 0;
|
||||
.tree-header {
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.tree-selected {
|
||||
color: #1d39c4;
|
||||
}
|
||||
.tree-title {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,107 @@
|
|||
<template lang="">
|
||||
<j-modal title="扫描" :visible="true" width="90%" @cancel="handleCancel">
|
||||
<div class="content">
|
||||
<Tree
|
||||
:data="treeData"
|
||||
class="tree"
|
||||
@change="changeTree"
|
||||
:unSelectKeys="unSelectKeys"
|
||||
></Tree>
|
||||
<Table
|
||||
:data="tableData"
|
||||
class="table"
|
||||
@change="changeTable"
|
||||
ref="formTableRef"
|
||||
></Table>
|
||||
</div>
|
||||
<template #footer>
|
||||
<j-button key="back" @click="handleCancel">取消</j-button>
|
||||
<PermissionButton
|
||||
key="submit"
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="handleOk"
|
||||
style="margin-left: 8px"
|
||||
:hasPermission="`DataCollect/Collector:update`"
|
||||
>
|
||||
确认
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-modal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
import { savePointBatch } from '@/api/data-collect/collector';
|
||||
import { Rule } from 'ant-design-vue/lib/form';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import Table from './Table.vue';
|
||||
import Tree from './Tree.vue';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const treeData = ref(props.data);
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
const loading = ref(false);
|
||||
const formTableRef = ref<FormInstance>();
|
||||
const tableData = ref();
|
||||
const tableDataMap = new Map();
|
||||
const unSelectKeys = ref();
|
||||
|
||||
const handleOk = async () => {
|
||||
loading.value = true;
|
||||
const data = await formTableRef.value?.validate();
|
||||
const list = data.map((item: any) => {
|
||||
return {
|
||||
name: item.name,
|
||||
provider: 'OPC_UA',
|
||||
collectorId: props.data?.id,
|
||||
collectorName: props.data?.name,
|
||||
pointKey: item.id,
|
||||
configuration: {
|
||||
interval: item.configuration?.interval?.value,
|
||||
},
|
||||
features: !item.features?.value ? [] : ['changedOnly'],
|
||||
accessModes: item.accessModes?.value || [],
|
||||
};
|
||||
});
|
||||
console.log(1112, props.data, data, list);
|
||||
const resp = await savePointBatch([...list]);
|
||||
if (resp.status === 200) {
|
||||
emit('change', true);
|
||||
}
|
||||
loading.value = false;
|
||||
};
|
||||
const handleCancel = () => {
|
||||
emit('change', false);
|
||||
};
|
||||
|
||||
const changeTree = (row: any, checked: boolean) => {
|
||||
checked ? tableDataMap.set(row.id, row) : tableDataMap.delete(row.id);
|
||||
tableData.value = [...tableDataMap.values()];
|
||||
};
|
||||
const changeTable = (value: string) => {
|
||||
unSelectKeys.value = value;
|
||||
tableDataMap.delete(value);
|
||||
tableData.value = [...tableDataMap.values()];
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.content {
|
||||
display: flex;
|
||||
min-height: 600px;
|
||||
.tree {
|
||||
width: 300px;
|
||||
}
|
||||
.table {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -13,19 +13,7 @@
|
|||
:gridColumn="2"
|
||||
:gridColumns="[1, 2]"
|
||||
:request="queryPoint"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'id', order: 'desc' }],
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'collectorId',
|
||||
value: props.data.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}"
|
||||
:defaultParams="defaultParams"
|
||||
:params="params"
|
||||
:rowSelection="{
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
|
@ -36,12 +24,23 @@
|
|||
<template #headerTitle>
|
||||
<j-space>
|
||||
<PermissionButton
|
||||
v-if="data?.provider !== 'OPC_UA'"
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="DataCollect/Collector:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
{{ data?.provider === 'OPC_UA' ? '扫描' : '新增点位' }}
|
||||
新增点位
|
||||
</PermissionButton>
|
||||
|
||||
<PermissionButton
|
||||
v-if="data?.provider === 'OPC_UA'"
|
||||
type="primary"
|
||||
@click="handlScan"
|
||||
hasPermission="DataCollect/Collector:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
扫描
|
||||
</PermissionButton>
|
||||
<j-dropdown v-if="data?.provider === 'OPC_UA'">
|
||||
<j-button
|
||||
|
@ -168,29 +167,29 @@
|
|||
</template>
|
||||
</j-pro-table>
|
||||
<SaveModBus
|
||||
v-if="visibleSaveModBus"
|
||||
v-if="visible.saveModBus"
|
||||
:data="current"
|
||||
@change="saveChange"
|
||||
/>
|
||||
<SaveOPCUA
|
||||
v-if="visibleSaveOPCUA"
|
||||
v-if="visible.saveOPCUA"
|
||||
:data="current"
|
||||
@change="saveChange"
|
||||
/>
|
||||
<WritePoint
|
||||
v-if="visibleWritePoint"
|
||||
v-if="visible.writePoint"
|
||||
:data="current"
|
||||
@change="saveChange"
|
||||
/>
|
||||
<BatchUpdate
|
||||
v-if="visibleBatchUpdate"
|
||||
v-if="visible.batchUpdate"
|
||||
:data="current"
|
||||
@change="saveChange"
|
||||
/>
|
||||
<Scan v-if="visible.scan" :data="current" @change="saveChange" />
|
||||
</j-spin>
|
||||
</template>
|
||||
<script lang="ts" setup name="PointPage">
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import {
|
||||
queryPoint,
|
||||
|
@ -205,6 +204,7 @@ import WritePoint from './components/WritePoint/index.vue';
|
|||
import BatchUpdate from './components/BatchUpdate/index.vue';
|
||||
import SaveModBus from './Save/SaveModBus.vue';
|
||||
import SaveOPCUA from './Save/SaveOPCUA.vue';
|
||||
import Scan from './Scan/index.vue';
|
||||
import { colorMap, getState } from '../data.ts';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
|
@ -220,15 +220,34 @@ const tableRef = ref<Record<string, any>>({});
|
|||
const params = ref<Record<string, any>>({});
|
||||
const opcImage = getImage('/DataCollect/device-opcua.png');
|
||||
const modbusImage = getImage('/DataCollect/device-modbus.png');
|
||||
const visibleSaveModBus = ref(false);
|
||||
const visibleSaveOPCUA = ref(false);
|
||||
const visibleWritePoint = ref(false);
|
||||
const visibleBatchUpdate = ref(false);
|
||||
const visible = reactive({
|
||||
saveModBus: false,
|
||||
saveOPCUA: false,
|
||||
writePoint: false,
|
||||
batchUpdate: false,
|
||||
scan: false,
|
||||
});
|
||||
const current = ref({});
|
||||
const accessModesOption = ref();
|
||||
const _selectedRowKeys = ref<string[]>([]);
|
||||
|
||||
const spinning = ref(false);
|
||||
const collectorId = ref(props.data.id);
|
||||
|
||||
const defaultParams = ref({
|
||||
sorts: [{ name: 'id', order: 'desc' }],
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'collectorId',
|
||||
value: collectorId.value,
|
||||
// value: '1610517928766550016', //测试
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const accessModesMODBUS_TCP = [
|
||||
{
|
||||
|
@ -314,21 +333,21 @@ const columns = [
|
|||
];
|
||||
|
||||
const handlAdd = () => {
|
||||
visibleSaveModBus.value = true;
|
||||
visible.saveModBus = true;
|
||||
current.value = {
|
||||
collectorId: props.data.id,
|
||||
collectorId: collectorId.value,
|
||||
provider: props.data?.provider || 'MODBUS_TCP',
|
||||
};
|
||||
};
|
||||
const handlEdit = (data: Object) => {
|
||||
if (data?.provider === 'OPC_UA') {
|
||||
visibleSaveOPCUA.value = true;
|
||||
visible.saveOPCUA = true;
|
||||
} else {
|
||||
visibleSaveModBus.value = true;
|
||||
visible.saveModBus = true;
|
||||
}
|
||||
current.value = cloneDeep(data);
|
||||
};
|
||||
const handlDelete = async (data: string | undefined) => {
|
||||
const handlDelete = async (data: string | undefined = undefined) => {
|
||||
spinning.value = true;
|
||||
const res = !data
|
||||
? await batchDeletePoint(_selectedRowKeys.value)
|
||||
|
@ -340,7 +359,6 @@ const handlDelete = async (data: string | undefined) => {
|
|||
}
|
||||
spinning.value = false;
|
||||
};
|
||||
|
||||
const handlBatchUpdate = () => {
|
||||
const dataSet = new Set(_selectedRowKeys.value);
|
||||
const dataMap = new Map();
|
||||
|
@ -348,10 +366,14 @@ const handlBatchUpdate = () => {
|
|||
dataSet.has(i.id) && dataMap.set(i.id, i);
|
||||
});
|
||||
current.value = [...dataMap.values()];
|
||||
visibleBatchUpdate.value = true;
|
||||
visible.batchUpdate = true;
|
||||
};
|
||||
const handlScan = () => {
|
||||
visible.scan = true;
|
||||
current.value = cloneDeep(props.data);
|
||||
};
|
||||
const clickEdit = async (data: object) => {
|
||||
visibleWritePoint.value = true;
|
||||
visible.writePoint = true;
|
||||
current.value = cloneDeep(data);
|
||||
};
|
||||
const clickRedo = async (data: object) => {
|
||||
|
@ -389,20 +411,10 @@ const getAccessModes = (item: Partial<Record<string, any>>) => {
|
|||
return item?.accessModes?.map((i) => i?.value);
|
||||
};
|
||||
|
||||
const getaccessModesOption = () => {
|
||||
return props.data?.provider !== 'MODBUS_TCP'
|
||||
? accessModesMODBUS_TCP.concat({
|
||||
label: '订阅',
|
||||
value: 'subscribe',
|
||||
})
|
||||
: accessModesMODBUS_TCP;
|
||||
};
|
||||
|
||||
const saveChange = (value: object) => {
|
||||
visibleSaveModBus.value = false;
|
||||
visibleSaveOPCUA.value = false;
|
||||
visibleWritePoint.value = false;
|
||||
visibleBatchUpdate.value = false;
|
||||
for (let key in visible) {
|
||||
visible[key] = false;
|
||||
}
|
||||
current.value = {};
|
||||
if (value) {
|
||||
tableRef.value?.reload();
|
||||
|
@ -438,10 +450,12 @@ watch(
|
|||
label: '订阅',
|
||||
value: 'subscribe',
|
||||
});
|
||||
tableRef?.value?.reload();
|
||||
defaultParams.value.terms[0].terms[0].value = value.id;
|
||||
// defaultParams.value.terms[0].terms[0].value = '1610517928766550016'; //测试
|
||||
tableRef?.value?.reload && tableRef?.value?.reload();
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -117,27 +117,65 @@ export const OPCUARules = {
|
|||
message: '最多可输入64个字符',
|
||||
},
|
||||
],
|
||||
|
||||
type: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择数据类型',
|
||||
},
|
||||
],
|
||||
|
||||
accessModes: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择访问类型',
|
||||
},
|
||||
],
|
||||
|
||||
interval: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入采集频率',
|
||||
},
|
||||
],
|
||||
|
||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||
};
|
||||
|
||||
export const FormTableColumns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 200,
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: 'nodeId',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '访问类型',
|
||||
dataIndex: 'accessModes',
|
||||
key: 'accessModes',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '采集频率',
|
||||
key: 'interval',
|
||||
dataIndex: 'interval',
|
||||
width: 280,
|
||||
},
|
||||
{
|
||||
title: '只推送变化的数据',
|
||||
key: 'features',
|
||||
dataIndex: 'features',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
dataIndex: 'action',
|
||||
|
||||
fixed: 'right',
|
||||
width: 80,
|
||||
},
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue