edit.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. import React, { useEffect, useState } from 'react';
  2. import type { UploadProps } from 'antd';
  3. import { Cascader } from 'antd';
  4. import { Checkbox, Col, Form, Input, message, Modal, Row, Select, Upload } from 'antd';
  5. import { createUser, editUser, queryRoleUser, queryTreeList } from '@/services/setting';
  6. import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
  7. import md5 from 'js-md5';
  8. import { queryRoleList } from '@/services/role';
  9. import { infoQuery } from '@/services/ReportingManagement';
  10. interface userEditPros {
  11. visible: boolean;
  12. editCallback: () => void;
  13. detailData: any;
  14. }
  15. /**
  16. * 用户管理编辑
  17. * @param props
  18. * @constructor
  19. */
  20. const Edit: React.FC<userEditPros> = (props) => {
  21. const { visible, editCallback, detailData } = props;
  22. const [form] = Form.useForm();
  23. const uploadHeaders = { Authorization: `${localStorage.getItem('token')}` };
  24. const [fileUrl, setFileUrl]: any = useState(
  25. detailData && detailData.photo ? detailData.photo : '',
  26. );
  27. const [loading, setLoading] = useState(false);
  28. const [roleList, setRoleList] = useState([]);
  29. const [selectList, setSelectList] = useState([]);
  30. const [areaList, setAreaList] = useState([]);
  31. const [isCurrent, setIsCurrent] = useState(false);
  32. const getBase64 = (img: any) => {
  33. const reader = new FileReader();
  34. reader.readAsDataURL(img);
  35. reader.onloadend = () => {
  36. const url = reader.result;
  37. setFileUrl(url);
  38. };
  39. };
  40. useEffect(() => {
  41. // 编辑时
  42. if (detailData) {
  43. infoQuery().then((res) => {
  44. if (res?.code === 0) {
  45. // 判断当前编辑用户数据和登录账号是否为同一个
  46. // 同一个则直接显示用户数据中user_role(角色名称)和parent_name(所属名称)
  47. if (res.data.record_id === detailData.record_id) {
  48. setIsCurrent(true);
  49. const user_role_list: any = [];
  50. const obj = {
  51. name: '',
  52. record_id: '',
  53. };
  54. detailData.user_role.forEach((el: { role_id: string; role_name: string }) => {
  55. obj.name = el.role_name;
  56. obj.record_id = el.role_id;
  57. user_role_list.push(obj);
  58. });
  59. setRoleList(user_role_list);
  60. } else {
  61. // 角色列表
  62. queryRoleList({ q: 'list' }).then((item) => {
  63. if (item.code === 0) {
  64. setRoleList(item.data.list);
  65. }
  66. });
  67. }
  68. }
  69. });
  70. // 编辑时,所属地区根据角色id回显数据
  71. const data = [...detailData?.user_role].sort((a: any, b: any) => b.level - a.level);
  72. if (data && data.length) {
  73. const param = {
  74. q: 'list',
  75. role_id: data[0].role_id,
  76. user_id: detailData.record_id,
  77. };
  78. // 根据角色id请求用户列表接口 保证所属名称字段编辑时回显
  79. queryRoleUser(param).then((item) => {
  80. if (item.code === 0) {
  81. setSelectList(item?.data || []);
  82. }
  83. });
  84. }
  85. } else {
  86. // 新增
  87. // 角色列表
  88. queryRoleList({ q: 'list' }).then((res) => {
  89. if (res.code === 0) {
  90. setRoleList(res.data.list);
  91. }
  92. });
  93. }
  94. // 地区列表
  95. queryTreeList({ q: 'tree' }).then((res) => {
  96. if (res && res.code === 0) {
  97. setAreaList(res.data.list || []);
  98. }
  99. });
  100. }, []);
  101. const handleLevel = (values: any) => {
  102. const data: any = roleList.filter((option: { record_id: string }) =>
  103. values.includes(option.record_id),
  104. );
  105. return [...data].sort((a: any, b: any) => b.level - a.level);
  106. };
  107. // 角色选择
  108. const onRoleChange = (selectedValues: any) => {
  109. // 切换角色时,所属名称要清空重新选择
  110. form.setFieldsValue({ parent_id: '' });
  111. const sortedData = handleLevel(selectedValues);
  112. if (sortedData && sortedData.length > 0) {
  113. const maxLevelObject = sortedData[0];
  114. const param = {
  115. q: 'list',
  116. role_id: maxLevelObject.record_id,
  117. };
  118. queryRoleUser(param).then((res) => {
  119. if (res.code === 0) {
  120. setSelectList(res?.data || []);
  121. }
  122. });
  123. } else {
  124. setSelectList([]);
  125. }
  126. };
  127. const filesProps: UploadProps = {
  128. maxCount: 1,
  129. action: '/web/v1/files',
  130. headers: uploadHeaders,
  131. listType: 'picture-card',
  132. showUploadList: false,
  133. onChange(info) {
  134. if (info.file.status === 'uploading') {
  135. setLoading(true);
  136. return;
  137. }
  138. if (info.file.status === 'done') {
  139. setLoading(false);
  140. getBase64(info.file.originFileObj);
  141. } else if (info.file.status === 'error') {
  142. setLoading(false);
  143. message.error('文件上传失败');
  144. }
  145. },
  146. };
  147. /**
  148. * 确定
  149. */
  150. const onOk = () => {
  151. form.validateFields().then((values) => {
  152. if (values) {
  153. const data = { ...values };
  154. if (values?.photo) {
  155. data.photo = values?.photo?.file?.response?.data?.url;
  156. }
  157. if (values?.password) {
  158. data.password = md5(values.password);
  159. }
  160. if (values?.role_id) {
  161. const user_role: { role_id: any }[] = [];
  162. values?.role_id.forEach((el: any) => {
  163. user_role.push({ role_id: el });
  164. });
  165. data.user_role = user_role;
  166. delete data.role_id;
  167. }
  168. if (values?.area) {
  169. data.province = values.area[0];
  170. data.city = values.area[1];
  171. data.district = values.area[2];
  172. delete data.area;
  173. }
  174. if (values?.parent_id) {
  175. data.parent_id = values?.parent_id;
  176. }
  177. if (detailData) {
  178. data.record_id = detailData.record_id;
  179. // 编辑
  180. editUser(data)
  181. .then((res) => {
  182. if (res.code === 0) {
  183. message.success('编辑成功');
  184. editCallback();
  185. } else {
  186. message.error(res?.message);
  187. editCallback();
  188. }
  189. })
  190. .catch((e) => {
  191. message.error(e?.message);
  192. editCallback();
  193. });
  194. } else {
  195. // 新增
  196. createUser(data)
  197. .then((res) => {
  198. if (res.code === 0) {
  199. message.success('保存成功');
  200. editCallback();
  201. } else {
  202. message.error(res?.message);
  203. editCallback();
  204. }
  205. })
  206. .catch((e) => {
  207. message.error(e?.message);
  208. editCallback();
  209. });
  210. }
  211. }
  212. });
  213. };
  214. /**
  215. * 取消
  216. */
  217. const onCancel = () => {
  218. editCallback();
  219. };
  220. const formItemLayout = {
  221. labelCol: {
  222. span: 6,
  223. },
  224. wrapperCol: {
  225. span: 16,
  226. },
  227. };
  228. const formItemLayoutTwo = {
  229. labelCol: {
  230. span: 3,
  231. },
  232. wrapperCol: {
  233. span: 21,
  234. },
  235. };
  236. const uploadButton = (
  237. <div>
  238. {loading ? <LoadingOutlined /> : <PlusOutlined />}
  239. <div className="ant-upload-text">上传</div>
  240. </div>
  241. );
  242. return (
  243. <Modal
  244. title={`${detailData ? '编辑' : '新增'}`}
  245. open={visible}
  246. onOk={onOk}
  247. onCancel={onCancel}
  248. width={800}
  249. >
  250. <Form form={form}>
  251. <Row>
  252. <Col span={12}>
  253. <Form.Item
  254. {...formItemLayout}
  255. name="user_name"
  256. label="用户姓名"
  257. rules={[{ required: true, message: '请输入用户姓名' }]}
  258. initialValue={detailData?.user_name || ''}
  259. >
  260. <Input placeholder="请输入用户姓名" />
  261. </Form.Item>
  262. </Col>
  263. <Col span={12}>
  264. <Form.Item {...formItemLayout} name="password" label="密码">
  265. <Input type="password" placeholder="请输入密码" />
  266. </Form.Item>
  267. </Col>
  268. <Col span={12}>
  269. <Form.Item
  270. {...formItemLayout}
  271. name="phone"
  272. label="手机号"
  273. rules={[
  274. { required: true, message: '请输入手机号' },
  275. {
  276. pattern:
  277. /^1((34[0-8])|(8\d{2})|(([35][0-35-9]|4[579]|66|7[35678]|9[1389])\d{1}))\d{7}$/,
  278. message: '请输入正确的手机号',
  279. },
  280. ]}
  281. initialValue={detailData?.phone || ''}
  282. >
  283. <Input placeholder="请输入手机号" />
  284. </Form.Item>
  285. </Col>
  286. <Col span={12}>
  287. <Form.Item
  288. {...formItemLayout}
  289. name="company"
  290. label="公司名称"
  291. initialValue={detailData?.company || ''}
  292. >
  293. <Input placeholder="请输入公司名称" />
  294. </Form.Item>
  295. </Col>
  296. <Col span={24}>
  297. <Form.Item
  298. {...formItemLayoutTwo}
  299. name="role_id"
  300. label="角色名称"
  301. rules={[{ required: true, message: '请选择角色名称' }]}
  302. initialValue={
  303. detailData && detailData?.user_role && detailData?.user_role.length
  304. ? detailData?.user_role?.map((item: any) => item.role_id)
  305. : []
  306. }
  307. >
  308. <Checkbox.Group
  309. options={roleList.map((option: { record_id: string; name: string }) => ({
  310. label: option.name,
  311. value: option.record_id,
  312. record_id: option.record_id,
  313. }))}
  314. disabled={isCurrent}
  315. onChange={onRoleChange}
  316. />
  317. </Form.Item>
  318. </Col>
  319. <Col span={24}>
  320. <Form.Item
  321. {...formItemLayoutTwo}
  322. name="parent_id"
  323. label="上级用户"
  324. initialValue={detailData?.parent_id || ''}
  325. >
  326. <Select placeholder="请选择所属名称" disabled={isCurrent}>
  327. {selectList && selectList.length
  328. ? selectList.map(
  329. (res: { user_name: string; record_id: string; parent_id: string }) => {
  330. return (
  331. <Select.Option key={res.record_id} value={res.record_id}>
  332. {res?.user_name}
  333. </Select.Option>
  334. );
  335. },
  336. )
  337. : null}
  338. </Select>
  339. </Form.Item>
  340. </Col>
  341. <Col span={24}>
  342. <Form.Item
  343. {...formItemLayoutTwo}
  344. name="area"
  345. label="所属地区"
  346. initialValue={
  347. detailData?.province || detailData?.city || detailData?.district
  348. ? [detailData?.province, detailData?.city, detailData?.district]
  349. : []
  350. }
  351. >
  352. <Cascader
  353. options={areaList}
  354. placeholder="请选择所属地区"
  355. fieldNames={{ label: 'name', value: 'name', children: 'children' }}
  356. />
  357. </Form.Item>
  358. </Col>
  359. <Col span={12}>
  360. <Form.Item {...formItemLayout} name="photo" label="头像" initialValue={[]}>
  361. <Upload {...filesProps}>
  362. {fileUrl === '' ? (
  363. uploadButton
  364. ) : (
  365. <img src={fileUrl} alt="data" style={{ width: '100%' }} />
  366. )}
  367. </Upload>
  368. </Form.Item>
  369. </Col>
  370. </Row>
  371. </Form>
  372. </Modal>
  373. );
  374. };
  375. export default Edit;