fix: bill, app detail

This commit is contained in:
archer
2023-07-19 08:36:06 +08:00
parent 58cbf10c85
commit 7a76f54148
12 changed files with 64 additions and 42 deletions

View File

@@ -27,19 +27,20 @@ import { useMarkdown } from '@/hooks/useMarkdown';
import { AppModuleItemType, VariableItemType } from '@/types/app'; import { AppModuleItemType, VariableItemType } from '@/types/app';
import { SystemInputEnum, VariableInputEnum } from '@/constants/app'; import { SystemInputEnum, VariableInputEnum } from '@/constants/app';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import MySelect from '@/components/Select';
import { MessageItemType } from '@/pages/api/openapi/v1/chat/completions'; import { MessageItemType } from '@/pages/api/openapi/v1/chat/completions';
import MyTooltip from '../MyTooltip';
import { fileDownload } from '@/utils/file'; import { fileDownload } from '@/utils/file';
import { htmlTemplate } from '@/constants/common'; import { htmlTemplate } from '@/constants/common';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useGlobalStore } from '@/store/global';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
const QuoteModal = dynamic(() => import('./QuoteModal')); const QuoteModal = dynamic(() => import('./QuoteModal'));
import styles from './index.module.scss';
import { QuoteItemType } from '@/pages/api/app/modules/kb/search'; import { QuoteItemType } from '@/pages/api/app/modules/kb/search';
import { FlowModuleTypeEnum } from '@/constants/flow'; import { FlowModuleTypeEnum } from '@/constants/flow';
import MyTooltip from '../MyTooltip';
import MySelect from '@/components/Select';
import styles from './index.module.scss';
const textareaMinH = '22px'; const textareaMinH = '22px';
export type StartChatFnProps = { export type StartChatFnProps = {
@@ -139,6 +140,7 @@ const ChatBox = (
const { copyData } = useCopyData(); const { copyData } = useCopyData();
const { toast } = useToast(); const { toast } = useToast();
const { userInfo } = useUserStore(); const { userInfo } = useUserStore();
const { isPc } = useGlobalStore();
const TextareaDom = useRef<HTMLTextAreaElement>(null); const TextareaDom = useRef<HTMLTextAreaElement>(null);
const controller = useRef(new AbortController()); const controller = useRef(new AbortController());
@@ -312,7 +314,7 @@ const ChatBox = (
setTimeout(() => { setTimeout(() => {
generatingScroll(); generatingScroll();
TextareaDom.current?.focus(); isPc && TextareaDom.current?.focus();
}, 100); }, 100);
} catch (err: any) { } catch (err: any) {
toast({ toast({
@@ -342,13 +344,13 @@ const ChatBox = (
[ [
isChatting, isChatting,
chatHistory, chatHistory,
setChatHistory,
resetInputVal, resetInputVal,
toast, toast,
scrollToBottom, scrollToBottom,
onStartChat, onStartChat,
generatingMessage, generatingMessage,
generatingScroll generatingScroll,
isPc
] ]
); );

View File

@@ -11,7 +11,7 @@ export enum OpenAiChatEnum {
export const defaultApp: AppSchema = { export const defaultApp: AppSchema = {
_id: '', _id: '',
userId: 'userId', userId: 'userId',
name: '模型名称', name: '模型加载中',
avatar: '/icon/logo.png', avatar: '/icon/logo.png',
intro: '', intro: '',
updateTime: Date.now(), updateTime: Date.now(),

View File

@@ -39,8 +39,12 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
const { kb_ids = [], userChatInput } = req.body as Props; const { kb_ids = [], userChatInput } = req.body as Props;
if (!userChatInput || !Array.isArray(kb_ids)) { if (!userChatInput) {
throw new Error('params is error'); throw new Error('用户输入为空');
}
if (!Array.isArray(kb_ids) || kb_ids.length === 0) {
throw new Error('没有选择知识库');
} }
const result = await kbSearch({ const result = await kbSearch({

View File

@@ -27,7 +27,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
_id: item._id, _id: item._id,
shareId: item.shareId, shareId: item.shareId,
name: item.name, name: item.name,
tokens: item.tokens, total: item.total,
maxContext: item.maxContext, maxContext: item.maxContext,
lastTime: item.lastTime lastTime: item.lastTime
})) }))

View File

@@ -188,7 +188,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
// bill // bill
finishTaskBill({ finishTaskBill({
billId billId,
shareId
}); });
} catch (err: any) { } catch (err: any) {
delTaskBill(billId); delTaskBill(billId);

View File

@@ -51,17 +51,8 @@ const Settings = ({ appId }: { appId: string }) => {
}, [appDetail, setIsLoading, toast, router]); }, [appDetail, setIsLoading, toast, router]);
// load app data // load app data
const { isLoading, refetch } = useQuery([appId], () => loadAppDetail(appId, true), { const { refetch } = useQuery([appId], () => loadAppDetail(appId, true), {
onError(err: any) { enabled: false
toast({
title: err?.message || '获取应用异常',
status: 'error'
});
router.replace('/app/list');
},
onSettled() {
router.prefetch(`/chat?appId=${appId}`);
}
}); });
return ( return (
@@ -168,7 +159,7 @@ const Settings = ({ appId }: { appId: string }) => {
)} )}
<ConfirmChild /> <ConfirmChild />
<Loading loading={isLoading} fixed={false} /> <Loading fixed={false} />
</Flex> </Flex>
); );
}; };

View File

@@ -38,6 +38,7 @@ import { defaultShareChat } from '@/constants/model';
import type { ShareChatEditType } from '@/types/app'; import type { ShareChatEditType } from '@/types/app';
import MyTooltip from '@/components/MyTooltip'; import MyTooltip from '@/components/MyTooltip';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { formatPrice } from '@/utils/user';
const Share = ({ appId }: { appId: string }) => { const Share = ({ appId }: { appId: string }) => {
const { toast } = useToast(); const { toast } = useToast();
@@ -82,12 +83,6 @@ const Share = ({ appId }: { appId: string }) => {
} }
}); });
// format share used token
const formatTokens = (tokens: number) => {
if (tokens < 10000) return tokens;
return `${(tokens / 10000).toFixed(2)}`;
};
return ( return (
<Box position={'relative'} pt={[0, 5, 8]} px={[5, 8]} minH={'50vh'}> <Box position={'relative'} pt={[0, 5, 8]} px={[5, 8]} minH={'50vh'}>
<Flex justifyContent={'space-between'}> <Flex justifyContent={'space-between'}>
@@ -118,7 +113,7 @@ const Share = ({ appId }: { appId: string }) => {
<Tr> <Tr>
<Th></Th> <Th></Th>
<Th></Th> <Th></Th>
<Th>tokens消</Th> <Th></Th>
<Th>使</Th> <Th>使</Th>
<Th></Th> <Th></Th>
</Tr> </Tr>
@@ -128,7 +123,7 @@ const Share = ({ appId }: { appId: string }) => {
<Tr key={item._id}> <Tr key={item._id}>
<Td>{item.name}</Td> <Td>{item.name}</Td>
<Td>{item.maxContext}</Td> <Td>{item.maxContext}</Td>
<Td>{formatTokens(item.tokens)}</Td> <Td>{formatPrice(item.total)}</Td>
<Td>{item.lastTime ? formatTimeToChatTime(item.lastTime) : '未使用'}</Td> <Td>{item.lastTime ? formatTimeToChatTime(item.lastTime) : '未使用'}</Td>
<Td> <Td>
<Flex> <Flex>

View File

@@ -4,6 +4,8 @@ import { Box, Flex, IconButton, useTheme } from '@chakra-ui/react';
import { useUserStore } from '@/store/user'; import { useUserStore } from '@/store/user';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { defaultApp } from '@/constants/model'; import { defaultApp } from '@/constants/model';
import { useToast } from '@/hooks/useToast';
import { useQuery } from '@tanstack/react-query';
import Tabs from '@/components/Tabs'; import Tabs from '@/components/Tabs';
import SideTabs from '@/components/SideTabs'; import SideTabs from '@/components/SideTabs';
@@ -28,8 +30,9 @@ enum TabEnum {
const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => { const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
const router = useRouter(); const router = useRouter();
const theme = useTheme(); const theme = useTheme();
const { toast } = useToast();
const { appId } = router.query as { appId: string }; const { appId } = router.query as { appId: string };
const { appDetail = defaultApp, clearAppModules } = useUserStore(); const { appDetail = defaultApp, loadAppDetail, clearAppModules } = useUserStore();
const setCurrentTab = useCallback( const setCurrentTab = useCallback(
(tab: `${TabEnum}`) => { (tab: `${TabEnum}`) => {
@@ -65,6 +68,19 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
}; };
}, []); }, []);
useQuery([appId], () => loadAppDetail(appId, true), {
onError(err: any) {
toast({
title: err?.message || '获取应用异常',
status: 'error'
});
router.replace('/app/list');
},
onSettled() {
router.prefetch(`/chat?appId=${appId}`);
}
});
return ( return (
<PageContainer> <PageContainer>
<Flex flexDirection={['column', 'row']} h={'100%'}> <Flex flexDirection={['column', 'row']} h={'100%'}>

View File

@@ -47,7 +47,7 @@ export const pushTaskBillListItem = async ({
}); });
} catch (error) {} } catch (error) {}
}; };
export const finishTaskBill = async ({ billId }: { billId: string }) => { export const finishTaskBill = async ({ billId, shareId }: { billId: string; shareId?: string }) => {
try { try {
// update bill // update bill
const res = await Bill.findByIdAndUpdate(billId, [ const res = await Bill.findByIdAndUpdate(billId, [
@@ -63,6 +63,13 @@ export const finishTaskBill = async ({ billId }: { billId: string }) => {
if (!res) return; if (!res) return;
const total = res.list.reduce((sum, item) => sum + item.amount, 0) || 0; const total = res.list.reduce((sum, item) => sum + item.amount, 0) || 0;
if (shareId) {
updateShareChatBill({
shareId,
total
});
}
console.log('finish bill:', formatPrice(total)); console.log('finish bill:', formatPrice(total));
// 账号扣费 // 账号扣费
@@ -85,16 +92,19 @@ export const delTaskBill = async (billId?: string) => {
export const updateShareChatBill = async ({ export const updateShareChatBill = async ({
shareId, shareId,
tokens total
}: { }: {
shareId: string; shareId: string;
tokens: number; total: number;
}) => { }) => {
try { try {
await ShareChat.findByIdAndUpdate(shareId, { await ShareChat.findOneAndUpdate(
$inc: { tokens }, { shareId },
{
$inc: { total },
lastTime: new Date() lastTime: new Date()
}); }
);
} catch (error) { } catch (error) {
console.log('update shareChat error', error); console.log('update shareChat error', error);
} }

View File

@@ -20,7 +20,7 @@ const ShareChatSchema = new Schema({
type: String, type: String,
required: true required: true
}, },
tokens: { total: {
type: Number, type: Number,
default: 0 default: 0
}, },

View File

@@ -25,7 +25,10 @@ export const generateToken = (userId: string) => {
/* set cookie */ /* set cookie */
export const setCookie = (res: NextApiResponse, userId: string) => { export const setCookie = (res: NextApiResponse, userId: string) => {
res.setHeader('Set-Cookie', `token=${generateToken(userId)}; Path=/; HttpOnly; Max-Age=604800`); res.setHeader(
'Set-Cookie',
`token=${generateToken(userId)}; Path=/; HttpOnly; Max-Age=604800; Samesite=None; Secure;`
);
}; };
/* clear cookie */ /* clear cookie */
export const clearCookie = (res: NextApiResponse) => { export const clearCookie = (res: NextApiResponse) => {

View File

@@ -137,7 +137,7 @@ export interface ShareChatSchema {
userId: string; userId: string;
appId: string; appId: string;
name: string; name: string;
tokens: number; total: number;
maxContext: number; maxContext: number;
lastTime: Date; lastTime: Date;
} }