index.tsx 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. import React, { useCallback, useEffect, useState } from 'react'
  2. import Tables from '@/components/Tables'
  3. import HeaderForm from '@/components/Formitem'
  4. import { Card, Modal, message, Button, Space, Upload, Drawer } from 'antd'
  5. import columns from './tableConfig'
  6. import columnsRoi from './tableConfigRoi'
  7. import config from './headerConfig'
  8. import formConfig from './formConfig'
  9. import formConfigRoi from './formConfigRoi'
  10. import { addWorks, deleteWorks, editWorks, editbookParams, getBookList, allBook, setConfigTypeApi, getBooktypeList, setChannelApi, importExcle, downLoadTem, exportExcle, bookRatioList, getBookAll, addRatio, deleteRatio } from '@/services/operating/book'
  11. import { useAjax } from '@/Hook/useAjax'
  12. import { DownloadOutlined, FormOutlined, UploadOutlined } from '@ant-design/icons'
  13. import { RcCustomRequestOptions } from 'antd/lib/upload/interface'
  14. import { useAccess } from 'umi'
  15. const Book: React.FC = () => {
  16. const [queryFrom, setQueryFrom] = useState<{ bookName?: string, status?: string, platformId?: string, typeId?: number | string, pageNum: number, pageSize: number }>({ pageNum: 1, pageSize: 20 })
  17. const [visible, setVisible] = useState(false)//弹窗
  18. const [visibleRoi, setVisibleRoi] = useState(false)// 新增or修改ROI弹窗
  19. const [roiVisible, setRoiVisible] = useState(false)//书籍卡点roi
  20. const [title, setTitle] = useState<string>('')//model标题
  21. const [platform, setPlatform] = useState<any[]>([])//平台信息
  22. const [bookify, setBookify] = useState<any[]>([])//分类信息
  23. const [book, setBook] = useState<any[]>([])//所有书
  24. const [defaultProps, setDefaultProps] = useState<editbookParams | {}>({})//默认值
  25. const [defaultRoiProps, setDefaultRoiProps] = useState<{ bookId: number, nodePrice: number, effectDay: string, overDay: string, type: string } | {}>({
  26. bookId: undefined,
  27. nodePrice: undefined,
  28. effectDay: undefined,
  29. overDay: undefined,
  30. type: undefined
  31. })//默认值
  32. const [submit, setSubmit] = useState<() => Promise<any>>()//存放formsubmit
  33. const callack = useCallback((fnc: () => Promise<any>) => { setSubmit(fnc) }, [])//form回调映射submit
  34. const [btnLoding, setBtnLoding] = useState<boolean>(false)//按钮loding
  35. const [btnRoiLoding, setBtnRoiLoding] = useState<boolean>(false)//按钮loding
  36. const [btnUploadLoding, setBtnUploadLoding] = useState<boolean>(false)//按钮loding
  37. const addWorksUse = useAjax((params: any) => addWorks(params))//添加请求
  38. const delData = useAjax((id: number) => deleteWorks(id))//删除请求
  39. const delDataRoi = useAjax((id: number) => deleteRatio(id))//删除请求
  40. const editData = useAjax((params: any) => editWorks(params))//编辑请求
  41. const getBookData = useAjax((params: { bookName?: string, status?: string, platformId?: string, pageNum: number, pageSize: number }) => getBookList(params))//搜索列表
  42. const allBookUse = useAjax(() => allBook())//添加请求
  43. const getBookify = useAjax(() => getBooktypeList())//搜索列表
  44. const setChannel = useAjax((params: { bookId: number, channel: string | null }) => setChannelApi(params))//搜索列表
  45. const setConfigType = useAjax((params: { bookId: number, typeId: number | null }) => setConfigTypeApi(params))//搜索列表
  46. const excleImport = useAjax((data: FormDataEntryValue) => importExcle(data), { msgNmae: "导入" })//搜索列表
  47. const excleExport = useAjax((data: any) => exportExcle(data), { formatResult: true })//导出
  48. const temDownLoad = useAjax(() => downLoadTem(), { formatResult: true })//模板下载
  49. const getBookRatioList = useAjax((params: { bookId?: number, pageNum: number, pageSize: number }) => bookRatioList(params))//ROI列表
  50. const [roiQueryFrom, setRoiQueryFrom] = useState<{ bookId?: number, pageNum: number, pageSize: number }>({ bookId: undefined, pageNum: 1, pageSize: 20 }) // ROI列表参数
  51. const [ratioData, setRatioData] = useState<any[]>([])//ROI数据
  52. const [ratio, setRatio] = useState<any>({})//ROI第一条数据数据
  53. const allBookData = useAjax(() => getBookAll())//添加请求
  54. const addRatioData = useAjax((params: { bookId: number, nodePrice: number, effectDay: string, overDay: string, type: string }) => addRatio(params))//添加请求
  55. const access = useAccess()
  56. /**显示 */
  57. let showModal = useCallback(() => {
  58. setTitle('添加')//设置标题
  59. setVisible(true)//开启弹窗
  60. }, [])
  61. /**隐藏 */
  62. let hideModal = useCallback(() => {
  63. setDefaultProps({})//清空默认值
  64. setTitle('')//清空标题
  65. setVisible(false)//关闭弹窗
  66. }, [])
  67. /**ROI修改or新增显示 */
  68. let showRoiModal = useCallback(() => {
  69. setVisibleRoi(true)//开启弹窗
  70. }, [])
  71. /**ROI修改or新增隐藏 */
  72. let hideRoiModal = useCallback(() => {
  73. setDefaultRoiProps({
  74. bookId: undefined,
  75. nodePrice: undefined,
  76. // ratio: undefined,
  77. effectDay: undefined,
  78. overDay: undefined,
  79. type: undefined
  80. })//清空默认值
  81. setVisibleRoi(false)//关闭弹窗
  82. }, [])
  83. /**ROI显示 */
  84. let showDrawer = useCallback((bookId: number) => {
  85. setRatioData([])
  86. setRoiQueryFrom({ ...roiQueryFrom, bookId })
  87. setDefaultRoiProps({ ...defaultRoiProps, bookId: bookId })
  88. setRoiVisible(true)//开启弹窗
  89. }, [])
  90. /**ROI隐藏 */
  91. let hideDrawer = useCallback(() => {
  92. setRoiVisible(false)
  93. }, [])
  94. /** 时间格式化 */
  95. let formatDate = (cellValue: any) => {
  96. if (cellValue == null || cellValue == "") return "";
  97. var date = new Date(cellValue)
  98. var year = date.getFullYear()
  99. var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
  100. var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
  101. var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
  102. var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
  103. var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
  104. return year + '' + month + '' + day + '' + hours + '' + minutes + '' + seconds
  105. }
  106. let downloadFile = (data: any, type: any, fileName: string) => {
  107. let blob = new Blob([data], { type: `application/${type};charset=utf-8` });
  108. let downloadElement = document.createElement('a');
  109. let href = window.URL.createObjectURL(blob);
  110. downloadElement.href = href;
  111. downloadElement.download = fileName;
  112. document.body.appendChild(downloadElement);
  113. downloadElement.click();
  114. document.body.removeChild(downloadElement);
  115. window.URL.revokeObjectURL(href);
  116. }
  117. /** 导出 */
  118. let excleExportHandle = useCallback(() => {
  119. exportExcle(queryFrom).then(res=>{
  120. downloadFile(res, 'octet-stream', formatDate(new Date()) + ".xlsx")
  121. })
  122. }, [queryFrom])
  123. /** 模板下载 */
  124. let downloadtem = useCallback(async () => {
  125. downLoadTem().then(res=>{
  126. downloadFile(res, 'octet-stream', formatDate(new Date()) + ".xlsx")
  127. })
  128. }, [])
  129. /**头部搜索 */
  130. let headerSeek = useCallback((bookName: string) => {
  131. if (bookName) {
  132. setQueryFrom({ ...queryFrom, bookName, pageNum: 1 })
  133. } else {
  134. setQueryFrom({ ...queryFrom, bookName: "", pageNum: 1 })
  135. }
  136. }, [queryFrom])
  137. let headerSeekType = useCallback((status: string) => {
  138. if (status) { // status
  139. setQueryFrom({ ...queryFrom, status, pageNum: 1 })
  140. } else {
  141. let data = { ...queryFrom }
  142. delete data.status
  143. setQueryFrom({ ...queryFrom, pageNum: 1 })
  144. }
  145. }, [queryFrom])
  146. let headerPlatform = useCallback((platformId: string) => {
  147. if (platformId) {
  148. setQueryFrom({ ...queryFrom, platformId, pageNum: 1 })
  149. } else {
  150. setQueryFrom({ ...queryFrom, platformId: "", pageNum: 1 })
  151. }
  152. }, [queryFrom])
  153. let handleTypeId = useCallback((id: number) => {
  154. setQueryFrom({ ...queryFrom, typeId: id ? id : "", pageNum: 1 })
  155. }, [queryFrom])
  156. /**新增请求 */
  157. let handleOk = useCallback(() => {
  158. (submit as () => Promise<any>)().then(res => {
  159. if (res) {
  160. setBtnLoding(true);
  161. let id = (defaultProps as editbookParams).id
  162. if (id) {
  163. let def = (defaultProps as editbookParams)
  164. let query = {
  165. id,
  166. platformId: def?.platformId,
  167. status: def?.status,
  168. author: def?.author ? def?.author : "",
  169. bookName: def?.bookName ? def.bookName : "",
  170. protagonist: def.protagonist ? def.protagonist : "",
  171. typeId: def.typeId ? def.typeId : "",
  172. channel: def.channel ? def.channel : "",
  173. wordCount: def.wordCount ? def.wordCount : "",
  174. source: def.source ? def.source : "",
  175. nodePrice: def.nodePrice ? def.nodePrice : "",
  176. ratio: def.ratio ? def.ratio : "",
  177. remark: def.remark ? def.remark : ""
  178. }
  179. editData.run({ ...query, ...res }).then(r => {
  180. setBtnLoding(false)
  181. getBookData.run(queryFrom)
  182. hideModal()
  183. message.success('编辑成功', 2)
  184. })
  185. } else {
  186. addWorksUse.run(res).then(res => {
  187. setBtnLoding(false)
  188. getBookData.run(queryFrom)
  189. hideModal()
  190. message.success('添加成功', 2)
  191. })
  192. }
  193. }
  194. })
  195. }, [submit])
  196. let handleRoiOk = useCallback(() => {
  197. (submit as () => Promise<any>)().then(res => {
  198. if (res) {
  199. let { nodePrice } = res
  200. setBtnRoiLoding(true)
  201. addRatioData.run({ ...res, nodePrice: nodePrice }).then(res => {
  202. setBtnRoiLoding(false)
  203. getBookData.run(queryFrom)
  204. setRoiQueryFrom({ ...roiQueryFrom, pageNum: 1, pageSize: 20 })
  205. hideRoiModal()
  206. message.success('添加编辑成功', 2)
  207. })
  208. }
  209. })
  210. }, [submit])
  211. /**编辑 */
  212. let edit = useCallback((props: { id: number, platformName: string, remark: string }) => {
  213. setDefaultProps(props)
  214. setTitle('编辑')
  215. setVisible(true)
  216. }, [title, defaultProps, visible])
  217. /** roi编辑/修改 */
  218. let editRoi = useCallback(() => {
  219. if (Object.keys(ratio).length > 0) {
  220. let { nodePrice } = ratio
  221. setDefaultRoiProps({ ...ratio, nodePrice: nodePrice ? Number(nodePrice) : undefined })
  222. } else {
  223. setDefaultRoiProps({ ...defaultRoiProps, effectDay: new Date })
  224. }
  225. showRoiModal()
  226. }, [defaultRoiProps, ratio])
  227. /**删除 */
  228. let delRoi = useCallback((id: number) => {
  229. delDataRoi.run(id).then(res => {
  230. if (res) {
  231. getBookData.run(queryFrom)
  232. setRoiQueryFrom({ ...roiQueryFrom, pageNum: 1, pageSize: 20 })
  233. message.success('删除成功', 2)
  234. }
  235. })
  236. }, [roiQueryFrom])
  237. /**删除 */
  238. let del = useCallback((id: number) => {
  239. delData.run(id).then(res => {
  240. if (res) {
  241. getBookData.run(queryFrom)
  242. message.success('删除成功', 2)
  243. }
  244. })
  245. }, [])
  246. /**分页 */
  247. let pageChange = useCallback((page: string | number, pageSize?: string | number) => {
  248. let query = { pageNum: page as number, pageSize: pageSize as number }
  249. setQueryFrom({ ...queryFrom, ...query })
  250. // getBookData.run({ ...queryFrom, ...query })
  251. }, [queryFrom])
  252. /**ROI分页 */
  253. let pageRoiChange = useCallback((page: string | number, pageSize?: string | number) => {
  254. let query = { pageNum: page as string, pageSize: pageSize as string }
  255. getBookRatioList.run({ ...roiQueryFrom, ...query }).then(res => {
  256. let records = res?.records.map((item: any, index: number) => {
  257. if (page == 1 && index === 0) {
  258. setRatio(item)
  259. item.index = "ok"
  260. } else {
  261. item.index = "no"
  262. }
  263. return item
  264. })
  265. setRatioData(records)
  266. })
  267. }, [ratio, ratioData])
  268. //副作用执行
  269. useEffect(() => {
  270. allBookUse.run().then(res => {
  271. res = res?.map((item: any) => {
  272. item.value = item.id + ""
  273. item.text = item.platformName
  274. return item
  275. })
  276. setPlatform(res)
  277. })
  278. getBookify.run().then(res => {
  279. res = res?.map((item: any) => {
  280. item.value = item.id + ""
  281. item.text = item.name
  282. return item
  283. })
  284. setBookify(res)
  285. })
  286. allBookData.run().then(res => {
  287. res = res?.map((item: any) => {
  288. item.value = item.id
  289. item.text = item.bookName
  290. return item
  291. })
  292. setBook(res)
  293. })
  294. }, [])
  295. useEffect(() => {
  296. if ('bookId' in roiQueryFrom && roiQueryFrom?.bookId) {
  297. getBookRatioList.run(roiQueryFrom).then(res => {
  298. setRatio({})
  299. let { pageNum } = roiQueryFrom
  300. let records = res?.records.map((item: any, index: number) => {
  301. if (pageNum === 1 && index === 0) {
  302. setRatio(item)
  303. item.index = "ok"
  304. } else {
  305. item.index = "no"
  306. }
  307. return item
  308. })
  309. setRatioData(records)
  310. })
  311. }
  312. }, [roiQueryFrom])
  313. useEffect(() => {
  314. getBookData.run(queryFrom)
  315. }, [queryFrom])
  316. const setData = (bookId: number, value: any, type: '1' | "2") => {
  317. if (type === '1') {
  318. setChannel.run({ bookId, channel: value }).then(res => {
  319. getBookData.refresh()
  320. })
  321. } else {
  322. setConfigType.run({ bookId, typeId: value }).then(res => {
  323. getBookData.refresh()
  324. })
  325. }
  326. }
  327. return <Card>
  328. <HeaderForm formConfig={config(showModal, headerSeek, headerSeekType, headerPlatform, platform, access, bookify, handleTypeId)} flow='row' />
  329. <Space style={{ marginBottom: "10px" }}>
  330. <Button type='primary' onClick={downloadtem}>模板下载</Button>
  331. {access['小说导入'] && <Upload
  332. accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
  333. action=""
  334. listType="text"
  335. onChange={() => { }}
  336. multiple={true}
  337. showUploadList={false}
  338. customRequest={(options: RcCustomRequestOptions) => {
  339. setBtnUploadLoding(true)
  340. let formData = new FormData();
  341. formData.append("file", options.file);
  342. excleImport.run(formData).then(res => {
  343. getBookData.run(queryFrom)
  344. setBtnUploadLoding(false)
  345. }).catch(() => {
  346. setBtnUploadLoding(false)
  347. })
  348. }}
  349. ><Button type='primary' icon={<UploadOutlined />} loading={btnUploadLoding} >导入</Button></Upload>}
  350. <Button type='primary' onClick={excleExportHandle}><DownloadOutlined />导出</Button>
  351. </Space>
  352. <Tables
  353. columns={columns(edit, del, showDrawer, access, setData, bookify)}
  354. dataSource={getBookData?.data?.records}
  355. total={getBookData?.data?.total}
  356. pageChange={pageChange}
  357. sizeChange={pageChange}
  358. size="small"
  359. bordered
  360. loading={getBookData?.loading}
  361. />
  362. <Modal
  363. title={`${title}书籍`}
  364. visible={visible}
  365. okText="确认"
  366. cancelText="取消"
  367. onCancel={hideModal}
  368. onOk={handleOk}
  369. confirmLoading={btnLoding}
  370. destroyOnClose={true}
  371. width={550}
  372. >
  373. <HeaderForm formConfig={formConfig(platform, bookify, access)} flow='row' getFormSubmit={callack} defaultProps={defaultProps} labelCol={{ span: 24 }} ew />
  374. </Modal>
  375. <Drawer
  376. title="书籍卡点管理"
  377. placement="right"
  378. closable={false}
  379. onClose={hideDrawer}
  380. visible={roiVisible}
  381. width={700}
  382. >
  383. <div>
  384. <Button type='primary' onClick={editRoi} style={{ marginBottom: '10px' }}><FormOutlined />新增/编辑</Button>
  385. <Tables
  386. columns={columnsRoi(delRoi)}
  387. dataSource={ratioData}
  388. total={getBookRatioList?.data?.total}
  389. pageChange={pageRoiChange}
  390. sizeChange={pageRoiChange}
  391. size="small"
  392. bordered
  393. loading={getBookRatioList?.loading}
  394. />
  395. </div>
  396. </Drawer>
  397. <Modal
  398. title="新增/编辑书籍卡点"
  399. visible={visibleRoi}
  400. okText="确认"
  401. cancelText="取消"
  402. onCancel={hideRoiModal}
  403. onOk={handleRoiOk}
  404. confirmLoading={btnRoiLoding}
  405. destroyOnClose={true}
  406. width={350}
  407. >
  408. <HeaderForm formConfig={formConfigRoi(book)} flow='row' getFormSubmit={callack} defaultProps={defaultRoiProps} labelCol={{ span: 24 }} ew />
  409. </Modal>
  410. </Card>
  411. }
  412. export default Book