index.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import { useIntl } from 'umi';
  2. import type { Field } from '@formily/core';
  3. import { createForm } from '@formily/core';
  4. import { createSchemaField } from '@formily/react';
  5. import React from 'react';
  6. import * as ICONS from '@ant-design/icons';
  7. import { Form, FormGrid, FormItem, Input, Select } from '@formily/antd';
  8. import type { ISchema } from '@formily/json-schema';
  9. import { action } from '@formily/reactive';
  10. import type { Response } from '@/utils/typings';
  11. import { service } from '@/pages/system/Relationship';
  12. import { Modal } from '@/components';
  13. import { message } from 'antd';
  14. interface Props {
  15. data: Partial<ReationItem>;
  16. close: () => void;
  17. }
  18. const Save = (props: Props) => {
  19. const intl = useIntl();
  20. const getTypes = () => service.getTypes();
  21. const useAsyncDataSource = (api: any) => (field: Field) => {
  22. field.loading = true;
  23. api(field).then(
  24. action.bound!((resp: Response<any>) => {
  25. field.dataSource = resp.result?.map((item: Record<string, unknown>) => ({
  26. ...item,
  27. label: item.name,
  28. value: JSON.stringify({
  29. objectType: item.id,
  30. objectTypeName: item.name,
  31. }),
  32. }));
  33. field.loading = false;
  34. }),
  35. );
  36. };
  37. const form = createForm({
  38. validateFirst: true,
  39. initialValues: props.data,
  40. });
  41. const SchemaField = createSchemaField({
  42. components: {
  43. FormItem,
  44. Input,
  45. Select,
  46. FormGrid,
  47. },
  48. scope: {
  49. icon(name: any) {
  50. return React.createElement(ICONS[name]);
  51. },
  52. },
  53. });
  54. const schema: ISchema = {
  55. type: 'object',
  56. properties: {
  57. layout: {
  58. type: 'void',
  59. 'x-decorator': 'FormGrid',
  60. 'x-decorator-props': {
  61. maxColumns: 2,
  62. minColumns: 2,
  63. columnGap: 24,
  64. },
  65. properties: {
  66. name: {
  67. title: '名称',
  68. type: 'string',
  69. 'x-decorator': 'FormItem',
  70. 'x-component': 'Input',
  71. 'x-decorator-props': {
  72. gridSpan: 2,
  73. },
  74. 'x-component-props': {
  75. placeholder: '请输入名称',
  76. },
  77. name: 'name',
  78. 'x-validator': [
  79. {
  80. max: 64,
  81. message: '最多可输入64个字符',
  82. },
  83. {
  84. required: true,
  85. message: '请输入名称',
  86. },
  87. ],
  88. },
  89. relation: {
  90. title: '标识',
  91. 'x-decorator-props': {
  92. gridSpan: 2,
  93. },
  94. type: 'string',
  95. 'x-disabled': !!props.data?.id,
  96. 'x-decorator': 'FormItem',
  97. 'x-component': 'Input',
  98. 'x-component-props': {
  99. placeholder: '请输入标识',
  100. },
  101. 'x-validator': [
  102. {
  103. max: 64,
  104. message: '最多可输入64个字符',
  105. },
  106. {
  107. required: true,
  108. message: '请输入标识',
  109. },
  110. // {
  111. // triggerType: 'onBlur',
  112. // // validator: (value: string) => {
  113. // // return new Promise((resolve) => {
  114. // // service
  115. // // .validateField('username', value)
  116. // // .then((resp) => {
  117. // // if (resp.status === 200) {
  118. // // if (resp.result.passed) {
  119. // // resolve('');
  120. // // } else {
  121. // // resolve(model === 'edit' ? '' : resp.result.reason);
  122. // // }
  123. // // }
  124. // // resolve('');
  125. // // })
  126. // // .catch(() => {
  127. // // return '验证失败!';
  128. // // });
  129. // // });
  130. // // },
  131. // },
  132. ],
  133. name: 'relation',
  134. required: true,
  135. },
  136. object: {
  137. title: '关联方',
  138. 'x-decorator-props': {
  139. gridSpan: 1,
  140. },
  141. type: 'string',
  142. 'x-decorator': 'FormItem',
  143. 'x-disabled': !!props.data?.id,
  144. 'x-component': 'Select',
  145. 'x-component-props': {
  146. placeholder: '请选择关联方',
  147. showArrow: true,
  148. filterOption: (input: string, option: any) =>
  149. option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
  150. },
  151. required: true,
  152. 'x-reactions': ['{{useAsyncDataSource(getTypes)}}'],
  153. },
  154. target: {
  155. title: '被关联方',
  156. 'x-decorator-props': {
  157. gridSpan: 1,
  158. },
  159. type: 'string',
  160. 'x-decorator': 'FormItem',
  161. 'x-disabled': !!props.data?.id,
  162. 'x-component': 'Select',
  163. 'x-component-props': {
  164. placeholder: '请选择被关联方',
  165. },
  166. 'x-reactions': {
  167. dependencies: ['..object'],
  168. fulfill: {
  169. state: {
  170. dataSource:
  171. '{{JSON.parse($deps[0] || "{}").objectType==="device"?[{label: "用户", value: JSON.stringify({"targetType":"user", "targetTypeName": "用户"})}] : []}}',
  172. },
  173. },
  174. },
  175. required: true,
  176. },
  177. description: {
  178. title: '说明',
  179. 'x-decorator': 'FormItem',
  180. 'x-component': 'Input.TextArea',
  181. 'x-component-props': {
  182. rows: 5,
  183. placeholder: '请输入说明',
  184. },
  185. 'x-decorator-props': {
  186. gridSpan: 2,
  187. },
  188. 'x-validator': [
  189. {
  190. max: 200,
  191. message: '最多可输入200个字符',
  192. },
  193. ],
  194. },
  195. },
  196. },
  197. },
  198. };
  199. const save = async () => {
  200. const value = await form.submit<any>();
  201. const temp: any = {
  202. ...props.data,
  203. ...value,
  204. ...JSON.parse(value?.object || '{}'),
  205. ...JSON.parse(value?.target || '{}'),
  206. };
  207. delete temp.object;
  208. delete temp.target;
  209. const response: any = await service[!props.data?.id ? 'save' : 'update']({ ...temp });
  210. if (response.status === 200) {
  211. message.success(
  212. intl.formatMessage({
  213. id: 'pages.data.option.success',
  214. defaultMessage: '操作成功',
  215. }),
  216. );
  217. props.close();
  218. } else {
  219. message.error('操作失败!');
  220. }
  221. };
  222. return (
  223. <Modal
  224. title={intl.formatMessage({
  225. id: `pages.data.option.${props.data.id ? 'edit' : 'add'}`,
  226. defaultMessage: '编辑',
  227. })}
  228. maskClosable={false}
  229. visible
  230. onCancel={props.close}
  231. onOk={save}
  232. width="35vw"
  233. permissionCode={'system/Relationship'}
  234. permission={['add', 'edit']}
  235. >
  236. <Form form={form} layout="vertical">
  237. <SchemaField schema={schema} scope={{ useAsyncDataSource, getTypes }} />
  238. </Form>
  239. </Modal>
  240. );
  241. };
  242. export default Save;