index.tsx 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { useVirtualList } from "ahooks";
  2. import { Button, Col, Row, Image, Spin, Space, Drawer, Empty } from "antd";
  3. import { JSXElementConstructor, Key, ReactElement, ReactFragment, ReactPortal, useEffect, useMemo, useRef, useState } from "react";
  4. import { MyIcon } from "@/global";
  5. import { useToken } from "@ant-design/pro-components";
  6. function ReadBook(props: { next: (listData: { id: number }) => Promise<any>, listData: any }) {
  7. let { next, listData } = props;
  8. const divRef = useRef<HTMLDivElement>(null);
  9. let { token } = useToken()
  10. const [isFetching, setIsFetching] = useState(true);
  11. const [newData, setNewData] = useState<any>(null);
  12. const [content, setContent] = useState<any>(null)
  13. const containerRef = useRef(null);
  14. const wrapperRef = useRef(null);
  15. useEffect(() => {
  16. const handleKeyDown = (event: KeyboardEvent) => {
  17. if (divRef.current) {
  18. if (event.key === "ArrowDown") {
  19. divRef.current.scrollBy(0, 50);
  20. } else if (event.key === "ArrowUp") {
  21. divRef.current.scrollBy(0, -50);
  22. }
  23. }
  24. };
  25. window.addEventListener("keydown", handleKeyDown);
  26. return () => {
  27. window.removeEventListener("keydown", handleKeyDown);
  28. };
  29. }, []);
  30. async function getBookContent(id: any) {
  31. let content = await next(id)
  32. console.log(content)
  33. // setContent(content)
  34. }
  35. useEffect(() => {
  36. if (divRef.current) {
  37. divRef.current.scrollTop = 0
  38. }
  39. }, [content, divRef])
  40. return (
  41. listData && <div
  42. style={{ height: '85vh', overflow: 'hidden', display: 'flex', justifyContent: 'space-around' }}
  43. >
  44. <div style={{ width: '20%', flexFlow: 'column', alignItems: 'center', display: 'flex', borderRight: '1px solid #efefef' }}>
  45. <div style={{ marginBottom: 20, marginTop: 20 }}>
  46. {listData?.vipFree && <MyIcon type="icon-vipmianfei" style={{ fontSize: 70, position: 'absolute', zIndex: 1 }} />}
  47. <Image src={listData?.picUrl} style={{ width: 150 }} onError={(e: any) => {
  48. e.target.src = localStorage.getItem("nocover")
  49. }} />
  50. </div>
  51. <Row style={{ width: '80%' }} gutter={[10, 5]}>
  52. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}><span>作者</span>:</span>{listData?.authorInfo?.authorName}</Col>
  53. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}><span>类别</span>:</span>{listData?.categoryInfo?.name}</Col>
  54. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}><span>来源</span>:</span>{({ "UPLOAD": "管理员", "CREATOR": "创作者" } as any)[listData.source]}</Col>
  55. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}><span>频道</span>:</span>{listData?.corpUserName == 0 ? "男频" : "女频"}</Col>
  56. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}>标签:</span> {
  57. listData?.labelInfoList?.map((tags: { id: string, name: string }, index: number) => {
  58. return tags?.name
  59. }).join(',')
  60. }</Col>
  61. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }} ><span style={{ color: token.colorText }}><span>状态</span>:</span>{["连载中", "已完结"][listData.bookStatus]}</Col>
  62. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}>评分:</span>{listData?.score || 0}</Col>
  63. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}>点击量:</span>{listData?.visitCount || 0}</Col>
  64. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}>总字数:</span>{listData?.wordCount || 0}</Col>
  65. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}>上架状态:</span>{["上架中", "已下架"][listData.shelveStatus]}</Col>
  66. <Col span={24} style={{ fontSize: 14, color: token.colorTextSecondary }}><span style={{ color: token.colorText }}>描述:</span>{listData?.bookDesc}</Col>
  67. </Row>
  68. </div>
  69. <div
  70. style={{ overflowY: 'auto', display: 'flex', flexFlow: "column", width: '75%', paddingTop: 20, paddingBottom: 20 }}
  71. ref={divRef}
  72. >
  73. <div >
  74. {listData.list?.map((ele: any, index: number) => (
  75. <a
  76. key={index}
  77. style={{ display: 'inline-block', marginRight: ele.index % 4 === 0 ? 0 : 20, marginBottom: 10, width: 190, overflow: 'hidden' }}
  78. onClick={() => { getBookContent(ele?.chapterInfo?.id) }}
  79. >
  80. <div style={{ display: 'flex', alignItems: 'center' }}>
  81. {ele.needPay && <MyIcon type="icon-jiesuo" style={{ marginRight: 5 }} />}
  82. <span >{ele?.chapterInfo?.chapterName}</span>
  83. </div>
  84. </a>
  85. ))}
  86. {listData.list?.length === 0 && <div style={{ width: "100%", height: "100%", marginTop: "10%" }}><Empty description={<Space direction='vertical'><div>暂无章节</div></Space>} /></div>}
  87. </div>
  88. {/* 阅读小说 */}
  89. <Drawer
  90. open={!!content}
  91. placement="right"
  92. onClose={() => { setContent(null) }}
  93. footer={null}
  94. width={'60%'}
  95. destroyOnClose={true}
  96. styles={{ body: { padding: 0 } }}
  97. closeIcon={false}
  98. // title={<div style={{ fontSize: 20 }}>{content?.chapterName}</div>}
  99. >
  100. {
  101. content && <>
  102. <div
  103. ref={divRef}
  104. style={{ borderTop: '1px solid #efefef', fontSize: 17, lineHeight: 2, padding: '0 40px', height: '87vh', overflowY: 'auto', paddingBottom: 50, paddingTop: 15, boxSizing: 'border-box' }} dangerouslySetInnerHTML={{ __html: content.content.replace(/\n/g, '<br/>') }}></div>
  105. <div style={{ borderTop: '1px solid #efefef', display: 'flex', justifyContent: 'center' }}>
  106. <Space style={{ marginTop: 15 }}>
  107. {content?.chapterNo > 1 && <Button onClick={() => {
  108. let upId = null
  109. for (let i = 0; i < listData?.list?.length; i++) {
  110. if (listData?.list[i].chapterInfo.id === content.id) {
  111. upId = listData?.list[i - 1].chapterInfo.id
  112. break;
  113. }
  114. }
  115. getBookContent(upId)
  116. }}>上一章</Button>}
  117. {content?.chapterNo < listData?.list?.length && <Button onClick={() => {
  118. let downId = null
  119. for (let i = 0; i < listData?.list?.length; i++) {
  120. if (listData?.list[i].chapterInfo.id === content.id) {
  121. downId = listData?.list[i + 1].chapterInfo.id
  122. break;
  123. }
  124. }
  125. getBookContent(downId)
  126. }}>下一章</Button>}
  127. </Space>
  128. </div>
  129. </>
  130. }
  131. </Drawer>
  132. </div>
  133. </div>
  134. );
  135. }
  136. export default ReadBook;