|
@@ -1,58 +1,95 @@
|
|
|
<script setup lang="ts">
|
|
|
-import { onMounted, ref } from 'vue';
|
|
|
+import { onMounted, ref, useTemplateRef } from 'vue';
|
|
|
|
|
|
+import ConfirmModal from '@/components/ConfirmModal.vue';
|
|
|
+import SvgIcon from '@/components/SvgIcon.vue';
|
|
|
import { useRequest } from '@/hooks/request';
|
|
|
-import { gatewayLinkGetList, gatewayLinkList, gatewayList } from '@/api';
|
|
|
-
|
|
|
-import type { GatewayListItem, GatewayQuery, InterfaceData, VerificationAgreement } from '@/types';
|
|
|
+import { t } from '@/i18n';
|
|
|
+import {
|
|
|
+ addGatewayLinkBatchUpdate,
|
|
|
+ gatewayLinkGetList,
|
|
|
+ gatewayLinkList,
|
|
|
+ gatewayList,
|
|
|
+ obtainListInterfaces,
|
|
|
+ obtainListPhysicalInterfaces,
|
|
|
+ orgGatewayUnregister,
|
|
|
+} from '@/api';
|
|
|
+
|
|
|
+import type { DefaultOptionType, SelectValue } from 'ant-design-vue/es/select';
|
|
|
+import type {
|
|
|
+ BatchUpdate,
|
|
|
+ GatewayListItem,
|
|
|
+ GatewayQuery,
|
|
|
+ InterfaceData,
|
|
|
+ LinkProtocolType,
|
|
|
+ ListInterfaces,
|
|
|
+ ListPhysicalInterfaces,
|
|
|
+ VerificationAgreement,
|
|
|
+} from '@/types';
|
|
|
|
|
|
const gatewayColumns = [
|
|
|
{
|
|
|
- title: '序号',
|
|
|
+ title: t('common.serialNumber'),
|
|
|
dataIndex: 'index',
|
|
|
key: 'index',
|
|
|
},
|
|
|
{
|
|
|
- title: '序列号',
|
|
|
+ title: t('common.sequenceNumber'),
|
|
|
dataIndex: 'snCode',
|
|
|
key: 'snCode',
|
|
|
ellipsis: true,
|
|
|
},
|
|
|
{
|
|
|
- title: '型号',
|
|
|
+ title: t('createDevice.modelNumber'),
|
|
|
dataIndex: 'modelName',
|
|
|
key: 'modelName',
|
|
|
ellipsis: true,
|
|
|
},
|
|
|
{
|
|
|
- title: '在线状态',
|
|
|
+ title: t('registerGateway.onlineStatus'),
|
|
|
dataIndex: 'state',
|
|
|
key: 'state',
|
|
|
ellipsis: true,
|
|
|
},
|
|
|
+ {
|
|
|
+ title: t('common.operation'),
|
|
|
+ dataIndex: 'action',
|
|
|
+ key: 'action',
|
|
|
+ width: 80,
|
|
|
+ },
|
|
|
];
|
|
|
|
|
|
const agreementColumns = [
|
|
|
{
|
|
|
- title: '站号',
|
|
|
+ title: t('registerGateway.stationNumber'),
|
|
|
dataIndex: 'station',
|
|
|
key: 'station',
|
|
|
+ ellipsis: true,
|
|
|
},
|
|
|
{
|
|
|
- title: '协议',
|
|
|
+ title: t('registerGateway.agreement'),
|
|
|
dataIndex: 'protocolName',
|
|
|
key: 'protocolName',
|
|
|
+ ellipsis: true,
|
|
|
},
|
|
|
{
|
|
|
- title: '关联设备',
|
|
|
- dataIndex: 'dev',
|
|
|
- key: 'dev',
|
|
|
+ title: t('registerGateway.associatedEquipment'),
|
|
|
+ dataIndex: 'deviceName',
|
|
|
+ key: 'deviceName',
|
|
|
+ ellipsis: true,
|
|
|
},
|
|
|
];
|
|
|
|
|
|
const gatewayData = ref<GatewayListItem[]>([]);
|
|
|
const interfaceList = ref<InterfaceData[]>([]);
|
|
|
const agreementList = ref<VerificationAgreement[]>([]);
|
|
|
+const gatewayId = ref<number>();
|
|
|
+const gatewayEditor = ref<boolean>(false);
|
|
|
+const interfaceSelectList = ref<ListInterfaces[]>([]);
|
|
|
+const listPhysicalInterfaces = ref<ListPhysicalInterfaces[]>([]);
|
|
|
+const gatewayLinks = ref<BatchUpdate[]>([]);
|
|
|
+const data: LinkProtocolType[] = [];
|
|
|
+
|
|
|
const activeKey = ref();
|
|
|
const gatewayQuery = ref<GatewayQuery>({
|
|
|
pageIndex: 1,
|
|
@@ -62,40 +99,136 @@ const gatewayQuery = ref<GatewayQuery>({
|
|
|
total: 0,
|
|
|
});
|
|
|
|
|
|
+const modalComponentRef = useTemplateRef('modalComponent');
|
|
|
+
|
|
|
const { handleRequest } = useRequest();
|
|
|
-const addGatewayList = () => {
|
|
|
+
|
|
|
+const getGatewayList = () => {
|
|
|
handleRequest(async () => {
|
|
|
const { records, total } = await gatewayList(gatewayQuery.value);
|
|
|
+ gatewayData.value = records;
|
|
|
+ gatewayQuery.value.total = total;
|
|
|
if (records.length) {
|
|
|
- gatewayData.value = records;
|
|
|
- gatewayQuery.value.total = total;
|
|
|
+ getObtainListInterfaces(gatewayData.value[0].modelId);
|
|
|
postLinkGetList(gatewayData.value[0].id);
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
|
|
|
+const addGatewayList = () => {
|
|
|
+ gatewayQuery.value.pageIndex = 1;
|
|
|
+ getGatewayList();
|
|
|
+};
|
|
|
+
|
|
|
+const addReset = () => {
|
|
|
+ gatewayQuery.value.searchContent = '';
|
|
|
+ gatewayQuery.value.state = -1;
|
|
|
+};
|
|
|
+
|
|
|
const rowClick = (record: GatewayListItem) => {
|
|
|
return {
|
|
|
onClick: () => {
|
|
|
- console.log(record);
|
|
|
- console.log(123);
|
|
|
+ gatewayId.value = record.id;
|
|
|
+ getObtainListInterfaces(record.modelId);
|
|
|
postLinkGetList(record.id);
|
|
|
},
|
|
|
};
|
|
|
};
|
|
|
|
|
|
+const getObtainListInterfaces = (id: number) => {
|
|
|
+ handleRequest(async () => {
|
|
|
+ interfaceSelectList.value = await obtainListInterfaces(id);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const getObtainListPhysicalInterfaces = (id: number, value?: InterfaceData) => {
|
|
|
+ handleRequest(async () => {
|
|
|
+ console.log(id, value);
|
|
|
+ listPhysicalInterfaces.value = await obtainListPhysicalInterfaces(id);
|
|
|
+ if (value) {
|
|
|
+ if (listPhysicalInterfaces.value.length) {
|
|
|
+ value.protocolType = listPhysicalInterfaces.value[0].protocolName;
|
|
|
+ } else {
|
|
|
+ value.protocolType = '';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const choosePhysicalInterface = (
|
|
|
+ selectValue: SelectValue,
|
|
|
+ option: DefaultOptionType,
|
|
|
+ id: number,
|
|
|
+ value: InterfaceData,
|
|
|
+ index: number,
|
|
|
+) => {
|
|
|
+ interfaceList.value[index].interfaceType = option.interfaceType;
|
|
|
+ interfaceList.value[index].linkName = option.name;
|
|
|
+
|
|
|
+ getObtainListPhysicalInterfaces(id, value);
|
|
|
+};
|
|
|
+
|
|
|
const postLinkGetList = (id: number) => {
|
|
|
handleRequest(async () => {
|
|
|
interfaceList.value = await gatewayLinkGetList(id);
|
|
|
if (interfaceList.value.length) {
|
|
|
activeKey.value = interfaceList.value[0].id;
|
|
|
agreementList.value = await gatewayLinkList(interfaceList.value[0].id);
|
|
|
+ getObtainListPhysicalInterfaces(interfaceList.value[0].interfaceId);
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
|
|
|
const switchPages = () => {
|
|
|
- addGatewayList();
|
|
|
+ getGatewayList();
|
|
|
+};
|
|
|
+
|
|
|
+const refreshData = () => {
|
|
|
+ gatewayQuery.value.pageIndex = 1;
|
|
|
+ getGatewayList();
|
|
|
+};
|
|
|
+
|
|
|
+const confirm = () => {
|
|
|
+ handleRequest(async () => {
|
|
|
+ if (gatewayId.value) {
|
|
|
+ await orgGatewayUnregister(gatewayId.value);
|
|
|
+ modalComponentRef.value?.hideView();
|
|
|
+ getGatewayList();
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const addGatewayDelete = (id: number) => {
|
|
|
+ gatewayId.value = id;
|
|
|
+ modalComponentRef.value?.showView();
|
|
|
+};
|
|
|
+
|
|
|
+const addSave = () => {
|
|
|
+ handleRequest(async () => {
|
|
|
+ interfaceList.value.forEach((item) => {
|
|
|
+ agreementList.value.forEach((item) => {
|
|
|
+ const { protocolId, station, isStandard, dataSendInterval, highFreqSendInterval, id, linkId } = item;
|
|
|
+ data.push({
|
|
|
+ id,
|
|
|
+ linkId,
|
|
|
+ protocolId,
|
|
|
+ station,
|
|
|
+ isStandard: String(isStandard),
|
|
|
+ dataSendInterval,
|
|
|
+ highFreqSendInterval,
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ gatewayLinks.value.push({
|
|
|
+ link: item,
|
|
|
+ protocols: data,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ console.log(gatewayLinks.value);
|
|
|
+ await addGatewayLinkBatchUpdate(gatewayLinks.value);
|
|
|
+
|
|
|
+ gatewayEditor.value = false;
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
@@ -106,19 +239,12 @@ onMounted(() => {
|
|
|
<template>
|
|
|
<div>
|
|
|
<AFlex justify="space-between">
|
|
|
- <div class="text-top">设备管理</div>
|
|
|
+ <div class="text-top">{{ $t('navigation.deviceManage') }}</div>
|
|
|
<div>
|
|
|
- <AButton class="deletion-button icon-button default-button">
|
|
|
- <AFlex align="center">
|
|
|
- <SvgIcon name="delete" />
|
|
|
-
|
|
|
- <span> 删除 </span>
|
|
|
- </AFlex>
|
|
|
- </AButton>
|
|
|
<AButton type="primary" class="icon-button">
|
|
|
<AFlex align="center">
|
|
|
<SvgIcon name="plus" />
|
|
|
- <span> 添加 </span>
|
|
|
+ <span> {{ $t('common.add') }} </span>
|
|
|
</AFlex>
|
|
|
</AButton>
|
|
|
</div>
|
|
@@ -128,29 +254,33 @@ onMounted(() => {
|
|
|
<ARow>
|
|
|
<ACol :span="12" class="gateway-left">
|
|
|
<AFlex justify="space-between" align="center" class="gateway-left-top">
|
|
|
- <div class="gateway-left-top-text">网关列表</div>
|
|
|
- <AButton type="text" class="icon-button gateway-left-top-icon">
|
|
|
+ <div class="gateway-left-top-text">{{ $t('navigation.gatewayList') }}</div>
|
|
|
+ <AButton type="text" @click="refreshData" class="icon-button gateway-left-top-icon">
|
|
|
<AFlex align="center">
|
|
|
<SvgIcon name="refresh-o" />
|
|
|
- <span> 刷新数据 </span>
|
|
|
+ <span> {{ $t('registerGateway.refreshData') }} </span>
|
|
|
</AFlex>
|
|
|
</AButton>
|
|
|
</AFlex>
|
|
|
|
|
|
<AFlex justify="space-between" align="center" class="input-bottom">
|
|
|
<div>
|
|
|
- <span class="gateway-left-text">搜索</span>
|
|
|
+ <span class="gateway-left-text">{{ $t('common.search') }}</span>
|
|
|
<AInput v-model:value="gatewayQuery.searchContent" placeholder="请输入序列号、型号" class="input-width" />
|
|
|
</div>
|
|
|
<div>
|
|
|
- <span class="gateway-left-text">状态</span>
|
|
|
- <ASelect placeholder="请选择" class="select-width" />
|
|
|
+ <span class="gateway-left-text">{{ $t('common.status') }}</span>
|
|
|
+ <ASelect class="select-width" v-model:value="gatewayQuery.state" placeholder="请选择" :allow-clear="true">
|
|
|
+ <ASelectOption :value="-1">{{ $t('common.all') }}</ASelectOption>
|
|
|
+ <ASelectOption :value="1">{{ $t('common.online') }}</ASelectOption>
|
|
|
+ <ASelectOption :value="0">{{ $t('common.offline') }}</ASelectOption>
|
|
|
+ </ASelect>
|
|
|
</div>
|
|
|
</AFlex>
|
|
|
|
|
|
<AFlex justify="flex-end">
|
|
|
- <AButton type="primary" class="query-button" @click="addGatewayList">查询</AButton>
|
|
|
- <AButton class="default-button">重置</AButton>
|
|
|
+ <AButton type="primary" class="query-button" @click="addGatewayList">{{ $t('common.query') }}</AButton>
|
|
|
+ <AButton @click="addReset" class="default-button">{{ $t('common.reset') }}</AButton>
|
|
|
</AFlex>
|
|
|
|
|
|
<ATable
|
|
@@ -165,7 +295,10 @@ onMounted(() => {
|
|
|
{{ index + 1 }}
|
|
|
</template>
|
|
|
<template v-else-if="column.key === 'state'">
|
|
|
- {{ record.state === 0 ? '离线' : '在线' }}
|
|
|
+ {{ record.state === 0 ? $t('common.offline') : $t('common.online') }}
|
|
|
+ </template>
|
|
|
+ <template v-else-if="column.key === 'action'">
|
|
|
+ <SvgIcon @click="addGatewayDelete(record.id)" class="icon-delete" name="delete" />
|
|
|
</template>
|
|
|
</template>
|
|
|
</ATable>
|
|
@@ -178,42 +311,122 @@ onMounted(() => {
|
|
|
:show-size-changer="true"
|
|
|
@change="switchPages"
|
|
|
show-quick-jumper
|
|
|
- :show-total="(total) => `共有${total}条`"
|
|
|
+ :show-total="(total) => $t('common.pageTotal', { total })"
|
|
|
/>
|
|
|
</AFlex>
|
|
|
</ACol>
|
|
|
<ACol :span="12" class="gateway-right">
|
|
|
<AFlex justify="space-between" align="center" class="gateway-right-top">
|
|
|
<div class="gateway-left-top-text">网关配置</div>
|
|
|
- <AButton type="text" class="icon-button gateway-left-top-icon">
|
|
|
- <AFlex align="center">
|
|
|
- <SvgIcon name="edit-o" />
|
|
|
- <span> 编辑 </span>
|
|
|
- </AFlex>
|
|
|
- </AButton>
|
|
|
+ <div v-if="gatewayEditor">
|
|
|
+ <AButton
|
|
|
+ v-if="gatewayEditor"
|
|
|
+ type="text"
|
|
|
+ class="icon-button gateway-left-top-icon"
|
|
|
+ @click="gatewayEditor = false"
|
|
|
+ >
|
|
|
+ <AFlex align="center">
|
|
|
+ <SvgIcon name="close" />
|
|
|
+ <span> 取消 </span>
|
|
|
+ </AFlex>
|
|
|
+ </AButton>
|
|
|
+ <AButton v-if="gatewayEditor" type="text" class="icon-button gateway-left-top-icon" @click="addSave">
|
|
|
+ <AFlex align="center">
|
|
|
+ <SvgIcon name="edit-o" />
|
|
|
+ <span> 保存 </span>
|
|
|
+ </AFlex>
|
|
|
+ </AButton>
|
|
|
+ </div>
|
|
|
+ <div v-else>
|
|
|
+ <AButton
|
|
|
+ v-if="!gatewayEditor"
|
|
|
+ type="text"
|
|
|
+ class="icon-button gateway-left-top-icon"
|
|
|
+ @click="gatewayEditor = true"
|
|
|
+ >
|
|
|
+ <AFlex align="center">
|
|
|
+ <SvgIcon name="edit-o" />
|
|
|
+ <span> 编辑 </span>
|
|
|
+ </AFlex>
|
|
|
+ </AButton>
|
|
|
+ </div>
|
|
|
</AFlex>
|
|
|
- <ACollapse v-model:active-key="activeKey" accordion v-if="interfaceList.length">
|
|
|
- <ACollapsePanel v-for="item in interfaceList" :key="item.id">
|
|
|
+ <ACollapse v-model:active-key="activeKey" accordion v-if="interfaceList.length" collapsible="icon">
|
|
|
+ <ACollapsePanel v-for="(item, index) in interfaceList" :key="item.id">
|
|
|
<template #header>
|
|
|
- <span>物理接口 {{ item.linkName }}</span>
|
|
|
+ <span class="interface-text-right">物理接口: </span>
|
|
|
+ <span v-if="!gatewayEditor">{{ item.linkName }}</span>
|
|
|
+ <ASelect
|
|
|
+ v-else
|
|
|
+ v-model:value="item.interfaceId"
|
|
|
+ class="interface-select"
|
|
|
+ :options="interfaceSelectList"
|
|
|
+ :field-names="{ label: 'name', value: 'id' }"
|
|
|
+ @change="(value, option) => choosePhysicalInterface(value, option, item.interfaceId, item, index)"
|
|
|
+ />
|
|
|
</template>
|
|
|
- <div class="gateway-right-text">协议类型: {{ item.protocolType }}</div>
|
|
|
- <ATable :columns="agreementColumns" :data-source="agreementList" :pagination="false" />
|
|
|
+ <AFlex align="center" class="gateway-type-bottom">
|
|
|
+ <div class="gateway-right-text">协议类型:</div>
|
|
|
+ <div>
|
|
|
+ <span v-if="!gatewayEditor">{{ item.protocolType }}</span>
|
|
|
+ <ASelect
|
|
|
+ v-else
|
|
|
+ v-model:value="item.protocolType"
|
|
|
+ class="interface-select"
|
|
|
+ :options="listPhysicalInterfaces"
|
|
|
+ :field-names="{ label: 'protocolName', value: 'protocolName' }"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </AFlex>
|
|
|
+
|
|
|
+ <ATable :columns="agreementColumns" :data-source="agreementList" :pagination="false">
|
|
|
+ <template #bodyCell="{ column, record }">
|
|
|
+ <template v-if="column.key === 'station'">
|
|
|
+ <AInputNumber v-if="gatewayEditor" v-model:value="record.station" :min="1" />
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </ATable>
|
|
|
</ACollapsePanel>
|
|
|
</ACollapse>
|
|
|
</ACol>
|
|
|
</ARow>
|
|
|
</div>
|
|
|
+ <ConfirmModal
|
|
|
+ ref="modalComponent"
|
|
|
+ :title="'删除确定'"
|
|
|
+ :description-text="'是否确认删除?'"
|
|
|
+ :icon="{ name: 'delete' }"
|
|
|
+ :icon-bg-color="'#F56C6C'"
|
|
|
+ @confirm="confirm"
|
|
|
+ />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
+.gateway-type-bottom {
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.interface-text-right {
|
|
|
+ margin-right: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.interface-select {
|
|
|
+ width: 192px;
|
|
|
+}
|
|
|
+
|
|
|
+.icon-delete {
|
|
|
+ font-size: 21px;
|
|
|
+ color: var(--antd-color-primary-hover);
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
.gateway-left-footer {
|
|
|
margin-top: 24px;
|
|
|
}
|
|
|
|
|
|
.gateway-right-text {
|
|
|
- margin-bottom: 16px;
|
|
|
+ margin-right: 10px;
|
|
|
font-size: 14px;
|
|
|
font-style: normal;
|
|
|
font-weight: 500;
|