index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import Authorization from '@/components/Authorization'
  2. import DatePicker from '@/components/DatePicker'
  3. import { contractReturnStore, tenderStore } from '@/store/mobx'
  4. import { iModalCommonProps } from '@/types/contract'
  5. import consts from '@/utils/consts'
  6. import { dayjsFormat, handleAutoCode } from '@/utils/util'
  7. import { Button, Form, Input, Modal, Select, Tree } from 'antd'
  8. import locale from 'antd/es/date-picker/locale/zh_CN'
  9. import dayjs from 'dayjs'
  10. import React, { ChangeEvent, useEffect, useState } from 'react'
  11. import { apiGetReturnWay } from '../Tabs/Receivable/api'
  12. import styles from './index.module.scss'
  13. const ContractModal: React.FC<iModalCommonProps> = ({ modalObj: { type, visible, confirmLoading, contractType }, onConfirm, onCancel, reload, row }) => {
  14. const { Option } = Select
  15. const [ form ] = Form.useForm()
  16. const [ options, setOptions ] = useState<string[]>([])
  17. const modalObj = {
  18. create: {
  19. title: '新建合同',
  20. cancelText: '取消',
  21. okText: '确认添加'
  22. },
  23. update: {
  24. title: '编辑合同',
  25. cancelText: '取消',
  26. okText: '确认'
  27. },
  28. close: {
  29. title: '关闭合同',
  30. cancelText: '取消',
  31. okText: '确认关闭'
  32. },
  33. del: {
  34. title: '删除合同',
  35. cancelText: '取消',
  36. okText: '确认删除'
  37. },
  38. unlock: {
  39. title: '解锁合同',
  40. cancelText: '取消',
  41. okText: '确认解锁'
  42. },
  43. return: {
  44. title: '添加回款',
  45. cancelText: '关闭',
  46. okText: '确认'
  47. }
  48. }
  49. useEffect(() => {
  50. if (visible) {
  51. form.setFieldsValue({ treeId: row.id, bidsectionId: row.bidsectionId })
  52. if (type === 'update') {
  53. const { content = '', name = '', price = '', partyA = '', partyB = '', partyASigner = '', partyBSigner = '', signerTime = '', remarks = '' } = contractReturnStore.contract
  54. form.setFieldsValue({ content, name, price, partyA, partyB, partyASigner, partyBSigner, signerTime: signerTime ? dayjs(signerTime) : '', remarks })
  55. } else if (type === 'return') {
  56. apiGetReturnWay().then(({ code = -1, data = [] }) => {
  57. if (code === consts.RET_CODE.SUCCESS) {
  58. const options = data.map((item: string) => (
  59. <Option key={item} value={item}>
  60. {item}
  61. </Option>
  62. ))
  63. setOptions(options)
  64. }
  65. })
  66. form.setFieldsValue({ contractsId: contractReturnStore.contract.id })
  67. } else {
  68. form.setFieldsValue({ id: contractReturnStore.contract.id })
  69. }
  70. }
  71. }, [ visible ])
  72. const autoCode = async () => {
  73. const ruleArr = await handleAutoCode(tenderStore.tender.bidsectionId, contractType === 'income' ? 'contractReturnRule' : 'contractPaidRule')
  74. form.setFieldsValue({ code: ruleArr.join('-') })
  75. }
  76. // 处理添加回款的金额不应该超出最大值
  77. const handleReturnPrice = (e: ChangeEvent<HTMLInputElement>) => {
  78. const maxPrice = parseFloat(contractReturnStore.contract.price) - parseFloat(contractReturnStore.contract.returned)
  79. if (parseFloat(e.target.value) > maxPrice) {
  80. form.setFieldsValue({ price: maxPrice })
  81. }
  82. }
  83. return (
  84. <Modal
  85. getContainer={false}
  86. visible={visible}
  87. title={modalObj[type]?.title}
  88. onCancel={onCancel}
  89. footer={
  90. <div className="pi-justify-end">
  91. {type === 'update' ? (
  92. <Authorization type="contract" auth="delete">
  93. <Button type="primary" key="delete" size="small" danger onClick={() => reload('del')}>
  94. 删除合同
  95. </Button>
  96. </Authorization>
  97. ) : null}
  98. <Button type="default" size="small" key="cancel" className="pi-btn-secondary" onClick={onCancel}>
  99. {modalObj[type]?.cancelText}
  100. </Button>
  101. <Button
  102. type="primary"
  103. size="small"
  104. key="ok"
  105. loading={confirmLoading}
  106. danger={type === 'del'}
  107. onClick={() => {
  108. form
  109. .validateFields()
  110. .then(values => {
  111. form.resetFields()
  112. if (type === 'update') {
  113. values.signerTime = dayjsFormat(values.signerTime, 'YYYY-MM-DD HH:mm:ss')
  114. }
  115. if (type === 'del') {
  116. delete values.warningText
  117. }
  118. if (type === 'return') {
  119. values.time = dayjsFormat(values.time, 'YYYY-MM-DD HH:mm:ss')
  120. }
  121. onConfirm(values, type)
  122. })
  123. .catch(info => {
  124. console.error('Validate Failed:', info)
  125. })
  126. }}>
  127. {modalObj[type]?.okText}
  128. </Button>
  129. </div>
  130. }>
  131. <Form form={form} layout="vertical" style={type === 'update' ? { maxHeight: '482px', overflowY: 'scroll', paddingRight: 5 } : { overflow: 'hidden' }}>
  132. <Form.Item name="bidsectionId" hidden>
  133. <Input />
  134. </Form.Item>
  135. {/* <Form.Item name="treeId" label="合同劳务" hidden>
  136. <Tree showLine={true} treeData={contractReturnStore.tree} />
  137. </Form.Item> */}
  138. <Form.Item name="treeId" label="合同劳务" hidden>
  139. <Input />
  140. </Form.Item>
  141. {type === 'create' ? (
  142. <>
  143. <Form.Item name="code" label="合同编号" rules={[ { required: true, message: '请输入合同编号' } ]} className={styles.contractFormItem}>
  144. <Input
  145. addonAfter={
  146. <span className="pi-pd-lr-11" onClick={() => autoCode()}>
  147. 自动编号
  148. </span>
  149. } />
  150. </Form.Item>
  151. <Form.Item name="name" label="合同名称" rules={[ { required: true, message: '请输入合同名称' } ]}>
  152. <Input placeholder="输入合同名称" />
  153. </Form.Item>
  154. {/* <Form.Item name="contractsType" label="合同类型" rules={[ { required: true, message: '请选择合同类型' } ]}>
  155. <Select showSearch>
  156. <Option value={1}>支出合同</Option>
  157. <Option value={2}>收入合同</Option>
  158. </Select>
  159. </Form.Item> */}
  160. <Form.Item name="price" label="合同金额" rules={[ { required: true, message: '请输入合同金额' } ]}>
  161. <Input type="number" placeholder="输入合同金额" addonAfter={<span>元</span>} />
  162. </Form.Item>
  163. </>
  164. ) : (
  165. ''
  166. )}
  167. {type === 'update' ? (
  168. <>
  169. <Form.Item name="content" label="项目内容" rules={[ { required: true, message: '请输入项目内容' } ]}>
  170. <Input />
  171. </Form.Item>
  172. <Form.Item name="name" label="合同名称" rules={[ { required: true, message: '请输入项目内容' } ]}>
  173. <Input />
  174. </Form.Item>
  175. <Form.Item name="price" label="合同金额" rules={[ { required: true, message: '请输入项目金额' } ]}>
  176. <Input />
  177. </Form.Item>
  178. <Form.Item name="partyA" label="甲方" rules={[ { required: true, message: '请输入甲方' } ]}>
  179. <Input />
  180. </Form.Item>
  181. <Form.Item name="partyASigner" label="甲方签约人" rules={[ { required: true, message: '请输入甲方签约人' } ]}>
  182. <Input />
  183. </Form.Item>
  184. <Form.Item name="partyB" label="乙方" rules={[ { required: true, message: '请输入乙方' } ]}>
  185. <Input />
  186. </Form.Item>
  187. <Form.Item name="partyBSigner" label="乙方签约人" rules={[ { required: true, message: '请输入乙方签约人' } ]}>
  188. <Input />
  189. </Form.Item>
  190. <Form.Item name="signerTime" label="合同签约日期" rules={[ { required: true, message: '请选择签约日期' } ]}>
  191. <DatePicker allowClear locale={locale} className="pi-width-100P" />
  192. </Form.Item>
  193. <Form.Item name="remarks" label="备注">
  194. <Input.TextArea maxLength={100} />
  195. </Form.Item>
  196. </>
  197. ) : (
  198. ''
  199. )}
  200. {type === 'close' ? (
  201. <>
  202. <Form.Item name="id" hidden>
  203. <Input />
  204. </Form.Item>
  205. <span>关闭后,合同将锁定,无法进行编辑、上传文件等操作。</span>
  206. </>
  207. ) : (
  208. ''
  209. )}
  210. {type === 'unlock' ? (
  211. <>
  212. <Form.Item name="id" hidden>
  213. <Input />
  214. </Form.Item>
  215. <span>解锁后,合同将锁定,无法进行编辑、上传文件等操作。</span>
  216. </>
  217. ) : (
  218. ''
  219. )}
  220. {type === 'del' ? (
  221. <>
  222. <Form.Item name="id" hidden>
  223. <Input />
  224. </Form.Item>
  225. <p className="mb-2">删除后,数据无法恢复,请谨慎操作。</p>
  226. <p className="mb-2">
  227. 请在下方文本框输入文本「<span className="pi-red">确认删除本合同</span>」,以此确认删除操作。
  228. </p>
  229. <Form.Item
  230. name="warningText"
  231. rules={[
  232. () => ({
  233. validator(rule, value) {
  234. if (!value || value !== '确认删除本合同') {
  235. return Promise.reject('请按照提示信息进行删除操作!')
  236. }
  237. return Promise.resolve()
  238. }
  239. })
  240. ]}>
  241. <Input placeholder="输入文本, 确认删除" />
  242. </Form.Item>
  243. </>
  244. ) : (
  245. ''
  246. )}
  247. {type === 'return' ? (
  248. <>
  249. <Form.Item name="contractsId" hidden>
  250. <Input />
  251. </Form.Item>
  252. <Form.Item name="time" label="回款日期" rules={[ { required: true, message: '请选择回款日期' } ]}>
  253. <DatePicker allowClear locale={locale} className="pi-width-100P" />
  254. </Form.Item>
  255. <Form.Item name="price" label="回款金额" rules={[ { required: true, message: '请选择回款金额' } ]}>
  256. <Input onChange={handleReturnPrice}/>
  257. </Form.Item>
  258. <Form.Item name="way" label="支付方式" rules={[ { required: true, message: '请选择回款方式' } ]}>
  259. <Select>{options}</Select>
  260. </Form.Item>
  261. <Form.Item name="remarks" label="备注">
  262. <Input.TextArea maxLength={100} />
  263. </Form.Item>
  264. </>
  265. ) : (
  266. ''
  267. )}
  268. </Form>
  269. </Modal>
  270. )
  271. }
  272. export default ContractModal