302 lines
8.2 KiB
TypeScript
302 lines
8.2 KiB
TypeScript
import request from '@/config/axios'
|
|
import { isEmpty } from '@/utils/is'
|
|
|
|
/**
|
|
* IoT 产品物模型
|
|
*/
|
|
export interface ThingModelData {
|
|
id?: number // 物模型功能编号
|
|
identifier?: string // 功能标识
|
|
name?: string // 功能名称
|
|
description?: string // 功能描述
|
|
productId?: number // 产品编号
|
|
productKey?: string // 产品标识
|
|
dataType: string // 数据类型,与 dataSpecs 的 dataType 保持一致
|
|
type: number // 功能类型
|
|
property: ThingModelProperty // 属性
|
|
event?: ThingModelEvent // 事件
|
|
service?: ThingModelService // 服务
|
|
}
|
|
|
|
/**
|
|
* ThingModelProperty 类型
|
|
*/
|
|
export interface ThingModelProperty {
|
|
[key: string]: any
|
|
}
|
|
|
|
/**
|
|
* ThingModelEvent 类型
|
|
*/
|
|
export interface ThingModelEvent {
|
|
[key: string]: any
|
|
}
|
|
|
|
/**
|
|
* ThingModelService 类型
|
|
*/
|
|
export interface ThingModelService {
|
|
[key: string]: any
|
|
}
|
|
|
|
/** dataSpecs 数值型数据结构 */
|
|
export interface DataSpecsNumberData {
|
|
dataType: 'int' | 'float' | 'double' // 数据类型,取值为 INT、FLOAT 或 DOUBLE
|
|
max: string // 最大值,必须与 dataType 设置一致,且为 STRING 类型
|
|
min: string // 最小值,必须与 dataType 设置一致,且为 STRING 类型
|
|
step: string // 步长,必须与 dataType 设置一致,且为 STRING 类型
|
|
precise?: string // 精度,当 dataType 为 FLOAT 或 DOUBLE 时可选
|
|
defaultValue?: string // 默认值,可选
|
|
unit: string // 单位的符号
|
|
unitName: string // 单位的名称
|
|
}
|
|
|
|
/** dataSpecs 枚举型数据结构 */
|
|
export interface DataSpecsEnumOrBoolData {
|
|
dataType: 'enum' | 'bool'
|
|
defaultValue?: string // 默认值,可选
|
|
name: string // 枚举项的名称
|
|
value: number | undefined // 枚举值
|
|
}
|
|
|
|
/** 物模型TSL响应数据结构 */
|
|
export interface IotThingModelTSLResp {
|
|
productId: number
|
|
productKey: string
|
|
properties: ThingModelProperty[]
|
|
events: ThingModelEvent[]
|
|
services: ThingModelService[]
|
|
}
|
|
|
|
/** 物模型属性 */
|
|
export interface ThingModelProperty {
|
|
identifier: string
|
|
name: string
|
|
accessMode: string
|
|
required?: boolean
|
|
dataType: string
|
|
description?: string
|
|
dataSpecs?: ThingModelProperty
|
|
dataSpecsList?: ThingModelProperty[]
|
|
}
|
|
|
|
/** 物模型事件 */
|
|
export interface ThingModelEvent {
|
|
identifier: string
|
|
name: string
|
|
required?: boolean
|
|
type: string
|
|
description?: string
|
|
outputParams?: ThingModelParam[]
|
|
method?: string
|
|
}
|
|
|
|
/** 物模型服务 */
|
|
export interface ThingModelService {
|
|
identifier: string
|
|
name: string
|
|
required?: boolean
|
|
callType: string
|
|
description?: string
|
|
inputParams?: ThingModelParam[]
|
|
outputParams?: ThingModelParam[]
|
|
method?: string
|
|
}
|
|
|
|
/** 物模型参数 */
|
|
export interface ThingModelParam {
|
|
identifier: string
|
|
name: string
|
|
direction: string
|
|
paraOrder?: number
|
|
dataType: string
|
|
dataSpecs?: ThingModelProperty
|
|
dataSpecsList?: ThingModelProperty[]
|
|
}
|
|
|
|
/** 数值型数据规范 */
|
|
export interface ThingModelNumericDataSpec {
|
|
dataType: 'int' | 'float' | 'double'
|
|
max: string
|
|
min: string
|
|
step: string
|
|
precise?: string
|
|
defaultValue?: string
|
|
unit?: string
|
|
unitName?: string
|
|
}
|
|
|
|
/** 布尔/枚举型数据规范 */
|
|
export interface ThingModelBoolOrEnumDataSpecs {
|
|
dataType: 'bool' | 'enum'
|
|
name: string
|
|
value: number
|
|
}
|
|
|
|
/** 文本/时间型数据规范 */
|
|
export interface ThingModelDateOrTextDataSpecs {
|
|
dataType: 'text' | 'date'
|
|
length?: number
|
|
defaultValue?: string
|
|
}
|
|
|
|
/** 数组型数据规范 */
|
|
export interface ThingModelArrayDataSpecs {
|
|
dataType: 'array'
|
|
size: number
|
|
childDataType: string
|
|
dataSpecsList?: ThingModelProperty[]
|
|
}
|
|
|
|
/** 结构体型数据规范 */
|
|
export interface ThingModelStructDataSpecs {
|
|
dataType: 'struct'
|
|
identifier: string
|
|
name: string
|
|
accessMode: string
|
|
required?: boolean
|
|
childDataType: string
|
|
dataSpecs?: ThingModelProperty
|
|
dataSpecsList?: ThingModelProperty[]
|
|
}
|
|
|
|
// IoT 产品物模型 API
|
|
export const ThingModelApi = {
|
|
// 查询产品物模型分页
|
|
getThingModelPage: async (params: any) => {
|
|
return await request.get({ url: `/iot/thing-model/page`, params })
|
|
},
|
|
|
|
// 获得产品物模型列表
|
|
getThingModelList: async (params: any) => {
|
|
return await request.get({ url: `/iot/thing-model/list`, params })
|
|
},
|
|
|
|
// 获得产品物模型 TSL
|
|
getThingModelTSLByProductId: async (productId: number) => {
|
|
return await request.get({
|
|
url: `/iot/thing-model/get-tsl?productId=${productId}`
|
|
})
|
|
},
|
|
|
|
// 查询产品物模型详情
|
|
getThingModel: async (id: number) => {
|
|
return await request.get({ url: `/iot/thing-model/get?id=` + id })
|
|
},
|
|
|
|
// 新增产品物模型
|
|
createThingModel: async (data: ThingModelData) => {
|
|
return await request.post({ url: `/iot/thing-model/create`, data })
|
|
},
|
|
|
|
// 修改产品物模型
|
|
updateThingModel: async (data: ThingModelData) => {
|
|
return await request.put({ url: `/iot/thing-model/update`, data })
|
|
},
|
|
|
|
// 删除产品物模型
|
|
deleteThingModel: async (id: number) => {
|
|
return await request.delete({ url: `/iot/thing-model/delete?id=` + id })
|
|
}
|
|
}
|
|
|
|
/** 公共校验规则 */
|
|
export const ThingModelFormRules = {
|
|
name: [
|
|
{ required: true, message: '功能名称不能为空', trigger: 'blur' },
|
|
{
|
|
pattern: /^[\u4e00-\u9fa5a-zA-Z0-9][\u4e00-\u9fa5a-zA-Z0-9\-_/\.]{0,29}$/,
|
|
message:
|
|
'支持中文、大小写字母、日文、数字、短划线、下划线、斜杠和小数点,必须以中文、英文或数字开头,不超过 30 个字符',
|
|
trigger: 'blur'
|
|
}
|
|
],
|
|
type: [{ required: true, message: '功能类型不能为空', trigger: 'blur' }],
|
|
identifier: [
|
|
{ required: true, message: '标识符不能为空', trigger: 'blur' },
|
|
{
|
|
pattern: /^[a-zA-Z0-9_]{1,50}$/,
|
|
message: '支持大小写字母、数字和下划线,不超过 50 个字符',
|
|
trigger: 'blur'
|
|
},
|
|
{
|
|
validator: (_: 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 是系统保留字段,不能用于标识符定义'
|
|
)
|
|
)
|
|
} else if (/^\d+$/.test(value)) {
|
|
callback(new Error('标识符不能是纯数字'))
|
|
} else {
|
|
callback()
|
|
}
|
|
},
|
|
trigger: 'blur'
|
|
}
|
|
],
|
|
'property.dataSpecs.childDataType': [{ required: true, message: '元素类型不能为空' }],
|
|
'property.dataSpecs.size': [
|
|
{ required: true, message: '元素个数不能为空' },
|
|
{
|
|
validator: (_: any, value: any, callback: any) => {
|
|
if (isEmpty(value)) {
|
|
callback(new Error('元素个数不能为空'))
|
|
return
|
|
}
|
|
if (isNaN(Number(value))) {
|
|
callback(new Error('元素个数必须是数字'))
|
|
return
|
|
}
|
|
callback()
|
|
},
|
|
trigger: 'blur'
|
|
}
|
|
],
|
|
'property.dataSpecs.length': [
|
|
{ required: true, message: '请输入文本字节长度', trigger: 'blur' },
|
|
{
|
|
validator: (_: any, value: any, callback: any) => {
|
|
if (isEmpty(value)) {
|
|
callback(new Error('文本长度不能为空'))
|
|
return
|
|
}
|
|
if (isNaN(Number(value))) {
|
|
callback(new Error('文本长度必须是数字'))
|
|
return
|
|
}
|
|
callback()
|
|
},
|
|
trigger: 'blur'
|
|
}
|
|
],
|
|
'property.accessMode': [{ required: true, message: '请选择读写类型', trigger: 'change' }]
|
|
}
|
|
|
|
/** 校验布尔值名称 */
|
|
export const validateBoolName = (_: any, value: string, callback: any) => {
|
|
if (isEmpty(value)) {
|
|
callback(new Error('布尔值名称不能为空'))
|
|
return
|
|
}
|
|
// 检查开头字符
|
|
if (!/^[\u4e00-\u9fa5a-zA-Z0-9]/.test(value)) {
|
|
callback(new Error('布尔值名称必须以中文、英文字母或数字开头'))
|
|
return
|
|
}
|
|
// 检查整体格式
|
|
if (!/^[\u4e00-\u9fa5a-zA-Z0-9][a-zA-Z0-9\u4e00-\u9fa5_-]*$/.test(value)) {
|
|
callback(new Error('布尔值名称只能包含中文、英文字母、数字、下划线和短划线'))
|
|
return
|
|
}
|
|
// 检查长度(一个中文算一个字符)
|
|
if (value.length > 20) {
|
|
callback(new Error('布尔值名称长度不能超过 20 个字符'))
|
|
return
|
|
}
|
|
|
|
callback()
|
|
}
|