index.tsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import { message, Modal } from 'antd';
  2. import { useIntl } from 'umi';
  3. import type { Field } from '@formily/core';
  4. import { createForm } from '@formily/core';
  5. import { createSchemaField } from '@formily/react';
  6. import React, { useEffect, useState } from 'react';
  7. import * as ICONS from '@ant-design/icons';
  8. import { Form, FormItem, Input, Password, Select, Switch } from '@formily/antd';
  9. import type { ISchema } from '@formily/json-schema';
  10. import { PlusOutlined } from '@ant-design/icons';
  11. import { action } from '@formily/reactive';
  12. import type { Response } from '@/utils/typings';
  13. import { service } from '@/pages/system/User';
  14. interface Props {
  15. model: 'add' | 'edit' | 'query';
  16. data: Partial<UserItem>;
  17. close: () => void;
  18. }
  19. const Save = (props: Props) => {
  20. const { model } = props;
  21. const intl = useIntl();
  22. const [data, setData] = useState<Partial<UserItem>>(props.data);
  23. const getRole = () => service.queryRoleList();
  24. const getOrg = () => service.queryOrgList();
  25. const useAsyncDataSource = (api: any) => (field: Field) => {
  26. field.loading = true;
  27. api(field).then(
  28. action.bound!((resp: Response<any>) => {
  29. field.dataSource = resp.result?.map((item: Record<string, unknown>) => ({
  30. label: item.name,
  31. value: item.id,
  32. }));
  33. field.loading = false;
  34. }),
  35. );
  36. };
  37. const getUser = async () => {
  38. if (props.data.id) {
  39. console.log('id');
  40. const response: Response<UserItem> = await service.queryDetail(props.data?.id);
  41. if (response.status === 200) {
  42. const temp = response.result as UserItem;
  43. temp.orgIdList = (temp.orgList as { id: string; name: string }[]).map((item) => item.id);
  44. temp.roleIdList = (temp.roleList as { id: string; name: string }[]).map((item) => item.id);
  45. setData(temp);
  46. }
  47. }
  48. };
  49. useEffect(() => {
  50. if (model === 'edit') {
  51. getUser();
  52. } else {
  53. setData({});
  54. }
  55. }, [props.data, props.model]);
  56. const form = createForm({
  57. validateFirst: true,
  58. initialValues: data,
  59. });
  60. const SchemaField = createSchemaField({
  61. components: {
  62. FormItem,
  63. Input,
  64. Password,
  65. Switch,
  66. Select,
  67. },
  68. scope: {
  69. icon(name: any) {
  70. return React.createElement(ICONS[name]);
  71. },
  72. },
  73. });
  74. const schema: ISchema = {
  75. type: 'object',
  76. properties: {
  77. name: {
  78. title: intl.formatMessage({
  79. id: 'pages.system.name',
  80. defaultMessage: '姓名',
  81. }),
  82. type: 'string',
  83. 'x-decorator': 'FormItem',
  84. 'x-component': 'Input',
  85. 'x-component-props': {},
  86. 'x-decorator-props': {},
  87. name: 'name',
  88. required: true,
  89. },
  90. username: {
  91. title: intl.formatMessage({
  92. id: 'pages.system.username',
  93. defaultMessage: '用户名',
  94. }),
  95. type: 'string',
  96. 'x-decorator': 'FormItem',
  97. 'x-component': 'Input',
  98. 'x-component-props': {
  99. disabled: model === 'edit',
  100. },
  101. 'x-decorator-props': {},
  102. name: 'username',
  103. required: true,
  104. },
  105. password: {
  106. type: 'string',
  107. title: intl.formatMessage({
  108. id: 'pages.system.password',
  109. defaultMessage: '密码',
  110. }),
  111. 'x-decorator': 'FormItem',
  112. 'x-component': 'Password',
  113. 'x-component-props': {
  114. checkStrength: true,
  115. placeholder: '********',
  116. },
  117. required: model === 'add',
  118. 'x-reactions': [
  119. {
  120. dependencies: ['.confirmPassword'],
  121. fulfill: {
  122. state: {
  123. selfErrors:
  124. '{{$deps[0] && $self.value && $self.value !==$deps[0] ? "确认密码不匹配" : ""}}',
  125. },
  126. },
  127. },
  128. ],
  129. 'x-decorator-props': {},
  130. name: 'password',
  131. },
  132. confirmPassword: {
  133. type: 'string',
  134. title: intl.formatMessage({
  135. id: 'pages.system.confirmPassword',
  136. defaultMessage: '确认密码?',
  137. }),
  138. 'x-decorator': 'FormItem',
  139. 'x-component': 'Password',
  140. 'x-component-props': {
  141. checkStrength: true,
  142. placeholder: '********',
  143. },
  144. 'x-reactions': [
  145. {
  146. dependencies: ['.password'],
  147. fulfill: {
  148. state: {
  149. selfErrors:
  150. '{{$deps[0] && $self.value && $self.value !== $deps[0] ? "确认密码不匹配" : ""}}',
  151. },
  152. },
  153. },
  154. ],
  155. 'x-decorator-props': {},
  156. name: 'confirmPassword',
  157. required: model === 'add',
  158. },
  159. roleIdList: {
  160. title: '角色',
  161. 'x-decorator': 'FormItem',
  162. 'x-component': 'Select',
  163. 'x-component-props': {
  164. mode: 'multiple',
  165. },
  166. 'x-reactions': ['{{useAsyncDataSource(getRole)}}'],
  167. 'x-decorator-props': {
  168. addonAfter: (
  169. <a
  170. onClick={() => {
  171. const tab: any = window.open(`${origin}/#/system/role?save=true`);
  172. tab!.onTabSaveSuccess = (value: any) => {
  173. form.setFieldState('roleIdList', (state) => {
  174. state.dataSource = state.dataSource?.concat([
  175. { label: value.name, value: value.id },
  176. ]);
  177. });
  178. };
  179. }}
  180. >
  181. <PlusOutlined />
  182. </a>
  183. ),
  184. },
  185. },
  186. orgIdList: {
  187. title: '部门',
  188. 'x-decorator': 'FormItem',
  189. 'x-component': 'Select',
  190. 'x-component-props': {
  191. mode: 'multiple',
  192. showArrow: true,
  193. },
  194. 'x-decorator-props': {
  195. addonAfter: (
  196. <a
  197. onClick={() => {
  198. const tab: any = window.open(`${origin}/#/system/department?save=true`);
  199. tab!.onTabSaveSuccess = (value: any) => {
  200. form.setFieldState('orgIdList', (state) => {
  201. console.log(value, 'value');
  202. state.dataSource = state.dataSource?.concat([
  203. { label: value.name, value: value.id },
  204. ]);
  205. });
  206. };
  207. }}
  208. >
  209. <PlusOutlined />
  210. </a>
  211. ),
  212. },
  213. 'x-reactions': ['{{useAsyncDataSource(getOrg)}}'],
  214. },
  215. },
  216. };
  217. const save = async () => {
  218. const value = await form.submit<UserItem>();
  219. const temp: any = {};
  220. temp.id = value.id;
  221. temp.user = value;
  222. temp.orgIdList = value.orgIdList;
  223. temp.roleIdList = value.roleIdList;
  224. const response = await service.saveUser(temp, model);
  225. if (response.status === 200) {
  226. message.success(
  227. intl.formatMessage({
  228. id: 'pages.data.option.success',
  229. defaultMessage: '操作成功',
  230. }),
  231. );
  232. } else {
  233. message.error('操作失败!');
  234. }
  235. props.close();
  236. };
  237. return (
  238. <Modal
  239. title={intl.formatMessage({
  240. id: `pages.data.option.${model}`,
  241. defaultMessage: '编辑',
  242. })}
  243. maskClosable={false}
  244. visible={model !== 'query'}
  245. onCancel={props.close}
  246. onOk={save}
  247. >
  248. <Form form={form} labelCol={4} wrapperCol={18}>
  249. <SchemaField schema={schema} scope={{ useAsyncDataSource, getRole, getOrg }} />
  250. </Form>
  251. </Modal>
  252. );
  253. };
  254. export default Save;