ApprovalModal.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. import React, { useState, useEffect } from 'react';
  2. import { Form, Select, Modal, Input, TreeSelect, Button } from 'antd';
  3. import moment from 'moment';
  4. import provinces from './provinces';
  5. import { queryApproval } from '@/services/approval';
  6. import FirmModal from './ManufacturerModal';
  7. import TableRender from './TableRender';
  8. const { Option } = Select;
  9. const { TreeNode } = TreeSelect;
  10. // 新建
  11. function AddModal(props) {
  12. const {
  13. total,
  14. dispatch,
  15. visible,
  16. onClose,
  17. onOk,
  18. data,
  19. currentUser,
  20. depUserTree,
  21. flowList = [],
  22. industryList = [],
  23. typeList = [],
  24. disabled,
  25. loading,
  26. supplierList = [],
  27. onAddFirm,
  28. } = props;
  29. const [form] = Form.useForm();
  30. const [codes, setCodes] = useState({
  31. type: '',
  32. industry: '',
  33. location: '',
  34. name: '',
  35. version: '',
  36. });
  37. const [type, setType] = useState({});
  38. const [addFirmVisible, setAddFirmVisible] = useState(false);
  39. const handleOk = () => {
  40. form.validateFields().then(fieldsValue => {
  41. let values = { ...fieldsValue, id: data.id };
  42. values.project_name = fieldsValue.project_name;
  43. values.flow_id = Number(fieldsValue.flow_id);
  44. values.type_id = Number(fieldsValue.type_id);
  45. // 获得flow下第一个node的id
  46. values.node_id = flowList.find(item => item.id == values.flow_id).Nodes[0].id;
  47. //项目分类为不为研发时
  48. if (fieldsValue.type_id != 7) {
  49. values.industry_id = Number(fieldsValue.industry_id);
  50. let [location, location_code] = fieldsValue.location.split('##');
  51. values.location = location;
  52. values.location_code = location_code;
  53. values.project_full_code = `${codes.type}${codes.industry}${codes.location}${codes.name}${codes.version}`;
  54. }
  55. if (fieldsValue.author) {
  56. values.author = Number(fieldsValue.author.split('||')[0]);
  57. values.author_dep_id = Number(fieldsValue.author.split('||')[1]);
  58. } else {
  59. values.author = null;
  60. }
  61. const supplierName = supplierList.find(item => item.id == fieldsValue.supplier_id)?.name;
  62. if (supplierName) values.supplier_name = supplierName;
  63. onOk(values);
  64. });
  65. };
  66. const renderTreeNodes = data => {
  67. return data.map(item => {
  68. let title = item.name;
  69. let code = item.code || '';
  70. if (code.length == 4) {
  71. code = code.substr(1);
  72. }
  73. if (code) {
  74. title += `(${code})`;
  75. }
  76. let key = `${item.name}##${code}`;
  77. return (
  78. <TreeNode title={title} key={key} value={key} dataRef={item} selectable={Boolean(code)}>
  79. {item.children && renderTreeNodes(item.children || [])}
  80. </TreeNode>
  81. );
  82. });
  83. };
  84. const changeType = id => {
  85. const item = typeList.find(item => item.id == id);
  86. setCodes({
  87. ...codes,
  88. type: item.code,
  89. });
  90. setType(item);
  91. form.setFieldsValue({ flow_id: id == 7 ? '4' : '1' });
  92. };
  93. const changeIndustry = id => {
  94. const item = industryList.find(item => item.id == id);
  95. setCodes({
  96. ...codes,
  97. industry: item.code,
  98. });
  99. };
  100. const changeVersion = index => {
  101. setCodes({
  102. ...codes,
  103. version: index,
  104. });
  105. };
  106. const changeLocation = value => {
  107. const [location, code] = value.split('##');
  108. setCodes({
  109. ...codes,
  110. location: code,
  111. });
  112. };
  113. const onBlurName = e => {
  114. let value = e.target.value.toUpperCase();
  115. while (value.length < 3) {
  116. value = value + 'V';
  117. }
  118. form.setFieldsValue({
  119. name: value,
  120. });
  121. setCodes({
  122. ...codes,
  123. name: value,
  124. });
  125. };
  126. const renderDetail = () => {
  127. return (
  128. <>
  129. <Form.Item
  130. label="行业名称"
  131. name="industry_id"
  132. initialValue={String(data.industry_id || '')}
  133. rules={[{ required: true, message: '请选择行业名称' }]}
  134. >
  135. <Select style={{ width: '100%' }} onChange={changeIndustry}>
  136. {industryList.map(item => (
  137. <Option key={item.id}>
  138. {item.name}({item.code})
  139. </Option>
  140. ))}
  141. </Select>
  142. </Form.Item>
  143. <div style={{ position: 'relative' }}>
  144. <Form.Item
  145. label="项目客户"
  146. name="supplier_id"
  147. initialValue={data.supplier_id}
  148. rules={[{ required: true, message: '请选择项目客户' }]}
  149. >
  150. <Select
  151. style={{ width: '100%' }}
  152. onChange={e => form.setFieldsValue({ supplier_id: e })}
  153. showSearch
  154. filterOption={(input, option) => {
  155. return (option?.children[0] ?? '').includes(input);
  156. }}
  157. >
  158. {supplierList.map(item => (
  159. <Option key={item.id} value={Number(item.id)}>
  160. {item.name}({item.id})
  161. </Option>
  162. ))}
  163. </Select>
  164. </Form.Item>
  165. <Button
  166. style={{ position: 'absolute', right: ' -18px', top: '0' }}
  167. type="primary"
  168. onClick={onAddFirm}
  169. >
  170. 新建客户
  171. </Button>
  172. </div>
  173. <Form.Item
  174. label="项目规模"
  175. name="process_info"
  176. initialValue={data.process_info}
  177. rules={[{ required: true, message: '请填写项目规模' }]}
  178. >
  179. <TableRender />
  180. </Form.Item>
  181. <Form.Item
  182. label="项目地区"
  183. name="location"
  184. initialValue={data.location}
  185. rules={[{ required: true, message: '请选择项目地区' }]}
  186. >
  187. <TreeSelect
  188. dropdownStyle={{ maxHeight: 300, overflow: 'auto' }}
  189. onChange={changeLocation}
  190. >
  191. {renderTreeNodes(provinces)}
  192. </TreeSelect>
  193. </Form.Item>
  194. <Form.Item
  195. label="项目简称"
  196. name="name"
  197. initialValue={data.name}
  198. rules={[
  199. { required: true, message: '请输入项目简称' },
  200. {
  201. validator: (rule, value) => {
  202. if (value && value.match(/[^A-Za-z]/g))
  203. return Promise.reject(new Error('项目简称只能是英文字符'));
  204. else return Promise.resolve();
  205. },
  206. },
  207. ]}
  208. >
  209. <Input maxLength={3} onBlur={onBlurName} />
  210. </Form.Item>
  211. <Form.Item
  212. label="项目期数"
  213. name="version"
  214. initialValue={data.version}
  215. rules={[{ required: true, message: '请选择项目期数' }]}
  216. >
  217. <Select style={{ width: '100%' }} onChange={changeVersion}>
  218. {['一期', '二期', '三期', '四期', '五期'].map((item, index) => (
  219. <Option key={index + 1}>{item}</Option>
  220. ))}
  221. </Select>
  222. </Form.Item>
  223. <Form.Item label="项目编号">
  224. {codes.type || '***'}-{codes.industry || '***'}-{codes.location || '***'}-
  225. {codes.name || '***'}-{codes.version || '*'}
  226. </Form.Item>
  227. </>
  228. );
  229. };
  230. useEffect(() => {
  231. if (data.id) {
  232. const type = typeList.find(item => item.id == data.type_id);
  233. const industry = industryList.find(item => item.id == data.industry_id);
  234. setCodes({
  235. type: type?.code,
  236. industry: industry?.code,
  237. location: data.location_code,
  238. name: data.name,
  239. version: data.version,
  240. });
  241. setType(type);
  242. } else {
  243. setCodes({
  244. type: '',
  245. industry: '',
  246. location: '',
  247. name: '',
  248. version: '',
  249. });
  250. setType({});
  251. }
  252. }, [data, visible]);
  253. useEffect(() => {
  254. form.resetFields();
  255. }, [visible]);
  256. return (
  257. <Modal
  258. title="项目立项"
  259. confirmLoading={loading}
  260. maskClosable={false}
  261. destroyOnClose
  262. visible={visible}
  263. onCancel={onClose}
  264. onOk={handleOk}
  265. >
  266. <Form labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} form={form}>
  267. <Form.Item
  268. label="项目名称"
  269. name="project_name"
  270. initialValue={String(data.project_name || '')}
  271. rules={[{ required: true, message: '请输入项目名称' }]}
  272. >
  273. <Input style={{ width: '100%' }} />
  274. </Form.Item>
  275. <Form.Item
  276. label="项目类别"
  277. name="type_id"
  278. initialValue={String(data.type_id || '')}
  279. rules={[{ required: true, message: '请选择项目类别' }]}
  280. >
  281. <Select style={{ width: '100%' }} onChange={changeType}>
  282. {typeList.map(item => (
  283. <Option key={item.id}>
  284. {item.name}({item.code})
  285. </Option>
  286. ))}
  287. </Select>
  288. </Form.Item>
  289. <Form.Item
  290. label="流程"
  291. name="flow_id"
  292. initialValue={String(data.flow_id || '')}
  293. rules={[{ required: true, message: '请选择流程' }]}
  294. >
  295. <Select style={{ width: '100%' }} disabled>
  296. {flowList
  297. .filter(item => item && item.id != 2 && item.id != 3)
  298. .map(item => (
  299. <Option key={item.id}>{item.name}</Option>
  300. ))}
  301. </Select>
  302. </Form.Item>
  303. {currentUser.IsSuper && (
  304. <Form.Item
  305. label="售前经理"
  306. name="author"
  307. initialValue={String(
  308. data.author && data.author_dep_id ? `${data.author}||${data.author_dep_id}` : ''
  309. )}
  310. >
  311. <TreeSelect
  312. showSearch
  313. allowClear
  314. style={{ width: '100%' }}
  315. multiple={false}
  316. filterTreeNode={(input, option) => {
  317. return option.props.title === input;
  318. }}
  319. treeData={depUserTree}
  320. />
  321. </Form.Item>
  322. )}
  323. {type?.id != 7 && renderDetail()}
  324. </Form>
  325. </Modal>
  326. );
  327. }
  328. export default AddModal;