diff --git a/apps/web-antd/src/views/operations/gateway/data.ts b/apps/web-antd/src/views/operations/gateway/data.ts index ea0bb74..9ceda22 100644 --- a/apps/web-antd/src/views/operations/gateway/data.ts +++ b/apps/web-antd/src/views/operations/gateway/data.ts @@ -1,52 +1,122 @@ import type { FormSchemaGetter } from '#/adapter/form'; 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) | null = + null; + +// 注册网络组件更新回调 +export const registerNetworkOptionsUpdate = ( + callback: (provider: string) => Promise, +) => { + 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 = () => [ - { - component: 'Input', - fieldName: 'enabled', - label: '启用状态 0 禁用', - }, { component: 'Input', fieldName: 'name', label: '网关名称', }, { - component: 'Input', + component: 'Select', + componentProps: { + allowClear: true, + filterOption: true, + options: providerOptions, + placeholder: '请选择', + showSearch: true, + }, 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', - fieldName: 'description', - label: '描述', - }, - { - component: 'Input', - fieldName: 'channel', - label: '通道 接入通道(方式),如网络组件', - }, - { - component: 'Input', - fieldName: 'channelId', - label: '通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID', - }, - { - component: 'Input', + component: 'Select', + componentProps: { + allowClear: true, + filterOption: true, + placeholder: '请选择消息协议', + showSearch: true, + }, fieldName: 'protocol', - label: '消息协议 消息协议', + label: '消息协议', }, { - component: 'Input', - fieldName: 'transport', - label: '传输协议,如TCP,MQTT,UDP', - }, - { - component: 'Textarea', - fieldName: 'gatewayConfig', - label: '网关配置', + component: 'Select', + componentProps: { + allowClear: true, + filterOption: true, + options: enabledOptions, + placeholder: '请选择', + showSearch: true, + }, + fieldName: 'enabled', + label: '启用状态', }, ]; @@ -58,41 +128,22 @@ export const columns: VxeGridProps['columns'] = [ title: '编号', field: 'id', }, - { - title: '启用状态 0 禁用', - field: 'enabled', - }, { title: '网关名称', field: 'name', }, { - title: '接入方式,如: mqtt-server-gateway', - field: 'provider', - }, - { - title: '描述', - field: 'description', - }, - { - title: '通道 接入通道(方式),如网络组件', - field: 'channel', - }, - { - title: '通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID', + title: '网络组件', field: 'channelId', }, { - title: '消息协议 消息协议', + title: '消息协议', field: 'protocol', }, { - title: '传输协议,如TCP,MQTT,UDP', - field: 'transport', - }, - { - title: '网关配置', - field: 'gatewayConfig', + title: '启用状态', + field: 'enabled', + slots: { default: 'enabled' }, }, { field: 'action', @@ -113,12 +164,6 @@ export const drawerSchema: FormSchemaGetter = () => [ triggerFields: [''], }, }, - { - label: '启用状态 0 禁用', - fieldName: 'enabled', - component: 'Input', - rules: 'required', - }, { label: '网关名称', fieldName: 'name', @@ -126,45 +171,94 @@ export const drawerSchema: FormSchemaGetter = () => [ rules: 'required', }, { - label: '接入方式,如: mqtt-server-gateway', + label: '接入方式', 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', }, { label: '描述', fieldName: 'description', - component: 'Input', - rules: 'required', + component: 'Textarea', + componentProps: { + placeholder: '请输入描述', + rows: 3, + }, }, { - label: '通道 接入通道(方式),如网络组件', + label: '接入通道(方式)', fieldName: 'channel', component: 'Input', - rules: 'required', + dependencies: { + show: () => false, + triggerFields: [''], + }, }, { - label: '通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID', - fieldName: 'channelId', - component: 'Input', - rules: 'required', - }, - { - label: '消息协议 消息协议', - fieldName: 'protocol', - component: 'Input', - rules: 'required', - }, - { - label: '传输协议,如TCP,MQTT,UDP', + label: '传输协议', fieldName: 'transport', component: 'Input', - rules: 'required', - }, - { - label: '网关配置', - fieldName: 'gatewayConfig', - component: 'Textarea', - rules: 'required', + dependencies: { + show: () => false, + triggerFields: [''], + }, }, ]; diff --git a/apps/web-antd/src/views/operations/gateway/gateway-drawer.vue b/apps/web-antd/src/views/operations/gateway/gateway-drawer.vue index 334c696..ad79ba9 100644 --- a/apps/web-antd/src/views/operations/gateway/gateway-drawer.vue +++ b/apps/web-antd/src/views/operations/gateway/gateway-drawer.vue @@ -6,10 +6,20 @@ import { $t } from '@vben/locales'; import { cloneDeep } from '@vben/utils'; 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 { drawerSchema } from './data'; +import { + drawerSchema, + getNetworkOptions, + getProtocolOptions, + providerOptions, + registerNetworkOptionsUpdate, +} from './data'; const emit = defineEmits<{ reload: [] }>(); @@ -27,13 +37,72 @@ const [BasicForm, formApi] = useVbenForm({ // 通用配置项 会影响到所有表单项 componentProps: { class: 'w-full', - } + }, }, schema: drawerSchema(), showDefaultActions: false, 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( { initializedGetter: defaultFormValueGetter(formApi), @@ -44,7 +113,6 @@ const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff( const [BasicDrawer, drawerApi] = useVbenDrawer({ // 在这里更改宽度 class: 'w-[550px]', - fullscreenButton: false, onBeforeClose, onClosed: handleClosed, onConfirm: handleConfirm, @@ -54,12 +122,39 @@ const [BasicDrawer, drawerApi] = useVbenDrawer({ } 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 }; isUpdate.value = !!id; if (isUpdate.value && id) { const record = await gatewayInfo(id); await formApi.setValues(record); + + // 如果是编辑模式,根据provider加载对应的网络组件选项 + if (record.provider && record.provider !== 'child-device') { + await loadNetworkOptions(String(record.provider)); + } } 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() { try { drawerApi.lock(true); @@ -98,4 +219,3 @@ async function handleClosed() { - diff --git a/apps/web-antd/src/views/operations/gateway/index.vue b/apps/web-antd/src/views/operations/gateway/index.vue index 4e4cabb..3558f8e 100644 --- a/apps/web-antd/src/views/operations/gateway/index.vue +++ b/apps/web-antd/src/views/operations/gateway/index.vue @@ -1,30 +1,30 @@ @@ -138,9 +207,10 @@ function handleDownloadExcel() { + type="primary" + v-access:code="['operations:gateway:remove']" + @click="handleMultiDelete" + > {{ $t('pages.common.delete') }} +