Commit 2fce7620 by archer

feat: custom title and set history top

parent 7fe39c25
import { GET, POST, DELETE } from './request'; import { GET, POST, DELETE, PUT } from './request';
import type { HistoryItemType } from '@/types/chat'; import type { HistoryItemType } from '@/types/chat';
import type { InitChatResponse, InitShareChatResponse } from './response/chat'; import type { InitChatResponse, InitShareChatResponse } from './response/chat';
import { RequestPaging } from '../types/index'; import { RequestPaging } from '../types/index';
...@@ -6,6 +6,7 @@ import type { ShareChatSchema } from '@/types/mongoSchema'; ...@@ -6,6 +6,7 @@ import type { ShareChatSchema } from '@/types/mongoSchema';
import type { ShareChatEditType } from '@/types/model'; import type { ShareChatEditType } from '@/types/model';
import { Obj2Query } from '@/utils/tools'; import { Obj2Query } from '@/utils/tools';
import { QuoteItemType } from '@/pages/api/openapi/kb/appKbSearch'; import { QuoteItemType } from '@/pages/api/openapi/kb/appKbSearch';
import type { Props as UpdateHistoryProps } from '@/pages/api/chat/history/updateChatHistory';
/** /**
* 获取初始化聊天内容 * 获取初始化聊天内容
...@@ -17,7 +18,7 @@ export const getInitChatSiteInfo = (modelId: '' | string, chatId: '' | string) = ...@@ -17,7 +18,7 @@ export const getInitChatSiteInfo = (modelId: '' | string, chatId: '' | string) =
* 获取历史记录 * 获取历史记录
*/ */
export const getChatHistory = (data: RequestPaging) => export const getChatHistory = (data: RequestPaging) =>
POST<HistoryItemType[]>('/chat/getHistory', data); POST<HistoryItemType[]>('/chat/history/getHistory', data);
/** /**
* 删除一条历史记录 * 删除一条历史记录
...@@ -28,7 +29,7 @@ export const delChatHistoryById = (id: string) => GET(`/chat/removeHistory?id=${ ...@@ -28,7 +29,7 @@ export const delChatHistoryById = (id: string) => GET(`/chat/removeHistory?id=${
* get history quotes * get history quotes
*/ */
export const getHistoryQuote = (params: { chatId: string; historyId: string }) => export const getHistoryQuote = (params: { chatId: string; historyId: string }) =>
GET<(QuoteItemType & { _id: string })[]>(`/chat/getHistoryQuote`, params); GET<(QuoteItemType & { _id: string })[]>(`/chat/history/getHistoryQuote`, params);
/** /**
* update history quote status * update history quote status
...@@ -37,7 +38,7 @@ export const updateHistoryQuote = (params: { ...@@ -37,7 +38,7 @@ export const updateHistoryQuote = (params: {
chatId: string; chatId: string;
historyId: string; historyId: string;
quoteId: string; quoteId: string;
}) => GET(`/chat/updateHistoryQuote`, params); }) => GET(`/chat/history/updateHistoryQuote`, params);
/** /**
* 删除一句对话 * 删除一句对话
...@@ -46,13 +47,10 @@ export const delChatRecordByIndex = (chatId: string, contentId: string) => ...@@ -46,13 +47,10 @@ export const delChatRecordByIndex = (chatId: string, contentId: string) =>
DELETE(`/chat/delChatRecordByContentId?chatId=${chatId}&contentId=${contentId}`); DELETE(`/chat/delChatRecordByContentId?chatId=${chatId}&contentId=${contentId}`);
/** /**
* 修改历史记录标题 * 修改历史记录: 标题/置顶
*/ */
export const updateChatHistoryTitle = (data: { export const putChatHistory = (data: UpdateHistoryProps) =>
chatId: string; PUT('/chat/history/updateChatHistory', data);
modelId: string;
newTitle: string;
}) => POST<string>('/chat/updateChatHistoryTitle', data);
/** /**
* create a shareChat * create a shareChat
......
...@@ -2,6 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next'; ...@@ -2,6 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response'; import { jsonRes } from '@/service/response';
import { connectToDatabase, Chat } from '@/service/mongo'; import { connectToDatabase, Chat } from '@/service/mongo';
import { authUser } from '@/service/utils/auth'; import { authUser } from '@/service/utils/auth';
import type { HistoryItemType } from '@/types/chat';
/* 获取历史记录 */ /* 获取历史记录 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) { export default async function handler(req: NextApiRequest, res: NextApiResponse) {
...@@ -14,13 +15,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) ...@@ -14,13 +15,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
{ {
userId userId
}, },
'_id title modelId updateTime latestChat' '_id title top customTitle modelId updateTime latestChat'
) )
.sort({ updateTime: -1 }) .sort({ top: -1, updateTime: -1 })
.limit(20); .limit(20);
jsonRes(res, { jsonRes<HistoryItemType[]>(res, {
data data: data.map((item) => ({
_id: item._id,
updateTime: item.updateTime,
modelId: item.modelId,
title: item.customTitle || item.title,
latestChat: item.latestChat,
top: item.top
}))
}); });
} catch (err) { } catch (err) {
jsonRes(res, { jsonRes(res, {
......
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response'; import { jsonRes } from '@/service/response';
import { connectToDatabase, Chat } from '@/service/mongo'; import { connectToDatabase, Chat } from '@/service/mongo';
import { authModel } from '@/service/utils/auth';
import { authUser } from '@/service/utils/auth'; import { authUser } from '@/service/utils/auth';
export type Props = {
chatId: '' | string;
customTitle?: string;
top?: boolean;
};
/* 更新聊天标题 */ /* 更新聊天标题 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) { export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try { try {
const { chatId, modelId, newTitle } = req.body as { const { chatId, customTitle, top } = req.body as Props;
chatId: '' | string;
modelId: '' | string;
newTitle: string;
};
const { userId } = await authUser({ req, authToken: true }); const { userId } = await authUser({ req, authToken: true });
await connectToDatabase(); await connectToDatabase();
await authModel({ modelId, userId, authOwner: false }); await Chat.findOneAndUpdate(
{
await Chat.findByIdAndUpdate( _id: chatId,
chatId, userId
},
{ {
title: newTitle, ...(customTitle ? { customTitle } : {}),
customTitle: true ...(top ? { top } : { top: null })
} // 自定义标题} }
); );
jsonRes(res); jsonRes(res);
} catch (err) { } catch (err) {
......
...@@ -77,15 +77,13 @@ export async function saveChat({ ...@@ -77,15 +77,13 @@ export async function saveChat({
}); });
return _id; return _id;
} else { } else {
// 已经有记录,追加入库
const chat = await Chat.findById(chatId);
await Chat.findByIdAndUpdate(chatId, { await Chat.findByIdAndUpdate(chatId, {
$push: { $push: {
content: { content: {
$each: content $each: content
} }
}, },
...(chat && !chat.customTitle ? { title: content[0].value.slice(0, 20) } : {}), title: content[0].value.slice(0, 20),
latestChat: content[1].value, latestChat: content[1].value,
updateTime: new Date() updateTime: new Date()
}); });
......
import React, { useCallback, useRef, useState, memo } from 'react';
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalBody,
ModalCloseButton,
Input,
useDisclosure,
Button
} from '@chakra-ui/react';
export const useEditTitle = ({
title,
placeholder = ''
}: {
title: string;
placeholder?: string;
}) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const inputRef = useRef<HTMLInputElement | null>(null);
const onSuccessCb = useRef<(content: string) => void | Promise<void>>();
const onErrorCb = useRef<(err: any) => void>();
const defaultValue = useRef('');
const onOpenModal = useCallback(
({
defaultVal,
onSuccess,
onError
}: {
defaultVal: string;
onSuccess: (content: string) => any;
onError?: (err: any) => void;
}) => {
onOpen();
onSuccessCb.current = onSuccess;
onErrorCb.current = onError;
defaultValue.current = defaultVal;
},
[onOpen]
);
const onclickConfirm = useCallback(async () => {
if (!inputRef.current) return;
try {
const val = inputRef.current.value;
await onSuccessCb.current?.(val);
onClose();
} catch (err) {
onErrorCb.current?.(err);
}
}, [onClose]);
// eslint-disable-next-line react/display-name
const EditModal = useCallback(
() => (
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>{title}</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Input
ref={inputRef}
defaultValue={defaultValue.current}
placeholder={placeholder}
autoFocus
maxLength={20}
/>
</ModalBody>
<ModalFooter>
<Button mr={3} variant={'outline'} onClick={onClose}>
取消
</Button>
<Button onClick={onclickConfirm}>确认</Button>
</ModalFooter>
</ModalContent>
</Modal>
),
[isOpen, onClose, onclickConfirm, placeholder, title]
);
return {
onOpenModal,
EditModal
};
};
...@@ -32,13 +32,16 @@ const ChatSchema = new Schema({ ...@@ -32,13 +32,16 @@ const ChatSchema = new Schema({
default: '历史记录' default: '历史记录'
}, },
customTitle: { customTitle: {
type: Boolean, type: String,
default: false default: ''
}, },
latestChat: { latestChat: {
type: String, type: String,
default: '' default: ''
}, },
top: {
type: Boolean
},
content: { content: {
type: [ type: [
{ {
......
...@@ -6,13 +6,14 @@ export const connectPg = async () => { ...@@ -6,13 +6,14 @@ export const connectPg = async () => {
return global.pgClient; return global.pgClient;
} }
const maxLink = Number(process.env.VECTOR_MAX_PROCESS || 10);
global.pgClient = new Pool({ global.pgClient = new Pool({
host: process.env.PG_HOST, host: process.env.PG_HOST,
port: process.env.PG_PORT ? +process.env.PG_PORT : 5432, port: process.env.PG_PORT ? +process.env.PG_PORT : 5432,
user: process.env.PG_USER, user: process.env.PG_USER,
password: process.env.PG_PASSWORD, password: process.env.PG_PASSWORD,
database: process.env.PG_DB_NAME, database: process.env.PG_DB_NAME,
max: 20, max: maxLink,
idleTimeoutMillis: 60000, idleTimeoutMillis: 60000,
connectionTimeoutMillis: 20000 connectionTimeoutMillis: 20000
}); });
......
...@@ -33,6 +33,7 @@ export type HistoryItemType = { ...@@ -33,6 +33,7 @@ export type HistoryItemType = {
modelId: string; modelId: string;
title: string; title: string;
latestChat: string; latestChat: string;
top: boolean;
}; };
export type ShareChatHistoryItemType = { export type ShareChatHistoryItemType = {
......
...@@ -85,10 +85,12 @@ export interface ChatSchema { ...@@ -85,10 +85,12 @@ export interface ChatSchema {
userId: string; userId: string;
modelId: string; modelId: string;
expiredTime: number; expiredTime: number;
loadAmount: number;
updateTime: Date; updateTime: Date;
title: string;
customTitle: string;
latestChat: string;
top: boolean;
content: ChatItemType[]; content: ChatItemType[];
customTitle: Boolean;
} }
export interface ChatPopulate extends ChatSchema { export interface ChatPopulate extends ChatSchema {
userId: UserModelSchema; userId: UserModelSchema;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment