feat(运维管理): 重构网关页面并添加新功能
-重新设计了网关列表和表单的结构,增加了更多字段和选项 - 添加了网络组件和消息协议的动态加载功能 - 实现了根据接入方式动态显示不同表单字段的逻辑 - 优化了表单验证和数据提交的流程 - 统一了启用状态的显示和操作 - 调整了部分UI样式,提高了用户体验
This commit is contained in:
parent
fe3c9b570e
commit
cb5ab82af4
|
@ -1,52 +1,122 @@
|
||||||
import type { FormSchemaGetter } from '#/adapter/form';
|
import type { FormSchemaGetter } from '#/adapter/form';
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { networkList } from '#/api/operations/network';
|
||||||
|
import { protocolList } from '#/api/operations/protocol';
|
||||||
|
|
||||||
|
import { enabledOptions, networkTypeOptions } from '../user.data';
|
||||||
|
|
||||||
|
export const providerOptions = [
|
||||||
|
...networkTypeOptions,
|
||||||
|
{
|
||||||
|
label: '网关子设备接入',
|
||||||
|
value: 'child-device',
|
||||||
|
channel: 'child-device',
|
||||||
|
transport: 'Gateway',
|
||||||
|
description:
|
||||||
|
'需要通过网关与平台进行数据通信的设备,将作为网关子设备接入到平台。',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 存储网络组件更新回调函数
|
||||||
|
let networkOptionsUpdateCallback: ((provider: string) => Promise<void>) | null =
|
||||||
|
null;
|
||||||
|
|
||||||
|
// 注册网络组件更新回调
|
||||||
|
export const registerNetworkOptionsUpdate = (
|
||||||
|
callback: (provider: string) => Promise<void>,
|
||||||
|
) => {
|
||||||
|
networkOptionsUpdateCallback = callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取网络组件选项
|
||||||
|
export const getNetworkOptions = async (networkType?: string) => {
|
||||||
|
try {
|
||||||
|
const params: any = { enabled: '1' };
|
||||||
|
if (networkType) {
|
||||||
|
params.networkType = networkType;
|
||||||
|
}
|
||||||
|
const response = await networkList(params);
|
||||||
|
return response.rows.map((item: any) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取网络组件失败:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取消息协议选项
|
||||||
|
export const getProtocolOptions = async () => {
|
||||||
|
try {
|
||||||
|
const response = await protocolList({ enabled: '1' });
|
||||||
|
return response.rows.map((item: any) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取消息协议失败:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const querySchema: FormSchemaGetter = () => [
|
export const querySchema: FormSchemaGetter = () => [
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'enabled',
|
|
||||||
label: '启用状态 0 禁用',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
fieldName: 'name',
|
fieldName: 'name',
|
||||||
label: '网关名称',
|
label: '网关名称',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: providerOptions,
|
||||||
|
placeholder: '请选择',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
fieldName: 'provider',
|
fieldName: 'provider',
|
||||||
label: '接入方式,如: mqtt-server-gateway',
|
label: '接入方式',
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// component: 'Select',
|
||||||
|
// componentProps: {
|
||||||
|
// allowClear: true,
|
||||||
|
// filterOption: true,
|
||||||
|
// placeholder: '请选择网络组件',
|
||||||
|
// showSearch: true,
|
||||||
|
// },
|
||||||
|
// fieldName: 'channelId',
|
||||||
|
// label: '网络组件',
|
||||||
|
// dependencies: {
|
||||||
|
// triggerFields: ['provider'],
|
||||||
|
// show: (values: any) =>
|
||||||
|
// values.provider && values.provider !== 'child-device',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Select',
|
||||||
fieldName: 'description',
|
componentProps: {
|
||||||
label: '描述',
|
allowClear: true,
|
||||||
},
|
filterOption: true,
|
||||||
{
|
placeholder: '请选择消息协议',
|
||||||
component: 'Input',
|
showSearch: true,
|
||||||
fieldName: 'channel',
|
},
|
||||||
label: '通道 接入通道(方式),如网络组件',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'channelId',
|
|
||||||
label: '通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'protocol',
|
fieldName: 'protocol',
|
||||||
label: '消息协议 消息协议',
|
label: '消息协议',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Select',
|
||||||
fieldName: 'transport',
|
componentProps: {
|
||||||
label: '传输协议,如TCP,MQTT,UDP',
|
allowClear: true,
|
||||||
},
|
filterOption: true,
|
||||||
{
|
options: enabledOptions,
|
||||||
component: 'Textarea',
|
placeholder: '请选择',
|
||||||
fieldName: 'gatewayConfig',
|
showSearch: true,
|
||||||
label: '网关配置',
|
},
|
||||||
|
fieldName: 'enabled',
|
||||||
|
label: '启用状态',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -58,41 +128,22 @@ export const columns: VxeGridProps['columns'] = [
|
||||||
title: '编号',
|
title: '编号',
|
||||||
field: 'id',
|
field: 'id',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '启用状态 0 禁用',
|
|
||||||
field: 'enabled',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '网关名称',
|
title: '网关名称',
|
||||||
field: 'name',
|
field: 'name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '接入方式,如: mqtt-server-gateway',
|
title: '网络组件',
|
||||||
field: 'provider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '描述',
|
|
||||||
field: 'description',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '通道 接入通道(方式),如网络组件',
|
|
||||||
field: 'channel',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID',
|
|
||||||
field: 'channelId',
|
field: 'channelId',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '消息协议 消息协议',
|
title: '消息协议',
|
||||||
field: 'protocol',
|
field: 'protocol',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '传输协议,如TCP,MQTT,UDP',
|
title: '启用状态',
|
||||||
field: 'transport',
|
field: 'enabled',
|
||||||
},
|
slots: { default: 'enabled' },
|
||||||
{
|
|
||||||
title: '网关配置',
|
|
||||||
field: 'gatewayConfig',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'action',
|
field: 'action',
|
||||||
|
@ -113,12 +164,6 @@ export const drawerSchema: FormSchemaGetter = () => [
|
||||||
triggerFields: [''],
|
triggerFields: [''],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: '启用状态 0 禁用',
|
|
||||||
fieldName: 'enabled',
|
|
||||||
component: 'Input',
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: '网关名称',
|
label: '网关名称',
|
||||||
fieldName: 'name',
|
fieldName: 'name',
|
||||||
|
@ -126,45 +171,94 @@ export const drawerSchema: FormSchemaGetter = () => [
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '接入方式,如: mqtt-server-gateway',
|
label: '接入方式',
|
||||||
fieldName: 'provider',
|
fieldName: 'provider',
|
||||||
component: 'Input',
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: providerOptions,
|
||||||
|
placeholder: '请选择',
|
||||||
|
showSearch: true,
|
||||||
|
onChange: async (value: string) => {
|
||||||
|
console.log('抽屉表单接入方式变化:', value);
|
||||||
|
if (networkOptionsUpdateCallback) {
|
||||||
|
await networkOptionsUpdateCallback(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '网络组件',
|
||||||
|
fieldName: 'channelId',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
placeholder: '请选择网络组件',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['provider'],
|
||||||
|
show: (values: any) =>
|
||||||
|
values.provider && values.provider !== 'child-device',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '消息协议',
|
||||||
|
fieldName: 'protocol',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
placeholder: '请选择消息协议',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['provider'],
|
||||||
|
show: (values: any) => values.provider && values.provider !== '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '启用状态',
|
||||||
|
fieldName: 'enabled',
|
||||||
|
component: 'RadioGroup',
|
||||||
|
componentProps: {
|
||||||
|
buttonStyle: 'solid',
|
||||||
|
options: enabledOptions,
|
||||||
|
optionType: 'button',
|
||||||
|
},
|
||||||
|
defaultValue: '1',
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '描述',
|
label: '描述',
|
||||||
fieldName: 'description',
|
fieldName: 'description',
|
||||||
component: 'Input',
|
component: 'Textarea',
|
||||||
rules: 'required',
|
componentProps: {
|
||||||
|
placeholder: '请输入描述',
|
||||||
|
rows: 3,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '通道 接入通道(方式),如网络组件',
|
label: '接入通道(方式)',
|
||||||
fieldName: 'channel',
|
fieldName: 'channel',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
rules: 'required',
|
dependencies: {
|
||||||
|
show: () => false,
|
||||||
|
triggerFields: [''],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID',
|
label: '传输协议',
|
||||||
fieldName: 'channelId',
|
|
||||||
component: 'Input',
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '消息协议 消息协议',
|
|
||||||
fieldName: 'protocol',
|
|
||||||
component: 'Input',
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '传输协议,如TCP,MQTT,UDP',
|
|
||||||
fieldName: 'transport',
|
fieldName: 'transport',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
rules: 'required',
|
dependencies: {
|
||||||
},
|
show: () => false,
|
||||||
{
|
triggerFields: [''],
|
||||||
label: '网关配置',
|
},
|
||||||
fieldName: 'gatewayConfig',
|
|
||||||
component: 'Textarea',
|
|
||||||
rules: 'required',
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -6,10 +6,20 @@ import { $t } from '@vben/locales';
|
||||||
import { cloneDeep } from '@vben/utils';
|
import { cloneDeep } from '@vben/utils';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { gatewayAdd, gatewayInfo, gatewayUpdate } from '#/api/operations/gateway';
|
import {
|
||||||
|
gatewayAdd,
|
||||||
|
gatewayInfo,
|
||||||
|
gatewayUpdate,
|
||||||
|
} from '#/api/operations/gateway';
|
||||||
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
|
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
|
||||||
|
|
||||||
import { drawerSchema } from './data';
|
import {
|
||||||
|
drawerSchema,
|
||||||
|
getNetworkOptions,
|
||||||
|
getProtocolOptions,
|
||||||
|
providerOptions,
|
||||||
|
registerNetworkOptionsUpdate,
|
||||||
|
} from './data';
|
||||||
|
|
||||||
const emit = defineEmits<{ reload: [] }>();
|
const emit = defineEmits<{ reload: [] }>();
|
||||||
|
|
||||||
|
@ -27,13 +37,72 @@ const [BasicForm, formApi] = useVbenForm({
|
||||||
// 通用配置项 会影响到所有表单项
|
// 通用配置项 会影响到所有表单项
|
||||||
componentProps: {
|
componentProps: {
|
||||||
class: 'w-full',
|
class: 'w-full',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
schema: drawerSchema(),
|
schema: drawerSchema(),
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
wrapperClass: 'grid-cols-2',
|
wrapperClass: 'grid-cols-2',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 更新抽屉表单的网络组件选项
|
||||||
|
async function updateDrawerNetworkOptions(provider: string) {
|
||||||
|
try {
|
||||||
|
if (provider && provider !== 'child-device') {
|
||||||
|
const networkOptions = await getNetworkOptions(provider);
|
||||||
|
console.log('网络组件选项:', provider);
|
||||||
|
await formApi.updateSchema(
|
||||||
|
drawerSchema().map((field: any) => {
|
||||||
|
if (field.fieldName === 'channelId') {
|
||||||
|
return {
|
||||||
|
...field,
|
||||||
|
componentProps: {
|
||||||
|
...field.componentProps,
|
||||||
|
options: networkOptions,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
await formApi.setFieldValue('channelId', ''); // 清空选中值
|
||||||
|
providerOptions.forEach((option) => {
|
||||||
|
if (option.value === provider) {
|
||||||
|
formApi.setFieldValue('channel', option.channel);
|
||||||
|
formApi.setFieldValue('transport', option.transport);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 如果是网关子设备接入,清空网络组件选项
|
||||||
|
await formApi.updateSchema(
|
||||||
|
drawerSchema().map((field: any) => {
|
||||||
|
if (field.fieldName === 'channelId') {
|
||||||
|
return {
|
||||||
|
...field,
|
||||||
|
componentProps: {
|
||||||
|
...field.componentProps,
|
||||||
|
options: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
await formApi.setFieldValue('channelId', ''); // 清空选中值
|
||||||
|
providerOptions.forEach((option) => {
|
||||||
|
if (option.value === provider) {
|
||||||
|
formApi.setFieldValue('channel', option.channel);
|
||||||
|
formApi.setFieldValue('transport', option.transport);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新抽屉表单网络组件选项失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册网络组件更新回调
|
||||||
|
registerNetworkOptionsUpdate(updateDrawerNetworkOptions);
|
||||||
|
|
||||||
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
|
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
|
||||||
{
|
{
|
||||||
initializedGetter: defaultFormValueGetter(formApi),
|
initializedGetter: defaultFormValueGetter(formApi),
|
||||||
|
@ -44,7 +113,6 @@ const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
|
||||||
const [BasicDrawer, drawerApi] = useVbenDrawer({
|
const [BasicDrawer, drawerApi] = useVbenDrawer({
|
||||||
// 在这里更改宽度
|
// 在这里更改宽度
|
||||||
class: 'w-[550px]',
|
class: 'w-[550px]',
|
||||||
fullscreenButton: false,
|
|
||||||
onBeforeClose,
|
onBeforeClose,
|
||||||
onClosed: handleClosed,
|
onClosed: handleClosed,
|
||||||
onConfirm: handleConfirm,
|
onConfirm: handleConfirm,
|
||||||
|
@ -54,12 +122,39 @@ const [BasicDrawer, drawerApi] = useVbenDrawer({
|
||||||
}
|
}
|
||||||
drawerApi.drawerLoading(true);
|
drawerApi.drawerLoading(true);
|
||||||
|
|
||||||
|
// 动态加载选项数据并更新schema
|
||||||
|
try {
|
||||||
|
const protocolOptions = await getProtocolOptions();
|
||||||
|
|
||||||
|
const updatedSchema = drawerSchema().map((field: any) => {
|
||||||
|
if (field.fieldName === 'protocol') {
|
||||||
|
return {
|
||||||
|
...field,
|
||||||
|
componentProps: {
|
||||||
|
...field.componentProps,
|
||||||
|
options: protocolOptions,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
});
|
||||||
|
|
||||||
|
await formApi.updateSchema(updatedSchema);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载选项数据失败:', error);
|
||||||
|
}
|
||||||
|
|
||||||
const { id } = drawerApi.getData() as { id?: number | string };
|
const { id } = drawerApi.getData() as { id?: number | string };
|
||||||
isUpdate.value = !!id;
|
isUpdate.value = !!id;
|
||||||
|
|
||||||
if (isUpdate.value && id) {
|
if (isUpdate.value && id) {
|
||||||
const record = await gatewayInfo(id);
|
const record = await gatewayInfo(id);
|
||||||
await formApi.setValues(record);
|
await formApi.setValues(record);
|
||||||
|
|
||||||
|
// 如果是编辑模式,根据provider加载对应的网络组件选项
|
||||||
|
if (record.provider && record.provider !== 'child-device') {
|
||||||
|
await loadNetworkOptions(String(record.provider));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await markInitialized();
|
await markInitialized();
|
||||||
|
|
||||||
|
@ -67,6 +162,32 @@ const [BasicDrawer, drawerApi] = useVbenDrawer({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 根据接入方式加载网络组件选项
|
||||||
|
async function loadNetworkOptions(provider: string) {
|
||||||
|
try {
|
||||||
|
if (provider && provider !== 'child-device') {
|
||||||
|
const networkOptions = await getNetworkOptions(provider);
|
||||||
|
|
||||||
|
await formApi.updateSchema(
|
||||||
|
drawerSchema().map((field: any) => {
|
||||||
|
if (field.fieldName === 'channelId') {
|
||||||
|
return {
|
||||||
|
...field,
|
||||||
|
componentProps: {
|
||||||
|
...field.componentProps,
|
||||||
|
options: networkOptions,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载网络组件选项失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleConfirm() {
|
async function handleConfirm() {
|
||||||
try {
|
try {
|
||||||
drawerApi.lock(true);
|
drawerApi.lock(true);
|
||||||
|
@ -98,4 +219,3 @@ async function handleClosed() {
|
||||||
<BasicForm />
|
<BasicForm />
|
||||||
</BasicDrawer>
|
</BasicDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Recordable } from '@vben/types';
|
import type { VbenFormProps } from '@vben/common-ui';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
import type { GatewayForm } from '#/api/operations/gateway/model';
|
||||||
|
|
||||||
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
|
import { Page, useVbenDrawer } from '@vben/common-ui';
|
||||||
import { getVxePopupContainer } from '@vben/utils';
|
import { getVxePopupContainer } from '@vben/utils';
|
||||||
|
|
||||||
import { Modal, Popconfirm, Space } from 'ant-design-vue';
|
import { Modal, Popconfirm, Space, Tag } from 'ant-design-vue';
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
import {
|
|
||||||
useVbenVxeGrid,
|
|
||||||
vxeCheckboxChecked,
|
|
||||||
type VxeGridProps
|
|
||||||
} from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
|
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
gatewayExport,
|
gatewayExport,
|
||||||
gatewayList,
|
gatewayList,
|
||||||
gatewayRemove,
|
gatewayRemove,
|
||||||
} from '#/api/operations/gateway';
|
} from '#/api/operations/gateway';
|
||||||
import type { GatewayForm } from '#/api/operations/gateway/model';
|
|
||||||
import { commonDownloadExcel } from '#/utils/file/download';
|
import { commonDownloadExcel } from '#/utils/file/download';
|
||||||
|
|
||||||
|
import {
|
||||||
|
columns,
|
||||||
|
getNetworkOptions,
|
||||||
|
getProtocolOptions,
|
||||||
|
querySchema,
|
||||||
|
registerNetworkOptionsUpdate,
|
||||||
|
} from './data';
|
||||||
import gatewayDrawer from './gateway-drawer.vue';
|
import gatewayDrawer from './gateway-drawer.vue';
|
||||||
import { columns, querySchema } from './data';
|
|
||||||
|
|
||||||
const formOptions: VbenFormProps = {
|
const formOptions: VbenFormProps = {
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
|
@ -35,15 +35,6 @@ const formOptions: VbenFormProps = {
|
||||||
},
|
},
|
||||||
schema: querySchema(),
|
schema: querySchema(),
|
||||||
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
|
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
|
||||||
// 处理区间选择器RangePicker时间格式 将一个字段映射为两个字段 搜索/导出会用到
|
|
||||||
// 不需要直接删除
|
|
||||||
// fieldMappingTime: [
|
|
||||||
// [
|
|
||||||
// 'createTime',
|
|
||||||
// ['params[beginTime]', 'params[endTime]'],
|
|
||||||
// ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'],
|
|
||||||
// ],
|
|
||||||
// ],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const gridOptions: VxeGridProps = {
|
const gridOptions: VxeGridProps = {
|
||||||
|
@ -76,7 +67,7 @@ const gridOptions: VxeGridProps = {
|
||||||
keyField: 'id',
|
keyField: 'id',
|
||||||
},
|
},
|
||||||
// 表格全局唯一表示 保存列配置需要用到
|
// 表格全局唯一表示 保存列配置需要用到
|
||||||
id: 'operations-gateway-index'
|
id: 'operations-gateway-index',
|
||||||
};
|
};
|
||||||
|
|
||||||
const [BasicTable, tableApi] = useVbenVxeGrid({
|
const [BasicTable, tableApi] = useVbenVxeGrid({
|
||||||
|
@ -84,6 +75,79 @@ const [BasicTable, tableApi] = useVbenVxeGrid({
|
||||||
gridOptions,
|
gridOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 更新网络组件选项
|
||||||
|
async function updateNetworkComponentOptions(provider: string) {
|
||||||
|
try {
|
||||||
|
if (provider && provider !== 'child-device') {
|
||||||
|
const networkOptions = await getNetworkOptions(provider);
|
||||||
|
|
||||||
|
await tableApi.formApi.updateSchema(
|
||||||
|
querySchema().map((field: any) => {
|
||||||
|
if (field.fieldName === 'channelId') {
|
||||||
|
return {
|
||||||
|
...field,
|
||||||
|
componentProps: {
|
||||||
|
...field.componentProps,
|
||||||
|
options: networkOptions,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 如果是网关子设备接入,清空网络组件选项
|
||||||
|
await tableApi.formApi.updateSchema(
|
||||||
|
querySchema().map((field: any) => {
|
||||||
|
if (field.fieldName === 'channelId') {
|
||||||
|
return {
|
||||||
|
...field,
|
||||||
|
componentProps: {
|
||||||
|
...field.componentProps,
|
||||||
|
options: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新网络组件选项失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册网络组件更新回调
|
||||||
|
registerNetworkOptionsUpdate(updateNetworkComponentOptions);
|
||||||
|
|
||||||
|
// 动态加载表单选项
|
||||||
|
async function loadFormOptions() {
|
||||||
|
try {
|
||||||
|
const protocolOptions = await getProtocolOptions();
|
||||||
|
|
||||||
|
// 更新表单字段的选项
|
||||||
|
await tableApi.formApi.updateSchema(
|
||||||
|
querySchema().map((field: any) => {
|
||||||
|
if (field.fieldName === 'protocol') {
|
||||||
|
return {
|
||||||
|
...field,
|
||||||
|
componentProps: {
|
||||||
|
...field.componentProps,
|
||||||
|
options: protocolOptions,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载表单选项失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件挂载后加载选项
|
||||||
|
loadFormOptions();
|
||||||
|
|
||||||
const [GatewayDrawer, drawerApi] = useVbenDrawer({
|
const [GatewayDrawer, drawerApi] = useVbenDrawer({
|
||||||
connectedComponent: gatewayDrawer,
|
connectedComponent: gatewayDrawer,
|
||||||
});
|
});
|
||||||
|
@ -118,9 +182,14 @@ function handleMultiDelete() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDownloadExcel() {
|
function handleDownloadExcel() {
|
||||||
commonDownloadExcel(gatewayExport, '设备接入网关数据', tableApi.formApi.form.values, {
|
commonDownloadExcel(
|
||||||
fieldMappingTime: formOptions.fieldMappingTime,
|
gatewayExport,
|
||||||
});
|
'设备接入网关数据',
|
||||||
|
tableApi.formApi.form.values,
|
||||||
|
{
|
||||||
|
fieldMappingTime: formOptions.fieldMappingTime,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -138,9 +207,10 @@ function handleDownloadExcel() {
|
||||||
<a-button
|
<a-button
|
||||||
:disabled="!vxeCheckboxChecked(tableApi)"
|
:disabled="!vxeCheckboxChecked(tableApi)"
|
||||||
danger
|
danger
|
||||||
type="primary"
|
type="primary"
|
||||||
v-access:code="['operations:gateway:remove']"
|
v-access:code="['operations:gateway:remove']"
|
||||||
@click="handleMultiDelete">
|
@click="handleMultiDelete"
|
||||||
|
>
|
||||||
{{ $t('pages.common.delete') }}
|
{{ $t('pages.common.delete') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
|
@ -152,6 +222,11 @@ function handleDownloadExcel() {
|
||||||
</a-button>
|
</a-button>
|
||||||
</Space>
|
</Space>
|
||||||
</template>
|
</template>
|
||||||
|
<template #enabled="{ row }">
|
||||||
|
<Tag :color="row.enabled === '1' ? 'success' : 'error'">
|
||||||
|
{{ row.enabled === '1' ? '启用' : '禁用' }}
|
||||||
|
</Tag>
|
||||||
|
</template>
|
||||||
<template #action="{ row }">
|
<template #action="{ row }">
|
||||||
<Space>
|
<Space>
|
||||||
<ghost-button
|
<ghost-button
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
import type { FormSchemaGetter } from '#/adapter/form';
|
import type { FormSchemaGetter } from '#/adapter/form';
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
import { networkTypeOptions,enabledOptions } from '../user.data';
|
||||||
|
|
||||||
const networkTypeOptions = [
|
// const networkTypeOptions = [
|
||||||
{ label: 'MQTT客户端', value: 'MQTT_CLIENT' },
|
// { label: 'MQTT客户端', value: 'MQTT_CLIENT' },
|
||||||
{ label: 'HTTP服务', value: 'HTTP_SERVER' },
|
// { label: 'HTTP服务', value: 'HTTP_SERVER' },
|
||||||
];
|
// ];
|
||||||
|
|
||||||
const enabledOptions = [
|
// const enabledOptions = [
|
||||||
{ label: '启用', value: '1' },
|
// { label: '启用', value: '1' },
|
||||||
{ label: '禁用', value: '0' },
|
// { label: '禁用', value: '0' },
|
||||||
];
|
// ];
|
||||||
|
|
||||||
// HTTP服务配置字段
|
// HTTP服务配置字段
|
||||||
const httpServerFields = [
|
const httpServerFields = [
|
||||||
|
|
|
@ -27,7 +27,7 @@ const [BasicForm, formApi] = useVbenForm({
|
||||||
// 默认占满两列
|
// 默认占满两列
|
||||||
formItemClass: 'col-span-2',
|
formItemClass: 'col-span-2',
|
||||||
// 默认label宽度 px
|
// 默认label宽度 px
|
||||||
labelWidth: 100,
|
labelWidth: 120,
|
||||||
// 通用配置项 会影响到所有表单项
|
// 通用配置项 会影响到所有表单项
|
||||||
componentProps: {
|
componentProps: {
|
||||||
class: 'w-full',
|
class: 'w-full',
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
export const networkTypeOptions = [
|
||||||
|
{
|
||||||
|
label: 'MQTT客户端',
|
||||||
|
value: 'MQTT_CLIENT',
|
||||||
|
channel: 'network',
|
||||||
|
transport: 'MQTT',
|
||||||
|
description:
|
||||||
|
'MQTT是ISO 标准下基于发布/订阅范式的消息协议,具有轻量、简单、开放和易于实现的特点。平台使用指定的ID接入其他远程平台,订阅消息。也可添加用户名和密码校验。可设置最大消息长度。可统一设置共享的订阅前缀。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'HTTP服务',
|
||||||
|
value: 'HTTP_SERVER',
|
||||||
|
channel: 'network',
|
||||||
|
transport: 'HTTP',
|
||||||
|
description:
|
||||||
|
'HTTP服务是一个简单的请求-响应的基于TCP的无状态协议。设备通过HTTP服务与平台进行灵活的短链接通信,仅支持设备和平台之间单对单的请求-响应模式',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export const enabledOptions = [
|
||||||
|
{ label: '启用', value: '1' },
|
||||||
|
{ label: '禁用', value: '0' },
|
||||||
|
];
|
Loading…
Reference in New Issue