update: 采集器 右侧卡片新增websocket
This commit is contained in:
parent
08ca907b99
commit
0d749d6867
|
@ -25,7 +25,7 @@
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
"global": "^4.4.0",
|
"global": "^4.4.0",
|
||||||
"jetlinks-store": "^0.0.3",
|
"jetlinks-store": "^0.0.3",
|
||||||
"jetlinks-ui-components": "^1.0.4",
|
"jetlinks-ui-components": "^1.0.5",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
"less-loader": "^11.1.0",
|
"less-loader": "^11.1.0",
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<j-table
|
<j-table
|
||||||
:dataSource="modelRef.dataSource"
|
:dataSource="modelRef.dataSource"
|
||||||
:columns="FormTableColumns"
|
:columns="FormTableColumns"
|
||||||
:scroll="{ x: 1100, y: 500 }"
|
:scroll="{ x: 1100, y: 550 }"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column: { dataIndex }, record, index }">
|
<template #bodyCell="{ column: { dataIndex }, record, index }">
|
||||||
<template v-if="dataIndex === 'name'">
|
<template v-if="dataIndex === 'name'">
|
||||||
|
@ -151,14 +151,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="dataIndex === 'action'">
|
<template v-if="dataIndex === 'action'">
|
||||||
<a-tooltip title="删除">
|
<j-tooltip title="删除">
|
||||||
<a-popconfirm
|
<j-popconfirm
|
||||||
title="确认删除"
|
title="确认删除"
|
||||||
@confirm="clickDelete(record.id)"
|
@confirm="clickDelete(record.id)"
|
||||||
>
|
>
|
||||||
<AIcon type="DeleteOutlined" />
|
<a><AIcon type="DeleteOutlined" /></a>
|
||||||
</a-popconfirm>
|
</j-popconfirm>
|
||||||
</a-tooltip>
|
</j-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</j-table>
|
</j-table>
|
||||||
|
|
|
@ -5,21 +5,15 @@
|
||||||
<j-checkbox v-model:checked="isSelected">隐藏已有节点</j-checkbox>
|
<j-checkbox v-model:checked="isSelected">隐藏已有节点</j-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<j-spin :spinning="spinning">
|
<j-spin :spinning="spinning">
|
||||||
|
|
||||||
<a-tree
|
<a-tree
|
||||||
v-model:checkedKeys="checkedKeys"
|
|
||||||
:tree-data="treeData"
|
|
||||||
default-expand-all
|
|
||||||
checkable
|
|
||||||
@check="onCheck"
|
|
||||||
:height="600"
|
|
||||||
>
|
|
||||||
<!-- <a-tree
|
|
||||||
:load-data="onLoadData"
|
:load-data="onLoadData"
|
||||||
:tree-data="treeData"
|
:tree-data="treeData"
|
||||||
v-model:checkedKeys="checkedKeys"
|
v-model:checkedKeys="checkedKeys"
|
||||||
checkable
|
checkable
|
||||||
@check="onCheck"
|
@check="onCheck"
|
||||||
> -->
|
:height="650"
|
||||||
|
>
|
||||||
<template #title="{ name, key }">
|
<template #title="{ name, key }">
|
||||||
<span
|
<span
|
||||||
:class="[
|
:class="[
|
||||||
|
@ -57,7 +51,7 @@ const props = defineProps({
|
||||||
const emits = defineEmits(['change']);
|
const emits = defineEmits(['change']);
|
||||||
|
|
||||||
// const channelId = '1610517801347788800'; //测试
|
// const channelId = '1610517801347788800'; //测试
|
||||||
const channelId = props.data?.channelId;
|
const channelId = props.data?.channelId;
|
||||||
|
|
||||||
const checkedKeys = ref<string[]>([]);
|
const checkedKeys = ref<string[]>([]);
|
||||||
const selectKeys = ref<string[]>([]);
|
const selectKeys = ref<string[]>([]);
|
||||||
|
|
|
@ -71,7 +71,6 @@ const handleOk = async () => {
|
||||||
accessModes: item.accessModes?.value || [],
|
accessModes: item.accessModes?.value || [],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
console.log(1112, props.data, data, list);
|
|
||||||
const resp = await savePointBatch([...list]);
|
const resp = await savePointBatch([...list]);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
emit('change', true);
|
emit('change', true);
|
||||||
|
|
|
@ -98,18 +98,14 @@
|
||||||
</template>
|
</template>
|
||||||
<template #action>
|
<template #action>
|
||||||
<div class="card-box-action">
|
<div class="card-box-action">
|
||||||
<a>
|
<j-popconfirm
|
||||||
<j-popconfirm
|
title="确定删除?"
|
||||||
title="确定删除?"
|
@confirm="handlDelete(slotProps.id)"
|
||||||
@confirm="handlDelete(slotProps.id)"
|
>
|
||||||
>
|
<a><AIcon type="DeleteOutlined" /></a>
|
||||||
<AIcon type="DeleteOutlined" />
|
</j-popconfirm>
|
||||||
</j-popconfirm>
|
<a @click="handlEdit(slotProps)"
|
||||||
</a>
|
><AIcon type="FormOutlined"
|
||||||
<a
|
|
||||||
><AIcon
|
|
||||||
@click="handlEdit(slotProps)"
|
|
||||||
type="FormOutlined"
|
|
||||||
/></a>
|
/></a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -125,28 +121,63 @@
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="card-box-content">
|
<div class="card-box-content">
|
||||||
<div class="card-box-content-left">
|
<div class="card-box-content-left">
|
||||||
<span>--</span>
|
<div class="card-box-content-left-1">
|
||||||
<a
|
<div
|
||||||
v-if="
|
class="ard-box-content-left-1-title"
|
||||||
getAccessModes(slotProps).includes(
|
v-if="propertyValue.has(slotProps.id)"
|
||||||
'write',
|
>
|
||||||
)
|
<j-ellipsis style="max-width: 150px">
|
||||||
"
|
{{
|
||||||
><AIcon
|
propertyValue.get(slotProps.id)
|
||||||
|
?.parseData[0] || 0
|
||||||
|
}}({{
|
||||||
|
propertyValue.get(slotProps.id)
|
||||||
|
?.dataType
|
||||||
|
}})
|
||||||
|
</j-ellipsis>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span v-else>--</span>
|
||||||
|
<a
|
||||||
|
v-if="
|
||||||
|
getAccessModes(slotProps).includes(
|
||||||
|
'write',
|
||||||
|
)
|
||||||
|
"
|
||||||
@click.stop="clickEdit(slotProps)"
|
@click.stop="clickEdit(slotProps)"
|
||||||
type="EditOutlined"
|
><AIcon type="EditOutlined"
|
||||||
/></a>
|
/></a>
|
||||||
<a
|
<a
|
||||||
v-if="
|
v-if="
|
||||||
getAccessModes(slotProps).includes(
|
getAccessModes(slotProps).includes(
|
||||||
'read',
|
'read',
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
><AIcon
|
|
||||||
@click.stop="clickRedo(slotProps)"
|
@click.stop="clickRedo(slotProps)"
|
||||||
type="RedoOutlined"
|
><AIcon type="RedoOutlined"
|
||||||
/></a>
|
/></a>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="propertyValue.has(slotProps.id)"
|
||||||
|
class="card-box-content-right-2"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
propertyValue.get(slotProps.id)
|
||||||
|
?.hex || ''
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
moment(
|
||||||
|
propertyValue.get(slotProps.id)
|
||||||
|
?.timestamp,
|
||||||
|
).format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-box-content-right">
|
<div class="card-box-content-right">
|
||||||
<div
|
<div
|
||||||
v-if="getRight1(slotProps)"
|
v-if="getRight1(slotProps)"
|
||||||
|
@ -207,6 +238,9 @@ import SaveOPCUA from './Save/SaveOPCUA.vue';
|
||||||
import Scan from './Scan/index.vue';
|
import Scan from './Scan/index.vue';
|
||||||
import { colorMap, getState } from '../data.ts';
|
import { colorMap, getState } from '../data.ts';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
import { getWebSocket } from '@/utils/websocket';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
@ -215,7 +249,6 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const menuStory = useMenuStore();
|
|
||||||
const tableRef = ref<Record<string, any>>({});
|
const tableRef = ref<Record<string, any>>({});
|
||||||
const params = ref<Record<string, any>>({});
|
const params = ref<Record<string, any>>({});
|
||||||
const opcImage = getImage('/DataCollect/device-opcua.png');
|
const opcImage = getImage('/DataCollect/device-opcua.png');
|
||||||
|
@ -242,7 +275,6 @@ const defaultParams = ref({
|
||||||
{
|
{
|
||||||
column: 'collectorId',
|
column: 'collectorId',
|
||||||
value: collectorId.value,
|
value: collectorId.value,
|
||||||
// value: '1610517928766550016', //测试
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -332,6 +364,9 @@ const columns = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const subRef = ref();
|
||||||
|
const propertyValue = ref(new Map());
|
||||||
|
|
||||||
const handlAdd = () => {
|
const handlAdd = () => {
|
||||||
visible.saveModBus = true;
|
visible.saveModBus = true;
|
||||||
current.value = {
|
current.value = {
|
||||||
|
@ -431,6 +466,7 @@ const cancelSelect = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = (dt: any) => {
|
const handleClick = (dt: any) => {
|
||||||
|
if (props.data?.provider !== 'OPC_UA') return;
|
||||||
if (_selectedRowKeys.value.includes(dt.id)) {
|
if (_selectedRowKeys.value.includes(dt.id)) {
|
||||||
const _index = _selectedRowKeys.value.findIndex((i) => i === dt.id);
|
const _index = _selectedRowKeys.value.findIndex((i) => i === dt.id);
|
||||||
_selectedRowKeys.value.splice(_index, 1);
|
_selectedRowKeys.value.splice(_index, 1);
|
||||||
|
@ -439,6 +475,32 @@ const handleClick = (dt: any) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const subscribeProperty = (value: any) => {
|
||||||
|
const list = value.map((item: any) => item.id);
|
||||||
|
const id = `collector-${props.data?.channelId || 'channel'}-${
|
||||||
|
props.data?.id || 'point'
|
||||||
|
}-data-${list.join('-')}`;
|
||||||
|
const topic = `/collector/${props.data?.channelId || '*'}/${
|
||||||
|
props.data?.id || '*'
|
||||||
|
}/data`;
|
||||||
|
subRef.value = getWebSocket(id, topic, {
|
||||||
|
pointId: list.join(','),
|
||||||
|
})
|
||||||
|
?.pipe(map((res) => res.payload))
|
||||||
|
.subscribe((payload: any) => {
|
||||||
|
propertyValue.value.set(payload.pointId, payload);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => tableRef?.value?._dataSource,
|
||||||
|
(value) => {
|
||||||
|
if (value.length !== 0) {
|
||||||
|
subscribeProperty(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(value) => {
|
(value) => {
|
||||||
|
@ -451,13 +513,19 @@ watch(
|
||||||
value: 'subscribe',
|
value: 'subscribe',
|
||||||
});
|
});
|
||||||
defaultParams.value.terms[0].terms[0].value = value.id;
|
defaultParams.value.terms[0].terms[0].value = value.id;
|
||||||
// defaultParams.value.terms[0].terms[0].value = '1610517928766550016'; //测试
|
|
||||||
tableRef?.value?.reload && tableRef?.value?.reload();
|
tableRef?.value?.reload && tableRef?.value?.reload();
|
||||||
|
cancelSelect();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (subRef.value) {
|
||||||
|
subRef.value?.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索
|
* 搜索
|
||||||
* @param params
|
* @param params
|
||||||
|
@ -492,12 +560,22 @@ const handleSearch = (e: any) => {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
.card-box-content-left {
|
.card-box-content-left {
|
||||||
flex: 0.2;
|
// flex: 0.2;
|
||||||
|
max-width: 220px;
|
||||||
border-right: 1px solid #e0e4e8;
|
border-right: 1px solid #e0e4e8;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
padding-right: 20px;
|
padding-right: 10px;
|
||||||
display: flex;
|
.card-box-content-left-1 {
|
||||||
justify-content: flex-start;
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
.card-box-content-left-1-title {
|
||||||
|
color: #000;
|
||||||
|
font-size: 20px;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// justify-content: space-between;
|
||||||
a {
|
a {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,6 @@ export const FormTableColumns = [
|
||||||
title: '操作',
|
title: '操作',
|
||||||
key: 'action',
|
key: 'action',
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 80,
|
width: 80,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue