index.tsx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
  2. import styles from './index.module.scss'
  3. import { pageTitTxtObj } from '../../D4impStor/D4edit'
  4. import { useParams } from 'react-router-dom'
  5. import { Button, Cascader, DatePicker, Input, Radio, Select } from 'antd'
  6. import { B3aForm1 } from '@/pages/B_enterTibet/B3_4page/B3edit/data'
  7. import dayjs from 'dayjs'
  8. import Z3upFiles from '@/components/Z3upFiles'
  9. import ZRichTexts from '@/components/ZRichTexts'
  10. import { MessageFu } from '@/utils/message'
  11. import history, { btnFlagFu2, cascaderObjFu, openGoodsInfoFu } from '@/utils/history'
  12. import B3GaddNow from '@/pages/B_enterTibet/B3goodsTable/B3GaddNow'
  13. import MyTable from '@/components/MyTable'
  14. import classNames from 'classnames'
  15. import MyPopconfirm from '@/components/MyPopconfirm'
  16. import { D4goodsTableC, statusObj } from '@/utils/tableData'
  17. import Y1cathet from '@/pages/Y_goodsDetails/Y1cathet'
  18. import X3auditInfo from '@/pages/X_stock/X3auditInfo'
  19. import B3flowTable from '@/pages/B_enterTibet/B3flowTable'
  20. import { FourTableType } from '@/pages/B_enterTibet/B3_4page/type'
  21. import { useDispatch, useSelector } from 'react-redux'
  22. import { D2_APIgetList } from '@/store/action/D2storSet'
  23. import { RootState } from '@/store'
  24. import {
  25. D6_APIcreate,
  26. D6_APIdel,
  27. D6_APIgetInfo,
  28. D6_APIrevocation,
  29. D6_APIsaveApply,
  30. D6_APIsaveAudit,
  31. D6_APIsaveCreate,
  32. D6_APIsaveDraft
  33. } from '@/store/action/D6putsStor'
  34. import { C1GoodType } from '@/pages/A3_ledger/C1ledger/type'
  35. import { EXbtnFu } from '@/utils/EXBtn'
  36. import D6impRelation from '../D6impRelation'
  37. function D6edit() {
  38. const { key, id } = useParams<any>()
  39. // key:1 新增 2编辑 3审批 4查看
  40. // 滚到顶部
  41. const sollrDom = useRef<HTMLDivElement>(null)
  42. // 顶部数据
  43. const [topInfo, setTopInfo] = useState({} as FourTableType)
  44. // 出库库房数组信息
  45. const dispatch = useDispatch()
  46. useEffect(() => {
  47. dispatch(D2_APIgetList({ pageNum: 1, pageSize: 99999 }))
  48. }, [dispatch])
  49. const { list: storSetList } = useSelector((state: RootState) => state.D2storSet.tableInfo)
  50. // 库房负责人txt
  51. const managerUser = useMemo(() => {
  52. let txt = ''
  53. if (topInfo.storageId && storSetList.length) {
  54. let obj = storSetList.find(v => v.id === topInfo.storageId)
  55. if (obj) txt = obj.managerUser
  56. }
  57. return txt
  58. }, [storSetList, topInfo.storageId])
  59. // 创建订单
  60. const creatFu = useCallback(async () => {
  61. const res = await D6_APIcreate()
  62. if (res.code === 0) {
  63. setTopInfo({ ...res.data, isReturn: 0 })
  64. }
  65. }, [])
  66. // 获取详情
  67. const getInfoFu = useCallback(async () => {
  68. const res = await D6_APIgetInfo(id)
  69. if (res.code === 0) {
  70. setTopInfo(res.data)
  71. // 设置富文本
  72. ZRichTextRef.current?.ritxtShowFu(JSON.parse(res.data.rtf) || '{}')
  73. }
  74. }, [id])
  75. useEffect(() => {
  76. if (key === '1') creatFu()
  77. else getInfoFu()
  78. if (sollrDom.current) sollrDom.current.scrollTop = 0
  79. }, [creatFu, getInfoFu, key])
  80. // 上传附件的ref
  81. const filesRef = useRef<any>(null)
  82. // const filesRes = filesRef.current.filesIdRes();
  83. // 富文本的ref
  84. const ZRichTextRef = useRef<any>(null)
  85. // 审批意见的ref
  86. const ZAuditRef = useRef<any>(null)
  87. const pageTitTxt = useMemo(() => {
  88. return Reflect.get(pageTitTxtObj, key)
  89. }, [key])
  90. const timeChange = useCallback(
  91. (e: any) => {
  92. setTopInfo({ ...topInfo, date: dayjs(e).format('YYYY-MM-DD') })
  93. },
  94. [topInfo]
  95. )
  96. const checkDataFu = useCallback(() => {
  97. if (!topInfo.name) {
  98. MessageFu.warning('申请名称不能为空')
  99. return true
  100. }
  101. if (!topInfo.sonTypeName) {
  102. MessageFu.warning('请选择业务类型')
  103. return true
  104. }
  105. if (!topInfo.storageId) {
  106. MessageFu.warning('请选择出库库房')
  107. return true
  108. }
  109. return false
  110. }, [topInfo])
  111. // 审批的sta
  112. const [auditSta, setAuDitSta] = useState('')
  113. // 新增的底部按钮点击
  114. const btnClickFu = useCallback(
  115. async (val: '草稿' | '创建' | '保存' | '审批') => {
  116. if (checkDataFu()) return
  117. if (val !== '草稿') {
  118. if (!topInfo.goods || (topInfo.goods && topInfo.goods.length === 0)) {
  119. return MessageFu.warning('请添加藏品')
  120. }
  121. }
  122. if (val === '审批') {
  123. // console.log('审批信息富文本', rtf2)
  124. if (!auditSta) {
  125. if (sollrDom.current) sollrDom.current.scrollTop = 0
  126. return MessageFu.warning('请选择审批结果')
  127. }
  128. const rtf2 = ZAuditRef.current?.resData()
  129. const res = await D6_APIsaveAudit({
  130. orderId: topInfo.id,
  131. rtfOpinion: rtf2,
  132. status: auditSta === '同意' ? 1 : 2
  133. })
  134. if (res.code === 0) {
  135. MessageFu.success('审批成功')
  136. // 跳详情页
  137. history.push(`/putsStor_edit/4/${topInfo.id}`)
  138. }
  139. } else {
  140. const rtf1 = ZRichTextRef.current?.fatherBtnOkFu() || { flag: true }
  141. // console.log('申请信息富文本', JSON.stringify(rtf1.val || ''))
  142. // 上传附件
  143. const filesRes = filesRef.current.filesIdRes()
  144. const obj = {
  145. ...topInfo,
  146. fileIds: filesRes.join(','),
  147. rtf: JSON.stringify(rtf1.val || ''),
  148. goodsIds: topInfo.goods.map(v => v.id).join(',')
  149. }
  150. // console.log(123, obj)
  151. // if (1 + 1 === 2) return
  152. if (val === '草稿') {
  153. // 存草稿 当前页保存 不跳转
  154. const res = await D6_APIsaveDraft(obj)
  155. if (res.code === 0) {
  156. MessageFu.success('草稿保存成功')
  157. }
  158. } else {
  159. const res = val === '创建' ? await D6_APIsaveCreate(obj) : await D6_APIsaveApply(obj)
  160. if (res.code === 0) {
  161. MessageFu.success(`${val}成功`)
  162. // 跳到详情页
  163. history.push(`/putsStor_edit/4/${topInfo.id}`)
  164. }
  165. }
  166. }
  167. },
  168. [auditSta, checkDataFu, topInfo]
  169. )
  170. // 打开侧边栏
  171. const [cathet, setCathet] = useState(0)
  172. const startBtn = useMemo(() => {
  173. return [
  174. {
  175. title: '藏品编号',
  176. render: (item: C1GoodType) => {
  177. return (
  178. <span
  179. onClick={() => setCathet(item.id)}
  180. className={classNames('D1GtNum', item.id === cathet ? 'D1GtNumAc' : '')}
  181. >
  182. {item.num}
  183. </span>
  184. )
  185. }
  186. }
  187. ]
  188. }, [cathet])
  189. const tableLastBtn = useMemo(() => {
  190. return [
  191. {
  192. title: '出库位置',
  193. width: 200,
  194. render: (item: C1GoodType) => {
  195. return item.siteStr ? item.siteStr.replaceAll(',', ' / ') : '(空)'
  196. }
  197. },
  198. {
  199. title: '操作',
  200. render: (item: C1GoodType) => {
  201. return (
  202. <>
  203. <Button size='small' type='text' onClick={() => openGoodsInfoFu(item.id)}>
  204. 查看
  205. </Button>
  206. {['3', '4'].includes(key) ? null : (
  207. <MyPopconfirm
  208. txtK='删除'
  209. onConfirm={() =>
  210. setTopInfo({
  211. ...topInfo,
  212. goods: topInfo.goods.filter(v => v.id !== item.id)
  213. })
  214. }
  215. />
  216. )}
  217. </>
  218. )
  219. }
  220. }
  221. ]
  222. }, [key, topInfo])
  223. // 点击新增
  224. const [nowSta, setNowSta] = useState({ key: '', id: '' })
  225. // 查看的按钮创建-提交-撤回
  226. const lookBtnFu = useCallback(
  227. async (val: '创建' | '提交' | '撤回') => {
  228. if (val !== '撤回') {
  229. if (!topInfo.goods || (topInfo.goods && topInfo.goods.length === 0)) {
  230. return MessageFu.warning('请添加藏品')
  231. }
  232. }
  233. const rtf1 = ZRichTextRef.current?.fatherBtnOkFu() || { flag: true }
  234. // console.log('申请信息富文本', JSON.stringify(rtf1.val || ''))
  235. // 上传附件
  236. const filesRes = filesRef.current.filesIdRes()
  237. const obj = {
  238. ...topInfo,
  239. fileIds: filesRes.join(','),
  240. rtf: JSON.stringify(rtf1.val || ''),
  241. goodsIds: topInfo.goods.map(v => v.id).join(',')
  242. }
  243. const res =
  244. val === '创建'
  245. ? await D6_APIsaveCreate(obj)
  246. : val === '提交'
  247. ? await D6_APIsaveApply(obj)
  248. : await D6_APIrevocation(id)
  249. if (res.code === 0) {
  250. if (sollrDom.current) sollrDom.current.scrollTop = 0
  251. MessageFu.success(val + '成功')
  252. getInfoFu()
  253. }
  254. },
  255. [getInfoFu, id, topInfo]
  256. )
  257. // 查看模式点击删除
  258. const delFu = useCallback(async () => {
  259. const res = await D6_APIdel(id)
  260. if (res.code === 0) {
  261. MessageFu.success('删除成功')
  262. history.push('/putsStor')
  263. }
  264. }, [id])
  265. // 查看模式点击审批 编辑
  266. const lookJumpFu = useCallback(
  267. (val: '审批' | '编辑') => {
  268. history.push(`/putsStor_edit/${val === '审批' ? 3 : 2}/${id}`)
  269. MessageFu.success(`已跳转至${val}页面`)
  270. },
  271. [id]
  272. )
  273. // 查看模式下的按钮
  274. const lookBtn = useMemo(() => {
  275. return (
  276. <>
  277. {btnFlagFu2(topInfo)['创建'] ? (
  278. <Button type='primary' onClick={() => lookBtnFu('创建')}>
  279. 创建
  280. </Button>
  281. ) : null}
  282. {btnFlagFu2(topInfo)['提交'] ? (
  283. <Button type='primary' onClick={() => lookBtnFu('提交')}>
  284. 提交
  285. </Button>
  286. ) : null}
  287. {btnFlagFu2(topInfo)['撤回'] ? (
  288. <MyPopconfirm
  289. txtK='撤回'
  290. onConfirm={() => lookBtnFu('撤回')}
  291. Dom={
  292. <Button type='primary' danger>
  293. 撤回
  294. </Button>
  295. }
  296. />
  297. ) : null}
  298. {btnFlagFu2(topInfo)['审批'] ? (
  299. <Button type='primary' onClick={() => lookJumpFu('审批')}>
  300. 审批
  301. </Button>
  302. ) : null}
  303. {btnFlagFu2(topInfo)['编辑'] ? (
  304. <Button type='primary' onClick={() => lookJumpFu('编辑')}>
  305. 编辑
  306. </Button>
  307. ) : null}
  308. {btnFlagFu2(topInfo)['重新提交'] ? (
  309. <Button type='primary' onClick={() => lookBtnFu('提交')}>
  310. 重新提交
  311. </Button>
  312. ) : null}
  313. {EXbtnFu(topInfo)}
  314. {btnFlagFu2(topInfo)['删除'] ? (
  315. <MyPopconfirm
  316. txtK='删除'
  317. onConfirm={() => delFu()}
  318. Dom={
  319. <Button type='primary' danger>
  320. 删除
  321. </Button>
  322. }
  323. />
  324. ) : null}
  325. <Button onClick={() => history.push('/putsStor')}>返回</Button>
  326. </>
  327. )
  328. }, [delFu, lookBtnFu, lookJumpFu, topInfo])
  329. return (
  330. <div className={styles.D6edit}>
  331. <div className='pageTitle'>藏品出库-{pageTitTxt}</div>
  332. <div className='D6main' ref={sollrDom}>
  333. {['3'].includes(key) ? (
  334. <X3auditInfo
  335. dirCode='putsStor'
  336. myUrl='cms/orderOut/upload'
  337. auditSta={auditSta}
  338. auditStaFu={val => setAuDitSta(val)}
  339. ref={ZAuditRef}
  340. />
  341. ) : null}
  342. {/* 表单字段、附件等 */}
  343. <div className='D6Tit'>
  344. 申请信息
  345. {key === '1' ? null : (
  346. <Button type='dashed'>{Reflect.get(statusObj, topInfo.status)}</Button>
  347. )}
  348. </div>
  349. <div className='D6rowAll'>
  350. <div className='D6row'>
  351. <div className='D6rowll'>
  352. <span> * </span>申请名称:
  353. </div>
  354. <div className='D6rowrr'>
  355. <Input
  356. value={topInfo.name}
  357. onChange={e => setTopInfo({ ...topInfo, name: e.target.value.trim() })}
  358. readOnly={['3', '4'].includes(key)}
  359. placeholder='请输入内容'
  360. maxLength={30}
  361. showCount
  362. />
  363. </div>
  364. </div>
  365. <div className='D6row'>
  366. <div className='D6rowll'>
  367. <span> * </span>业务类型:
  368. </div>
  369. <div className='D6rowrr'>
  370. <Cascader
  371. value={topInfo.sonTypeName ? topInfo.sonTypeName.split(',') : []}
  372. onChange={e => setTopInfo({ ...topInfo, sonTypeName: e ? e.join(',') : '' })}
  373. disabled={['3', '4'].includes(key)}
  374. options={cascaderObjFu()['藏品出库']}
  375. changeOnSelect
  376. placeholder='请选择'
  377. fieldNames={{ label: 'name', value: 'id', children: 'children' }}
  378. allowClear={false}
  379. />
  380. </div>
  381. </div>
  382. {B3aForm1.map(v => (
  383. <div className='D6row' key={v.name}>
  384. <div className='D6rowll'>{v.name}:</div>
  385. <div className='D6rowrr'>
  386. {topInfo[v.key as 'name']}
  387. {['3', '4'].includes(key) && v.name === '发起人'
  388. ? ' - ' + topInfo.createTime || ''
  389. : ''}
  390. </div>
  391. </div>
  392. ))}
  393. <div className='D6row'>
  394. <div className='D6rowll'>
  395. <span> * </span>是否归还:
  396. </div>
  397. <div className='D6rowrr'>
  398. <Radio.Group
  399. disabled={['3', '4'].includes(key)}
  400. value={topInfo.isReturn}
  401. onChange={e =>
  402. setTopInfo({
  403. ...topInfo,
  404. isReturn: e.target.value,
  405. returnDate: e.target.value === 0 ? '' : topInfo.returnDate
  406. })
  407. }
  408. options={[
  409. { value: 1, label: '是' },
  410. { value: 0, label: '否' }
  411. ]}
  412. />
  413. </div>
  414. </div>
  415. <div className='D6row'>
  416. <div className='D6rowll'> 预计归还日期:</div>
  417. <div className='D6rowrr'>
  418. <DatePicker
  419. placeholder={topInfo.isReturn !== 1 ? '(空)' : '请选择日期'}
  420. disabled={['3', '4'].includes(key) || topInfo.isReturn !== 1}
  421. allowClear={true}
  422. value={topInfo.returnDate ? dayjs(topInfo.returnDate) : null}
  423. onChange={e =>
  424. setTopInfo({ ...topInfo, returnDate: e ? dayjs(e).format('YYYY-MM-DD') : '' })
  425. }
  426. />
  427. </div>
  428. </div>
  429. <div className='D6row'>
  430. <div className='D6rowll'>
  431. <span> * </span>业务日期:
  432. </div>
  433. <div className='D6rowrr'>
  434. <DatePicker
  435. disabled={['3', '4'].includes(key)}
  436. allowClear={false}
  437. value={dayjs(topInfo.date)}
  438. onChange={timeChange}
  439. />
  440. </div>
  441. </div>
  442. <div className='D6row'>
  443. <div className='D6rowll'>原因事由:</div>
  444. <div className='D6rowrr'>
  445. <Input
  446. value={topInfo.reason}
  447. onChange={e => setTopInfo({ ...topInfo, reason: e.target.value })}
  448. readOnly={['3', '4'].includes(key)}
  449. placeholder='请输入内容'
  450. maxLength={30}
  451. showCount
  452. />
  453. </div>
  454. </div>
  455. <div className='D6row D6row2'>
  456. <div className='D6rowll'>附件:</div>
  457. <div className='D6rowrr'>
  458. <Z3upFiles
  459. max={10}
  460. isLook={['3', '4'].includes(key)}
  461. ref={filesRef}
  462. fileCheck={false}
  463. dirCode='putsStor'
  464. myUrl='cms/orderOut/upload'
  465. lookData={topInfo.files || []}
  466. size={500}
  467. />
  468. </div>
  469. </div>
  470. <div className='D6row D6rowFull'>
  471. <div className='D6rowll'>备注:</div>
  472. <div className='D6rowrr'>
  473. <ZRichTexts
  474. check={false}
  475. dirCode='putsStor'
  476. myUrl='cms/orderOut/upload'
  477. isLook={['3', '4'].includes(key)}
  478. ref={ZRichTextRef}
  479. isOne={true}
  480. upAudioBtnNone={true}
  481. />
  482. </div>
  483. </div>
  484. </div>
  485. <div className='D6Tit'>库房信息</div>
  486. <div className='D6rowAll'>
  487. <div className='D6row'>
  488. <div className='D6rowll'>
  489. <span> * </span>出库库房:
  490. </div>
  491. <div className='D6rowrr'>
  492. <Select
  493. options={storSetList}
  494. value={topInfo.storageId}
  495. onChange={(storageId, arr) => {
  496. setTopInfo({ ...topInfo, storageId, goods: [] })
  497. }}
  498. disabled={['3', '4'].includes(key)}
  499. fieldNames={{ value: 'id', label: 'name' }}
  500. placeholder='请选择'
  501. />
  502. </div>
  503. </div>
  504. <div className='D6row D6row3'>
  505. <div className='D6rowll'>库房负责人:</div>
  506. <div className='D6rowrr'>{managerUser || '(空)'}</div>
  507. </div>
  508. </div>
  509. {/* 藏品清单 */}
  510. <div className='D6googsBox'>
  511. <div className='D6Tit2'>
  512. <div className='D6Tit2ll'>藏品清单</div>
  513. <div className='D6Tit2rr'>
  514. {['3', '4'].includes(key) ? null : (
  515. <Button
  516. type='primary'
  517. onClick={() => {
  518. if (!topInfo.storageId) return MessageFu.warning('请先选择出库库房')
  519. setNowSta({ key: '5', id: 'cms/orderOut/goods/getList' })
  520. }}
  521. >
  522. 新增
  523. </Button>
  524. )}
  525. </div>
  526. </div>
  527. {/* 表格 */}
  528. <MyTable
  529. list={topInfo.goods || []}
  530. columnsTemp={D4goodsTableC}
  531. startBtn={startBtn}
  532. lastBtn={tableLastBtn}
  533. pagingInfo={false}
  534. />
  535. </div>
  536. {/* 相关入库单 */}
  537. {key === '4' ? <D6impRelation list={topInfo.relatedOrder || []} /> : null}
  538. {/* 申请流程 */}
  539. {['3', '4'].includes(key) ? <B3flowTable tableArr={topInfo.audits || []} /> : null}
  540. </div>
  541. {/* 底部按钮 */}
  542. <div className='D6btn'>
  543. {key === '4' ? (
  544. lookBtn
  545. ) : (
  546. <>
  547. {key === '3' ? (
  548. <Button type='primary' onClick={() => btnClickFu('审批')}>
  549. 审批
  550. </Button>
  551. ) : (
  552. <Button type='primary' onClick={() => btnClickFu(key === '1' ? '创建' : '保存')}>
  553. {key === '1' ? '创建' : '保存'}
  554. </Button>
  555. )}
  556. {key === '1' ? (
  557. <Button type='primary' onClick={() => btnClickFu('草稿')}>
  558. 存草稿
  559. </Button>
  560. ) : null}
  561. <MyPopconfirm txtK='取消' onConfirm={() => history.push('/putsStor')} />
  562. </>
  563. )}
  564. </div>
  565. {/* 打开侧边栏 */}
  566. <Y1cathet sId={cathet} closeFu={() => setCathet(0)} />
  567. {/* 新增弹窗 */}
  568. {nowSta.id ? (
  569. <B3GaddNow
  570. nowSta={nowSta}
  571. closeFu={() => setNowSta({ key: '', id: '' })}
  572. dataResFu={data => setTopInfo({ ...topInfo, goods: data })}
  573. oldCheckArr={topInfo.goods || []}
  574. canObj={{ storageId: topInfo.storageId }}
  575. />
  576. ) : null}
  577. </div>
  578. )
  579. }
  580. const MemoD6edit = React.memo(D6edit)
  581. export default MemoD6edit