Files
FastGPT/client/src/pages/number/index.tsx
2023-06-11 19:18:40 +08:00

277 lines
8.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useCallback, useRef, useState } from 'react';
import { Card, Box, Flex, Button, Input, Grid, useDisclosure } from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { UserUpdateParams } from '@/types/user';
import { putUserInfo, getPromotionInitData } from '@/api/user';
import { useToast } from '@/hooks/useToast';
import { useGlobalStore } from '@/store/global';
import { useUserStore } from '@/store/user';
import { UserType } from '@/types/user';
import { clearCookie } from '@/utils/user';
import { useRouter } from 'next/router';
import { useQuery } from '@tanstack/react-query';
import dynamic from 'next/dynamic';
import { useSelectFile } from '@/hooks/useSelectFile';
import { compressImg } from '@/utils/file';
import { useCopyData } from '@/utils/tools';
import Loading from '@/components/Loading';
import Avatar from '@/components/Avatar';
import MyIcon from '@/components/Icon';
import Tabs from '@/components/Tabs';
const PayRecordTable = dynamic(() => import('./components/PayRecordTable'), {
loading: () => <Loading fixed={false} />,
ssr: false
});
const BilTable = dynamic(() => import('./components/BillTable'), {
loading: () => <Loading fixed={false} />,
ssr: false
});
const PromotionTable = dynamic(() => import('./components/PromotionTable'), {
loading: () => <Loading fixed={false} />,
ssr: false
});
const InformTable = dynamic(() => import('./components/InformTable'), {
loading: () => <Loading fixed={false} />,
ssr: false
});
const PayModal = dynamic(() => import('./components/PayModal'), {
loading: () => <Loading fixed={false} />,
ssr: false
});
const WxConcat = dynamic(() => import('@/components/WxConcat'), {
loading: () => <Loading fixed={false} />,
ssr: false
});
enum TableEnum {
'bill' = 'bill',
'pay' = 'pay',
'promotion' = 'promotion',
'inform' = 'inform'
}
const NumberSetting = ({ tableType }: { tableType: `${TableEnum}` }) => {
const tableList = useRef([
{ label: '账单', id: TableEnum.bill, Component: <BilTable /> },
{ label: '充值', id: TableEnum.pay, Component: <PayRecordTable /> },
{ label: '佣金', id: TableEnum.promotion, Component: <PromotionTable /> },
{ label: '通知', id: TableEnum.inform, Component: <InformTable /> }
]);
const [currentTab, setCurrentTab] = useState(tableType);
const router = useRouter();
const { copyData } = useCopyData();
const { userInfo, updateUserInfo, initUserInfo, setUserInfo } = useUserStore();
const { setLoading } = useGlobalStore();
const { register, handleSubmit, reset } = useForm<UserUpdateParams>({
defaultValues: userInfo as UserType
});
const { toast } = useToast();
const {
isOpen: isOpenPayModal,
onClose: onClosePayModal,
onOpen: onOpenPayModal
} = useDisclosure();
const {
isOpen: isOpenWxConcat,
onClose: onCloseWxConcat,
onOpen: onOpenWxConcat
} = useDisclosure();
const { File, onOpen: onOpenSelectFile } = useSelectFile({
fileType: '.jpg,.png',
multiple: false
});
const onclickSave = useCallback(
async (data: UserUpdateParams) => {
setLoading(true);
try {
await putUserInfo({
openaiKey: data.openaiKey,
avatar: data.avatar
});
updateUserInfo({
openaiKey: data.openaiKey,
avatar: data.avatar
});
reset(data);
toast({
title: '更新成功',
status: 'success'
});
} catch (error) {}
setLoading(false);
},
[reset, setLoading, toast, updateUserInfo]
);
const onSelectFile = useCallback(
async (e: File[]) => {
const file = e[0];
if (!file) return;
try {
const base64 = await compressImg({
file,
maxW: 100,
maxH: 100
});
onclickSave({
...userInfo,
avatar: base64
});
} catch (err: any) {
toast({
title: typeof err === 'string' ? err : '头像选择异常',
status: 'warning'
});
}
},
[onclickSave, toast, userInfo]
);
const onclickLogOut = useCallback(() => {
clearCookie();
setUserInfo(null);
router.replace('/login');
}, [router, setUserInfo]);
useQuery(['init'], initUserInfo, {
onSuccess(res) {
reset(res);
}
});
const { data: { invitedAmount = 0, historyAmount = 0, residueAmount = 0 } = {} } = useQuery(
['getPromotionInitData'],
getPromotionInitData
);
return (
<Box py={[5, 10]} px={'5vw'}>
<Grid gridTemplateColumns={['1fr', '3fr 300px']} gridGap={4}>
<Card px={6} py={4}>
<Flex justifyContent={'space-between'}>
<Box fontSize={'xl'} fontWeight={'bold'}>
</Box>
<Button variant={'base'} size={'xs'} onClick={onclickLogOut}>
退
</Button>
</Flex>
<Flex mt={6} alignItems={'center'}>
<Box flex={'0 0 50px'}>:</Box>
<Avatar
src={userInfo?.avatar}
w={['28px', '36px']}
h={['28px', '36px']}
cursor={'pointer'}
title={'点击切换头像'}
onClick={onOpenSelectFile}
/>
</Flex>
<Flex mt={6} alignItems={'center'}>
<Box flex={'0 0 50px'}>:</Box>
<Box>{userInfo?.username}</Box>
</Flex>
<Box mt={6}>
<Flex alignItems={'center'}>
<Box flex={'0 0 50px'}>:</Box>
<Box>
<strong>{userInfo?.balance}</strong>
</Box>
<Button size={['xs', 'sm']} w={['70px', '80px']} ml={5} onClick={onOpenPayModal}>
</Button>
</Flex>
<Box fontSize={'xs'} color={'blackAlpha.500'}>
openai openai
</Box>
</Box>
<Flex mt={6} alignItems={'center'}>
<Box flex={'0 0 85px'}>openaiKey:</Box>
<Input
{...register(`openaiKey`)}
maxW={'300px'}
placeholder={'openai账号。回车或失去焦点保存'}
size={'sm'}
onBlur={handleSubmit(onclickSave)}
onKeyDown={(e) => {
if (e.keyCode === 13) {
handleSubmit(onclickSave)();
}
}}
></Input>
</Flex>
</Card>
<Card px={6} py={4}>
<Box fontSize={'xl'} fontWeight={'bold'}>
</Box>
{[
{ label: '佣金比例', value: `${userInfo?.promotion.rate || 15}%` },
{ label: '已注册用户数', value: `${invitedAmount}` },
{ label: '累计佣金', value: `${historyAmount}` }
].map((item) => (
<Flex key={item.label} alignItems={'center'} mt={4} justifyContent={'space-between'}>
<Box w={'120px'}>{item.label}</Box>
<Box fontWeight={'bold'}>{item.value}</Box>
</Flex>
))}
<Button
mt={4}
variant={'base'}
w={'100%'}
onClick={() =>
copyData(`${location.origin}/?inviterId=${userInfo?._id}`, '已复制邀请链接')
}
>
</Button>
<Button
mt={4}
leftIcon={<MyIcon name="withdraw" w={'22px'} />}
px={4}
title={residueAmount < 50 ? '最低提现额度为50元' : ''}
isDisabled={residueAmount < 50}
variant={'base'}
colorScheme={'myBlue'}
onClick={onOpenWxConcat}
>
{residueAmount < 50 ? '50元起提' : '提现'}
</Button>
</Card>
</Grid>
<Card mt={4} px={[3, 6]} py={4}>
<Tabs
w={'200px'}
list={tableList.current}
activeId={currentTab}
size={'sm'}
onChange={(id: any) => setCurrentTab(id)}
/>
<Box>
{(() => {
const item = tableList.current.find((item) => item.id === currentTab);
return item ? item.Component : null;
})()}
</Box>
</Card>
{isOpenPayModal && <PayModal onClose={onClosePayModal} />}
{isOpenWxConcat && <WxConcat onClose={onCloseWxConcat} />}
<File onSelect={onSelectFile} />
</Box>
);
};
export default NumberSetting;
NumberSetting.getInitialProps = ({ query, req }: any) => {
return {
tableType: query?.type || TableEnum.bill
};
};