feat: 滚动加载组件

This commit is contained in:
archer
2023-03-25 13:55:53 +08:00
parent 3db690773f
commit 4eaf3a1be0
9 changed files with 131 additions and 47 deletions

View File

@@ -27,6 +27,7 @@
"hyperdown": "^2.4.29",
"immer": "^9.0.19",
"jsonwebtoken": "^9.0.0",
"lodash": "^4.17.21",
"mammoth": "^1.5.1",
"mongoose": "^6.10.0",
"nanoid": "^4.0.1",
@@ -51,6 +52,7 @@
"@svgr/webpack": "^6.5.1",
"@types/formidable": "^2.0.5",
"@types/jsonwebtoken": "^9.0.1",
"@types/lodash": "^4.14.191",
"@types/node": "18.14.0",
"@types/nodemailer": "^6.4.7",
"@types/react": "18.0.28",

5
pnpm-lock.yaml generated
View File

@@ -10,6 +10,7 @@ specifiers:
'@tanstack/react-query': ^4.24.10
'@types/formidable': ^2.0.5
'@types/jsonwebtoken': ^9.0.1
'@types/lodash': ^4.14.191
'@types/node': 18.14.0
'@types/nodemailer': ^6.4.7
'@types/nprogress': ^0.2.0
@@ -31,6 +32,7 @@ specifiers:
immer: ^9.0.19
jsonwebtoken: ^9.0.0
lint-staged: ^13.1.2
lodash: ^4.17.21
mammoth: ^1.5.1
mongoose: ^6.10.0
nanoid: ^4.0.1
@@ -70,6 +72,7 @@ dependencies:
hyperdown: registry.npmmirror.com/hyperdown/2.4.29
immer: registry.npmmirror.com/immer/9.0.19
jsonwebtoken: registry.npmmirror.com/jsonwebtoken/9.0.0
lodash: registry.npmmirror.com/lodash/4.17.21
mammoth: registry.npmmirror.com/mammoth/1.5.1
mongoose: registry.npmmirror.com/mongoose/6.10.0
nanoid: registry.npmmirror.com/nanoid/4.0.1
@@ -94,6 +97,7 @@ devDependencies:
'@svgr/webpack': registry.npmmirror.com/@svgr/webpack/6.5.1
'@types/formidable': registry.npmmirror.com/@types/formidable/2.0.5
'@types/jsonwebtoken': registry.npmmirror.com/@types/jsonwebtoken/9.0.1
'@types/lodash': registry.npmmirror.com/@types/lodash/4.14.191
'@types/node': registry.npmmirror.com/@types/node/18.14.0
'@types/nodemailer': registry.npmmirror.com/@types/nodemailer/6.4.7
'@types/react': registry.npmmirror.com/@types/react/18.0.28
@@ -4794,7 +4798,6 @@ packages:
resolution: {integrity: sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.191.tgz}
name: '@types/lodash'
version: 4.14.191
dev: false
registry.npmmirror.com/@types/mdast/3.0.10:
resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.10.tgz}

View File

@@ -37,7 +37,7 @@ function checkRes(data: ResponseDataType) {
console.log('error->', data, 'data is empty');
return Promise.reject('服务器异常');
} else if (data.code < 200 || data.code >= 400) {
return Promise.reject(data.message);
return Promise.reject(data);
}
return data.data;
}

View File

@@ -62,8 +62,8 @@ const Layout = ({ children }: { children: JSX.Element }) => {
<Box h={'100%'} position={'fixed'} left={0} top={0} w={'80px'}>
<Navbar navbarList={navbarList} />
</Box>
<Box ml={'80px'} p={7} h={'100%'}>
<Box maxW={'1100px'} m={'auto'} h={'100%'}>
<Box ml={'80px'} h={'100%'}>
<Box maxW={'1100px'} m={'auto'} h={'100%'} p={7} overflowY={'auto'}>
<Auth>{children}</Auth>
</Box>
</Box>

View File

@@ -1,16 +1,63 @@
import React from 'react';
import React, { useRef, useEffect, useMemo } from 'react';
import type { BoxProps } from '@chakra-ui/react';
import { Box } from '@chakra-ui/react';
import { throttle } from 'lodash';
interface Props extends BoxProps {
nextPage: () => void;
isLoadAll: boolean;
requesting: boolean;
children: React.ReactNode;
}
const ScrollData = ({ children, nextPage, ...props }: Props) => {
const ScrollData = ({ children, nextPage, isLoadAll, requesting, ...props }: Props) => {
const elementRef = useRef<HTMLDivElement>(null);
const loadText = useMemo(() => {
if (requesting) return '请求中……';
if (isLoadAll) return '已加载全部';
return '点击加载更多';
}, [isLoadAll, requesting]);
useEffect(() => {
if (!elementRef.current) return;
const scrolling = throttle((e: Event) => {
const element = e.target as HTMLDivElement;
if (!element) return;
// 当前滚动位置
const scrollTop = element.scrollTop;
// 可视高度
const clientHeight = element.clientHeight;
// 内容总高度
const scrollHeight = element.scrollHeight;
// 判断是否滚动到底部
if (scrollTop + clientHeight + 100 >= scrollHeight) {
nextPage();
}
}, 100);
elementRef.current.addEventListener('scroll', scrolling);
return () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
elementRef.current?.removeEventListener('scroll', scrolling);
};
}, [elementRef, nextPage]);
return (
<Box {...props} overflow={'auto'}>
<Box {...props} ref={elementRef} overflow={'auto'}>
{children}
<Box
mt={2}
fontSize={'xs'}
color={'blackAlpha.500'}
textAlign={'center'}
cursor={loadText === '点击加载更多' ? 'pointer' : 'default'}
onClick={() => {
if (loadText !== '点击加载更多') return;
nextPage();
}}
>
{loadText}
</Box>
</Box>
);
};

View File

@@ -37,6 +37,7 @@ export const usePaging = <T = any>({
setIsLoadAll(true);
}
setTotal(res.total);
setPageNum(num);
return data;
});
} catch (error: any) {
@@ -53,15 +54,18 @@ export const usePaging = <T = any>({
[api, isLoadAll, pageSize, params, requesting, toast]
);
useQuery(['init', pageNum], () => getData(pageNum, pageNum === 1));
const nextPage = useCallback(() => getData(pageNum + 1), [getData, pageNum]);
useQuery(['init'], () => getData(1, true));
return {
pageNum,
pageSize,
setPageNum,
total,
data,
getData,
requesting
requesting,
isLoadAll,
nextPage
};
};

View File

@@ -4,6 +4,7 @@ import axios from 'axios';
import { connectToDatabase, User, Pay } from '@/service/mongo';
import { authToken } from '@/service/utils/tools';
import { PaySchema } from '@/types/mongoSchema';
import dayjs from 'dayjs';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -28,6 +29,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
`https://sif268.laf.dev/wechat-order-query?order_number=${payOrder.orderId}&api_key=${process.env.WXPAYCODE}`
);
// 校验下是否超过一天
const orderTime = dayjs(payOrder.createTime);
const diffInHours = dayjs().diff(orderTime, 'hours');
if (data.trade_state === 'SUCCESS') {
// 订单已支付
try {
@@ -47,7 +52,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
$inc: { balance: payOrder.price }
});
jsonRes(res, {
data: 'success'
data: '支付成功'
});
}
} catch (error) {
@@ -56,17 +61,19 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
});
console.log(error);
}
} else if (data.trade_state === 'CLOSED') {
} else if (data.trade_state === 'CLOSED' || diffInHours > 24) {
// 订单已关闭
await Pay.findByIdAndUpdate(payId, {
status: 'CLOSED'
});
jsonRes(res, {
data: '订单已过期'
});
} else {
throw new Error(data.trade_state_desc);
}
throw new Error('订单已过期');
} catch (err) {
console.log(err);
// console.log(err);
jsonRes(res, {
code: 500,
error: err

View File

@@ -28,8 +28,9 @@ const ImportDataModal = dynamic(() => import('./components/ImportDataModal'));
const DataList = () => {
const {
setPageNum,
pageNum,
nextPage,
isLoadAll,
requesting,
data: dataList,
getData
} = usePaging<DataListItem>({
@@ -75,7 +76,7 @@ const DataList = () => {
</Card>
{/* 数据表 */}
<Card mt={3} flex={'1 0 0'} h={['auto', '0']} px={6} py={4}>
<ScrollData h={'100%'} nextPage={() => setPageNum(pageNum + 1)}>
<ScrollData h={'100%'} nextPage={nextPage} isLoadAll={isLoadAll} requesting={requesting}>
<TableContainer>
<Table>
<Thead>

View File

@@ -32,6 +32,7 @@ import { PaySchema } from '@/types/mongoSchema';
import dayjs from 'dayjs';
import { formatPrice } from '@/utils/user';
import WxConcat from '@/components/WxConcat';
import ScrollData from '@/components/ScrollData';
const PayModal = dynamic(() => import('./components/PayModal'));
@@ -52,7 +53,12 @@ const NumberSetting = () => {
control,
name: 'accounts'
});
const { setPageNum, data: bills } = usePaging<UserBillType>({
const {
nextPage,
isLoadAll,
requesting,
data: bills
} = usePaging<UserBillType>({
api: getUserBills,
pageSize: 30
});
@@ -84,9 +90,14 @@ const NumberSetting = () => {
const handleRefreshPayOrder = useCallback(
async (payId: string) => {
try {
setLoading(true);
await checkPayResult(payId);
try {
const data = await checkPayResult(payId);
toast({
title: data,
status: 'info'
});
const res = await getPayOrders();
setPayOrders(res);
} catch (error: any) {
@@ -96,6 +107,7 @@ const NumberSetting = () => {
});
console.log(error);
}
setLoading(false);
},
[setLoading, toast]
@@ -196,8 +208,8 @@ const NumberSetting = () => {
</Table>
</TableContainer>
</Card>
<Card mt={6} px={6} py={4}>
<Flex alignItems={'flex-end'}>
<Card mt={6} py={4}>
<Flex alignItems={'flex-end'} px={6} mb={1}>
<Box fontSize={'xl'} fontWeight={'bold'}>
</Box>
@@ -205,7 +217,7 @@ const NumberSetting = () => {
wx联系
</Button>
</Flex>
<TableContainer maxH={'400px'} overflowY={'auto'}>
<TableContainer maxH={'400px'} overflowY={'auto'} px={6}>
<Table>
<Thead>
<Tr>
@@ -240,11 +252,18 @@ const NumberSetting = () => {
</Table>
</TableContainer>
</Card>
<Card mt={6} px={6} py={4}>
<Box fontSize={'xl'} fontWeight={'bold'}>
使(30)
<Card mt={6} py={4}>
<Box fontSize={'xl'} fontWeight={'bold'} px={6} mb={1}>
使
</Box>
<TableContainer maxH={'400px'} overflowY={'auto'}>
<ScrollData
maxH={'400px'}
px={6}
isLoadAll={isLoadAll}
requesting={requesting}
nextPage={nextPage}
>
<TableContainer>
<Table>
<Thead>
<Tr>
@@ -266,6 +285,7 @@ const NumberSetting = () => {
</Tbody>
</Table>
</TableContainer>
</ScrollData>
</Card>
{showPay && <PayModal onClose={() => setShowPay(false)} />}
{/* wx 联系 */}