index.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. import { ArrayItems, FormItem, FormLayout, Input, NumberPicker, Select } from '@formily/antd';
  2. import { createSchemaField, observer } from '@formily/react';
  3. import type { ISchema } from '@formily/json-schema';
  4. import { DataTypeList, DateTypeList, FileTypeList } from '@/pages/device/data';
  5. import { Store } from 'jetlinks-store';
  6. import { useAsyncDataSource } from '@/utils/util';
  7. import { service } from '@/pages/device/components/Metadata';
  8. import MetadataModel from '@/pages/device/components/Metadata/Base/model';
  9. import BooleanEnum from '@/components/Metadata/BooleanParam';
  10. import EnumParam from '@/components/Metadata/EnumParam';
  11. import ArrayParam from '@/components/Metadata/ArrayParam';
  12. import { useIntl } from '@/.umi/plugin-locale/localeExports';
  13. import Editable from '../EditTable';
  14. // 不算是自定义组件。只是抽离了JSONSchema
  15. interface Props {
  16. keys?: string;
  17. isFunction?: boolean;
  18. }
  19. const JsonParam = observer((props: Props) => {
  20. const intl = useIntl();
  21. const SchemaField = createSchemaField({
  22. components: {
  23. FormItem,
  24. Input,
  25. Select,
  26. JsonParam,
  27. ArrayItems,
  28. Editable,
  29. FormLayout,
  30. NumberPicker,
  31. BooleanEnum,
  32. EnumParam,
  33. ArrayParam,
  34. },
  35. });
  36. const getUnit = () =>
  37. service.getUnit().then((resp) => {
  38. const _data = resp.result.map((item: any) => ({
  39. label: item.description,
  40. value: item.id,
  41. }));
  42. // 缓存单位数据
  43. Store.set('units', _data);
  44. return _data;
  45. });
  46. const checkArray: any = (arr: any) => {
  47. if (Array.isArray(arr) && arr.length) {
  48. return arr.every((item: any) => {
  49. if (item.valueType?.type === 'object') {
  50. return item.id && item.name && checkArray(item.json?.properties);
  51. }
  52. return item.id && item.name && item.valueType;
  53. });
  54. }
  55. return false;
  56. };
  57. const schema: ISchema = {
  58. type: 'object',
  59. properties: {
  60. [props?.keys || 'properties']: {
  61. type: 'array',
  62. 'x-component': 'ArrayItems',
  63. 'x-decorator': 'FormItem',
  64. 'x-reactions': {
  65. dependencies: ['.type'],
  66. fulfill: {
  67. state: {
  68. value: [{}],
  69. },
  70. },
  71. },
  72. 'x-validator': [
  73. {
  74. triggerType: 'onBlur',
  75. validator: (value: any[]) => {
  76. return new Promise((resolve) => {
  77. if (props.keys === 'inputs' && value.length === 0) {
  78. resolve('');
  79. }
  80. const flag = checkArray(value);
  81. if (!!flag) {
  82. resolve('');
  83. } else {
  84. resolve('请配置参数');
  85. }
  86. });
  87. },
  88. },
  89. ],
  90. items: {
  91. type: 'object',
  92. 'x-decorator': 'ArrayItems.Item',
  93. properties: {
  94. sort: {
  95. type: 'void',
  96. 'x-decorator': 'FormItem',
  97. 'x-component': 'ArrayItems.SortHandle',
  98. },
  99. config: {
  100. type: 'void',
  101. title: '配置参数',
  102. 'x-decorator': 'Editable.Popover',
  103. 'x-component': 'FormLayout',
  104. 'x-component-props': {
  105. layout: 'vertical',
  106. },
  107. 'x-decorator-props': {
  108. placement: 'left',
  109. },
  110. 'x-reactions':
  111. '{{(field)=>field.title = field.query(".config.name").get("value") || field.title}}',
  112. properties: {
  113. id: {
  114. title: '标识',
  115. required: true,
  116. 'x-decorator': 'FormItem',
  117. 'x-component': 'Input',
  118. 'x-validator': [
  119. {
  120. max: 64,
  121. message: '最多可输入64个字符',
  122. },
  123. {
  124. required: true,
  125. message: '请输入标识',
  126. },
  127. {
  128. validateId: true,
  129. message: 'ID只能由数字、26个英文字母或者下划线组成',
  130. },
  131. ],
  132. },
  133. name: {
  134. title: '名称',
  135. required: true,
  136. 'x-decorator': 'FormItem',
  137. 'x-component': 'Input',
  138. 'x-validator': [
  139. {
  140. max: 64,
  141. message: '最多可输入64个字符',
  142. },
  143. {
  144. required: true,
  145. message: '请输入名称',
  146. },
  147. ],
  148. },
  149. valueType: {
  150. type: 'object',
  151. properties: {
  152. type: {
  153. title: '数据类型',
  154. required: true,
  155. 'x-decorator': 'FormItem',
  156. 'x-component': 'Select',
  157. enum:
  158. MetadataModel.type === 'functions'
  159. ? DataTypeList.filter((item) => item.value !== 'file')
  160. : DataTypeList.filter((item) =>
  161. [
  162. 'int',
  163. 'long',
  164. 'float',
  165. 'double',
  166. 'string',
  167. 'boolean',
  168. 'date',
  169. ].includes(item.value),
  170. ),
  171. },
  172. booleanConfig: {
  173. title: '布尔值',
  174. type: 'void',
  175. 'x-decorator': 'FormItem',
  176. 'x-component': 'BooleanEnum',
  177. 'x-reactions': {
  178. dependencies: ['..valueType.type'],
  179. fulfill: {
  180. state: {
  181. visible: "{{['boolean'].includes($deps[0])}}",
  182. },
  183. },
  184. },
  185. },
  186. enumConfig: {
  187. title: intl.formatMessage({
  188. id: 'pages.device.productDetail.metadata.enum',
  189. defaultMessage: '枚举项',
  190. }),
  191. type: 'void',
  192. 'x-decorator': 'FormItem',
  193. 'x-component': 'EnumParam',
  194. 'x-reactions': {
  195. dependencies: ['..valueType.type'],
  196. fulfill: {
  197. state: {
  198. visible: "{{['enum'].includes($deps[0])}}",
  199. },
  200. },
  201. },
  202. },
  203. elementType: {
  204. title: intl.formatMessage({
  205. id: 'pages.device.productDetail.metadata.elementConfiguration',
  206. defaultMessage: '元素配置',
  207. }),
  208. 'x-decorator': 'FormItem',
  209. 'x-component': 'ArrayParam',
  210. 'x-reactions': {
  211. dependencies: ['..valueType.type'],
  212. fulfill: {
  213. state: {
  214. visible: "{{['array'].includes($deps[0])}}",
  215. },
  216. },
  217. },
  218. },
  219. fileType: {
  220. title: intl.formatMessage({
  221. id: 'pages.device.productDetail.metadata.fileType',
  222. defaultMessage: '文件类型',
  223. }),
  224. 'x-decorator': 'FormItem',
  225. 'x-component': 'Select',
  226. 'x-visible': false,
  227. enum: FileTypeList,
  228. 'x-reactions': {
  229. dependencies: ['..valueType.type'],
  230. fulfill: {
  231. state: {
  232. visible: "{{['file'].includes($deps[0])}}",
  233. },
  234. },
  235. },
  236. },
  237. unit: {
  238. title: '单位',
  239. 'x-decorator': 'FormItem',
  240. 'x-component': 'Select',
  241. 'x-visible': false,
  242. 'x-component-props': {
  243. showSearch: true,
  244. allowClear: true,
  245. showArrow: true,
  246. filterOption: (input: string, option: any) =>
  247. option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
  248. },
  249. enum: Store.get('units'),
  250. 'x-reactions': [
  251. {
  252. dependencies: ['..valueType.type'],
  253. fulfill: {
  254. state: {
  255. visible:
  256. !props.isFunction &&
  257. "{{['int','float','long','double'].includes($deps[0])}}",
  258. },
  259. },
  260. },
  261. '{{useAsyncDataSource(getUnit)}}',
  262. ],
  263. },
  264. format: {
  265. title: '时间格式',
  266. 'x-decorator': 'FormItem',
  267. 'x-component': 'Select',
  268. enum: DateTypeList,
  269. 'x-visible': false,
  270. default: 'string',
  271. 'x-validator': [
  272. {
  273. required: true,
  274. message: '请选择时间格式',
  275. },
  276. ],
  277. 'x-reactions': {
  278. dependencies: ['..valueType.type'],
  279. fulfill: {
  280. state: {
  281. visible: "{{['date'].includes($deps[0])}}",
  282. },
  283. },
  284. },
  285. },
  286. expands: {
  287. type: 'object',
  288. properties: {
  289. maxLength: {
  290. title: '最大长度',
  291. 'x-decorator': 'FormItem',
  292. 'x-component': 'NumberPicker',
  293. 'x-decorator-props': {
  294. tooltip: intl.formatMessage({
  295. id: 'pages.device.productDetail.metadata.maxLength.byte',
  296. defaultMessage: '字节',
  297. }),
  298. },
  299. 'x-component-props': {
  300. min: 1,
  301. },
  302. 'x-validator': [
  303. {
  304. format: 'integer',
  305. message: '请输入1-2147483647之间的正整数',
  306. },
  307. {
  308. max: 2147483647,
  309. message: '请输入1-2147483647之间的正整数',
  310. },
  311. {
  312. min: 1,
  313. message: '请输入1-2147483647之间的正整数',
  314. },
  315. ],
  316. 'x-reactions': {
  317. dependencies: ['..type'],
  318. fulfill: {
  319. state: {
  320. visible:
  321. !props.isFunction &&
  322. "{{['string','password'].includes($deps[0])}}",
  323. },
  324. },
  325. },
  326. },
  327. },
  328. },
  329. },
  330. },
  331. 'valueType.scale': {
  332. title: '精度',
  333. 'x-decorator': 'FormItem',
  334. 'x-component': 'NumberPicker',
  335. 'x-visible': false,
  336. default: 2,
  337. 'x-validator': [
  338. {
  339. format: 'integer',
  340. message: '请输入0-2147483647之间的正整数',
  341. },
  342. {
  343. max: 2147483647,
  344. message: '请输入0-2147483647之间的正整数',
  345. },
  346. {
  347. min: 0,
  348. message: '请输入0-2147483647之间的正整数',
  349. },
  350. ],
  351. 'x-component-props': {
  352. min: 1,
  353. },
  354. 'x-reactions': {
  355. dependencies: ['..valueType.type'],
  356. fulfill: {
  357. state: {
  358. visible: !props.isFunction && "{{['float','double'].includes($deps[0])}}",
  359. },
  360. },
  361. },
  362. },
  363. json: {
  364. type: 'string',
  365. title: 'JSON对象',
  366. 'x-visible': false,
  367. 'x-decorator': 'FormItem',
  368. 'x-component': 'JsonParam',
  369. 'x-component-props': {
  370. isFunction: props.isFunction,
  371. },
  372. 'x-reactions': {
  373. dependencies: ['.valueType.type'],
  374. fulfill: {
  375. state: {
  376. visible: "{{['object'].includes($deps[0])}}",
  377. },
  378. },
  379. },
  380. },
  381. },
  382. },
  383. remove: {
  384. type: 'void',
  385. 'x-decorator': 'FormItem',
  386. 'x-component': 'ArrayItems.Remove',
  387. },
  388. },
  389. },
  390. properties: {
  391. add: {
  392. type: 'void',
  393. title: '添加参数',
  394. 'x-component': 'ArrayItems.Addition',
  395. },
  396. },
  397. },
  398. },
  399. };
  400. return <SchemaField schema={schema} scope={{ useAsyncDataSource, getUnit }} />;
  401. });
  402. export default JsonParam;