This commit is contained in:
Archer
2023-12-31 14:12:51 +08:00
committed by GitHub
parent ccca0468da
commit 9ccfda47b7
270 changed files with 8182 additions and 1295 deletions

View File

@@ -14,7 +14,7 @@ import {
import { BillItemType } from '@fastgpt/global/support/wallet/bill/type.d';
import dayjs from 'dayjs';
import { BillSourceMap } from '@fastgpt/global/support/wallet/bill/constants';
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools';
import MyModal from '@/components/MyModal';
import { useTranslation } from 'next-i18next';
@@ -25,49 +25,107 @@ const BillDetail = ({ bill, onClose }: { bill: BillItemType; onClose: () => void
[bill.list]
);
const {
hasModel,
hasTokens,
hasInputTokens,
hasOutputTokens,
hasTextLen,
hasDuration,
hasDataLen
} = useMemo(() => {
let hasModel = false;
let hasTokens = false;
let hasInputTokens = false;
let hasOutputTokens = false;
let hasTextLen = false;
let hasDuration = false;
let hasDataLen = false;
bill.list.forEach((item) => {
if (item.model !== undefined) {
hasModel = true;
}
if (item.tokenLen !== undefined) {
hasTokens = true;
}
if (item.inputTokens !== undefined) {
hasInputTokens = true;
}
if (item.outputTokens !== undefined) {
hasOutputTokens = true;
}
if (item.textLen !== undefined) {
hasTextLen = true;
}
if (item.duration !== undefined) {
hasDuration = true;
}
if (item.dataLen !== undefined) {
hasDataLen = true;
}
});
return {
hasModel,
hasTokens,
hasInputTokens,
hasOutputTokens,
hasTextLen,
hasDuration,
hasDataLen
};
}, [bill.list]);
return (
<MyModal
isOpen={true}
onClose={onClose}
iconSrc="/imgs/modal/bill.svg"
title={t('user.Bill Detail')}
maxW={['90vw', '700px']}
>
<ModalBody>
<Flex alignItems={'center'} pb={4}>
<Box flex={'0 0 80px'}>:</Box>
<Box flex={'0 0 80px'}>{t('wallet.bill.bill username')}:</Box>
<Box>{t(bill.memberName)}</Box>
</Flex>
<Flex alignItems={'center'} pb={4}>
<Box flex={'0 0 80px'}>:</Box>
<Box flex={'0 0 80px'}>{t('wallet.bill.Number')}:</Box>
<Box>{bill.id}</Box>
</Flex>
<Flex alignItems={'center'} pb={4}>
<Box flex={'0 0 80px'}>:</Box>
<Box flex={'0 0 80px'}>{t('wallet.bill.Time')}:</Box>
<Box>{dayjs(bill.time).format('YYYY/MM/DD HH:mm:ss')}</Box>
</Flex>
<Flex alignItems={'center'} pb={4}>
<Box flex={'0 0 80px'}>:</Box>
<Box flex={'0 0 80px'}>{t('wallet.bill.App name')}:</Box>
<Box>{t(bill.appName) || '-'}</Box>
</Flex>
<Flex alignItems={'center'} pb={4}>
<Box flex={'0 0 80px'}>:</Box>
<Box flex={'0 0 80px'}>{t('wallet.bill.Source')}:</Box>
<Box>{BillSourceMap[bill.source]}</Box>
</Flex>
<Flex alignItems={'center'} pb={4}>
<Box flex={'0 0 80px'}>:</Box>
<Box flex={'0 0 80px'}>{t('wallet.bill.Total')}:</Box>
<Box fontWeight={'bold'}>{bill.total}</Box>
</Flex>
<Box pb={4}>
<Box flex={'0 0 80px'} mb={1}>
{t('wallet.bill.Bill Module')}
</Box>
<TableContainer>
<Table>
<Thead>
<Tr>
<Th></Th>
<Th>AI模型</Th>
<Th>Token长度</Th>
<Th>{t('wallet.bill.Module name')}</Th>
{hasModel && <Th>{t('wallet.bill.Ai model')}</Th>}
{hasTokens && <Th>{t('wallet.bill.Token Length')}</Th>}
{hasInputTokens && <Th>{t('wallet.bill.Input Token Length')}</Th>}
{hasOutputTokens && <Th>{t('wallet.bill.Output Token Length')}</Th>}
{hasTextLen && <Th>{t('wallet.bill.Text Length')}</Th>}
{hasDuration && <Th>{t('wallet.bill.Duration')}</Th>}
{hasDataLen && <Th>{t('wallet.bill.Data Length')}</Th>}
<Th>()</Th>
</Tr>
</Thead>
@@ -75,9 +133,15 @@ const BillDetail = ({ bill, onClose }: { bill: BillItemType; onClose: () => void
{filterBillList.map((item, i) => (
<Tr key={i}>
<Td>{t(item.moduleName)}</Td>
<Td>{item.model || '-'}</Td>
<Td>{item.tokenLen || '-'}</Td>
<Td>{formatPrice(item.amount)}</Td>
{hasModel && <Td>{item.model ?? '-'}</Td>}
{hasTokens && <Td>{item.tokenLen ?? '-'}</Td>}
{hasInputTokens && <Td>{item.inputTokens ?? '-'}</Td>}
{hasOutputTokens && <Td>{item.outputTokens ?? '-'}</Td>}
{hasTextLen && <Td>{item.textLen ?? '-'}</Td>}
{hasDuration && <Td>{item.duration ?? '-'}</Td>}
{hasDataLen && <Td>{item.dataLen ?? '-'}</Td>}
<Td>{formatStorePrice2Read(item.amount)}</Td>
</Tr>
))}
</Tbody>

View File

@@ -29,7 +29,7 @@ import MyTooltip from '@/components/MyTooltip';
import { langMap, setLngStore } from '@/web/common/utils/i18n';
import { useRouter } from 'next/router';
import MySelect from '@/components/Select';
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools';
import { putUpdateMemberName } from '@/web/support/user/team/api';
import { getDocPath } from '@/web/common/system/doc';
@@ -239,7 +239,7 @@ const UserInfo = () => {
{t('user.team.Balance')}:&nbsp;
</Box>
<Box flex={1}>
<strong>{formatPrice(userInfo?.team?.balance).toFixed(3)}</strong>
<strong>{formatStorePrice2Read(userInfo?.team?.balance).toFixed(3)}</strong>
</Box>
{feConfigs?.show_pay && userInfo?.team?.canWrite && (
<Button size={['sm', 'md']} ml={5} onClick={onOpenPayModal}>

View File

@@ -8,7 +8,6 @@ import { getErrText } from '@fastgpt/global/common/error/utils';
import { useTranslation } from 'next-i18next';
import Markdown from '@/components/Markdown';
import MyModal from '@/components/MyModal';
import { priceMd } from '@/web/common/system/staticData';
const PayModal = ({ onClose }: { onClose: () => void }) => {
const router = useRouter();
@@ -68,13 +67,12 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
onClose={payId ? undefined : onClose}
title={t('user.Pay')}
iconSrc="/imgs/modal/pay.svg"
isCentered={!payId}
>
<ModalBody px={0} minH={payId ? 'auto' : '70vh'} display={'flex'} flexDirection={'column'}>
<ModalBody px={0} display={'flex'} flexDirection={'column'}>
{!payId && (
<>
<Grid gridTemplateColumns={'repeat(4,1fr)'} gridGap={5} mb={4} px={6}>
{[10, 20, 50, 100].map((item) => (
<Grid gridTemplateColumns={'repeat(3,1fr)'} gridGap={5} mb={4} px={6}>
{[10, 20, 50, 100, 200, 500].map((item) => (
<Button
key={item}
variant={item === inputVal ? 'solid' : 'outline'}
@@ -84,7 +82,7 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
</Button>
))}
</Grid>
<Box mb={4} px={6}>
<Box px={6}>
<Input
value={inputVal}
type={'number'}
@@ -95,9 +93,6 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
}}
></Input>
</Box>
<Box flex={[1, '1 0 0']} overflow={'overlay'} px={6}>
<Markdown source={priceMd} />
</Box>
</>
)}
{/* 付费二维码 */}

View File

@@ -15,7 +15,7 @@ import { getPayOrders, checkPayResult } from '@/web/support/wallet/pay/api';
import type { PaySchema } from '@fastgpt/global/support/wallet/pay/type.d';
import dayjs from 'dayjs';
import { useQuery } from '@tanstack/react-query';
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools';
import { useToast } from '@/web/common/hooks/useToast';
import { useLoading } from '@/web/common/hooks/useLoading';
import MyIcon from '@/components/Icon';
@@ -85,7 +85,7 @@ const PayRecordTable = () => {
<Td>
{item.createTime ? dayjs(item.createTime).format('YYYY/MM/DD HH:mm:ss') : '-'}
</Td>
<Td>{formatPrice(item.price)}</Td>
<Td>{formatStorePrice2Read(item.price)}</Td>
<Td>{item.status}</Td>
<Td>
{item.status === 'NOTPAY' && (

View File

@@ -1,9 +1,8 @@
import React, { useCallback, useMemo, useRef } from 'react';
import { Box, Flex, useTheme } from '@chakra-ui/react';
import React, { useCallback } from 'react';
import { Box, Flex, useDisclosure, useTheme } from '@chakra-ui/react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useRouter } from 'next/router';
import dynamic from 'next/dynamic';
import { clearToken } from '@/web/support/user/auth';
import { useUserStore } from '@/web/support/user/useUserStore';
import { useConfirm } from '@/web/common/hooks/useConfirm';
import PageContainer from '@/components/PageContainer';
@@ -20,11 +19,13 @@ const BillTable = dynamic(() => import('./components/BillTable'));
const PayRecordTable = dynamic(() => import('./components/PayRecordTable'));
const InformTable = dynamic(() => import('./components/InformTable'));
const ApiKeyTable = dynamic(() => import('./components/ApiKeyTable'));
const PriceBox = dynamic(() => import('@/components/support/wallet/Price'));
enum TabEnum {
'info' = 'info',
'promotion' = 'promotion',
'bill' = 'bill',
'price' = 'price',
'pay' = 'pay',
'inform' = 'inform',
'apikey' = 'apikey',
@@ -50,6 +51,15 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
}
]
: []),
...(feConfigs?.isPlus && feConfigs?.show_pay
? [
{
icon: 'support/pay/priceLight',
label: t('support.user.Price'),
id: TabEnum.price
}
]
: []),
...(feConfigs?.show_promotion
? [
{
@@ -97,6 +107,11 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
const { openConfirm, ConfirmModal } = useConfirm({
content: '确认退出登录?'
});
const {
isOpen: isOpenPriceBox,
onOpen: onOpenPriceBox,
onClose: onClosePriceBox
} = useDisclosure();
const router = useRouter();
const theme = useTheme();
@@ -109,6 +124,8 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
setUserInfo(null);
router.replace('/login');
})();
} else if (tab === TabEnum.price) {
onOpenPriceBox();
} else {
router.replace({
query: {
@@ -117,7 +134,7 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
});
}
},
[openConfirm, router, setUserInfo]
[onOpenPriceBox, openConfirm, router, setUserInfo]
);
return (
@@ -169,6 +186,8 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
</Flex>
<ConfirmModal />
</PageContainer>
{isOpenPriceBox && <PriceBox onClose={onClosePriceBox} />}
</>
);
};