index.ts 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. import request from '@/config/axios'
  2. import { isEmpty } from '@/utils/is'
  3. /**
  4. * IoT 产品物模型
  5. */
  6. export interface ThingModelData {
  7. id?: number // 物模型功能编号
  8. identifier?: string // 功能标识
  9. name?: string // 功能名称
  10. description?: string // 功能描述
  11. productId?: number // 产品编号
  12. productKey?: string // 产品标识
  13. dataType: string // 数据类型,与 dataSpecs 的 dataType 保持一致
  14. type: number // 功能类型
  15. property: ThingModelProperty // 属性
  16. event?: ThingModelEvent // 事件
  17. service?: ThingModelService // 服务
  18. }
  19. /**
  20. * ThingModelProperty 类型
  21. */
  22. export interface ThingModelProperty {
  23. [key: string]: any
  24. }
  25. /**
  26. * ThingModelEvent 类型
  27. */
  28. export interface ThingModelEvent {
  29. [key: string]: any
  30. }
  31. /**
  32. * ThingModelService 类型
  33. */
  34. export interface ThingModelService {
  35. [key: string]: any
  36. }
  37. /** dataSpecs 数值型数据结构 */
  38. export interface DataSpecsNumberData {
  39. dataType: 'int' | 'float' | 'double' // 数据类型,取值为 INT、FLOAT 或 DOUBLE
  40. max: string // 最大值,必须与 dataType 设置一致,且为 STRING 类型
  41. min: string // 最小值,必须与 dataType 设置一致,且为 STRING 类型
  42. step: string // 步长,必须与 dataType 设置一致,且为 STRING 类型
  43. precise?: string // 精度,当 dataType 为 FLOAT 或 DOUBLE 时可选
  44. defaultValue?: string // 默认值,可选
  45. unit: string // 单位的符号
  46. unitName: string // 单位的名称
  47. }
  48. /** dataSpecs 枚举型数据结构 */
  49. export interface DataSpecsEnumOrBoolData {
  50. dataType: 'enum' | 'bool'
  51. defaultValue?: string // 默认值,可选
  52. name: string // 枚举项的名称
  53. value: number | undefined // 枚举值
  54. }
  55. /** 物模型TSL响应数据结构 */
  56. export interface IotThingModelTSLResp {
  57. productId: number
  58. productKey: string
  59. properties: ThingModelProperty[]
  60. events: ThingModelEvent[]
  61. services: ThingModelService[]
  62. }
  63. /** 物模型属性 */
  64. export interface ThingModelProperty {
  65. identifier: string
  66. name: string
  67. accessMode: string
  68. required?: boolean
  69. dataType: string
  70. description?: string
  71. dataSpecs?: ThingModelProperty
  72. dataSpecsList?: ThingModelProperty[]
  73. }
  74. /** 物模型事件 */
  75. export interface ThingModelEvent {
  76. identifier: string
  77. name: string
  78. required?: boolean
  79. type: string
  80. description?: string
  81. outputParams?: ThingModelParam[]
  82. method?: string
  83. }
  84. /** 物模型服务 */
  85. export interface ThingModelService {
  86. identifier: string
  87. name: string
  88. required?: boolean
  89. callType: string
  90. description?: string
  91. inputParams?: ThingModelParam[]
  92. outputParams?: ThingModelParam[]
  93. method?: string
  94. }
  95. /** 物模型参数 */
  96. export interface ThingModelParam {
  97. identifier: string
  98. name: string
  99. direction: string
  100. paraOrder?: number
  101. dataType: string
  102. dataSpecs?: ThingModelProperty
  103. dataSpecsList?: ThingModelProperty[]
  104. }
  105. /** 数值型数据规范 */
  106. export interface ThingModelNumericDataSpec {
  107. dataType: 'int' | 'float' | 'double'
  108. max: string
  109. min: string
  110. step: string
  111. precise?: string
  112. defaultValue?: string
  113. unit?: string
  114. unitName?: string
  115. }
  116. /** 布尔/枚举型数据规范 */
  117. export interface ThingModelBoolOrEnumDataSpecs {
  118. dataType: 'bool' | 'enum'
  119. name: string
  120. value: number
  121. }
  122. /** 文本/时间型数据规范 */
  123. export interface ThingModelDateOrTextDataSpecs {
  124. dataType: 'text' | 'date'
  125. length?: number
  126. defaultValue?: string
  127. }
  128. /** 数组型数据规范 */
  129. export interface ThingModelArrayDataSpecs {
  130. dataType: 'array'
  131. size: number
  132. childDataType: string
  133. dataSpecsList?: ThingModelProperty[]
  134. }
  135. /** 结构体型数据规范 */
  136. export interface ThingModelStructDataSpecs {
  137. dataType: 'struct'
  138. identifier: string
  139. name: string
  140. accessMode: string
  141. required?: boolean
  142. childDataType: string
  143. dataSpecs?: ThingModelProperty
  144. dataSpecsList?: ThingModelProperty[]
  145. }
  146. // IoT 产品物模型 API
  147. export const ThingModelApi = {
  148. // 查询产品物模型分页
  149. getThingModelPage: async (params: any) => {
  150. return await request.get({ url: `/iot/thing-model/page`, params })
  151. },
  152. // 获得产品物模型列表
  153. getThingModelList: async (params: any) => {
  154. return await request.get({ url: `/iot/thing-model/list`, params })
  155. },
  156. // 获得产品物模型 TSL
  157. getThingModelTSLByProductId: async (productId: number) => {
  158. return await request.get({
  159. url: `/iot/thing-model/get-tsl?productId=${productId}`
  160. })
  161. },
  162. // 查询产品物模型详情
  163. getThingModel: async (id: number) => {
  164. return await request.get({ url: `/iot/thing-model/get?id=` + id })
  165. },
  166. // 新增产品物模型
  167. createThingModel: async (data: ThingModelData) => {
  168. return await request.post({ url: `/iot/thing-model/create`, data })
  169. },
  170. // 修改产品物模型
  171. updateThingModel: async (data: ThingModelData) => {
  172. return await request.put({ url: `/iot/thing-model/update`, data })
  173. },
  174. // 删除产品物模型
  175. deleteThingModel: async (id: number) => {
  176. return await request.delete({ url: `/iot/thing-model/delete?id=` + id })
  177. }
  178. }
  179. /** 公共校验规则 */
  180. export const ThingModelFormRules = {
  181. name: [
  182. { required: true, message: '功能名称不能为空', trigger: 'blur' },
  183. {
  184. pattern: /^[\u4e00-\u9fa5a-zA-Z0-9][\u4e00-\u9fa5a-zA-Z0-9\-_/\.]{0,29}$/,
  185. message:
  186. '支持中文、大小写字母、日文、数字、短划线、下划线、斜杠和小数点,必须以中文、英文或数字开头,不超过 30 个字符',
  187. trigger: 'blur'
  188. }
  189. ],
  190. type: [{ required: true, message: '功能类型不能为空', trigger: 'blur' }],
  191. identifier: [
  192. { required: true, message: '标识符不能为空', trigger: 'blur' },
  193. {
  194. pattern: /^[a-zA-Z0-9_]{1,50}$/,
  195. message: '支持大小写字母、数字和下划线,不超过 50 个字符',
  196. trigger: 'blur'
  197. },
  198. {
  199. validator: (_: any, value: string, callback: any) => {
  200. const reservedKeywords = ['set', 'get', 'post', 'property', 'event', 'time', 'value']
  201. if (reservedKeywords.includes(value)) {
  202. callback(
  203. new Error(
  204. 'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义'
  205. )
  206. )
  207. } else if (/^\d+$/.test(value)) {
  208. callback(new Error('标识符不能是纯数字'))
  209. } else {
  210. callback()
  211. }
  212. },
  213. trigger: 'blur'
  214. }
  215. ],
  216. 'property.dataSpecs.childDataType': [{ required: true, message: '元素类型不能为空' }],
  217. 'property.dataSpecs.size': [
  218. { required: true, message: '元素个数不能为空' },
  219. {
  220. validator: (_: any, value: any, callback: any) => {
  221. if (isEmpty(value)) {
  222. callback(new Error('元素个数不能为空'))
  223. return
  224. }
  225. if (isNaN(Number(value))) {
  226. callback(new Error('元素个数必须是数字'))
  227. return
  228. }
  229. callback()
  230. },
  231. trigger: 'blur'
  232. }
  233. ],
  234. 'property.dataSpecs.length': [
  235. { required: true, message: '请输入文本字节长度', trigger: 'blur' },
  236. {
  237. validator: (_: any, value: any, callback: any) => {
  238. if (isEmpty(value)) {
  239. callback(new Error('文本长度不能为空'))
  240. return
  241. }
  242. if (isNaN(Number(value))) {
  243. callback(new Error('文本长度必须是数字'))
  244. return
  245. }
  246. callback()
  247. },
  248. trigger: 'blur'
  249. }
  250. ],
  251. 'property.accessMode': [{ required: true, message: '请选择读写类型', trigger: 'change' }]
  252. }
  253. /** 校验布尔值名称 */
  254. export const validateBoolName = (_: any, value: string, callback: any) => {
  255. if (isEmpty(value)) {
  256. callback(new Error('布尔值名称不能为空'))
  257. return
  258. }
  259. // 检查开头字符
  260. if (!/^[\u4e00-\u9fa5a-zA-Z0-9]/.test(value)) {
  261. callback(new Error('布尔值名称必须以中文、英文字母或数字开头'))
  262. return
  263. }
  264. // 检查整体格式
  265. if (!/^[\u4e00-\u9fa5a-zA-Z0-9][a-zA-Z0-9\u4e00-\u9fa5_-]*$/.test(value)) {
  266. callback(new Error('布尔值名称只能包含中文、英文字母、数字、下划线和短划线'))
  267. return
  268. }
  269. // 检查长度(一个中文算一个字符)
  270. if (value.length > 20) {
  271. callback(new Error('布尔值名称长度不能超过 20 个字符'))
  272. return
  273. }
  274. callback()
  275. }