index.tsx 19 KB

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