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 { InitChatResponse, InitShareChatResponse } from './response/chat';
import { RequestPaging } from '../types/index';
......@@ -6,6 +6,7 @@ import type { ShareChatSchema } from '@/types/mongoSchema';
import type { ShareChatEditType } from '@/types/model';
import { Obj2Query } from '@/utils/tools';
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) =
* 获取历史记录
*/
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=${
* get history quotes
*/
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
......@@ -37,7 +38,7 @@ export const updateHistoryQuote = (params: {
chatId: string;
historyId: string;
quoteId: string;
}) => GET(`/chat/updateHistoryQuote`, params);
}) => GET(`/chat/history/updateHistoryQuote`, params);
/**
* 删除一句对话
......@@ -46,13 +47,10 @@ export const delChatRecordByIndex = (chatId: string, contentId: string) =>
DELETE(`/chat/delChatRecordByContentId?chatId=${chatId}&contentId=${contentId}`);
/**
* 修改历史记录标题
* 修改历史记录: 标题/置顶
*/
export const updateChatHistoryTitle = (data: {
chatId: string;
modelId: string;
newTitle: string;
}) => POST<string>('/chat/updateChatHistoryTitle', data);
export const putChatHistory = (data: UpdateHistoryProps) =>
PUT('/chat/history/updateChatHistory', data);
/**
* create a shareChat
......
......@@ -2,6 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, Chat } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import type { HistoryItemType } from '@/types/chat';
/* 获取历史记录 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
......@@ -14,13 +15,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
{
userId
},
'_id title modelId updateTime latestChat'
'_id title top customTitle modelId updateTime latestChat'
)
.sort({ updateTime: -1 })
.sort({ top: -1, updateTime: -1 })
.limit(20);
jsonRes(res, {
data
jsonRes<HistoryItemType[]>(res, {
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) {
jsonRes(res, {
......
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, Chat } from '@/service/mongo';
import { authModel } 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) {
try {
const { chatId, modelId, newTitle } = req.body as {
chatId: '' | string;
modelId: '' | string;
newTitle: string;
};
const { chatId, customTitle, top } = req.body as Props;
const { userId } = await authUser({ req, authToken: true });
await connectToDatabase();
await authModel({ modelId, userId, authOwner: false });
await Chat.findByIdAndUpdate(
chatId,
await Chat.findOneAndUpdate(
{
_id: chatId,
userId
},
{
title: newTitle,
customTitle: true
} // 自定义标题}
...(customTitle ? { customTitle } : {}),
...(top ? { top } : { top: null })
}
);
jsonRes(res);
} catch (err) {
......
......@@ -77,15 +77,13 @@ export async function saveChat({
});
return _id;
} else {
// 已经有记录,追加入库
const chat = await Chat.findById(chatId);
await Chat.findByIdAndUpdate(chatId, {
$push: {
content: {
$each: content
}
},
...(chat && !chat.customTitle ? { title: content[0].value.slice(0, 20) } : {}),
title: content[0].value.slice(0, 20),
latestChat: content[1].value,
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({
default: '历史记录'
},
customTitle: {
type: Boolean,
default: false
type: String,
default: ''
},
latestChat: {
type: String,
default: ''
},
top: {
type: Boolean
},
content: {
type: [
{
......
......@@ -6,13 +6,14 @@ export const connectPg = async () => {
return global.pgClient;
}
const maxLink = Number(process.env.VECTOR_MAX_PROCESS || 10);
global.pgClient = new Pool({
host: process.env.PG_HOST,
port: process.env.PG_PORT ? +process.env.PG_PORT : 5432,
user: process.env.PG_USER,
password: process.env.PG_PASSWORD,
database: process.env.PG_DB_NAME,
max: 20,
max: maxLink,
idleTimeoutMillis: 60000,
connectionTimeoutMillis: 20000
});
......
......@@ -33,6 +33,7 @@ export type HistoryItemType = {
modelId: string;
title: string;
latestChat: string;
top: boolean;
};
export type ShareChatHistoryItemType = {
......
......@@ -85,10 +85,12 @@ export interface ChatSchema {
userId: string;
modelId: string;
expiredTime: number;
loadAmount: number;
updateTime: Date;
title: string;
customTitle: string;
latestChat: string;
top: boolean;
content: ChatItemType[];
customTitle: Boolean;
}
export interface ChatPopulate extends ChatSchema {
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