import type { Rule } from 'ant-design-vue/es/form'; import type { PageParam, PageResult } from '@vben/request'; import { isEmpty } from '@vben/utils'; import { requestClient } from '#/api/request'; export namespace ThingModelApi { /** IoT 物模型数据 */ export interface ThingModel { id?: number; productId?: number; productKey?: string; identifier?: string; name?: string; description?: string; dataType?: string; type?: number; // 参见 IoTThingModelTypeEnum 枚举类 property?: Property; event?: Event; service?: Service; } /** IoT 物模型属性 */ export interface Property { identifier?: string; name?: string; accessMode?: string; required?: boolean; dataType?: string; description?: string; dataSpecs?: ThingModelDataSpecs; dataSpecsList?: ThingModelPropertyDataSpecs[]; } /** IoT 物模型服务 */ export interface Service { identifier?: string; name?: string; required?: boolean; callType?: string; description?: string; inputParams?: Param[]; outputParams?: Param[]; method?: string; } /** IoT 物模型事件 */ export interface Event { identifier?: string; name?: string; required?: boolean; type?: string; description?: string; outputParams?: Param[]; method?: string; } /** IoT 物模型参数 */ export interface Param { identifier?: string; name?: string; direction?: string; paraOrder?: number; dataType?: string; dataSpecs?: ThingModelDataSpecs; dataSpecsList?: ThingModelPropertyDataSpecs[]; } /** IoT 物模型 TSL(树形)响应 */ export interface ThingModelTSL { productId?: number; productKey?: string; properties?: Property[]; events?: Event[]; services?: Service[]; } /** IoT 数据定义(数值型) */ export interface ThingModelDataSpecs { accessMode?: string; childDataType?: string; dataSpecs?: ThingModelDataSpecs; dataSpecsList?: ThingModelPropertyDataSpecs[]; dataType?: string; defaultValue?: string; description?: string; identifier?: string; length?: number | string; min?: number | string; max?: number | string; name?: string; precise?: string; required?: boolean; size?: number | string; step?: number | string; unit?: string; unitName?: string; value?: number | string; } /** IoT 数据定义(数值型) */ export type DataSpecsNumberData = ThingModelDataSpecs; /** IoT 数据定义(枚举/布尔型) */ export type DataSpecsEnumOrBoolData = ThingModelDataSpecs; export type ThingModelPropertyDataSpecs = Property & ThingModelDataSpecs; } /** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */ function buildRequiredNumberValidator(label: string) { return (_rule: any, value: any, callback: any) => { if (isEmpty(value)) { callback(new Error(`${label}不能为空`)); return; } if (Number.isNaN(Number(value))) { callback(new Error(`${label}必须是数字`)); return; } callback(); }; } /** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */ export function buildIdentifierLikeNameValidator(label: string) { return (_rule: any, value: string, callback: any) => { if (isEmpty(value)) { callback(new Error(`${label}不能为空`)); return; } if (!/^[一-龥A-Za-z0-9]/.test(value)) { callback(new Error(`${label}必须以中文、英文字母或数字开头`)); return; } if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) { callback( new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`), ); return; } if (value.length > 20) { callback(new Error(`${label}长度不能超过 20 个字符`)); return; } callback(); }; } /** IoT 物模型表单校验规则 */ export const ThingModelFormRules: Record = { name: [ { required: true, message: '功能名称不能为空', trigger: 'blur' }, { pattern: /^[一-龥A-Za-z0-9][一-龥A-Za-z0-9\-_/.]{0,29}$/, message: '支持中文、大小写字母、日文、数字、短划线、下划线、斜杠和小数点,必须以中文、英文或数字开头,不超过 30 个字符', trigger: 'blur', }, ], type: [{ required: true, message: '功能类型不能为空', trigger: 'blur' }], identifier: [ { required: true, message: '标识符不能为空', trigger: 'blur' }, { pattern: /^[a-zA-Z][a-zA-Z0-9_]{0,31}$/, message: '支持大小写字母、数字和下划线,必须以字母开头,不超过 32 个字符', trigger: 'blur', }, { validator: (_rule: any, value: string, callback: any) => { const reservedKeywords = [ 'set', 'get', 'post', 'property', 'event', 'time', 'value', ]; if (reservedKeywords.includes(value)) { callback( new Error( 'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义', ), ); return; } if (/^\d+$/.test(value)) { callback(new Error('标识符不能是纯数字')); return; } callback(); }, trigger: 'blur', }, ], childDataType: [{ required: true, message: '元素类型不能为空' }], size: [ { required: true, validator: buildRequiredNumberValidator('元素个数'), trigger: 'blur', }, ], length: [ { required: true, validator: buildRequiredNumberValidator('文本长度'), trigger: 'blur', }, ], accessMode: [ { required: true, message: '请选择读写类型', trigger: 'change' }, ], callType: [{ required: true, message: '请选择调用方式', trigger: 'change' }], eventType: [{ required: true, message: '请选择事件类型', trigger: 'change' }], }; /** 校验布尔值名称 */ export const validateBoolName = buildIdentifierLikeNameValidator('布尔值名称'); /** 查询产品物模型分页 */ export function getThingModelPage(params: PageParam) { return requestClient.get>( '/iot/thing-model/page', { params }, ); } /** 查询产品物模型详情 */ export function getThingModel(id: number) { return requestClient.get( `/iot/thing-model/get?id=${id}`, ); } /** 根据产品 ID 查询物模型列表 */ export function getThingModelListByProductId(productId: number) { return requestClient.get( '/iot/thing-model/list', { params: { productId }, }, ); } /** 新增物模型 */ export function createThingModel(data: ThingModelApi.ThingModel) { return requestClient.post('/iot/thing-model/create', data); } /** 修改物模型 */ export function updateThingModel(data: ThingModelApi.ThingModel) { return requestClient.put('/iot/thing-model/update', data); } /** 删除物模型 */ export function deleteThingModel(id: number) { return requestClient.delete(`/iot/thing-model/delete?id=${id}`); } /** 获取物模型 TSL */ export function getThingModelTSLByProductId(productId: number) { return requestClient.get( '/iot/thing-model/get-tsl', { params: { productId }, }, ); }