feat(运维管理): 调整系统配置,添加运维管理相关页面
- 关闭tab标签、前端更新检测(后期正式环境开启回来) - 添加网络组件、协议管理、设备接入网关页面(未完成)和对接接口
This commit is contained in:
parent
f53bed6616
commit
fe3c9b570e
|
@ -0,0 +1,61 @@
|
||||||
|
import type { GatewayVO, GatewayForm, GatewayQuery } from './model';
|
||||||
|
|
||||||
|
import type { ID, IDS } from '#/api/common';
|
||||||
|
import type { PageResult } from '#/api/common';
|
||||||
|
|
||||||
|
import { commonExport } from '#/api/helper';
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备接入网关列表
|
||||||
|
* @param params
|
||||||
|
* @returns 设备接入网关列表
|
||||||
|
*/
|
||||||
|
export function gatewayList(params?: GatewayQuery) {
|
||||||
|
return requestClient.get<PageResult<GatewayVO>>('/operations/gateway/list', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出设备接入网关列表
|
||||||
|
* @param params
|
||||||
|
* @returns 设备接入网关列表
|
||||||
|
*/
|
||||||
|
export function gatewayExport(params?: GatewayQuery) {
|
||||||
|
return commonExport('/operations/gateway/export', params ?? {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备接入网关详情
|
||||||
|
* @param id id
|
||||||
|
* @returns 设备接入网关详情
|
||||||
|
*/
|
||||||
|
export function gatewayInfo(id: ID) {
|
||||||
|
return requestClient.get<GatewayVO>(`/operations/gateway/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增设备接入网关
|
||||||
|
* @param data
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function gatewayAdd(data: GatewayForm) {
|
||||||
|
return requestClient.postWithMsg<void>('/operations/gateway', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新设备接入网关
|
||||||
|
* @param data
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function gatewayUpdate(data: GatewayForm) {
|
||||||
|
return requestClient.putWithMsg<void>('/operations/gateway', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除设备接入网关
|
||||||
|
* @param id id
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function gatewayRemove(id: ID | IDS) {
|
||||||
|
return requestClient.deleteWithMsg<void>(`/operations/gateway/${id}`);
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
import type { PageQuery, BaseEntity } from '#/api/common';
|
||||||
|
|
||||||
|
export interface GatewayVO {
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关名称
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接入方式,如: mqtt-server-gateway
|
||||||
|
*/
|
||||||
|
provider: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通道 接入通道(方式),如网络组件
|
||||||
|
*/
|
||||||
|
channel: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID
|
||||||
|
*/
|
||||||
|
channelId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息协议 消息协议
|
||||||
|
*/
|
||||||
|
protocol: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传输协议,如TCP,MQTT,UDP
|
||||||
|
*/
|
||||||
|
transport: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关配置
|
||||||
|
*/
|
||||||
|
gatewayConfig: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GatewayForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接入方式,如: mqtt-server-gateway
|
||||||
|
*/
|
||||||
|
provider?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通道 接入通道(方式),如网络组件
|
||||||
|
*/
|
||||||
|
channel?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID
|
||||||
|
*/
|
||||||
|
channelId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息协议 消息协议
|
||||||
|
*/
|
||||||
|
protocol?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传输协议,如TCP,MQTT,UDP
|
||||||
|
*/
|
||||||
|
transport?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关配置
|
||||||
|
*/
|
||||||
|
gatewayConfig?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GatewayQuery extends PageQuery {
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接入方式,如: mqtt-server-gateway
|
||||||
|
*/
|
||||||
|
provider?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通道 接入通道(方式),如网络组件
|
||||||
|
*/
|
||||||
|
channel?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID
|
||||||
|
*/
|
||||||
|
channelId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息协议 消息协议
|
||||||
|
*/
|
||||||
|
protocol?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传输协议,如TCP,MQTT,UDP
|
||||||
|
*/
|
||||||
|
transport?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关配置
|
||||||
|
*/
|
||||||
|
gatewayConfig?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
import type { NetworkVO, NetworkForm, NetworkQuery } from './model';
|
||||||
|
|
||||||
|
import type { ID, IDS } from '#/api/common';
|
||||||
|
import type { PageResult } from '#/api/common';
|
||||||
|
|
||||||
|
import { commonExport } from '#/api/helper';
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询网络组件列表
|
||||||
|
* @param params
|
||||||
|
* @returns 网络组件列表
|
||||||
|
*/
|
||||||
|
export function networkList(params?: NetworkQuery) {
|
||||||
|
return requestClient.get<PageResult<NetworkVO>>('/operations/network/list', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出网络组件列表
|
||||||
|
* @param params
|
||||||
|
* @returns 网络组件列表
|
||||||
|
*/
|
||||||
|
export function networkExport(params?: NetworkQuery) {
|
||||||
|
return commonExport('/operations/network/export', params ?? {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询网络组件详情
|
||||||
|
* @param id id
|
||||||
|
* @returns 网络组件详情
|
||||||
|
*/
|
||||||
|
export function networkInfo(id: ID) {
|
||||||
|
return requestClient.get<NetworkVO>(`/operations/network/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增网络组件
|
||||||
|
* @param data
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function networkAdd(data: NetworkForm) {
|
||||||
|
return requestClient.postWithMsg<void>('/operations/network', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新网络组件
|
||||||
|
* @param data
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function networkUpdate(data: NetworkForm) {
|
||||||
|
return requestClient.putWithMsg<void>('/operations/network', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除网络组件
|
||||||
|
* @param id id
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function networkRemove(id: ID | IDS) {
|
||||||
|
return requestClient.deleteWithMsg<void>(`/operations/network/${id}`);
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
import type { PageQuery, BaseEntity } from '#/api/common';
|
||||||
|
|
||||||
|
export interface NetworkVO {
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件名称
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件类型 HTTP_SERVER、MQTT_CLIENT 等
|
||||||
|
*/
|
||||||
|
networkType: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络配置
|
||||||
|
*/
|
||||||
|
networkConfig: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NetworkForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件类型 HTTP_SERVER、MQTT_CLIENT 等
|
||||||
|
*/
|
||||||
|
networkType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络配置
|
||||||
|
*/
|
||||||
|
networkConfig?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NetworkQuery extends PageQuery {
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件类型 HTTP_SERVER、MQTT_CLIENT 等
|
||||||
|
*/
|
||||||
|
networkType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络配置
|
||||||
|
*/
|
||||||
|
networkConfig?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
import type { ProtocolVO, ProtocolForm, ProtocolQuery } from './model';
|
||||||
|
|
||||||
|
import type { ID, IDS } from '#/api/common';
|
||||||
|
import type { PageResult } from '#/api/common';
|
||||||
|
|
||||||
|
import { commonExport } from '#/api/helper';
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备协议列表
|
||||||
|
* @param params
|
||||||
|
* @returns 设备协议列表
|
||||||
|
*/
|
||||||
|
export function protocolList(params?: ProtocolQuery) {
|
||||||
|
return requestClient.get<PageResult<ProtocolVO>>('/operations/protocol/list', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出设备协议列表
|
||||||
|
* @param params
|
||||||
|
* @returns 设备协议列表
|
||||||
|
*/
|
||||||
|
export function protocolExport(params?: ProtocolQuery) {
|
||||||
|
return commonExport('/operations/protocol/export', params ?? {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备协议详情
|
||||||
|
* @param id id
|
||||||
|
* @returns 设备协议详情
|
||||||
|
*/
|
||||||
|
export function protocolInfo(id: ID) {
|
||||||
|
return requestClient.get<ProtocolVO>(`/operations/protocol/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增设备协议
|
||||||
|
* @param data
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function protocolAdd(data: ProtocolForm) {
|
||||||
|
return requestClient.postWithMsg<void>('/operations/protocol', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新设备协议
|
||||||
|
* @param data
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function protocolUpdate(data: ProtocolForm) {
|
||||||
|
return requestClient.putWithMsg<void>('/operations/protocol', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除设备协议
|
||||||
|
* @param id id
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
export function protocolRemove(id: ID | IDS) {
|
||||||
|
return requestClient.deleteWithMsg<void>(`/operations/protocol/${id}`);
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
import type { PageQuery, BaseEntity } from '#/api/common';
|
||||||
|
|
||||||
|
export interface ProtocolVO {
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议名称
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议包类型 local、jar
|
||||||
|
*/
|
||||||
|
protocolType: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议配置
|
||||||
|
*/
|
||||||
|
protocolConfig: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProtocolForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议包类型 local、jar
|
||||||
|
*/
|
||||||
|
protocolType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议配置
|
||||||
|
*/
|
||||||
|
protocolConfig?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProtocolQuery extends PageQuery {
|
||||||
|
/**
|
||||||
|
* 启用状态 0 禁用
|
||||||
|
*/
|
||||||
|
enabled?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议包类型 local、jar
|
||||||
|
*/
|
||||||
|
protocolType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议配置
|
||||||
|
*/
|
||||||
|
protocolConfig?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
|
@ -30,6 +30,10 @@ export const overridesPreferences = defineOverridesPreferences({
|
||||||
* 2. 切换租户登录后不会重新加载菜单
|
* 2. 切换租户登录后不会重新加载菜单
|
||||||
*/
|
*/
|
||||||
// loginExpiredMode: 'modal',
|
// loginExpiredMode: 'modal',
|
||||||
|
// 是否开启检查更新
|
||||||
|
enableCheckUpdates: false,
|
||||||
|
// 检查更新的时间间隔,单位为分钟
|
||||||
|
checkUpdatesInterval: 1,
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
/**
|
/**
|
||||||
|
@ -42,6 +46,8 @@ export const overridesPreferences = defineOverridesPreferences({
|
||||||
* 标签tab 持久化 关闭
|
* 标签tab 持久化 关闭
|
||||||
*/
|
*/
|
||||||
persist: false,
|
persist: false,
|
||||||
|
// 隐藏tab显示
|
||||||
|
enable: false,
|
||||||
// styleType: 'card',
|
// styleType: 'card',
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<h1 class="text-2xl font-bold mb-4">Test Detail Page</h1>
|
||||||
|
<p>This is a placeholder for the test detail page.</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,170 @@
|
||||||
|
import type { FormSchemaGetter } from '#/adapter/form';
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
|
||||||
|
export const querySchema: FormSchemaGetter = () => [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'enabled',
|
||||||
|
label: '启用状态 0 禁用',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'name',
|
||||||
|
label: '网关名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'provider',
|
||||||
|
label: '接入方式,如: mqtt-server-gateway',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'description',
|
||||||
|
label: '描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'channel',
|
||||||
|
label: '通道 接入通道(方式),如网络组件',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'channelId',
|
||||||
|
label: '通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'protocol',
|
||||||
|
label: '消息协议 消息协议',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'transport',
|
||||||
|
label: '传输协议,如TCP,MQTT,UDP',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Textarea',
|
||||||
|
fieldName: 'gatewayConfig',
|
||||||
|
label: '网关配置',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
||||||
|
// export const columns: () => VxeGridProps['columns'] = () => [
|
||||||
|
export const columns: VxeGridProps['columns'] = [
|
||||||
|
{ type: 'checkbox', width: 60 },
|
||||||
|
{
|
||||||
|
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',
|
||||||
|
field: 'channelId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '消息协议 消息协议',
|
||||||
|
field: 'protocol',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '传输协议,如TCP,MQTT,UDP',
|
||||||
|
field: 'transport',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '网关配置',
|
||||||
|
field: 'gatewayConfig',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'action' },
|
||||||
|
title: '操作',
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const drawerSchema: FormSchemaGetter = () => [
|
||||||
|
{
|
||||||
|
label: '编号',
|
||||||
|
fieldName: 'id',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
show: () => false,
|
||||||
|
triggerFields: [''],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '启用状态 0 禁用',
|
||||||
|
fieldName: 'enabled',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '网关名称',
|
||||||
|
fieldName: 'name',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '接入方式,如: mqtt-server-gateway',
|
||||||
|
fieldName: 'provider',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '描述',
|
||||||
|
fieldName: 'description',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '通道 接入通道(方式),如网络组件',
|
||||||
|
fieldName: 'channel',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '通道id 接入使用的通道ID,如: 网络组件ID,modbus通道ID',
|
||||||
|
fieldName: 'channelId',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '消息协议 消息协议',
|
||||||
|
fieldName: 'protocol',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '传输协议,如TCP,MQTT,UDP',
|
||||||
|
fieldName: 'transport',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '网关配置',
|
||||||
|
fieldName: 'gatewayConfig',
|
||||||
|
component: 'Textarea',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
];
|
|
@ -0,0 +1,101 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenDrawer } from '@vben/common-ui';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
import { cloneDeep } from '@vben/utils';
|
||||||
|
|
||||||
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
import { gatewayAdd, gatewayInfo, gatewayUpdate } from '#/api/operations/gateway';
|
||||||
|
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
|
||||||
|
|
||||||
|
import { drawerSchema } from './data';
|
||||||
|
|
||||||
|
const emit = defineEmits<{ reload: [] }>();
|
||||||
|
|
||||||
|
const isUpdate = ref(false);
|
||||||
|
const title = computed(() => {
|
||||||
|
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
|
||||||
|
});
|
||||||
|
|
||||||
|
const [BasicForm, formApi] = useVbenForm({
|
||||||
|
commonConfig: {
|
||||||
|
// 默认占满两列
|
||||||
|
formItemClass: 'col-span-2',
|
||||||
|
// 默认label宽度 px
|
||||||
|
labelWidth: 80,
|
||||||
|
// 通用配置项 会影响到所有表单项
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
schema: drawerSchema(),
|
||||||
|
showDefaultActions: false,
|
||||||
|
wrapperClass: 'grid-cols-2',
|
||||||
|
});
|
||||||
|
|
||||||
|
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
|
||||||
|
{
|
||||||
|
initializedGetter: defaultFormValueGetter(formApi),
|
||||||
|
currentGetter: defaultFormValueGetter(formApi),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const [BasicDrawer, drawerApi] = useVbenDrawer({
|
||||||
|
// 在这里更改宽度
|
||||||
|
class: 'w-[550px]',
|
||||||
|
fullscreenButton: false,
|
||||||
|
onBeforeClose,
|
||||||
|
onClosed: handleClosed,
|
||||||
|
onConfirm: handleConfirm,
|
||||||
|
onOpenChange: async (isOpen) => {
|
||||||
|
if (!isOpen) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
drawerApi.drawerLoading(true);
|
||||||
|
|
||||||
|
const { id } = drawerApi.getData() as { id?: number | string };
|
||||||
|
isUpdate.value = !!id;
|
||||||
|
|
||||||
|
if (isUpdate.value && id) {
|
||||||
|
const record = await gatewayInfo(id);
|
||||||
|
await formApi.setValues(record);
|
||||||
|
}
|
||||||
|
await markInitialized();
|
||||||
|
|
||||||
|
drawerApi.drawerLoading(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleConfirm() {
|
||||||
|
try {
|
||||||
|
drawerApi.lock(true);
|
||||||
|
const { valid } = await formApi.validate();
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
|
||||||
|
const data = cloneDeep(await formApi.getValues());
|
||||||
|
await (isUpdate.value ? gatewayUpdate(data) : gatewayAdd(data));
|
||||||
|
resetInitialized();
|
||||||
|
emit('reload');
|
||||||
|
drawerApi.close();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
drawerApi.lock(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleClosed() {
|
||||||
|
await formApi.resetForm();
|
||||||
|
resetInitialized();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<BasicDrawer :title="title">
|
||||||
|
<BasicForm />
|
||||||
|
</BasicDrawer>
|
||||||
|
</template>
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
|
||||||
|
import { getVxePopupContainer } from '@vben/utils';
|
||||||
|
|
||||||
|
import { Modal, Popconfirm, Space } from 'ant-design-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import {
|
||||||
|
useVbenVxeGrid,
|
||||||
|
vxeCheckboxChecked,
|
||||||
|
type VxeGridProps
|
||||||
|
} from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import {
|
||||||
|
gatewayExport,
|
||||||
|
gatewayList,
|
||||||
|
gatewayRemove,
|
||||||
|
} from '#/api/operations/gateway';
|
||||||
|
import type { GatewayForm } from '#/api/operations/gateway/model';
|
||||||
|
import { commonDownloadExcel } from '#/utils/file/download';
|
||||||
|
|
||||||
|
import gatewayDrawer from './gateway-drawer.vue';
|
||||||
|
import { columns, querySchema } from './data';
|
||||||
|
|
||||||
|
const formOptions: VbenFormProps = {
|
||||||
|
commonConfig: {
|
||||||
|
labelWidth: 80,
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
schema: querySchema(),
|
||||||
|
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 = {
|
||||||
|
checkboxConfig: {
|
||||||
|
// 高亮
|
||||||
|
highlight: true,
|
||||||
|
// 翻页时保留选中状态
|
||||||
|
reserve: true,
|
||||||
|
// 点击行选中
|
||||||
|
// trigger: 'row',
|
||||||
|
},
|
||||||
|
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
||||||
|
// columns: columns(),
|
||||||
|
columns,
|
||||||
|
height: 'auto',
|
||||||
|
keepSource: true,
|
||||||
|
pagerConfig: {},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues = {}) => {
|
||||||
|
return await gatewayList({
|
||||||
|
pageNum: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
},
|
||||||
|
// 表格全局唯一表示 保存列配置需要用到
|
||||||
|
id: 'operations-gateway-index'
|
||||||
|
};
|
||||||
|
|
||||||
|
const [BasicTable, tableApi] = useVbenVxeGrid({
|
||||||
|
formOptions,
|
||||||
|
gridOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [GatewayDrawer, drawerApi] = useVbenDrawer({
|
||||||
|
connectedComponent: gatewayDrawer,
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
drawerApi.setData({});
|
||||||
|
drawerApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleEdit(row: Required<GatewayForm>) {
|
||||||
|
drawerApi.setData({ id: row.id });
|
||||||
|
drawerApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete(row: Required<GatewayForm>) {
|
||||||
|
await gatewayRemove(row.id);
|
||||||
|
await tableApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMultiDelete() {
|
||||||
|
const rows = tableApi.grid.getCheckboxRecords();
|
||||||
|
const ids = rows.map((row: Required<GatewayForm>) => row.id);
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
okType: 'danger',
|
||||||
|
content: `确认删除选中的${ids.length}条记录吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
await gatewayRemove(ids);
|
||||||
|
await tableApi.query();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDownloadExcel() {
|
||||||
|
commonDownloadExcel(gatewayExport, '设备接入网关数据', tableApi.formApi.form.values, {
|
||||||
|
fieldMappingTime: formOptions.fieldMappingTime,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page :auto-content-height="true">
|
||||||
|
<BasicTable table-title="设备接入网关列表">
|
||||||
|
<template #toolbar-tools>
|
||||||
|
<Space>
|
||||||
|
<a-button
|
||||||
|
v-access:code="['operations:gateway:export']"
|
||||||
|
@click="handleDownloadExcel"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.export') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
:disabled="!vxeCheckboxChecked(tableApi)"
|
||||||
|
danger
|
||||||
|
type="primary"
|
||||||
|
v-access:code="['operations:gateway:remove']"
|
||||||
|
@click="handleMultiDelete">
|
||||||
|
{{ $t('pages.common.delete') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
v-access:code="['operations:gateway:add']"
|
||||||
|
@click="handleAdd"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.add') }}
|
||||||
|
</a-button>
|
||||||
|
</Space>
|
||||||
|
</template>
|
||||||
|
<template #action="{ row }">
|
||||||
|
<Space>
|
||||||
|
<ghost-button
|
||||||
|
v-access:code="['operations:gateway:edit']"
|
||||||
|
@click.stop="handleEdit(row)"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.edit') }}
|
||||||
|
</ghost-button>
|
||||||
|
<Popconfirm
|
||||||
|
:get-popup-container="getVxePopupContainer"
|
||||||
|
placement="left"
|
||||||
|
title="确认删除?"
|
||||||
|
@confirm="handleDelete(row)"
|
||||||
|
>
|
||||||
|
<ghost-button
|
||||||
|
danger
|
||||||
|
v-access:code="['operations:gateway:remove']"
|
||||||
|
@click.stop=""
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.delete') }}
|
||||||
|
</ghost-button>
|
||||||
|
</Popconfirm>
|
||||||
|
</Space>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<GatewayDrawer @reload="tableApi.query()" />
|
||||||
|
</Page>
|
||||||
|
</template>
|
|
@ -0,0 +1,348 @@
|
||||||
|
import type { FormSchemaGetter } from '#/adapter/form';
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
const networkTypeOptions = [
|
||||||
|
{ label: 'MQTT客户端', value: 'MQTT_CLIENT' },
|
||||||
|
{ label: 'HTTP服务', value: 'HTTP_SERVER' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const enabledOptions = [
|
||||||
|
{ label: '启用', value: '1' },
|
||||||
|
{ label: '禁用', value: '0' },
|
||||||
|
];
|
||||||
|
|
||||||
|
// HTTP服务配置字段
|
||||||
|
const httpServerFields = [
|
||||||
|
{
|
||||||
|
label: '本地地址',
|
||||||
|
fieldName: 'localAddress',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入本地地址',
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
defaultValue: '0.0.0.0',
|
||||||
|
help: '绑定到服务器上的网卡地址,绑定到所有网卡:0.0.0.0',
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'HTTP_SERVER',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '本地端口',
|
||||||
|
fieldName: 'localPort',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择本地端口',
|
||||||
|
min: 1,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
help: '监听指定端口的请求',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values) => values.networkType === 'HTTP_SERVER',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '公网地址',
|
||||||
|
fieldName: 'publicAddress',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入公网地址',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
help: '对外提供访问的地址,内网环境时填写服务器的内网IP地址',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values) => values.networkType === 'HTTP_SERVER',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '公网端口',
|
||||||
|
fieldName: 'publicPort',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入端口',
|
||||||
|
min: 1,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
help: '对外提供访问的端口',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values) => values.networkType === 'HTTP_SERVER',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '开启TLS',
|
||||||
|
fieldName: 'enableTls',
|
||||||
|
component: 'RadioGroup',
|
||||||
|
componentProps: {
|
||||||
|
buttonStyle: 'solid',
|
||||||
|
optionType: 'button',
|
||||||
|
options: [
|
||||||
|
{ label: '是', value: '1' },
|
||||||
|
{ label: '否', value: '0' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
defaultValue: '0',
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values) => values.networkType === 'HTTP_SERVER',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// MQTT客户端配置字段
|
||||||
|
const mqttClientFields = [
|
||||||
|
{
|
||||||
|
label: '远程地址',
|
||||||
|
fieldName: 'remoteAddress',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入远程地址',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'MQTT_CLIENT',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '远程端口',
|
||||||
|
fieldName: 'remotePort',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入远程端口',
|
||||||
|
min: 1,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'MQTT_CLIENT',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ClientId',
|
||||||
|
fieldName: 'clientId',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入ClientId',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'MQTT_CLIENT',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '用户名',
|
||||||
|
fieldName: 'username',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入用户名',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'MQTT_CLIENT',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '密码',
|
||||||
|
fieldName: 'password',
|
||||||
|
component: 'InputPassword',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入密码',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'MQTT_CLIENT',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '订阅前缀',
|
||||||
|
fieldName: 'subscriptionPrefix',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入订阅前缀',
|
||||||
|
},
|
||||||
|
help: '当连接的服务为EMQ时,可能需要使用共享的订阅前缀,如:$queue或$share',
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'MQTT_CLIENT',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '最大消息长度',
|
||||||
|
fieldName: 'maxMessageLength',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入最大消息长度',
|
||||||
|
min: 1,
|
||||||
|
},
|
||||||
|
defaultValue: 8192,
|
||||||
|
help: '单次收发消息的最大长度,单位:字节;设置过大可能会影响性能',
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'MQTT_CLIENT',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '开启TLS',
|
||||||
|
fieldName: 'enableTls',
|
||||||
|
component: 'RadioGroup',
|
||||||
|
componentProps: {
|
||||||
|
buttonStyle: 'solid',
|
||||||
|
optionType: 'button',
|
||||||
|
options: [
|
||||||
|
{ label: '是', value: '1' },
|
||||||
|
{ label: '否', value: '0' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
defaultValue: '0',
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['networkType'],
|
||||||
|
show: (values: any) => values.networkType === 'MQTT_CLIENT',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const querySchema: FormSchemaGetter = () => [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'name',
|
||||||
|
label: '组件名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: enabledOptions,
|
||||||
|
placeholder: '请选择',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
fieldName: 'enabled',
|
||||||
|
label: '启用状态',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: networkTypeOptions,
|
||||||
|
placeholder: '请选择',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
fieldName: 'networkType',
|
||||||
|
label: '网络类型',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
||||||
|
// export const columns: () => VxeGridProps['columns'] = () => [
|
||||||
|
export const columns: VxeGridProps['columns'] = [
|
||||||
|
{ type: 'checkbox', width: 60 },
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
field: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '组件名称',
|
||||||
|
field: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '网络类型',
|
||||||
|
field: 'networkType',
|
||||||
|
slots: { default: 'networkType' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '启用状态',
|
||||||
|
field: 'enabled',
|
||||||
|
slots: { default: 'enabled' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
field: 'description',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'action' },
|
||||||
|
title: '操作',
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 基础字段
|
||||||
|
const baseFields = [
|
||||||
|
{
|
||||||
|
label: '编号',
|
||||||
|
fieldName: 'id',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
show: () => false,
|
||||||
|
triggerFields: [''],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '组件名称',
|
||||||
|
fieldName: 'name',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入名称',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '网络类型',
|
||||||
|
fieldName: 'networkType',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: networkTypeOptions,
|
||||||
|
placeholder: '请选择网络类型',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '启用状态',
|
||||||
|
fieldName: 'enabled',
|
||||||
|
component: 'RadioGroup',
|
||||||
|
componentProps: {
|
||||||
|
buttonStyle: 'solid',
|
||||||
|
options: enabledOptions,
|
||||||
|
optionType: 'button',
|
||||||
|
},
|
||||||
|
defaultValue: '1',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '描述',
|
||||||
|
fieldName: 'description',
|
||||||
|
component: 'Textarea',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入描述',
|
||||||
|
rows: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const drawerSchema: FormSchemaGetter = () => [
|
||||||
|
...baseFields,
|
||||||
|
// HTTP服务配置字段
|
||||||
|
...httpServerFields,
|
||||||
|
// MQTT客户端配置字段
|
||||||
|
...mqttClientFields,
|
||||||
|
];
|
||||||
|
|
||||||
|
// 导出字段配置供组件使用
|
||||||
|
export { httpServerFields, mqttClientFields };
|
|
@ -0,0 +1,230 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { VbenFormProps } from '@vben/common-ui';
|
||||||
|
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
import type { NetworkForm } from '#/api/operations/network/model';
|
||||||
|
|
||||||
|
import { Page, useVbenDrawer } from '@vben/common-ui';
|
||||||
|
import { getVxePopupContainer } from '@vben/utils';
|
||||||
|
|
||||||
|
import { Modal, Popconfirm, Space, Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
|
||||||
|
import {
|
||||||
|
networkExport,
|
||||||
|
networkList,
|
||||||
|
networkRemove,
|
||||||
|
} from '#/api/operations/network';
|
||||||
|
import { commonDownloadExcel } from '#/utils/file/download';
|
||||||
|
|
||||||
|
import { columns, querySchema } from './data';
|
||||||
|
import networkDrawer from './network-drawer.vue';
|
||||||
|
|
||||||
|
const formOptions: VbenFormProps = {
|
||||||
|
commonConfig: {
|
||||||
|
labelWidth: 80,
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
schema: querySchema(),
|
||||||
|
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 = {
|
||||||
|
checkboxConfig: {
|
||||||
|
// 高亮
|
||||||
|
highlight: true,
|
||||||
|
// 翻页时保留选中状态
|
||||||
|
reserve: true,
|
||||||
|
// 点击行选中
|
||||||
|
// trigger: 'row',
|
||||||
|
},
|
||||||
|
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
||||||
|
// columns: columns(),
|
||||||
|
columns,
|
||||||
|
height: 'auto',
|
||||||
|
keepSource: true,
|
||||||
|
pagerConfig: {},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues = {}) => {
|
||||||
|
return await networkList({
|
||||||
|
pageNum: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
},
|
||||||
|
// 表格全局唯一表示 保存列配置需要用到
|
||||||
|
id: 'operations-network-index',
|
||||||
|
};
|
||||||
|
|
||||||
|
const [BasicTable, tableApi] = useVbenVxeGrid({
|
||||||
|
formOptions,
|
||||||
|
gridOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [NetworkDrawer, drawerApi] = useVbenDrawer({
|
||||||
|
connectedComponent: networkDrawer,
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
drawerApi.setData({});
|
||||||
|
drawerApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleEdit(row: Required<NetworkForm>) {
|
||||||
|
drawerApi.setData({ id: row.id });
|
||||||
|
drawerApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete(row: Required<NetworkForm>) {
|
||||||
|
await networkRemove(row.id);
|
||||||
|
await tableApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMultiDelete() {
|
||||||
|
const rows = tableApi.grid.getCheckboxRecords();
|
||||||
|
const ids = rows.map((row: Required<NetworkForm>) => row.id);
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
okType: 'danger',
|
||||||
|
content: `确认删除选中的${ids.length}条记录吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
await networkRemove(ids);
|
||||||
|
await tableApi.query();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDownloadExcel() {
|
||||||
|
commonDownloadExcel(
|
||||||
|
networkExport,
|
||||||
|
'网络组件数据',
|
||||||
|
tableApi.formApi.form.values,
|
||||||
|
{
|
||||||
|
fieldMappingTime: formOptions.fieldMappingTime,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析网络配置JSON
|
||||||
|
function parseNetworkConfig(networkConfig: string) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(networkConfig);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析网络配置失败:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化网络配置显示
|
||||||
|
function formatNetworkConfig(row: any) {
|
||||||
|
const config = parseNetworkConfig(row.networkConfig);
|
||||||
|
if (!config) {
|
||||||
|
return '配置解析失败';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.networkType === 'HTTP_SERVER') {
|
||||||
|
return `本地: ${config.localAddress}:${config.localPort} | 公网: ${config.publicAddress}:${config.publicPort} | TLS: ${config.enableTls === '1' ? '是' : '否'}`;
|
||||||
|
} else if (row.networkType === 'MQTT_CLIENT') {
|
||||||
|
return `远程: ${config.remoteAddress}:${config.remotePort} | ClientId: ${config.clientId} | TLS: ${config.enableTls === '1' ? '是' : '否'}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '未知配置';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page :auto-content-height="true">
|
||||||
|
<BasicTable table-title="网络组件列表">
|
||||||
|
<template #toolbar-tools>
|
||||||
|
<Space>
|
||||||
|
<a-button
|
||||||
|
v-access:code="['operations:network:export']"
|
||||||
|
@click="handleDownloadExcel"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.export') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
:disabled="!vxeCheckboxChecked(tableApi)"
|
||||||
|
danger
|
||||||
|
type="primary"
|
||||||
|
v-access:code="['operations:network:remove']"
|
||||||
|
@click="handleMultiDelete"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.delete') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
v-access:code="['operations:network:add']"
|
||||||
|
@click="handleAdd"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.add') }}
|
||||||
|
</a-button>
|
||||||
|
</Space>
|
||||||
|
</template>
|
||||||
|
<template #networkType="{ row }">
|
||||||
|
<Tag color="processing">{{ row.networkType }}</Tag>
|
||||||
|
</template>
|
||||||
|
<template #enabled="{ row }">
|
||||||
|
<Tag :color="row.enabled === '1' ? 'success' : 'error'">
|
||||||
|
{{ row.enabled === '1' ? '启用' : '禁用' }}
|
||||||
|
</Tag>
|
||||||
|
</template>
|
||||||
|
<template #action="{ row }">
|
||||||
|
<Space>
|
||||||
|
<ghost-button
|
||||||
|
v-access:code="['operations:network:edit']"
|
||||||
|
@click.stop="handleEdit(row)"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.edit') }}
|
||||||
|
</ghost-button>
|
||||||
|
<Popconfirm
|
||||||
|
:get-popup-container="getVxePopupContainer"
|
||||||
|
placement="left"
|
||||||
|
title="确认删除?"
|
||||||
|
@confirm="handleDelete(row)"
|
||||||
|
>
|
||||||
|
<ghost-button
|
||||||
|
danger
|
||||||
|
v-access:code="['operations:network:remove']"
|
||||||
|
@click.stop=""
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.delete') }}
|
||||||
|
</ghost-button>
|
||||||
|
</Popconfirm>
|
||||||
|
</Space>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<NetworkDrawer @reload="tableApi.query()" />
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.network-config-display {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-summary {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,147 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenDrawer } from '@vben/common-ui';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
import { cloneDeep } from '@vben/utils';
|
||||||
|
|
||||||
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
import {
|
||||||
|
networkAdd,
|
||||||
|
networkInfo,
|
||||||
|
networkUpdate,
|
||||||
|
} from '#/api/operations/network';
|
||||||
|
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
|
||||||
|
|
||||||
|
import { drawerSchema } from './data';
|
||||||
|
|
||||||
|
const emit = defineEmits<{ reload: [] }>();
|
||||||
|
|
||||||
|
const isUpdate = ref(false);
|
||||||
|
const title = computed(() => {
|
||||||
|
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
|
||||||
|
});
|
||||||
|
|
||||||
|
const [BasicForm, formApi] = useVbenForm({
|
||||||
|
commonConfig: {
|
||||||
|
// 默认占满两列
|
||||||
|
formItemClass: 'col-span-2',
|
||||||
|
// 默认label宽度 px
|
||||||
|
labelWidth: 100,
|
||||||
|
// 通用配置项 会影响到所有表单项
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
schema: drawerSchema(),
|
||||||
|
showDefaultActions: false,
|
||||||
|
wrapperClass: 'grid-cols-2',
|
||||||
|
});
|
||||||
|
|
||||||
|
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
|
||||||
|
{
|
||||||
|
initializedGetter: defaultFormValueGetter(formApi),
|
||||||
|
currentGetter: defaultFormValueGetter(formApi),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const [BasicDrawer, drawerApi] = useVbenDrawer({
|
||||||
|
// 在这里更改宽度
|
||||||
|
class: 'w-[800px]',
|
||||||
|
fullscreenButton: false,
|
||||||
|
onBeforeClose,
|
||||||
|
onClosed: handleClosed,
|
||||||
|
onConfirm: handleConfirm,
|
||||||
|
onOpenChange: async (isOpen) => {
|
||||||
|
if (!isOpen) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
drawerApi.drawerLoading(true);
|
||||||
|
|
||||||
|
const { id } = drawerApi.getData() as { id?: number | string };
|
||||||
|
isUpdate.value = !!id;
|
||||||
|
|
||||||
|
if (isUpdate.value && id) {
|
||||||
|
const record = await networkInfo(id);
|
||||||
|
|
||||||
|
// 解析网络配置JSON
|
||||||
|
if (record.networkConfig) {
|
||||||
|
try {
|
||||||
|
const configData = JSON.parse(record.networkConfig);
|
||||||
|
// 将解析的配置数据合并到表单中
|
||||||
|
const formData = { ...record, ...configData };
|
||||||
|
await formApi.setValues(formData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析网络配置失败:', error);
|
||||||
|
await formApi.setValues(record);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await formApi.setValues(record);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 确保表单有初始值
|
||||||
|
await formApi.setValues({
|
||||||
|
networkType: 'MQTT_CLIENT',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await markInitialized();
|
||||||
|
drawerApi.drawerLoading(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleConfirm() {
|
||||||
|
try {
|
||||||
|
drawerApi.lock(true);
|
||||||
|
const { valid } = await formApi.validate();
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
|
||||||
|
const formData = cloneDeep(await formApi.getValues());
|
||||||
|
|
||||||
|
// 分离基础字段和配置字段
|
||||||
|
const baseFields = new Set([
|
||||||
|
'description',
|
||||||
|
'enabled',
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'networkType',
|
||||||
|
]);
|
||||||
|
const baseData: any = {};
|
||||||
|
const configData: any = {};
|
||||||
|
|
||||||
|
Object.keys(formData).forEach((key) => {
|
||||||
|
if (baseFields.has(key)) {
|
||||||
|
baseData[key] = formData[key];
|
||||||
|
} else {
|
||||||
|
configData[key] = formData[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 将配置字段转换为JSON字符串
|
||||||
|
baseData.networkConfig = JSON.stringify(configData);
|
||||||
|
|
||||||
|
await (isUpdate.value ? networkUpdate(baseData) : networkAdd(baseData));
|
||||||
|
resetInitialized();
|
||||||
|
emit('reload');
|
||||||
|
drawerApi.close();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
drawerApi.lock(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleClosed() {
|
||||||
|
await formApi.resetForm();
|
||||||
|
resetInitialized();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<BasicDrawer :title="title">
|
||||||
|
<BasicForm />
|
||||||
|
</BasicDrawer>
|
||||||
|
</template>
|
|
@ -0,0 +1,138 @@
|
||||||
|
import type { FormSchemaGetter } from '#/adapter/form';
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
const enabledOptions = [
|
||||||
|
{ label: '启用', value: '1' },
|
||||||
|
{ label: '禁用', value: '0' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const protocolTypeOptions = [
|
||||||
|
{ label: 'local', value: 'local' },
|
||||||
|
{ label: 'jar', value: 'jar' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const querySchema: FormSchemaGetter = () => [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'name',
|
||||||
|
label: '协议名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: protocolTypeOptions,
|
||||||
|
placeholder: '请选择',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
fieldName: 'protocolType',
|
||||||
|
label: '协议包类型',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: enabledOptions,
|
||||||
|
placeholder: '请选择',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
fieldName: 'enabled',
|
||||||
|
label: '启用状态',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
||||||
|
// export const columns: () => VxeGridProps['columns'] = () => [
|
||||||
|
export const columns: VxeGridProps['columns'] = [
|
||||||
|
{ type: 'checkbox', width: 60 },
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
field: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '协议名称',
|
||||||
|
field: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '协议包类型',
|
||||||
|
slots: { default: 'protocolType' },
|
||||||
|
field: 'protocolType',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '协议配置',
|
||||||
|
field: 'protocolConfig',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '启用状态',
|
||||||
|
slots: { default: 'enabled' },
|
||||||
|
field: 'enabled',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
field: 'description',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'action' },
|
||||||
|
title: '操作',
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const drawerSchema: FormSchemaGetter = () => [
|
||||||
|
{
|
||||||
|
label: '编号',
|
||||||
|
fieldName: 'id',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
show: () => false,
|
||||||
|
triggerFields: [''],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '协议名称',
|
||||||
|
fieldName: 'name',
|
||||||
|
component: 'Input',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '协议包类型',
|
||||||
|
fieldName: 'protocolType',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: protocolTypeOptions,
|
||||||
|
placeholder: '请选择',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '协议配置',
|
||||||
|
fieldName: 'protocolConfig',
|
||||||
|
component: 'Textarea',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '启用状态',
|
||||||
|
fieldName: 'enabled',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
filterOption: true,
|
||||||
|
options: enabledOptions,
|
||||||
|
placeholder: '请选择',
|
||||||
|
showSearch: true,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '描述',
|
||||||
|
fieldName: 'description',
|
||||||
|
component: 'Textarea',
|
||||||
|
},
|
||||||
|
];
|
|
@ -0,0 +1,190 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { VbenFormProps } from '@vben/common-ui';
|
||||||
|
|
||||||
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
import type { ProtocolForm } from '#/api/operations/protocol/model';
|
||||||
|
|
||||||
|
import { Page, useVbenDrawer } from '@vben/common-ui';
|
||||||
|
import { getVxePopupContainer } from '@vben/utils';
|
||||||
|
|
||||||
|
import { Modal, Popconfirm, Space, Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
|
||||||
|
import {
|
||||||
|
protocolExport,
|
||||||
|
protocolList,
|
||||||
|
protocolRemove,
|
||||||
|
} from '#/api/operations/protocol';
|
||||||
|
import { commonDownloadExcel } from '#/utils/file/download';
|
||||||
|
|
||||||
|
import { columns, querySchema } from './data';
|
||||||
|
import protocolDrawer from './protocol-drawer.vue';
|
||||||
|
|
||||||
|
const formOptions: VbenFormProps = {
|
||||||
|
commonConfig: {
|
||||||
|
labelWidth: 80,
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
schema: querySchema(),
|
||||||
|
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 = {
|
||||||
|
checkboxConfig: {
|
||||||
|
// 高亮
|
||||||
|
highlight: true,
|
||||||
|
// 翻页时保留选中状态
|
||||||
|
reserve: true,
|
||||||
|
// 点击行选中
|
||||||
|
// trigger: 'row',
|
||||||
|
},
|
||||||
|
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
||||||
|
// columns: columns(),
|
||||||
|
columns,
|
||||||
|
height: 'auto',
|
||||||
|
keepSource: true,
|
||||||
|
pagerConfig: {},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues = {}) => {
|
||||||
|
return await protocolList({
|
||||||
|
pageNum: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
},
|
||||||
|
// 表格全局唯一表示 保存列配置需要用到
|
||||||
|
id: 'operations-protocol-index',
|
||||||
|
};
|
||||||
|
|
||||||
|
const [BasicTable, tableApi] = useVbenVxeGrid({
|
||||||
|
formOptions,
|
||||||
|
gridOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [ProtocolDrawer, drawerApi] = useVbenDrawer({
|
||||||
|
connectedComponent: protocolDrawer,
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
drawerApi.setData({});
|
||||||
|
drawerApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleEdit(row: Required<ProtocolForm>) {
|
||||||
|
drawerApi.setData({ id: row.id });
|
||||||
|
drawerApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete(row: Required<ProtocolForm>) {
|
||||||
|
await protocolRemove(row.id);
|
||||||
|
await tableApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMultiDelete() {
|
||||||
|
const rows = tableApi.grid.getCheckboxRecords();
|
||||||
|
const ids = rows.map((row: Required<ProtocolForm>) => row.id);
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
okType: 'danger',
|
||||||
|
content: `确认删除选中的${ids.length}条记录吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
await protocolRemove(ids);
|
||||||
|
await tableApi.query();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDownloadExcel() {
|
||||||
|
commonDownloadExcel(
|
||||||
|
protocolExport,
|
||||||
|
'设备协议数据',
|
||||||
|
tableApi.formApi.form.values,
|
||||||
|
{
|
||||||
|
fieldMappingTime: formOptions.fieldMappingTime,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page :auto-content-height="true">
|
||||||
|
<BasicTable table-title="设备协议列表">
|
||||||
|
<template #toolbar-tools>
|
||||||
|
<Space>
|
||||||
|
<a-button
|
||||||
|
v-access:code="['operations:protocol:export']"
|
||||||
|
@click="handleDownloadExcel"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.export') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
:disabled="!vxeCheckboxChecked(tableApi)"
|
||||||
|
danger
|
||||||
|
type="primary"
|
||||||
|
v-access:code="['operations:protocol:remove']"
|
||||||
|
@click="handleMultiDelete"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.delete') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
v-access:code="['operations:protocol:add']"
|
||||||
|
@click="handleAdd"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.add') }}
|
||||||
|
</a-button>
|
||||||
|
</Space>
|
||||||
|
</template>
|
||||||
|
<template #protocolType="{ row }">
|
||||||
|
<Tag color="processing">{{ row.protocolType }}</Tag>
|
||||||
|
</template>
|
||||||
|
<template #enabled="{ row }">
|
||||||
|
<Tag :color="row.enabled === '1' ? 'success' : 'error'">
|
||||||
|
{{ row.enabled === '1' ? '启用' : '禁用' }}
|
||||||
|
</Tag>
|
||||||
|
</template>
|
||||||
|
<template #action="{ row }">
|
||||||
|
<Space>
|
||||||
|
<ghost-button
|
||||||
|
v-access:code="['operations:protocol:edit']"
|
||||||
|
@click.stop="handleEdit(row)"
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.edit') }}
|
||||||
|
</ghost-button>
|
||||||
|
<Popconfirm
|
||||||
|
:get-popup-container="getVxePopupContainer"
|
||||||
|
placement="left"
|
||||||
|
title="确认删除?"
|
||||||
|
@confirm="handleDelete(row)"
|
||||||
|
>
|
||||||
|
<ghost-button
|
||||||
|
danger
|
||||||
|
v-access:code="['operations:protocol:remove']"
|
||||||
|
@click.stop=""
|
||||||
|
>
|
||||||
|
{{ $t('pages.common.delete') }}
|
||||||
|
</ghost-button>
|
||||||
|
</Popconfirm>
|
||||||
|
</Space>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<ProtocolDrawer @reload="tableApi.query()" />
|
||||||
|
</Page>
|
||||||
|
</template>
|
|
@ -0,0 +1,101 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenDrawer } from '@vben/common-ui';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
import { cloneDeep } from '@vben/utils';
|
||||||
|
|
||||||
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
import { protocolAdd, protocolInfo, protocolUpdate } from '#/api/operations/protocol';
|
||||||
|
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
|
||||||
|
|
||||||
|
import { drawerSchema } from './data';
|
||||||
|
|
||||||
|
const emit = defineEmits<{ reload: [] }>();
|
||||||
|
|
||||||
|
const isUpdate = ref(false);
|
||||||
|
const title = computed(() => {
|
||||||
|
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
|
||||||
|
});
|
||||||
|
|
||||||
|
const [BasicForm, formApi] = useVbenForm({
|
||||||
|
commonConfig: {
|
||||||
|
// 默认占满两列
|
||||||
|
formItemClass: 'col-span-2',
|
||||||
|
// 默认label宽度 px
|
||||||
|
labelWidth: 80,
|
||||||
|
// 通用配置项 会影响到所有表单项
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
schema: drawerSchema(),
|
||||||
|
showDefaultActions: false,
|
||||||
|
wrapperClass: 'grid-cols-2',
|
||||||
|
});
|
||||||
|
|
||||||
|
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
|
||||||
|
{
|
||||||
|
initializedGetter: defaultFormValueGetter(formApi),
|
||||||
|
currentGetter: defaultFormValueGetter(formApi),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const [BasicDrawer, drawerApi] = useVbenDrawer({
|
||||||
|
// 在这里更改宽度
|
||||||
|
class: 'w-[550px]',
|
||||||
|
fullscreenButton: false,
|
||||||
|
onBeforeClose,
|
||||||
|
onClosed: handleClosed,
|
||||||
|
onConfirm: handleConfirm,
|
||||||
|
onOpenChange: async (isOpen) => {
|
||||||
|
if (!isOpen) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
drawerApi.drawerLoading(true);
|
||||||
|
|
||||||
|
const { id } = drawerApi.getData() as { id?: number | string };
|
||||||
|
isUpdate.value = !!id;
|
||||||
|
|
||||||
|
if (isUpdate.value && id) {
|
||||||
|
const record = await protocolInfo(id);
|
||||||
|
await formApi.setValues(record);
|
||||||
|
}
|
||||||
|
await markInitialized();
|
||||||
|
|
||||||
|
drawerApi.drawerLoading(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleConfirm() {
|
||||||
|
try {
|
||||||
|
drawerApi.lock(true);
|
||||||
|
const { valid } = await formApi.validate();
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
|
||||||
|
const data = cloneDeep(await formApi.getValues());
|
||||||
|
await (isUpdate.value ? protocolUpdate(data) : protocolAdd(data));
|
||||||
|
resetInitialized();
|
||||||
|
emit('reload');
|
||||||
|
drawerApi.close();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
drawerApi.lock(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleClosed() {
|
||||||
|
await formApi.resetForm();
|
||||||
|
resetInitialized();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<BasicDrawer :title="title">
|
||||||
|
<BasicForm />
|
||||||
|
</BasicDrawer>
|
||||||
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue