feat: share窗口

This commit is contained in:
archer
2023-03-21 23:47:26 +08:00
parent d065539707
commit 984baf60f0
11 changed files with 33 additions and 13 deletions

View File

@@ -5,7 +5,8 @@ import type { InitChatResponse } from './response/chat';
/** /**
* 获取一个聊天框的ID * 获取一个聊天框的ID
*/ */
export const getChatSiteId = (modelId: string) => GET<string>(`/chat/generate?modelId=${modelId}`); export const getChatSiteId = (modelId: string, isShare = false) =>
GET<string>(`/chat/generate?modelId=${modelId}&isShare=${isShare ? 'true' : 'false'}`);
/** /**
* 获取初始化聊天内容 * 获取初始化聊天内容

View File

@@ -1,3 +1,4 @@
import { getToken } from '../utils/user';
interface StreamFetchProps { interface StreamFetchProps {
url: string; url: string;
data: any; data: any;
@@ -9,7 +10,8 @@ export const streamFetch = ({ url, data, onMessage }: StreamFetchProps) =>
const res = await fetch(url, { const res = await fetch(url, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json',
Authorization: getToken() || ''
}, },
body: JSON.stringify(data) body: JSON.stringify(data)
}); });

View File

@@ -17,6 +17,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
prompt: ChatItemType; prompt: ChatItemType;
chatId: string; chatId: string;
}; };
const { authorization } = req.headers;
try { try {
if (!chatId || !prompt) { if (!chatId || !prompt) {
@@ -25,7 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
await connectToDatabase(); await connectToDatabase();
const { chat, userApiKey, systemKey, userId } = await authChat(chatId); const { chat, userApiKey, systemKey, userId } = await authChat(chatId, authorization);
const model: ModelSchema = chat.modelId; const model: ModelSchema = chat.modelId;

View File

@@ -7,7 +7,10 @@ import type { ModelSchema } from '@/types/mongoSchema';
/* 获取我的模型 */ /* 获取我的模型 */
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) { export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try { try {
const { modelId } = req.query; const { modelId, isShare = 'false' } = req.query as {
modelId: string;
isShare?: 'true' | 'false';
};
const { authorization } = req.headers; const { authorization } = req.headers;
if (!authorization) { if (!authorization) {
@@ -40,6 +43,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
expiredTime: Date.now() + model.security.expiredTime, expiredTime: Date.now() + model.security.expiredTime,
loadAmount: model.security.maxLoadAmount, loadAmount: model.security.maxLoadAmount,
updateTime: Date.now(), updateTime: Date.now(),
isShare: isShare === 'true',
content: [] content: []
}); });

View File

@@ -12,6 +12,7 @@ import { pushBill } from '@/service/events/bill';
export default async function handler(req: NextApiRequest, res: NextApiResponse) { export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try { try {
const { prompt, chatId } = req.body as { prompt: ChatItemType[]; chatId: string }; const { prompt, chatId } = req.body as { prompt: ChatItemType[]; chatId: string };
const { authorization } = req.headers;
if (!prompt || !chatId) { if (!prompt || !chatId) {
throw new Error('缺少参数'); throw new Error('缺少参数');
@@ -19,7 +20,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
await connectToDatabase(); await connectToDatabase();
const { chat, userApiKey, systemKey, userId } = await authChat(chatId); const { chat, userApiKey, systemKey, userId } = await authChat(chatId, authorization);
const model = chat.modelId; const model = chat.modelId;

View File

@@ -281,7 +281,7 @@ const SlideBar = ({
mr={3} mr={3}
onClick={async () => { onClick={async () => {
copyData( copyData(
`${location.origin}/chat?chatId=${await getChatSiteId(modelId)}`, `${location.origin}/chat?chatId=${await getChatSiteId(modelId, true)}`,
'已复制分享链接' '已复制分享链接'
); );
onCloseShare(); onCloseShare();
@@ -299,7 +299,7 @@ const SlideBar = ({
onClose(); onClose();
}} }}
> >
</Button> </Button>
</ModalFooter> </ModalFooter>
</ModalContent> </ModalContent>

View File

@@ -12,8 +12,8 @@ const BillSchema = new Schema({
required: true required: true
}, },
time: { time: {
type: Number, type: Date,
default: () => Date.now() default: () => new Date()
}, },
textLen: { textLen: {
// 提示词+响应的总字数 // 提示词+响应的总字数

View File

@@ -25,6 +25,10 @@ const ChatSchema = new Schema({
type: Number, type: Number,
required: true required: true
}, },
isShare: {
type: Boolean,
default: false
},
content: { content: {
type: [ type: [
{ {

View File

@@ -2,6 +2,7 @@ import { Configuration, OpenAIApi } from 'openai';
import { Chat } from '../mongo'; import { Chat } from '../mongo';
import type { ChatPopulate } from '@/types/mongoSchema'; import type { ChatPopulate } from '@/types/mongoSchema';
import { formatPrice } from '@/utils/user'; import { formatPrice } from '@/utils/user';
import { authToken } from './tools';
export const getOpenAIApi = (apiKey: string) => { export const getOpenAIApi = (apiKey: string) => {
const configuration = new Configuration({ const configuration = new Configuration({
@@ -11,7 +12,7 @@ export const getOpenAIApi = (apiKey: string) => {
return new OpenAIApi(configuration, undefined); return new OpenAIApi(configuration, undefined);
}; };
export const authChat = async (chatId: string) => { export const authChat = async (chatId: string, authorization?: string) => {
// 获取 chat 数据 // 获取 chat 数据
const chat = await Chat.findById<ChatPopulate>(chatId) const chat = await Chat.findById<ChatPopulate>(chatId)
.populate({ .populate({
@@ -36,12 +37,17 @@ export const authChat = async (chatId: string) => {
return Promise.reject('聊天框已过期'); return Promise.reject('聊天框已过期');
} }
// 分享校验
if (!chat.isShare) {
await authToken(authorization);
}
// 获取 user 的 apiKey // 获取 user 的 apiKey
const user = chat.userId; const user = chat.userId;
const userApiKey = user.accounts?.find((item: any) => item.type === 'openai')?.value; const userApiKey = user.accounts?.find((item: any) => item.type === 'openai')?.value;
if (!userApiKey && formatPrice(user.balance) <= -1) { if (!userApiKey && formatPrice(user.balance) <= 0) {
return Promise.reject('该账号余额不足'); return Promise.reject('该账号余额不足');
} }

View File

@@ -69,6 +69,7 @@ export interface ChatSchema {
expiredTime: number; expiredTime: number;
loadAmount: number; loadAmount: number;
updateTime: number; updateTime: number;
isShare: boolean;
content: ChatItemType[]; content: ChatItemType[];
} }
export interface ChatPopulate extends ChatSchema { export interface ChatPopulate extends ChatSchema {
@@ -80,7 +81,7 @@ export interface BillSchema {
_id: string; _id: string;
userId: string; userId: string;
chatId: string; chatId: string;
time: number; time: Date;
textLen: number; textLen: number;
price: number; price: number;
} }

View File

@@ -8,7 +8,7 @@ export const adaptBill = (bill: BillSchema): UserBillType => {
id: bill._id, id: bill._id,
userId: bill.userId, userId: bill.userId,
chatId: bill.chatId, chatId: bill.chatId,
time: dayjs(bill.time).format('YYYY/MM/DD hh:mm:ss'), time: dayjs(bill.time).format('YYYY/MM/DD HH:mm:ss'),
textLen: bill.textLen, textLen: bill.textLen,
price: formatPrice(bill.price) price: formatPrice(bill.price)
}; };