|
@@ -0,0 +1,225 @@
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+import React, { useState, useEffect } from 'react';
|
|
|
|
+import { View, Text, ScrollView, Button } from '@tarojs/components';
|
|
|
|
+import { observer, inject } from 'mobx-react';
|
|
|
|
+import './index.less';
|
|
|
|
+import TopNavBar from '@src/components/TopNavBar/index';
|
|
|
|
+import Taro from '@tarojs/taro';
|
|
|
|
+import BookConfigPuP from '@src/components/bookConfigPup';
|
|
|
|
+import { BookStore } from '@src/store/book';
|
|
|
|
+import useApi from '@src/Hook/useApi';
|
|
|
|
+import { UpLoading } from '@src/components/PupPetry/Loading';
|
|
|
|
+import { getReadLog, setReadLog } from '@src/utils/loginSto';
|
|
|
|
+
|
|
|
|
+interface Config {
|
|
|
|
+ size: 'pre_15' | 'pre_17' | 'pre_19' | 'pre_21' | 'pre_23' | 'pre_25' | 'pre_27' | 'pre_29' | any;
|
|
|
|
+ off_on: boolean;
|
|
|
|
+ bg: 'bg_b' | 'bg_h' | 'bg_l' | 'bg_hh';
|
|
|
|
+ lh: 'lh_72' | 'lh_84' | 'lh_96';
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type PageStateProps = {
|
|
|
|
+ store: {
|
|
|
|
+ bookStore: BookStore,
|
|
|
|
+ indexStore,
|
|
|
|
+ appInfoStore
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+interface BookArticleProps extends PageStateProps { }
|
|
|
|
+
|
|
|
|
+const BookArticle: React.FC<BookArticleProps> = ({ store }) => {
|
|
|
|
+ const [isLoad, setIsLoad] = useState(false)
|
|
|
|
+ const { bookStore, indexStore, appInfoStore } = store
|
|
|
|
+ const { openBookData } = bookStore
|
|
|
|
+ const [bookConfig, setBookConfig] = useState<Config>({ size: 'pre_21', off_on: true, bg: 'bg_b', lh: 'lh_72' });
|
|
|
|
+ const [pup, setPup] = useState(false);
|
|
|
|
+ const { getBookContent } = useApi(appInfoStore)
|
|
|
|
+ const [currentScrollId, setCurrentScrollId] = useState('');
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ // ComponentDidMount
|
|
|
|
+ try {
|
|
|
|
+ Taro.getStorage({
|
|
|
|
+ key: 'bookConfig',
|
|
|
|
+ success: (res) => {
|
|
|
|
+ setBookConfig(JSON.parse(res.data));
|
|
|
|
+ },
|
|
|
|
+ fail: () => {
|
|
|
|
+ setConfig({ size: 'pre_21', off_on: true, bg: 'bg_b', lh: 'lh_72' });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ } catch (e) {
|
|
|
|
+ console.error('Error loading book config:', e);
|
|
|
|
+ }
|
|
|
|
+ //假如存在阅读记录获取对应章节的条数
|
|
|
|
+ let readLogId = getReadLog(openBookData?.bookId)
|
|
|
|
+ getBookContent({ pageNum: 1, pageSize:readLogId? Number(readLogId?.split('-')[1]) : 2 }).then(res => {
|
|
|
|
+ //继续阅读时跳转到上次阅读的段落
|
|
|
|
+ console.log(readLogId)
|
|
|
|
+ setCurrentScrollId(readLogId)
|
|
|
|
+ })
|
|
|
|
+ return () => {
|
|
|
|
+ console.log("卸载");
|
|
|
|
+ reportRead(); // 上报
|
|
|
|
+ };
|
|
|
|
+ }, []);
|
|
|
|
+
|
|
|
|
+ const reportRead = () => {
|
|
|
|
+ // 这里可以填写上报逻辑
|
|
|
|
+ };
|
|
|
|
+ //设置配置
|
|
|
|
+ const setConfig = (data: Config) => {
|
|
|
|
+ if (data) {
|
|
|
|
+ setBookConfig(data);
|
|
|
|
+ Taro.setStorage({
|
|
|
|
+ key: 'bookConfig',
|
|
|
|
+ data: JSON.stringify(data),
|
|
|
|
+ success: (res: any) => {
|
|
|
|
+ console.log('添加bookConfig===>成功!', res);
|
|
|
|
+ },
|
|
|
|
+ fail: (err) => {
|
|
|
|
+ console.log('添加bookConfig===>失败', err);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 控制自义定头部背景
|
|
|
|
+ store.bookStore.setData({ bookConfig: data });
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ /**计算字体 */
|
|
|
|
+ const setSize = (parms: number) => {
|
|
|
|
+ let num = bookConfig.size.split('_');
|
|
|
|
+ if (num[1] && parms) {
|
|
|
|
+ setConfig({ ...bookConfig, size: num[0] + '_' + (Number(num[1]) + 2) });
|
|
|
|
+ } else {
|
|
|
|
+ setConfig({ ...bookConfig, size: num[0] + '_' + (Number(num[1]) - 2) });
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ /**设置背景 */
|
|
|
|
+ const setBg = (bg: 'bg_b' | 'bg_h' | 'bg_l' | 'bg_hh') => {
|
|
|
|
+ setConfig({ ...bookConfig, bg });
|
|
|
|
+ if (!bookConfig.off_on) {
|
|
|
|
+ setOff(bg);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ /**设置行高*/
|
|
|
|
+ const setLh = (lh: 'lh_72' | 'lh_84' | 'lh_96') => {
|
|
|
|
+ setConfig({ ...bookConfig, lh });
|
|
|
|
+ };
|
|
|
|
+ /**关灯 */
|
|
|
|
+ const setOff = (bg?: 'bg_b' | 'bg_h' | 'bg_l' | 'bg_hh') => {
|
|
|
|
+ const newOffOn = !bookConfig.off_on;
|
|
|
|
+ const newConfig = bg ? { ...bookConfig, bg, off_on: newOffOn } : { ...bookConfig, off_on: newOffOn };
|
|
|
|
+ setConfig(newConfig);
|
|
|
|
+ Taro.setNavigationBarColor({
|
|
|
|
+ frontColor: newOffOn ? '#000000' : '#ffffff',
|
|
|
|
+ backgroundColor: newOffOn ? '#fff' : '#111111'
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ /**菜单 */
|
|
|
|
+ const togglePup = () => {
|
|
|
|
+ setPup(!pup);
|
|
|
|
+ };
|
|
|
|
+ //设置setNavigationBarColor
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ Taro.setNavigationBarColor({
|
|
|
|
+ frontColor: bookConfig.off_on ? '#000000' : '#ffffff',
|
|
|
|
+ backgroundColor: bookConfig.off_on ? '#fff' : '#111'
|
|
|
|
+ });
|
|
|
|
+ }, [bookConfig.off_on]);
|
|
|
|
+ const onLoad = async () => {
|
|
|
|
+ if (openBookData?.contentData) {
|
|
|
|
+ let { size, current, total, records } = openBookData.contentData
|
|
|
|
+ if (records.length < total) {
|
|
|
|
+ console.log("加载")
|
|
|
|
+ setIsLoad(true)
|
|
|
|
+ await getBookContent({ pageNum: 1, pageSize: size + 2 }).then(res => {
|
|
|
|
+ setIsLoad(false)
|
|
|
|
+ })
|
|
|
|
+ } else {
|
|
|
|
+ Taro.showToast({
|
|
|
|
+ title: '没有更多了~~',
|
|
|
|
+ duration: 1000,
|
|
|
|
+ icon: 'none'
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 计算阅读的位置,存放以备下次阅读的时候跳转到对应位置
|
|
|
|
+ const handleScroll = () => {
|
|
|
|
+ const query = Taro.createSelectorQuery();
|
|
|
|
+ query.selectAll('.shrot-text').boundingClientRect(); // 选择所有子元素
|
|
|
|
+ query.selectViewport().scrollOffset(); // 获取视口的滚动位置
|
|
|
|
+ query.exec(res => {
|
|
|
|
+ const items = res[0]; // 子元素的位置信息
|
|
|
|
+ const scrollTop = res[1].scrollTop + indexStore.navHeight; // 视口的滚动距离
|
|
|
|
+ // 遍历所有子元素,判断哪个子元素在可视区域
|
|
|
|
+ for (let item of items) {
|
|
|
|
+ if (item.top <= scrollTop && item.bottom >= scrollTop) {
|
|
|
|
+ if (openBookData?.bookId) {
|
|
|
|
+ setReadLog({ [openBookData.bookId]: item.id })
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ const { size, bg, off_on, lh } = bookConfig;
|
|
|
|
+ return (
|
|
|
|
+ <ScrollView
|
|
|
|
+ lowerThreshold={indexStore.navHeight}
|
|
|
|
+ refresherTriggered={isLoad}
|
|
|
|
+ onScrollToLower={onLoad}
|
|
|
|
+ style={{ height: `calc(100vh - ${indexStore.navHeight}px)` }}
|
|
|
|
+ scrollY={true}
|
|
|
|
+ refresherDefaultStyle='black'
|
|
|
|
+ scrollWithAnimation={true}
|
|
|
|
+ scrollIntoView={currentScrollId}
|
|
|
|
+ onScroll={handleScroll}
|
|
|
|
+ >
|
|
|
|
+ <View className={`book_article ${off_on ? bg : 'bg_hh'} ${off_on ? 'cl_h' : 'cl_b'}`} onClick={togglePup}>
|
|
|
|
+ <View className='header'>
|
|
|
|
+ <View className='btns'>
|
|
|
|
+ <View className='left'>
|
|
|
|
+ <Text
|
|
|
|
+ onClick={() => { size !== 'pre_15' && setSize(0) }}
|
|
|
|
+ className={!off_on ? size === 'pre_15' ? 'cl_e5' : '' : size === 'pre_15' ? 'cl_d6' : ''}
|
|
|
|
+ >字小</Text>
|
|
|
|
+ <Text
|
|
|
|
+ onClick={() => { size !== 'pre_29' && setSize(1) }}
|
|
|
|
+ className={!off_on ? size === 'pre_29' ? 'cl_e5' : '' : size === 'pre_29' ? 'cl_d6' : ''}
|
|
|
|
+ >字大</Text>
|
|
|
|
+ </View>
|
|
|
|
+ <View className='right'>
|
|
|
|
+ <Text onClick={() => { setOff() }}>{off_on ? '关灯' : '开灯'}</Text>
|
|
|
|
+ <Text onClick={togglePup}>菜单</Text>
|
|
|
|
+ </View>
|
|
|
|
+ </View>
|
|
|
|
+ </View>
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ openBookData?.contentData?.records?.map(item => {
|
|
|
|
+ let arr = item.paragraphInfo.content?.split(/\s/ig)
|
|
|
|
+ return <View
|
|
|
|
+ id={'paragraphNo-' + item.paragraphInfo.paragraphNo}
|
|
|
|
+ key={item.paragraphInfo.paragraphNo}
|
|
|
|
+ className={`pre ${size} ${lh}`}
|
|
|
|
+ >
|
|
|
|
+ {
|
|
|
|
+ arr?.map((str, index) => {
|
|
|
|
+ return <Text className='shrot-text' id={'paragraphNo-' + item.paragraphInfo.paragraphNo + '-' + index} key={index}>{str}</Text>
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ </View>
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ {pup && <BookConfigPuP {...bookConfig} off_on={off_on} setOff={setOff} setSize={setSize} setBg={setBg} setLh={setLh} />}
|
|
|
|
+ </View>
|
|
|
|
+ {
|
|
|
|
+ isLoad && <UpLoading />
|
|
|
|
+ }
|
|
|
|
+ </ScrollView>
|
|
|
|
+ );
|
|
|
|
+};
|
|
|
|
+export default inject('store')(observer(TopNavBar(BookArticle, { isToBack: true, isReloadBook: true })));
|