shenwu 8 maanden geleden
bovenliggende
commit
c37b930df2

+ 1 - 1
src/pages/MiniApp/BookManage/Long/index.tsx

@@ -19,7 +19,7 @@ const Page: React.FC = () => {
                 distributorId: initialState?.currentUser?.distributorId,
                 appType:initialState?.selectApp?.appType || ""
             }}
-            headerTitle={"长篇小说充值记录列表"}
+            headerTitle={"长篇小说列表"}
             rowKey={(r) => r.id}
             search={{
                 labelWidth: 120,

+ 71 - 10
src/pages/MiniApp/BookManage/Short/index.tsx

@@ -2,31 +2,92 @@ import { PageContainer, ProTable } from "@ant-design/pro-components"
 import { columns } from "./tableConfig"
 import { useAjax } from "@/Hook/useAjax"
 import { useModel } from "@umijs/max"
-import { shortBookOrderList } from "@/services/miniApp/payLog"
-
+import { shortBookInfoList, shortBookInfoParagraphList } from "@/services/miniApp/bookManage"
+import { useState } from "react"
+import { Drawer } from "antd"
+import ReadText from "../components/readText"
+const wordCountRanges: any = {
+    "": { start: null, end: null }, // 全部
+    "0-2": { start: 0, end: 2 * 10000 },
+    "2-5": { start: 2 * 10000, end: 5 * 10000 },
+    "5-10": { start: 5 * 10000, end: 10 * 10000 },
+    "10-20": { start: 10 * 10000, end: 20 * 10000 },
+    "20-40": { start: 20 * 10000, end: 40 * 10000 },
+    "40-100": { start: 40 * 10000, end: 100 * 10000 },
+    "100-150": { start: 100 * 10000, end: 150 * 10000 },
+    "150-200": { start: 150 * 10000, end: 200 * 10000 },
+    "200-300": { start: 200 * 10000, end: 300 * 10000 },
+    "300-0": { start: 300 * 10000, end: null }, // 300万以上
+};
 const Page: React.FC = () => {
     let { initialState } = useModel("@@initialState")
-    let getList = useAjax((params) => shortBookOrderList(params), { type: 'table' })
+    let { state } = useModel('global')
+    const [openBook, setOpneBook] = useState<any>(null)//阅读小说
+    let getList = useAjax((params) => shortBookInfoList(params), { type: 'table' })
+    let getParagraphList = useAjax((params) => shortBookInfoParagraphList(params))
+
+
+    // 看小说
+    const lookBook = (params: any) => {
+        let { id, pageNum, pageSize } = params
+        return getParagraphList.run({ id, pageNum, pageSize, backContent: 1 }).then(res => {
+            setOpneBook({ ...res.data, ...params })
+            return res.data
+        })
+    }
     return <PageContainer title={false}
-        tabProps={{ type: 'card'}}
-        >
+        tabProps={{ type: 'card' }}
+    >
         <ProTable<any, any>
             params={{
                 miniappId: initialState?.selectApp?.id || "",
                 distributorId: initialState?.currentUser?.distributorId,
-             appType:initialState?.selectApp?.appType || ""
+                appType: initialState?.selectApp?.appType || ""
             }}
-            headerTitle={"短篇小说充值记录列表"}
-            rowKey={(r) => r.id}
+            headerTitle={"短篇小说列表"}
+            rowKey={(r) => r.bookId}
             search={{
-                labelWidth: 120,
+                labelWidth: 90,
+                searchGutter: [10, 15],
+            }}
+            // ghost={true}//去除表格的背景一些配置改变ui
+            beforeSearchSubmit={(params) => {//处理搜索数据
+                let newParams = Object.entries(params).reduce((acc: any, [key, value]) => {
+                    // 过滤掉空值,包括空字符串和 null
+                    if (value !== '' && value != null) {
+                        acc[key] = value;
+                    }
+                    if (key === 'wordCount' && value) {
+                        let obj = wordCountRanges[value]
+                        acc['startWordCount'] = obj.start
+                        acc['endWordCount'] = obj.end
+                        delete acc[key]
+                    }
+                    return acc;
+                }, {});
+                return newParams
             }}
             request={async (params) => {
                 return await getList.run(params)
             }}
-            columns={columns()}
+            columns={columns({ authList: state?.authList, enumList: state?.enumList,lookBook })}
         // bordered
         />
+        {/* 阅读小说 */}
+        <Drawer
+            open={!!openBook}
+            placement="right"
+            onClose={() => { setOpneBook(null) }}
+            footer={null}
+            width={'65%'}
+            destroyOnClose={true}
+            // getContainer={false}
+            bodyStyle={{ padding: 0 }}
+            closeIcon={false}
+            title={<div style={{ fontSize: 20}}>{openBook?.bookName ? openBook?.bookName : ""}</div>}
+        >
+            <ReadText data={openBook} next={lookBook} />
+        </Drawer>
     </PageContainer>
 
 }

+ 282 - 71
src/pages/MiniApp/BookManage/Short/tableConfig.tsx

@@ -1,104 +1,315 @@
+import { getDescriptions } from "@/utils";
 import { ProColumns } from "@ant-design/pro-components";
-import { Badge } from "antd";
-
-export const columns = (): ProColumns<any>[] => {
-    let payChannelObj: any = { '1': '微信小程序支付' };
-    let orderTypeObj: any = { '1': '书币充值', "2": "vip充值", "3": "购买整本" };
-    let orderStatusObj: any = { '1': '待支付', "2": "已支付" };
-    return [
-        {
-            title: "用户Id",
-            dataIndex: 'userId',
-            key: "userId",
-            align: "center",
+import { Badge, Col, Image, Row, Space, Tag } from "antd";
+import { createStyles } from "antd-style";
+const useStyles = createStyles(({ token }) => {
+    return {
+        bookLabel: {
+            color: token.colorTextTertiary
+        }
+    }
+})
+const brightColors = [
+    "#FF6347", // 番茄红
+    "#FF4500", // 橙红色
+    "#FFD700", // 金黄色
+    "#32CD32", // 鲜绿色
+    "#00FF7F", // 麦绿色
+    "#00CED1", // 暗青色
+    "#4682B4", // 钢蓝色
+    "#6A5ACD", // 鲜紫色
+    "#FF69B4", // 热粉红色
+    "#FF1493"  // 深粉红色
+];
+export const columns = (props: { authList?: any[], enumList?: { [key: string]: any }, lookBook: (data: any) => void }): ProColumns<any>[] => {
+    let { authList, enumList, lookBook } = props
+    let { styles } = useStyles()
+    return enumList?.BOOK_STATUS ? [
+        {
+            title: '封面',
+            dataIndex: 'picUrl',
+            key: 'picUrl',
+            width: 90,
+            ellipsis: true,
+            align: 'center',
             hideInSearch: true,
+            render: (a: any, b: any) => {
+                return <Image src={b?.shortBookInfoVO?.picUrl} style={{ width: 50 }} />
+            }
         },
         {
-            title: "小说名称",
-            dataIndex: 'bookName',
-            key: "bookName",
-            align: "center",
+            title: '作品详情',
+            dataIndex: 'authorId',
+            key: 'authorId',
+            ellipsis: true,
             hideInSearch: true,
+            render: (a, b) => {
+                let { bookName, wordCount, labelInfoList, bookStatus, categoryInfo, authorInfo, score } = b?.shortBookInfoVO
+                let arr = enumList?.BOOK_STATUS?.values
+                return <Row >
+                    <Col span={24}>
+                        <Space size={[5, 0]} wrap>
+                            <a style={{ fontSize: 14, color: "#337ab7" }} onClick={() => {
+                                lookBook?.({ ...b.shortBookInfoVO, pageNum: 1, pageSize: 2 })
+                            }}>[{categoryInfo?.name}]{bookName}</a>
+                            <span style={{ fontSize: 11 }} className={styles.bookLabel}>[{arr[bookStatus]?.description}]</span>
+                            <Space size={[0, 0]}>
+                                {
+                                    labelInfoList?.map((tags: { id: string, name: string }, index: number) => {
+                                        return <Tag key={tags?.id} color={brightColors[index]}>{tags?.name}</Tag>
+                                    })
+                                }
+                            </Space>
+                        </Space>
+                    </Col>
+                    <Col span={24} className={styles.bookLabel}><span ><span>作者</span>:</span>{authorInfo?.authorName}</Col>
+                    <Col span={24} className={styles.bookLabel}><span >总字数:</span>{wordCount || 0}</Col>
+                    <Col span={24} className={styles.bookLabel}><span >评分:</span>{score || 0}</Col>
+                </Row>
+            }
         },
         {
-            title: "支付渠道",
-            dataIndex: 'payChannel',
-            key: "payChannel",
-            align: "center",
-            valueType:'select',
-            valueEnum:payChannelObj,
-            render: (a: any,b:any) => {
-                return payChannelObj[b.payChannel]
-            },
+            title: '所属频道',
+            dataIndex: 'workDirection',
+            key: 'workDirection',
+            align: 'center',
+            width: 80,
+            ellipsis: true,
+            hideInSearch: true,
+            render: (a: any, b: any) => {
+                return enumList?.WORK_DIRECTION?.values[b.shortBookInfoVO.workDirection]?.description
+            }
         },
         {
-            title: "支付金额",
-            dataIndex: 'amount',
-            key: "amount",
+            title: '点击量',
+            dataIndex: 'visitCount',
+            key: 'visitCount',
+            width: 90,
+            ellipsis: true,
+            align: 'center',
             hideInSearch: true,
-            align: "center",
+            render: (a, b) => {
+                let { visitCount } = b?.shortBookInfoVO
+                return visitCount
+            }
         },
         {
-            title: "订单类型",
-            dataIndex: 'orderType',
-            key: "orderType",
-            valueType:'select',
-            valueEnum:orderTypeObj,
-            align: "center",
-            render: (a: any,b:any) => {
-                return orderTypeObj[b.orderType]
+            title: '上架状态',
+            dataIndex: 'shelveStatus',
+            key: 'shelveStatus',
+            width: 90,
+            ellipsis: true,
+            align: 'center',
+            hideInSearch: true,
+            render: (a: any, b) => {
+                let arr: any = enumList?.SHELVE_STATUS?.values
+                let { shelveStatus } = b?.shortBookInfoVO
+                return arr[shelveStatus]?.description && <Badge text={arr[shelveStatus]?.description} status={shelveStatus == 0 ? "processing" : "default"} />
             }
         },
         {
-            title: "订单状态",
-            dataIndex: 'orderStatus',
-            key: "orderStatus",
-            valueType:'select',
-            valueEnum:orderStatusObj,
-            align: "center",
-            render: (a: any,b:any) => {
-                return <Badge text={orderStatusObj[b.orderStatus]} status={b.orderStatus != 1 ? "success" : "warning"} />
+            title: '来源',
+            dataIndex: 'source',
+            key: 'source',
+            width: 90,
+            ellipsis: true,
+            align: 'center',
+            hideInSearch: true,
+            render: (a: any, b) => {
+                let { source } = b?.shortBookInfoVO
+                let arr: any = new Map(enumList?.SOURCE?.values?.map(({ value, description }: any) => [value, description]))
+                return arr.get(source)
             }
         },
         {
-            title: "用户订单号",
-            dataIndex: 'orderId',
-            key: "orderId",
-            align: "center",
+            title: '收费类型',
+            dataIndex: 'paymentType',
+            key: 'paymentType',
+            width: 100,
+            ellipsis: true,
+            align: 'center',
+            hideInSearch: true,
+            render: (a: any, b: any) => {
+                let arr = getDescriptions(enumList?.PAYMENT_TYPE?.values || [], b?.paymentType || [])
+                return <Space size={[0,5]} wrap>
+                    {
+                        arr?.map(str=>{
+                            return <Tag bordered={false} key={str}>{str}</Tag>
+                        })
+                    }
+                </Space>
+            }
+        },
+        {
+            title: 'VIP免费',
+            dataIndex: 'vipFree',
+            key: 'vipFree',
+            width: 70,
+            ellipsis: true,
+            align: 'center',
+            hideInSearch: true,
+            render: (a: any, b) => {
+                return <Badge text={a ? "是" : "否"} status={a ? "processing" : "default"} />
+            }
         },
         {
-            title: "商户订单号",
-            dataIndex: 'merchantOrderId',
-            key: "merchantOrderId",
-            align: "center",
+            title: '收费金额',
+            tooltip:"收费金额(整本)",
+            dataIndex: 'paymentAmount',
+            key: 'paymentAmount',
+            width: 100,
+            ellipsis: true,
+            align: 'center',
+            hideInSearch: true,
         },
         {
-            title: "下单时间",
-            dataIndex: 'orderTime',
-            key: "orderTime",
+            title: '收费书币',
+            tooltip:"收费书币(/千字、/本、/段|章节)",
+            dataIndex: 'paymentCoin',
+            key: 'paymentCoin',
+            width: 100,
+            ellipsis: true,
+            align: 'center',
             hideInSearch: true,
-            align: "center",
         },
         {
-            title: "支付时间",
-            tooltip: "实际到账时间",
-            dataIndex: 'payTime',
-            key: "payTime",
+            title: '开始收费段落',
+            dataIndex: 'beginPayParagraphNo',
+            key: 'beginPayParagraphNo',
+            width: 100,
+            ellipsis: true,
+            align: 'center',
             hideInSearch: true,
-            align: "center",
+        },
+        {
+            title: '操作',
+            dataIndex: 'cz',
+            key: 'cz',
+            width: 90,
+            ellipsis: true,
+            align: 'center',
+            hideInSearch: true,
+            render:(a:any,b:any)=>{
+                return <a>付费配置</a>
+            }
         },
         // 搜索条件
         {
-            title: "开始时间",
-            dataIndex: 'startTime',
-            valueType: 'dateTime',
-            hideInTable: true
+            title: "小说名称",
+            dataIndex: 'bookName',
+            valueType: 'text',
+            hideInTable: true,
+            fieldProps: { placeholder: "请输入小说名称" },
+            colSize: 1,
+        },
+        {
+            title: "作者",
+            dataIndex: 'authorId',
+            valueType: 'select',
+            hideInTable: true,
+            fieldProps: { showSearch: true, placeholder: '请选择作者' },
+            colSize: 1,
+            valueEnum: new Map(authList?.map(({ id, authorName }) => [id, authorName]))
+        },
+        {
+            title: "频道",
+            dataIndex: 'workDirection',
+            valueType: 'segmented',
+            hideInTable: true,
+            fieldProps: { type: 'primary', style: { width: 'auto' } },
+            colSize: 3,
+            initialValue: '',
+            valueEnum: () => {
+                let arr = enumList?.WORK_DIRECTION?.values
+                return arr ? new Map([{ value: '', description: "全部" }, ...arr]?.map(({ value, description }: any) => [value, description])) : {}
+            }
+        },
+        {
+            title: "来源",
+            dataIndex: 'source',
+            valueType: 'segmented',
+            hideInTable: true,
+            fieldProps: { type: 'primary', style: { width: 'auto' } },
+            colSize: 3,
+            initialValue: '',
+            valueEnum: () => {
+                let arr = enumList?.SOURCE?.values
+                return arr ? new Map([{ value: '', description: "全部" }, ...arr]?.map(({ value, description }: any) => [value, description])) : {}
+            }
+        },
+        {
+            title: "连载",
+            dataIndex: 'bookStatus',
+            valueType: 'segmented',
+            hideInTable: true,
+            fieldProps: { type: 'primary', style: { width: 'auto' } },
+            colSize: 3,
+            initialValue: '',
+            valueEnum: () => {
+                let arr = enumList?.BOOK_STATUS?.values
+                return arr ? new Map([{ value: '', description: "全部" }, ...arr]?.map(({ value, description }: any) => [value, description])) : {}
+            }
+        },
+        {
+            title: "上架",
+            dataIndex: 'shelveStatus',
+            valueType: 'segmented',
+            hideInTable: true,
+            fieldProps: { type: 'primary', style: { width: 'auto' } },
+            colSize: 3,
+            initialValue: '',
+            valueEnum: () => {
+                let arr = enumList?.SHELVE_STATUS?.values
+                return arr ? new Map([{ value: '', description: "全部" }, ...arr]?.map(({ value, description }: any) => [value, description])) : {}
+            }
         },
         {
-            title: "结束时间",
-            dataIndex: 'endTime',
-            valueType: 'dateTime',
-            hideInTable: true
+            title: "付费",
+            dataIndex: 'paymentType',
+            valueType: 'segmented',
+            hideInTable: true,
+            fieldProps: { type: 'primary', style: { width: 'auto' } },
+            colSize: 3,
+            initialValue: '',
+            valueEnum: () => {
+                let arr = enumList?.PAYMENT_TYPE?.values
+                return arr ? new Map([{ value: '', description: "全部" }, ...arr]?.map(({ value, description }: any) => [value, description])) : {}
+            }
+        },
+        {
+            title: "VIP",
+            dataIndex: 'vipFree',
+            valueType: 'segmented',
+            hideInTable: true,
+            fieldProps: { type: 'primary', style: { width: 'auto' } },
+            colSize: 3,
+            initialValue: '',
+            valueEnum: () => {
+                let arr = enumList?.VIP_FREE?.values
+                return arr ? new Map([{ value: '', description: "全部" }, ...arr]?.map(({ value, description }: any) => [value, description])) : {}
+            }
+        },
+        {
+            title: "字数",
+            dataIndex: 'wordCount',
+            valueType: 'segmented',
+            hideInTable: true,
+            fieldProps: { type: 'primary', style: { width: 'auto' } },
+            colSize: 3,
+            initialValue: '',
+            valueEnum: {
+                "": "全部",
+                "0-2": "2万内",
+                "2-5": "2-5万",
+                "5-10": "5-10万",
+                "10-20": "10-20万",
+                "20-40": "20-40万",
+                "40-100": "40-100万",
+                "100-150": "100-150万",
+                "150-200": "150-200万",
+                "200-300": "200-300万",
+                "300-0": "300万以上",
+            },
         },
-    ];
+    ] : []
 }

+ 136 - 0
src/pages/MiniApp/BookManage/components/readBook/index.tsx

@@ -0,0 +1,136 @@
+import { useVirtualList } from "ahooks";
+import { Button, Col, Row, Image, Spin, Space, Drawer } from "antd";
+import { JSXElementConstructor, Key, ReactElement, ReactFragment, ReactPortal, useEffect, useRef, useState } from "react";
+import { ReactComponent as SuoSvg } from '@/assets/suo.svg';
+function ReadBook(props: { next: (data: { id: number }) => Promise<any>, listData: any }) {
+    let { next, listData } = props;
+    const divRef = useRef<HTMLDivElement>(null);
+    const [isFetching, setIsFetching] = useState(true);
+    const [newData, setNewData] = useState<any>(null);
+    const [content, setContent] = useState<any>(null)
+    const list = useVirtualList(listData?.list || [],{
+        containerTarget: undefined,
+        wrapperTarget: undefined,
+        itemHeight: 0
+    });
+
+    useEffect(() => {
+        const handleKeyDown = (event: KeyboardEvent) => {
+            if (divRef.current) {
+                if (event.key === "ArrowDown") {
+                    divRef.current.scrollBy(0, 50);
+                } else if (event.key === "ArrowUp") {
+                    divRef.current.scrollBy(0, -50);
+                }
+            }
+        };
+        window.addEventListener("keydown", handleKeyDown);
+        return () => {
+            window.removeEventListener("keydown", handleKeyDown);
+        };
+    }, []);
+
+
+    async function getBookContent(id: any) {
+        let content = await next(id)
+        setContent(content)
+    }
+    useEffect(() => {
+        if (divRef.current) {
+            divRef.current.scrollTop = 0
+        }
+    }, [content, divRef])
+    return (
+        listData && <div
+            style={{ height: '85vh', overflow: 'hidden', display: 'flex', justifyContent: 'space-around' }}
+        >
+            <div style={{ width: '20%', flexFlow: 'column', alignItems: 'center', display: 'flex', borderRight: '1px solid #efefef' }}>
+                <Image src={listData?.picUrl} style={{ width: 150, marginBottom: 20 }} />
+                <Row style={{ width: '80%' }}>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}><span>作者</span>:</span>{listData?.authorName}</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}><span>来源</span>:</span>{({ "UPLOAD": "管理员", "CREATOR": "创作者" } as any)[listData.source]}</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}><span>频道</span>:</span>{listData?.corpUserName == 0 ? "男频" : "女频"}</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}>标签:</span> {
+                        listData?.labels?.map((tags: { id: string, name: string }, index: number) => {
+                            return tags?.name
+                        }).join(',')
+                    }</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }} ><span style={{ color: "#333" }}><span>状态</span>:</span>{["连载中", "已完结"][listData.bookStatus]}</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}>评分:</span>{listData?.score || 0}</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}>点击量:</span>{listData?.visitCount}</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}>总字数:</span>{listData?.wordCount}</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}>上架状态:</span>{["上架中", "已下架"][listData.shelveStatus]}</Col>
+                    <Col span={24} style={{ fontSize: 14, color: "#777" }}><span style={{ color: "#333" }}>描述:</span>{listData.bookDesc}</Col>
+
+                </Row>
+            </div>
+            <div
+                style={{ overflowY: 'auto', display: 'flex', flexFlow: "column", width: '75%' }}
+                ref={divRef}
+            >
+                <div >
+                    {/* {list?.map((ele) => (
+                        <a
+                            key={ele.index}
+                            style={{ display: 'inline-block', marginRight: ele.index % 4 === 0 ? 0 : 20, marginBottom: 10, width: 190, overflow: 'hidden' }}
+                            onClick={() => { getBookContent(ele.data.chapterInfo.id) }}
+                        >
+                            <div style={{ display: 'flex', alignItems: 'center' }}>
+                                {ele.data.needPay && <SuoSvg width={15} height={15} style={{ marginRight: 5 }} />}
+                                <span >{ele.data.chapterInfo.chapterName}</span>
+                            </div>
+                        </a>
+                    ))} */}
+                </div>
+                {/* 阅读小说 */}
+                <Drawer
+                    open={!!content}
+                    placement="right"
+                    onClose={() => { setContent(null) }}
+                    footer={null}
+                    width={'60%'}
+                    destroyOnClose={true}
+                    bodyStyle={{ padding: 0 }}
+                    closeIcon={false}
+                    title={<div style={{ fontSize: 20 }}>{content?.chapterName}</div>}
+                >
+                    {
+                        content && <>
+                            <div
+                                ref={divRef}
+                                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>
+                            <div style={{ borderTop: '1px solid #efefef', display: 'flex', justifyContent: 'center' }}>
+                                <Space style={{ marginTop: 15 }}>
+                                    {content?.chapterNo > 1 && <Button onClick={() => {
+                                        let upId = null
+                                        for (let i = 0; i < listData?.list?.length; i++) {
+                                            if (listData?.list[i].chapterInfo.id === content.id) {
+                                                upId = listData?.list[i - 1].chapterInfo.id
+                                                break;
+                                            }
+                                        }
+                                        getBookContent(upId)
+                                    }}>上一章</Button>}
+                                    {content?.chapterNo < listData?.list?.length && <Button onClick={() => {
+                                        let downId = null
+                                        for (let i = 0; i < listData?.list?.length; i++) {
+                                            if (listData?.list[i].chapterInfo.id === content.id) {
+                                                downId = listData?.list[i + 1].chapterInfo.id
+                                                break;
+                                            }
+                                        }
+                                        getBookContent(downId)
+                                    }}>下一章</Button>}
+                                </Space>
+                            </div>
+                        </>
+                    }
+                </Drawer>
+
+            </div>
+
+        </div>
+    );
+}
+
+export default ReadBook;

+ 102 - 0
src/pages/MiniApp/BookManage/components/readText/index.tsx

@@ -0,0 +1,102 @@
+import { useToken } from "@ant-design/pro-components";
+import { Col, Row, Spin, Image } from "antd";
+import { useEffect, useRef, useState } from "react";
+
+function ReadText(props: { next: (data: { pageNum: number, pageSize: number, id: number }) => Promise<any>, data: any }) {
+    let { next, data } = props;
+    const divRef = useRef<HTMLDivElement>(null);
+    const [isFetching, setIsFetching] = useState(true);
+    const [newData, setNewData] = useState<any>(null);
+    let {token} = useToken()
+    console.log(data)
+    // 存放首次的size
+    useEffect(() => {
+        setNewData(data);
+    }, []);
+
+    useEffect(() => {
+        const handleKeyDown = (event: KeyboardEvent) => {
+            if (divRef.current) {
+                if (event.key === "ArrowDown") {
+                    divRef.current.scrollBy(0, 50);
+                } else if (event.key === "ArrowUp") {
+                    divRef.current.scrollBy(0, -50);
+                }
+            }
+        };
+
+        window.addEventListener("keydown", handleKeyDown);
+
+        return () => {
+            window.removeEventListener("keydown", handleKeyDown);
+        };
+    }, []);
+
+    const handleScroll = () => {
+        if (divRef.current) {
+            const { scrollTop, scrollHeight, clientHeight } = divRef.current;
+            if (scrollTop + clientHeight >= scrollHeight / 2 && isFetching) {
+                if (newData.current * newData.size < newData.total) {
+                    getText();
+                }
+            }
+            if (scrollTop + clientHeight >= scrollHeight) {
+                console.log("到底了");
+                getText();
+            }
+        }
+    };
+
+    async function getText() {
+        if (newData.current * newData.size < newData.total) {
+            setIsFetching(false);
+            console.log("还有内容");
+            let r = await next({ ...data, pageNum: 1, pageSize: newData.size + data.size }); // Replace with actual data
+            setNewData(r);
+            setIsFetching(true);
+        }
+    }
+
+    return (
+        data && <div
+            style={{ height: '90vh', overflow: 'hidden', display: 'flex', justifyContent: 'space-around' }}
+        >
+            <div style={{ width: '20%', flexFlow: 'column', alignItems: 'center', display: 'flex', borderRight: '1px solid #efefef' }}>
+                <Image src={data?.picUrl} style={{ width: 150, marginBottom: 20, marginTop: 20 }} />
+                <Row style={{ width: '80%' }} gutter={[10, 5]}>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText }}><span>作者</span>:</span>{data?.authorInfo?.authorName}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}><span>类别</span>:</span>{data?.categoryInfo?.name}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}><span>来源</span>:</span>{({ "UPLOAD": "管理员", "CREATOR": "创作者" } as any)[data.source]}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}><span>频道</span>:</span>{data?.corpUserName == 0 ? "男频" : "女频"}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}>标签:</span> {
+                        data?.labelInfoList?.map((tags: { id: string, name: string }, index: number) => {
+                            return tags?.name
+                        }).join(',')
+                    }</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }} ><span style={{ color: token. colorText  }}><span>状态</span>:</span>{["连载中", "已完结"][data.bookStatus]}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}>评分:</span>{data?.score || 0}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}>点击量:</span>{data?.visitCount || 0}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}>总字数:</span>{data?.wordCount || 0}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}>上架状态:</span>{["上架中", "已下架"][data.shelveStatus]}</Col>
+                    <Col span={24} style={{ fontSize: 14, color:token.colorTextSecondary }}><span style={{ color: token. colorText  }}>描述:</span>{data?.bookDesc}</Col>
+
+                </Row>
+            </div>
+            <div
+                style={{ overflowY: 'auto', display: 'flex', flexFlow: "column", width: '75%', paddingBottom: 50, boxSizing: 'border-box' }}
+                onScroll={handleScroll}
+                ref={divRef}
+            >
+                <Spin spinning={!data?.size}>
+                    {
+                        newData?.records?.map((item: { shortBookContentVO: { contentId: number, content: string } }) => {
+                            return <div style={{ fontSize: 17, lineHeight: 2 }} key={item.shortBookContentVO.contentId} dangerouslySetInnerHTML={{ __html: item.shortBookContentVO.content.replace(/\n/g, '<br/>') }}></div>
+                        })
+                    }
+                </Spin>
+            </div>
+        </div>
+    );
+}
+
+export default ReadText;

+ 13 - 0
src/utils/index.ts

@@ -0,0 +1,13 @@
+/**传入数组枚举数组和key数组 找到在枚举数组中的description值
+ * @param {Array} enumArr 枚举数组
+ * @param {Array} arr 要查找的数组
+ * */ 
+export function getDescriptions(enumArr: any[], arr: any[]) {
+    // 创建一个字典来存储 value 和 description 的映射
+    const valueToDescription = enumArr.reduce((acc, item) => {
+        acc[item.value] = item.description;
+        return acc;
+    }, {});
+    // 使用 arr2 中的 value 查找对应的 description
+    return arr.map(value => valueToDescription[value]);
+}