Merge branch 'dev-edge' into dev
This commit is contained in:
commit
0680878a2d
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -61,3 +61,4 @@ export const scanOpcUAList = (data: any) =>
|
||||||
|
|
||||||
export const queryTypeList = () => server.get(`/data-collect/opc/data-types`);
|
export const queryTypeList = () => server.get(`/data-collect/opc/data-types`);
|
||||||
|
|
||||||
|
export const getProviders = () => server.get('/data-collect/channel/gateway/codec/providers')
|
|
@ -55,4 +55,5 @@ export const USER_CENTER_MENU_BUTTON_CODE = 'user-center-passwd-update'
|
||||||
export const protocolList = [
|
export const protocolList = [
|
||||||
{ label: 'OPC-UA', value: 'OPC_UA', alias: 'opc-ua' },
|
{ label: 'OPC-UA', value: 'OPC_UA', alias: 'opc-ua' },
|
||||||
{ label: 'Modbus/TCP', value: 'MODBUS_TCP', alias: 'modbus-tcp' },
|
{ label: 'Modbus/TCP', value: 'MODBUS_TCP', alias: 'modbus-tcp' },
|
||||||
|
{ label: 'GATEWAY', value: 'COLLECTOR_GATEWAY', alias: 'collector-gateway' },
|
||||||
]
|
]
|
||||||
|
|
|
@ -417,6 +417,21 @@ const findDetailRouteItem = (item: any, components: any) => {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const findSaveRouteItem = (item: any, components: any) => {
|
||||||
|
const { code, url } = item
|
||||||
|
const Component = components[`${item.code}/Save`]
|
||||||
|
if (Component) {
|
||||||
|
return [{
|
||||||
|
url: `${url}/detail/:id`,
|
||||||
|
code: `${code}/Save`,
|
||||||
|
component: Component,
|
||||||
|
name: '详情信息',
|
||||||
|
isShow: false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
export const handleMenus = (menuData: any[], components: any, level: number = 1) => {
|
export const handleMenus = (menuData: any[], components: any, level: number = 1) => {
|
||||||
if (menuData && menuData.length) {
|
if (menuData && menuData.length) {
|
||||||
return menuData.map(item => {
|
return menuData.map(item => {
|
||||||
|
@ -434,8 +449,8 @@ export const handleMenus = (menuData: any[], components: any, level: number = 1)
|
||||||
const extraRoute = hasExtraChildren(item, extraRouteObj)
|
const extraRoute = hasExtraChildren(item, extraRouteObj)
|
||||||
const detail_components = findDetailRouteItem(item, components)
|
const detail_components = findDetailRouteItem(item, components)
|
||||||
|
|
||||||
|
|
||||||
if (extraRoute && !isApp) { // 包含额外的子路由
|
if (extraRoute && !isApp) { // 包含额外的子路由
|
||||||
|
console.log(extraRoute)
|
||||||
route.children = route.children ? [...route.children, ...extraRoute] : extraRoute
|
route.children = route.children ? [...route.children, ...extraRoute] : extraRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
<template>
|
||||||
|
<j-modal
|
||||||
|
:maskClosable="false"
|
||||||
|
:width='820'
|
||||||
|
title="选择网关设备"
|
||||||
|
visible
|
||||||
|
@cancel="cancel"
|
||||||
|
@ok="confirm"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<j-advanced-search
|
||||||
|
:columns="columns"
|
||||||
|
class="scene-search"
|
||||||
|
target="scene-triggrt-device-device"
|
||||||
|
type='simple'
|
||||||
|
@search="handleSearch"
|
||||||
|
/>
|
||||||
|
<j-divider style='margin: 0' />
|
||||||
|
<j-pro-table
|
||||||
|
ref='actionRef'
|
||||||
|
:bodyStyle='{
|
||||||
|
paddingRight: 0,
|
||||||
|
paddingLeft: 0
|
||||||
|
}'
|
||||||
|
:columns='columns'
|
||||||
|
:defaultParams="{
|
||||||
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
|
terms: [{value: 'gateway', termType: 'eq', column: 'deviceType'}]
|
||||||
|
}"
|
||||||
|
:gridColumn='2'
|
||||||
|
:params='params'
|
||||||
|
:request='query'
|
||||||
|
:scroll="{y: 350}"
|
||||||
|
model='CARD'
|
||||||
|
>
|
||||||
|
<template #card="slotProps">
|
||||||
|
<CardBox
|
||||||
|
:active="selectKey.id === slotProps.id"
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:statusNames="{
|
||||||
|
online: 'processing',
|
||||||
|
offline: 'error',
|
||||||
|
notActive: 'warning',
|
||||||
|
}"
|
||||||
|
:statusText="slotProps.state?.text"
|
||||||
|
:value='slotProps'
|
||||||
|
@click="handleClick"
|
||||||
|
>
|
||||||
|
<template #img>
|
||||||
|
<slot name="img">
|
||||||
|
<img :src="slotProps.photoUrl || getImage('/device/instance/device-card.png')" height='80' width='80' />
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
<template #content>
|
||||||
|
<Ellipsis style='width: calc(100% - 100px)'>
|
||||||
|
<span style="font-size: 16px;font-weight: 600" >
|
||||||
|
{{ slotProps.name }}
|
||||||
|
</span>
|
||||||
|
</Ellipsis>
|
||||||
|
<j-row>
|
||||||
|
<j-col :span="12">
|
||||||
|
<div class="card-item-content-text">
|
||||||
|
设备类型
|
||||||
|
</div>
|
||||||
|
<div>{{ slotProps.deviceType?.text }}</div>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<div class="card-item-content-text">
|
||||||
|
产品名称
|
||||||
|
</div>
|
||||||
|
<div>{{ slotProps.productName }}</div>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
</j-pro-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</j-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script name="GateWayDevice" setup>
|
||||||
|
import { getImage } from '@/utils/comm'
|
||||||
|
import {query} from "@/api/device/instance";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const emit = defineEmits(['cancel', 'confirm'])
|
||||||
|
|
||||||
|
const selectKey = reactive({
|
||||||
|
id: props.value,
|
||||||
|
name: props.name
|
||||||
|
})
|
||||||
|
const params = ref()
|
||||||
|
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
width: 300,
|
||||||
|
ellipsis: true,
|
||||||
|
fixed: 'left',
|
||||||
|
search: {
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '设备名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 200,
|
||||||
|
ellipsis: true,
|
||||||
|
search: {
|
||||||
|
type: 'string',
|
||||||
|
first: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
search: {
|
||||||
|
type: 'date'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'state',
|
||||||
|
width: 90,
|
||||||
|
search: {
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: '禁用', value: 'notActive' },
|
||||||
|
{ label: '离线', value: 'offline' },
|
||||||
|
{ label: '在线', value: 'online' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// const deviceQuery = (p) => {
|
||||||
|
// const sorts = [];
|
||||||
|
//
|
||||||
|
// if (props.rowKeys) {
|
||||||
|
// props.rowKeys.forEach(rowKey => {
|
||||||
|
// sorts.push({
|
||||||
|
// name: 'id',
|
||||||
|
// value: rowKey,
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// sorts.push({ name: 'createTime', order: 'desc' });
|
||||||
|
// const terms = [
|
||||||
|
// ...p.terms,
|
||||||
|
// { terms: [{ column: "productId", value: props.productId }]}
|
||||||
|
// ]
|
||||||
|
// return query({ ...p, terms, sorts })
|
||||||
|
// }
|
||||||
|
|
||||||
|
const handleClick = (detail) => {
|
||||||
|
console.log(detail)
|
||||||
|
selectKey.id = detail.id
|
||||||
|
selectKey.name = detail.name
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearch = (p) => {
|
||||||
|
params.value = p
|
||||||
|
}
|
||||||
|
const cancel = () => {
|
||||||
|
emit('cancel')
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirm = () => {
|
||||||
|
emit('confirm', selectKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,71 @@
|
||||||
|
<template>
|
||||||
|
<j-button
|
||||||
|
v-if="!value"
|
||||||
|
style="width: 100%"
|
||||||
|
@click="showModal"
|
||||||
|
>
|
||||||
|
选择网关设备
|
||||||
|
</j-button>
|
||||||
|
<div v-else class="gateway-form-item">
|
||||||
|
<span>
|
||||||
|
<j-ellipsis>
|
||||||
|
{{ name }}
|
||||||
|
</j-ellipsis>
|
||||||
|
</span>
|
||||||
|
<j-button type="link" @click="showModal">
|
||||||
|
重新选择
|
||||||
|
</j-button>
|
||||||
|
</div>
|
||||||
|
<DeviceModal
|
||||||
|
v-if="visible"
|
||||||
|
:name="name"
|
||||||
|
:value="value"
|
||||||
|
@cancel="cancel"
|
||||||
|
@confirm="confirm"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script name="GateWayFormItem" setup>
|
||||||
|
import DeviceModal from './GateWayDeviceModal.vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:value', 'update:name'])
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
const showModal = () =>{
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirm = (select) => {
|
||||||
|
console.log(select)
|
||||||
|
emit('update:value', select.id)
|
||||||
|
emit('update:name', select.name)
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.gateway-form-item {
|
||||||
|
display: flex;
|
||||||
|
>span {
|
||||||
|
line-height: 32px;
|
||||||
|
max-width: calc(100% - 88px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -92,6 +92,17 @@
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
<j-form-item
|
||||||
|
v-if="formData.provider === 'COLLECTOR_GATEWAY'"
|
||||||
|
:name="['configuration','deviceId']"
|
||||||
|
:rules="[{ required: true, message: '请选择网关设备'}]"
|
||||||
|
label="选择网关设备"
|
||||||
|
>
|
||||||
|
<GateWayFormItem
|
||||||
|
v-model:name="formData.configuration.deviceName"
|
||||||
|
v-model:value="formData.configuration.deviceId"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-if="formData.provider === 'OPC_UA'"
|
v-if="formData.provider === 'OPC_UA'"
|
||||||
label="安全模式"
|
label="安全模式"
|
||||||
|
@ -198,6 +209,7 @@ import type { FormInstance } from 'ant-design-vue';
|
||||||
import type { FormDataType } from '../type.d';
|
import type { FormDataType } from '../type.d';
|
||||||
import { cloneDeep, isArray } from 'lodash-es';
|
import { cloneDeep, isArray } from 'lodash-es';
|
||||||
import { protocolList } from '@/utils/consts';
|
import { protocolList } from '@/utils/consts';
|
||||||
|
import GateWayFormItem from "@/views/DataCollect/Channel/Save/GateWayFormItem.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
@ -222,7 +234,15 @@ const Options = ref({
|
||||||
const formData = ref<FormDataType>(cloneDeep(FormState));
|
const formData = ref<FormDataType>(cloneDeep(FormState));
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
const params = await formRef.value?.validate();
|
const params: any = await formRef.value?.validate();
|
||||||
|
if (params?.provider === 'COLLECTOR_GATEWAY') {
|
||||||
|
params.configuration.deviceName = formData.value.configuration.deviceName
|
||||||
|
}
|
||||||
|
|
||||||
|
params.circuitBreaker = {
|
||||||
|
type: 'Ignore'
|
||||||
|
}
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = !id
|
const response = !id
|
||||||
? await save(params).catch(() => {})
|
? await save(params).catch(() => {})
|
||||||
|
@ -284,7 +304,7 @@ const getProvidersList = async () => {
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const arr = resp.result
|
const arr = resp.result
|
||||||
.filter(
|
.filter(
|
||||||
(item: any) => item.id === 'modbus-tcp' || item.id === 'opc-ua',
|
(item: any) => ['collector-gateway', 'modbus-tcp', 'opc-ua'].includes(item.id),
|
||||||
)
|
)
|
||||||
.map((it: any) => it.id);
|
.map((it: any) => it.id);
|
||||||
const providers: any = protocolList.filter((item: any) =>
|
const providers: any = protocolList.filter((item: any) =>
|
||||||
|
@ -302,7 +322,9 @@ getCertificateList();
|
||||||
watch(
|
watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value.id) formData.value = value as FormDataType;
|
if (value.id) {
|
||||||
|
formData.value = value as FormDataType;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,6 +15,8 @@ export const FormState: FormDataType = {
|
||||||
authType: 'anonymous',
|
authType: 'anonymous',
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
|
deviceId: undefined,
|
||||||
|
deviceName: undefined,
|
||||||
},
|
},
|
||||||
description: '',
|
description: '',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export interface ConfigurationType {
|
export interface ConfigurationType {
|
||||||
port: string | undefined;
|
port: string | undefined;
|
||||||
host: string | undefined;;
|
host: string | undefined;
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
|
@ -8,7 +8,8 @@ export interface ConfigurationType {
|
||||||
securityMode: string | undefined,
|
securityMode: string | undefined,
|
||||||
certId: string | undefined,
|
certId: string | undefined,
|
||||||
authType: string | undefined,
|
authType: string | undefined,
|
||||||
|
deviceId: string | undefined,
|
||||||
|
deviceName: string | undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormDataType {
|
export interface FormDataType {
|
||||||
|
|
|
@ -271,7 +271,7 @@ import {
|
||||||
import { ModBusRules, checkProviderData } from '../../data.ts';
|
import { ModBusRules, checkProviderData } from '../../data.ts';
|
||||||
import type { FormInstance } from 'ant-design-vue';
|
import type { FormInstance } from 'ant-design-vue';
|
||||||
import type { Rule } from 'ant-design-vue/lib/form';
|
import type { Rule } from 'ant-design-vue/lib/form';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import {cloneDeep, omit} from 'lodash-es';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
@ -343,10 +343,18 @@ const handleOk = async () => {
|
||||||
|
|
||||||
// address是多余字段,但是react版本上使用到了这个字段
|
// address是多余字段,但是react版本上使用到了这个字段
|
||||||
params.configuration.parameter = {
|
params.configuration.parameter = {
|
||||||
...params.configuration.parameter,
|
...params.configuration.parameter,
|
||||||
address: data?.pointKey,
|
address: data?.pointKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (props.data.provider === 'COLLECTOR_GATEWAY') {
|
||||||
|
const configuration = cloneDeep(params.configuration)
|
||||||
|
params.configuration = {
|
||||||
|
configuration: configuration,
|
||||||
|
interval: params.interval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = !id
|
const response = !id
|
||||||
? await savePointBatch(params).catch(() => {})
|
? await savePointBatch(params).catch(() => {})
|
||||||
|
@ -439,22 +447,31 @@ watch(
|
||||||
watch(
|
watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value.id && value.provider === 'MODBUS_TCP') {
|
if (value.id && ['MODBUS_TCP', 'COLLECTOR_GATEWAY'].includes(value.provider)) {
|
||||||
const _value: any = cloneDeep(value);
|
const _value: any = cloneDeep(value);
|
||||||
const { writeByteCount, byteCount } =
|
const { writeByteCount, byteCount } =
|
||||||
_value.configuration.parameter;
|
props.data.provider === 'COLLECTOR_GATEWAY' ? _value.configuration.configuration.parameter: _value.configuration.parameter;
|
||||||
|
|
||||||
|
if (props.data.provider === 'COLLECTOR_GATEWAY') {
|
||||||
|
formData.value = {
|
||||||
|
...omit(_value, ['configuration']),
|
||||||
|
..._value.configuration,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
formData.value = _value;
|
formData.value = _value;
|
||||||
if (!!_value.accessModes[0]?.value) {
|
}
|
||||||
formData.value.accessModes = value.accessModes.map(
|
|
||||||
(i: any) => i.value,
|
if (!!_value.accessModes[0]?.value) {
|
||||||
);
|
formData.value.accessModes = value.accessModes.map(
|
||||||
}
|
(i: any) => i.value,
|
||||||
if (!!_value.features[0]?.value) {
|
);
|
||||||
formData.value.features = value.features.map(
|
}
|
||||||
(i: any) => i.value,
|
if (!!_value.features[0]?.value) {
|
||||||
);
|
formData.value.features = value.features.map(
|
||||||
}
|
(i: any) => i.value,
|
||||||
formData.value.nspwc = !!writeByteCount || !!byteCount;
|
);
|
||||||
|
}
|
||||||
|
formData.value.nspwc = !!writeByteCount || !!byteCount;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<j-space>
|
<j-space>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
v-if="data?.provider == 'MODBUS_TCP'"
|
v-if="['MODBUS_TCP', 'COLLECTOR_GATEWAY'].includes(data?.provider)"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handlAdd"
|
@click="handlAdd"
|
||||||
hasPermission="DataCollect/Collector:add"
|
hasPermission="DataCollect/Collector:add"
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
show-search
|
show-search
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
:disabled="!!id"
|
:disabled="!!id"
|
||||||
|
@select="channelSelect"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
|
@ -40,93 +41,110 @@
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="从机地址"
|
v-if="provider === 'COLLECTOR_GATEWAY'"
|
||||||
:name="['configuration', 'unitId']"
|
label="通讯协议"
|
||||||
v-if="visibleUnitId"
|
:name="['collectorProvider']"
|
||||||
:rules="LeftTreeRules.unitId"
|
:rules="[{ required: true, message: '请选择通讯协议' }]"
|
||||||
>
|
>
|
||||||
<j-input-number
|
<j-select
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入从机地址"
|
v-model:value="formData.collectorProvider"
|
||||||
v-model:value="formData.configuration.unitId"
|
:options="providerListItems"
|
||||||
:min="0"
|
placeholder="请选择通讯协议"
|
||||||
:max="255"
|
allowClear
|
||||||
/>
|
show-search
|
||||||
|
:filter-option="filterOption"
|
||||||
|
:disabled="!!id"
|
||||||
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
|
v-if="visibleUnitId"
|
||||||
|
:name="['configuration', 'unitId']"
|
||||||
|
:rules="LeftTreeRules.unitId"
|
||||||
|
label="从机地址"
|
||||||
|
>
|
||||||
|
<j-input-number
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请输入从机地址"
|
||||||
|
v-model:value="formData.configuration.unitId"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item
|
||||||
|
v-if="provider !== 'COLLECTOR_GATEWAY'"
|
||||||
:name="['configuration', 'inheritBreakerSpec', 'type']"
|
:name="['configuration', 'inheritBreakerSpec', 'type']"
|
||||||
:rules="LeftTreeRules.type"
|
:rules="LeftTreeRules.type"
|
||||||
label="点位熔断处理"
|
label="点位熔断处理"
|
||||||
>
|
>
|
||||||
<j-card-select
|
<j-card-select
|
||||||
:showImage="false"
|
:showImage="false"
|
||||||
v-model:value="formData.configuration.inheritBreakerSpec.type"
|
v-model:value="formData.configuration.inheritBreakerSpec.type"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '降频', value: 'LowerFrequency' },
|
{ label: '降频', value: 'LowerFrequency' },
|
||||||
{ label: '断开', value: 'Break' },
|
{ label: '断开', value: 'Break' },
|
||||||
{ label: '忽略', value: 'Ignore' },
|
{ label: '忽略', value: 'Ignore' },
|
||||||
]"
|
]"
|
||||||
@change="changeCardSelectType"
|
@change="changeCardSelectType"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<p style="color: #616161">
|
<p style="color: #616161" v-if="provider !== 'COLLECTOR_GATEWAY'">
|
||||||
{{ getTypeTooltip(formData.configuration.inheritBreakerSpec.type) }}
|
{{ getTypeTooltip(formData.configuration.inheritBreakerSpec.type) }}
|
||||||
</p>
|
</p>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="双字高低位切换"
|
|
||||||
:name="['configuration', 'endian']"
|
|
||||||
v-if="visibleEndian"
|
v-if="visibleEndian"
|
||||||
|
:name="['configuration', 'endian']"
|
||||||
:rules="LeftTreeRules.endian"
|
:rules="LeftTreeRules.endian"
|
||||||
|
label="双字高低位切换"
|
||||||
>
|
>
|
||||||
<j-card-select
|
<j-card-select
|
||||||
:showImage="false"
|
:showImage="false"
|
||||||
v-model:value="formData.configuration.endian"
|
v-model:value="formData.configuration.endian"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: 'AB', value: 'BIG' },
|
{ label: 'AB', value: 'BIG' },
|
||||||
{ label: 'BA', value: 'LITTLE' },
|
{ label: 'BA', value: 'LITTLE' },
|
||||||
]"
|
]"
|
||||||
@change="changeCardSelectEndian"
|
@change="changeCardSelectEndian"
|
||||||
:column="2"
|
:column="2"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="单字高低位切换"
|
|
||||||
:name="['configuration', 'endianIn']"
|
|
||||||
v-if="visibleEndian"
|
v-if="visibleEndian"
|
||||||
|
:name="['configuration', 'endianIn']"
|
||||||
:rules="LeftTreeRules.endianIn"
|
:rules="LeftTreeRules.endianIn"
|
||||||
|
label="单字高低位切换"
|
||||||
>
|
>
|
||||||
<j-card-select
|
<j-card-select
|
||||||
:showImage="false"
|
:showImage="false"
|
||||||
v-model:value="formData.configuration.endianIn"
|
v-model:value="formData.configuration.endianIn"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: 'AB', value: 'BIG' },
|
{ label: 'AB', value: 'BIG' },
|
||||||
{ label: 'BA', value: 'LITTLE' },
|
{ label: 'BA', value: 'LITTLE' },
|
||||||
]"
|
]"
|
||||||
@change="changeCardSelectEndianIn"
|
@change="changeCardSelectEndianIn"
|
||||||
:column="2"
|
:column="2"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<div style="color: #616161" v-if="visibleEndian">
|
<div v-if="visibleEndian" style="color: #616161">
|
||||||
<p>当前内存布局: {{ endianData }}</p>
|
<p>当前内存布局: {{ endianData }}</p>
|
||||||
<p>
|
<p>
|
||||||
只有4字节数据类型(int32、ieee754 float)
|
只有4字节数据类型(int32、ieee754 float)
|
||||||
具有4种内存布局,其它只有ABCD、DCBA两种内存布局(以双字配置为准)
|
具有4种内存布局,其它只有ABCD、DCBA两种内存布局(以双字配置为准)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="请求超时时间配置"
|
|
||||||
:name="['configuration', 'requsetTimeout']"
|
:name="['configuration', 'requsetTimeout']"
|
||||||
|
label="请求超时时间配置"
|
||||||
>
|
>
|
||||||
<j-input-number
|
<j-input-number
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入请求超时时间配置"
|
placeholder="请输入请求超时时间配置"
|
||||||
v-model:value="formData.configuration.requsetTimeout"
|
v-model:value="formData.configuration.requsetTimeout"
|
||||||
addon-after="ms"
|
addon-after="ms"
|
||||||
:max="2147483648"
|
:max="2147483648"
|
||||||
:min="1"
|
:min="1"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
|
||||||
<j-form-item label="说明" name="description">
|
<j-form-item label="说明" name="description">
|
||||||
<j-textarea
|
<j-textarea
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
|
@ -154,11 +172,12 @@
|
||||||
</template>
|
</template>
|
||||||
</j-modal>
|
</j-modal>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" name="CollectorTreeSave" setup>
|
||||||
import { save, update } from '@/api/data-collect/collector';
|
import { save, update, getProviders } from '@/api/data-collect/collector';
|
||||||
import { LeftTreeRules } from '../../data';
|
import { LeftTreeRules } from '../../data';
|
||||||
import type { FormInstance } from 'ant-design-vue';
|
import type { FormInstance } from 'ant-design-vue';
|
||||||
import {cloneDeep} from "lodash-es";
|
import {cloneDeep, omit} from "lodash-es";
|
||||||
|
import {protocolList} from "@/utils/consts";
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const visibleEndian = ref(false);
|
const visibleEndian = ref(false);
|
||||||
|
@ -179,17 +198,34 @@ const emit = defineEmits(['change']);
|
||||||
|
|
||||||
const id = props.data.id;
|
const id = props.data.id;
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
|
const provider = ref()
|
||||||
|
const providerListItems = ref()
|
||||||
|
|
||||||
|
const geyProviderList = async () => {
|
||||||
|
const resp: any = await getProviders();
|
||||||
|
if (resp.success) {
|
||||||
|
providerListItems.value = resp.result.map((item: any) => ({ label: item.name, value: item.id }))
|
||||||
|
} else {
|
||||||
|
providerListItems.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const _channelListAll = computed(() => {
|
const _channelListAll = computed(() => {
|
||||||
return props.channelListAll || [];
|
return props.channelListAll || [];
|
||||||
})
|
})
|
||||||
|
|
||||||
const channelList = computed(() => {
|
const channelList = computed(() => {
|
||||||
return _channelListAll.value.map((item: any) => ({
|
return _channelListAll.value.map((item: any) => ({
|
||||||
|
provider: item.provider,
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name,
|
label: item.name,
|
||||||
}));
|
}));
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const channelSelect = (key: string, detail: any) => {
|
||||||
|
console.log(detail)
|
||||||
|
provider.value = detail.provider
|
||||||
|
}
|
||||||
|
|
||||||
const endianData = computed(() => {
|
const endianData = computed(() => {
|
||||||
const { endian, endianIn } = formData.value.configuration;
|
const { endian, endianIn } = formData.value.configuration;
|
||||||
|
@ -209,6 +245,7 @@ const endianData = computed(() => {
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
channelId: undefined,
|
channelId: undefined,
|
||||||
name: '',
|
name: '',
|
||||||
|
collectorProvider: undefined,
|
||||||
configuration: {
|
configuration: {
|
||||||
unitId: '',
|
unitId: '',
|
||||||
type: 'LowerFrequency',
|
type: 'LowerFrequency',
|
||||||
|
@ -227,24 +264,52 @@ const formData = ref({
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
const data = await formRef.value?.validate();
|
const _data: any = await formRef.value?.validate();
|
||||||
|
|
||||||
const { provider, name } = _channelListAll.value.find(
|
if (_data) {
|
||||||
(item: any) => item.id === formData.value.channelId,
|
const { name } = _channelListAll.value.find(
|
||||||
);
|
(item: any) => item.id === formData.value.channelId,
|
||||||
const params = {
|
);
|
||||||
...data,
|
|
||||||
provider,
|
let _copyData = _data
|
||||||
|
|
||||||
|
if (['COLLECTOR_GATEWAY'].includes(provider.value)) {
|
||||||
|
const copyData = cloneDeep(_data)
|
||||||
|
_copyData = omit(copyData, ['configuration', 'collectorProvider'])
|
||||||
|
|
||||||
|
_copyData.configuration = {
|
||||||
|
configuration: {
|
||||||
|
..._data.configuration,
|
||||||
|
inheritBreakerSpec: {
|
||||||
|
type: 'Ignore'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
collectorProvider: _data.collectorProvider
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
..._copyData,
|
||||||
|
provider: provider.value,
|
||||||
channelName: name,
|
channelName: name,
|
||||||
};
|
circuitBreaker: {
|
||||||
|
type: 'Ignore'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = !id
|
|
||||||
? await save(params).catch(() => { success: false })
|
try {
|
||||||
: await update(id, { ...props.data, ...params }).catch(() => { success: false });
|
const response = !id
|
||||||
loading.value = false;
|
? await save(params)
|
||||||
if (response.success) {
|
: await update(id, { ...props.data, ...params })
|
||||||
emit('change', true);
|
loading.value = false;
|
||||||
|
if (response.success) {
|
||||||
|
emit('change', true);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -253,7 +318,8 @@ const getTypeTooltip = (value: string) => {
|
||||||
case 'LowerFrequency': return '连续20次采集异常后,降低采集频率至设定频率的1/10,故障处理后,采集频率将恢复至设定频率。';
|
case 'LowerFrequency': return '连续20次采集异常后,降低采集频率至设定频率的1/10,故障处理后,采集频率将恢复至设定频率。';
|
||||||
// case 'Break': return '连续10分钟异常,停止采集数据进入断开状态,设备重新启用后恢复采集状态。'
|
// case 'Break': return '连续10分钟异常,停止采集数据进入断开状态,设备重新启用后恢复采集状态。'
|
||||||
case 'Break': return '连续20次采集异常后,降低采集频率至设定频率的1/10,10分钟内未排除故障,将停止采集。'
|
case 'Break': return '连续20次采集异常后,降低采集频率至设定频率的1/10,10分钟内未排除故障,将停止采集。'
|
||||||
default: return '忽略异常,保持设定采集频率。';
|
case 'Ignore': return '忽略异常,保持设定采集频率。';
|
||||||
|
default: return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +346,7 @@ watch(
|
||||||
(value) => {
|
(value) => {
|
||||||
const dt = _channelListAll.value.find((item) => item.id === value);
|
const dt = _channelListAll.value.find((item) => item.id === value);
|
||||||
visibleUnitId.value = visibleEndian.value =
|
visibleUnitId.value = visibleEndian.value =
|
||||||
dt?.provider && dt?.provider === 'MODBUS_TCP';
|
dt?.provider && ['MODBUS_TCP', 'COLLECTOR_GATEWAY'].includes(dt?.provider);
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
);
|
||||||
|
@ -290,20 +356,37 @@ watch(
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value.id) {
|
if (value.id) {
|
||||||
let copyValue = cloneDeep(value)
|
let copyValue = cloneDeep(value)
|
||||||
if (!copyValue?.configuration?.inheritBreakerSpec) {
|
if (!copyValue?.configuration?.inheritBreakerSpec && copyValue.provider !== 'COLLECTOR_GATEWAY') {
|
||||||
copyValue.configuration = {
|
copyValue.configuration = {
|
||||||
...copyValue.configuration,
|
...copyValue.configuration,
|
||||||
inheritBreakerSpec: {
|
inheritBreakerSpec: {
|
||||||
type: value.circuitBreaker.type
|
type: value.circuitBreaker?.type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
copyValue.circuitBreaker.type = 'Ignore'
|
copyValue.circuitBreaker.type = 'Ignore'
|
||||||
}
|
}
|
||||||
formData.value = copyValue
|
|
||||||
|
if (copyValue.provider === 'COLLECTOR_GATEWAY') {
|
||||||
|
formData.value = {
|
||||||
|
...omit(copyValue, ['configuration']),
|
||||||
|
...copyValue.configuration,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formData.value = copyValue
|
||||||
|
}
|
||||||
|
|
||||||
|
provider.value = copyValue?.provider
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (provider.value === 'COLLECTOR_GATEWAY') {
|
||||||
|
geyProviderList()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -36,25 +36,38 @@
|
||||||
<Ellipsis class="tree-left-title">
|
<Ellipsis class="tree-left-title">
|
||||||
{{ name }}
|
{{ name }}
|
||||||
</Ellipsis>
|
</Ellipsis>
|
||||||
|
<!-- <j-tag-->
|
||||||
|
<!-- class="tree-left-tag"-->
|
||||||
|
<!-- v-if="data.id !== '*'"-->
|
||||||
|
<!-- :color="-->
|
||||||
|
<!-- data?.uniformState?.value === 'normal' || data?.state?.value === 'disabled' ?-->
|
||||||
|
<!-- colorMap.get(data?.runningState?.value) :-->
|
||||||
|
<!-- colorMap.get(data?.uniformState?.value)-->
|
||||||
|
<!-- "-->
|
||||||
|
<!-- >{{-->
|
||||||
|
<!-- data?.uniformState?.value === 'normal' || data?.state?.value === 'disabled' ?-->
|
||||||
|
<!-- data?.runningState?.text :-->
|
||||||
|
<!-- data?.uniformState?.text-->
|
||||||
|
<!-- }}</j-tag-->
|
||||||
|
<!-- >-->
|
||||||
<j-tag
|
<j-tag
|
||||||
class="tree-left-tag"
|
class="tree-left-tag"
|
||||||
v-if="data.id !== '*'"
|
v-if="data.id !== '*'"
|
||||||
:color="
|
:color="colorMap.get(data?.uniformState?.value)"
|
||||||
data?.uniformState?.value === 'normal' || data?.state?.value === 'disabled' ?
|
>{{ data?.uniformState?.text }}</j-tag
|
||||||
colorMap.get(data?.runningState?.value) :
|
|
||||||
colorMap.get(data?.uniformState?.value)
|
|
||||||
"
|
|
||||||
>{{
|
|
||||||
data?.uniformState?.value === 'normal' || data?.state?.value === 'disabled' ?
|
|
||||||
data?.runningState?.text :
|
|
||||||
data?.uniformState?.text
|
|
||||||
}}</j-tag
|
|
||||||
>
|
>
|
||||||
<j-tag
|
<j-tag
|
||||||
class="tree-left-tag2"
|
class="tree-left-tag2"
|
||||||
v-if="data.id !== '*'"
|
v-if="data.id !== '*'"
|
||||||
:color="colorMap.get(data?.state?.value)"
|
:color="
|
||||||
>{{ data?.state?.text }}</j-tag
|
data?.state?.value === 'disabled' ? colorMap.get(data?.runningState?.value) :
|
||||||
|
colorMap.get(data?.state?.value)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
data?.state?.text
|
||||||
|
}}
|
||||||
|
</j-tag
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
v-if="data.id !== '*'"
|
v-if="data.id !== '*'"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<template>
|
||||||
|
<EditTable provider="collector-gateway" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import EditTable from '../components/EditTable/index.vue'
|
||||||
|
</script>
|
|
@ -104,12 +104,12 @@ const handleData = (data: any[], type: string) => {
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const resp = await treeMapping({
|
const resp = await treeMapping({
|
||||||
terms: [
|
// terms: [
|
||||||
{
|
// {
|
||||||
column: 'provider',
|
// column: 'provider',
|
||||||
value: _props.type,
|
// value: _props.type,
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
});
|
});
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<j-spin :spinning="loading" v-if="metadata.properties.length">
|
<j-spin v-if="metadata.properties?.length" :spinning="loading">
|
||||||
<j-card :bordered="false" borderStyle="padding: 0">
|
<j-card :bordered="false" borderStyle="padding: 0">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<j-space>
|
<j-space>
|
||||||
|
@ -28,14 +28,9 @@
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
allowClear
|
allowClear
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
|
:options="channelList"
|
||||||
|
@select="(_, option) => { record.provider = option.provider }"
|
||||||
>
|
>
|
||||||
<j-select-option
|
|
||||||
v-for="item in channelList"
|
|
||||||
:key="item.value"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
>{{ item.label }}</j-select-option
|
|
||||||
>
|
|
||||||
</j-select>
|
</j-select>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
@ -188,16 +183,16 @@ const visible = ref<boolean>(false);
|
||||||
const getChannel = async () => {
|
const getChannel = async () => {
|
||||||
const resp: any = await queryChannelNoPaging({
|
const resp: any = await queryChannelNoPaging({
|
||||||
paging: false,
|
paging: false,
|
||||||
terms: [
|
// terms: [
|
||||||
{
|
// {
|
||||||
terms: [
|
// terms: [
|
||||||
{
|
// {
|
||||||
column: 'provider',
|
// column: 'provider',
|
||||||
value: props.provider,
|
// value: props.provider,
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
});
|
});
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
channelList.value = resp.result?.map((item: any) => ({
|
channelList.value = resp.result?.map((item: any) => ({
|
||||||
|
@ -211,12 +206,12 @@ const getChannel = async () => {
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
getChannel();
|
getChannel();
|
||||||
const _metadata = metadata.properties.map((item: any) => ({
|
const _metadata = metadata.properties?.map?.((item: any) => ({
|
||||||
metadataId: item.id,
|
metadataId: item.id,
|
||||||
metadataName: `${item.name}(${item.id})`,
|
metadataName: `${item.name}(${item.id})`,
|
||||||
metadataType: 'property',
|
metadataType: 'property',
|
||||||
name: item.name,
|
name: item.name,
|
||||||
}));
|
})) || [];
|
||||||
if (_metadata && _metadata.length) {
|
if (_metadata && _metadata.length) {
|
||||||
const resp: any = await queryMapping(
|
const resp: any = await queryMapping(
|
||||||
'device',
|
'device',
|
||||||
|
@ -269,6 +264,7 @@ const onSave = () => {
|
||||||
(i: any) => i.channelId,
|
(i: any) => i.channelId,
|
||||||
);
|
);
|
||||||
if (arr && arr.length !== 0) {
|
if (arr && arr.length !== 0) {
|
||||||
|
console.log(arr)
|
||||||
const resp = await saveMapping(
|
const resp = await saveMapping(
|
||||||
instanceStore.current.id,
|
instanceStore.current.id,
|
||||||
props.provider,
|
props.provider,
|
||||||
|
|
|
@ -122,6 +122,7 @@ import Modbus from './Modbus/index.vue';
|
||||||
import OPCUA from './OPCUA/index.vue';
|
import OPCUA from './OPCUA/index.vue';
|
||||||
import EdgeMap from './EdgeMap/index.vue';
|
import EdgeMap from './EdgeMap/index.vue';
|
||||||
import Parsing from './Parsing/index.vue';
|
import Parsing from './Parsing/index.vue';
|
||||||
|
import GateWay from './GateWay/index.vue'
|
||||||
import Log from './Log/index.vue';
|
import Log from './Log/index.vue';
|
||||||
import { _deploy, _disconnect } from '@/api/device/instance';
|
import { _deploy, _disconnect } from '@/api/device/instance';
|
||||||
import { getImage, onlyMessage } from '@/utils/comm';
|
import { getImage, onlyMessage } from '@/utils/comm';
|
||||||
|
@ -181,7 +182,8 @@ const tabs = {
|
||||||
EdgeMap,
|
EdgeMap,
|
||||||
Parsing,
|
Parsing,
|
||||||
Log,
|
Log,
|
||||||
MetadataMap
|
MetadataMap,
|
||||||
|
GateWay
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStatus = (id: string) => {
|
const getStatus = (id: string) => {
|
||||||
|
@ -225,7 +227,7 @@ const getDetail = () => {
|
||||||
) {
|
) {
|
||||||
list.value.push({
|
list.value.push({
|
||||||
key: 'Modbus',
|
key: 'Modbus',
|
||||||
tab: 'Modbus TCP',
|
tab: '数采映射',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
@ -234,9 +236,18 @@ const getDetail = () => {
|
||||||
) {
|
) {
|
||||||
list.value.push({
|
list.value.push({
|
||||||
key: 'OPCUA',
|
key: 'OPCUA',
|
||||||
tab: 'OPC UA',
|
tab: '数采映射',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
instanceStore.current?.protocol === 'collector-gateway' &&
|
||||||
|
!keys.includes('GateWay')
|
||||||
|
) {
|
||||||
|
list.value.push({
|
||||||
|
key: 'GateWay',
|
||||||
|
tab: '数采映射',
|
||||||
|
});
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
instanceStore.current?.deviceType?.value === 'gateway' &&
|
instanceStore.current?.deviceType?.value === 'gateway' &&
|
||||||
!keys.includes('ChildDevice')
|
!keys.includes('ChildDevice')
|
||||||
|
|
|
@ -14,40 +14,47 @@
|
||||||
<a @click="goBack">返回</a>
|
<a @click="goBack">返回</a>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="showType === 'network'">
|
<template v-if="showType === 'network'">
|
||||||
<Network
|
|
||||||
v-if="provider.id !== 'plugin_gateway'"
|
|
||||||
:bindProduct='bindProduct'
|
|
||||||
:provider="provider"
|
|
||||||
:data="data"
|
|
||||||
/>
|
|
||||||
<Plugin
|
<Plugin
|
||||||
v-else
|
v-if="provider.id === 'plugin_gateway'"
|
||||||
:bindProduct='bindProduct'
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:data="data"
|
||||||
:data="data"
|
:provider="provider"
|
||||||
|
/>
|
||||||
|
<GateWay
|
||||||
|
v-else-if="provider.id === 'collector-gateway'"
|
||||||
|
:bindProduct='bindProduct'
|
||||||
|
:data="data"
|
||||||
|
:provider="provider"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Network
|
||||||
|
v-else
|
||||||
|
:bindProduct='bindProduct'
|
||||||
|
:data="data"
|
||||||
|
:provider="provider"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<Media
|
<Media
|
||||||
v-if="showType === 'media'"
|
v-else-if="showType === 'media'"
|
||||||
:bindProduct='bindProduct'
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
<Channel
|
<Channel
|
||||||
v-if="showType === 'channel'"
|
v-else-if="showType === 'channel'"
|
||||||
:bindProduct='bindProduct'
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
<Edge
|
<Edge
|
||||||
v-if="showType === 'edge'"
|
v-else-if="showType === 'edge'"
|
||||||
:bindProduct='bindProduct'
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
<Cloud
|
<Cloud
|
||||||
v-if="showType === 'cloud'"
|
v-else-if="showType === 'cloud'"
|
||||||
:bindProduct='bindProduct'
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
|
@ -65,6 +72,7 @@ import Provider from '../components/Provider/index.vue';
|
||||||
import Media from '../components/Media/index.vue';
|
import Media from '../components/Media/index.vue';
|
||||||
import Channel from '../components/Channel/index.vue';
|
import Channel from '../components/Channel/index.vue';
|
||||||
import Edge from '../components/Edge/index.vue';
|
import Edge from '../components/Edge/index.vue';
|
||||||
|
import GateWay from '../components/Edge/geteway.vue';
|
||||||
import Cloud from '../components/Cloud/index.vue';
|
import Cloud from '../components/Cloud/index.vue';
|
||||||
import Plugin from '../components/Plugin/index.vue'
|
import Plugin from '../components/Plugin/index.vue'
|
||||||
import { getProviders, detail } from '@/api/link/accessConfig';
|
import { getProviders, detail } from '@/api/link/accessConfig';
|
||||||
|
@ -131,9 +139,11 @@ const getTypeList = (result: Record<string, any>) => {
|
||||||
} else if (item.id === 'OneNet' || item.id === 'Ctwing') {
|
} else if (item.id === 'OneNet' || item.id === 'Ctwing') {
|
||||||
item.type = 'cloud';
|
item.type = 'cloud';
|
||||||
cloud.push(item);
|
cloud.push(item);
|
||||||
} else if (item.id === 'modbus-tcp' || item.id === 'opc-ua') {
|
} else if (item.id === 'modbus-tcp' || item.id === 'opc-ua' || item.id === 'collector-gateway') {
|
||||||
item.type = 'channel';
|
item.type = 'channel';
|
||||||
channel.push(item);
|
if (item.id === 'collector-gateway') {
|
||||||
|
channel.push(item);
|
||||||
|
}
|
||||||
} else if (
|
} else if (
|
||||||
item.id === 'official-edge-gateway' ||
|
item.id === 'official-edge-gateway' ||
|
||||||
item.id === 'edge-child-device'
|
item.id === 'edge-child-device'
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
<template>
|
||||||
|
<div class="card-last">
|
||||||
|
<j-row :gutter="[24, 24]">
|
||||||
|
<j-col :span="12">
|
||||||
|
<title-component data="基本信息" />
|
||||||
|
<div>
|
||||||
|
<j-form
|
||||||
|
:model="formState"
|
||||||
|
autocomplete="off"
|
||||||
|
layout="vertical"
|
||||||
|
name="basic"
|
||||||
|
@finish="onFinish"
|
||||||
|
>
|
||||||
|
<j-form-item
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入名称',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多可输入64个字符',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
label="名称"
|
||||||
|
name="name"
|
||||||
|
>
|
||||||
|
<j-input
|
||||||
|
v-model:value="formState.name"
|
||||||
|
placeholder="请输入名称"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item label="说明" name="description">
|
||||||
|
<j-textarea
|
||||||
|
v-model:value="formState.description"
|
||||||
|
:maxlength="200"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入说明"
|
||||||
|
show-count
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item>
|
||||||
|
<PermissionButton
|
||||||
|
v-if="view === 'false'"
|
||||||
|
:hasPermission="`link/AccessConfig:${
|
||||||
|
id === ':id' ? 'add' : 'update'
|
||||||
|
}`"
|
||||||
|
html-type="submit"
|
||||||
|
type="primary"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</PermissionButton>
|
||||||
|
</j-form-item>
|
||||||
|
</j-form>
|
||||||
|
</div>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<div class="doc" style="height: 600px">
|
||||||
|
<TitleComponent data="配置概览" />
|
||||||
|
<p>接入方式:{{ provider.name }}</p>
|
||||||
|
<p>
|
||||||
|
{{ provider.description }}
|
||||||
|
</p>
|
||||||
|
<p>设备接入指引</p>
|
||||||
|
<TitleComponent data="设备接入指引" />
|
||||||
|
<p>1、数据采集菜单中配置数采通道、点位</p>
|
||||||
|
<p>2、创建数采设备接入网关</p>
|
||||||
|
<p>3、创建产品,并选中接入方式为数采设备接入</p>
|
||||||
|
<p>4、添加设备,单独为每一个设备进行数据点绑定</p>
|
||||||
|
</div>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="GateWay" setup>
|
||||||
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
import { update, save } from '@/api/link/accessConfig';
|
||||||
|
import { ProtocolMapping } from '../../data';
|
||||||
|
|
||||||
|
interface FormState {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
const route = useRoute();
|
||||||
|
const view = route.query.view as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
provider: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const type = ref(props.provider.type || props.data.type);
|
||||||
|
|
||||||
|
const formState = ref<FormState>({
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
});
|
||||||
|
const onFinish = async (values: any) => {
|
||||||
|
const providerId = props.provider.id;
|
||||||
|
const params = {
|
||||||
|
...values,
|
||||||
|
provider: providerId,
|
||||||
|
protocol: providerId,
|
||||||
|
transport: ProtocolMapping.get(providerId),
|
||||||
|
channel: props.provider.channel,
|
||||||
|
};
|
||||||
|
const resp =
|
||||||
|
id === ':id' ? await save(params) : await update({ ...params, id });
|
||||||
|
if (resp.status === 200) {
|
||||||
|
onlyMessage('操作成功', 'success');
|
||||||
|
history.back();
|
||||||
|
if ((window as any).onTabSaveSuccess) {
|
||||||
|
(window as any).onTabSaveSuccess(resp);
|
||||||
|
setTimeout(() => window.close(), 300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (id !== ':id') {
|
||||||
|
formState.value = {
|
||||||
|
name: props.data.name,
|
||||||
|
description: props.data?.description || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.card-last {
|
||||||
|
padding-right: 5px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -151,17 +151,11 @@
|
||||||
/^([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/,
|
/^([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/,
|
||||||
message: '请输入正确的IP地址',
|
message: '请输入正确的IP地址',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
max: 65535,
|
|
||||||
message: '请输入1~65535之间的正整数'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
min: 1,
|
|
||||||
message: '请输入1~65535之间的正整数'
|
|
||||||
},
|
|
||||||
]"
|
]"
|
||||||
|
:validateFirst="true"
|
||||||
>
|
>
|
||||||
<j-input-number
|
<j-input
|
||||||
style="width: 105%"
|
style="width: 105%"
|
||||||
v-model:value="
|
v-model:value="
|
||||||
formState.hostPort.publicHost
|
formState.hostPort.publicHost
|
||||||
|
@ -176,12 +170,8 @@
|
||||||
<j-col :span="6">
|
<j-col :span="6">
|
||||||
<j-form-item
|
<j-form-item
|
||||||
:name="['hostPort', 'publicPort']"
|
:name="['hostPort', 'publicPort']"
|
||||||
:rules="[
|
:rules="rules.publicPort"
|
||||||
{
|
:validateFirst="true"
|
||||||
required: true,
|
|
||||||
message: '输入端口',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
>
|
>
|
||||||
<div class="form-label"></div>
|
<div class="form-label"></div>
|
||||||
|
|
||||||
|
@ -598,6 +588,15 @@ const dynamicValidateForm = reactive<{ cluster: Form2[] }>({
|
||||||
cluster: [],
|
cluster: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
publicPort: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '输入端口',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
const removeCluster = (item: Form2) => {
|
const removeCluster = (item: Form2) => {
|
||||||
let index = dynamicValidateForm.cluster.indexOf(item);
|
let index = dynamicValidateForm.cluster.indexOf(item);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ ProtocolMapping.set('Ctwing', 'HTTP');
|
||||||
ProtocolMapping.set('modbus-tcp', 'MODBUS_TCP');
|
ProtocolMapping.set('modbus-tcp', 'MODBUS_TCP');
|
||||||
ProtocolMapping.set('opc-ua', 'OPC_UA');
|
ProtocolMapping.set('opc-ua', 'OPC_UA');
|
||||||
ProtocolMapping.set('edge-child-device', 'EdgeGateway');
|
ProtocolMapping.set('edge-child-device', 'EdgeGateway');
|
||||||
|
ProtocolMapping.set('collector-gateway', 'collector-gateway');
|
||||||
ProtocolMapping.set('official-edge-gateway', 'MQTT');
|
ProtocolMapping.set('official-edge-gateway', 'MQTT');
|
||||||
|
|
||||||
const NetworkTypeMapping = new Map();
|
const NetworkTypeMapping = new Map();
|
||||||
|
@ -44,6 +45,7 @@ BackMap.set('gb28181-2016', getImage('/access/gb28181.png'));
|
||||||
BackMap.set('mqtt-client-gateway', getImage('/access/mqtt-broke.png'));
|
BackMap.set('mqtt-client-gateway', getImage('/access/mqtt-broke.png'));
|
||||||
BackMap.set('edge-child-device', getImage('/access/child-device.png'));
|
BackMap.set('edge-child-device', getImage('/access/child-device.png'));
|
||||||
BackMap.set('official-edge-gateway', getImage('/access/edge.png'));
|
BackMap.set('official-edge-gateway', getImage('/access/edge.png'));
|
||||||
|
BackMap.set('collector-gateway', getImage('/access/collector-gateway.png'));
|
||||||
|
|
||||||
const descriptionList = {
|
const descriptionList = {
|
||||||
'udp-device-gateway':
|
'udp-device-gateway':
|
||||||
|
|
|
@ -94,9 +94,9 @@ export default defineConfig(({ mode}) => {
|
||||||
[env.VITE_APP_BASE_API]: {
|
[env.VITE_APP_BASE_API]: {
|
||||||
// target: 'http://192.168.32.226:8844',
|
// target: 'http://192.168.32.226:8844',
|
||||||
// target: 'http://192.168.32.244:8881',
|
// target: 'http://192.168.32.244:8881',
|
||||||
// target: 'http://192.168.32.163:8844', //张季本地
|
target: 'http://192.168.32.163:8844', //张季本地
|
||||||
// target: 'http://120.77.179.54:8844', // 120测试
|
// target: 'http://120.77.179.54:8844', // 120测试
|
||||||
target: 'http://192.168.33.46:8844', // 本地开发环境
|
// target: 'http://192.168.33.46:8844', // 本地开发环境
|
||||||
ws: 'ws://192.168.33.46:8844',
|
ws: 'ws://192.168.33.46:8844',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, '')
|
rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
|
|
Loading…
Reference in New Issue