164 lines
3.8 KiB
TypeScript
164 lines
3.8 KiB
TypeScript
import { prisma } from '@/lib/prisma'
|
||
import type { MessageParam } from '@anthropic-ai/sdk/resources'
|
||
|
||
export interface ConversationData {
|
||
id: string
|
||
title: string | null
|
||
messages: MessageParam[]
|
||
createdAt: Date
|
||
updatedAt: Date
|
||
}
|
||
|
||
export class ConversationService {
|
||
/**
|
||
* 创建新对话
|
||
*/
|
||
static async createConversation(userId: string, initialMessage: string): Promise<string> {
|
||
// 生成对话标题(取用户消息的前30个字符)
|
||
const title = initialMessage.length > 30
|
||
? initialMessage.substring(0, 30) + '...'
|
||
: initialMessage
|
||
|
||
const systemMessage: MessageParam = {
|
||
role: "user",
|
||
content: `你是PC DIY商店的专业AI助手。你的主要职责是:
|
||
|
||
1. 帮助用户查找和推荐PC配件
|
||
2. 提供配件的价格、性能和兼容性信息
|
||
3. 根据用户预算和需求推荐最适合的配件
|
||
4. 解答关于PC装机的技术问题`
|
||
}
|
||
|
||
const assistantGreeting: MessageParam = {
|
||
role: "assistant",
|
||
content: "您好!我是PC DIY商店的AI助手,很高兴为您服务。请告诉我您需要什么帮助?"
|
||
}
|
||
|
||
const userMessage: MessageParam = {
|
||
role: "user",
|
||
content: initialMessage
|
||
}
|
||
|
||
const initialMessages = [systemMessage, assistantGreeting, userMessage]
|
||
|
||
const conversation = await prisma.conversation.create({
|
||
data: {
|
||
userId,
|
||
title,
|
||
messages: JSON.stringify(initialMessages)
|
||
}
|
||
})
|
||
|
||
return conversation.id
|
||
}
|
||
|
||
/**
|
||
* 获取对话
|
||
*/
|
||
static async getConversation(conversationId: string, userId: string): Promise<ConversationData | null> {
|
||
const conversation = await prisma.conversation.findFirst({
|
||
where: {
|
||
id: conversationId,
|
||
userId
|
||
}
|
||
})
|
||
|
||
if (!conversation) {
|
||
return null
|
||
}
|
||
|
||
return {
|
||
id: conversation.id,
|
||
title: conversation.title,
|
||
messages: JSON.parse(conversation.messages) as MessageParam[],
|
||
createdAt: conversation.createdAt,
|
||
updatedAt: conversation.updatedAt
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新对话消息
|
||
*/
|
||
static async updateConversationMessages(
|
||
conversationId: string,
|
||
userId: string,
|
||
messages: MessageParam[]
|
||
): Promise<void> {
|
||
await prisma.conversation.updateMany({
|
||
where: {
|
||
id: conversationId,
|
||
userId
|
||
},
|
||
data: {
|
||
messages: JSON.stringify(messages),
|
||
updatedAt: new Date()
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 获取用户的对话列表
|
||
*/
|
||
static async getUserConversations(userId: string, page = 1, limit = 20) {
|
||
const skip = (page - 1) * limit
|
||
|
||
const [conversations, total] = await Promise.all([
|
||
prisma.conversation.findMany({
|
||
where: { userId },
|
||
select: {
|
||
id: true,
|
||
title: true,
|
||
createdAt: true,
|
||
updatedAt: true
|
||
},
|
||
orderBy: { updatedAt: 'desc' },
|
||
skip,
|
||
take: limit
|
||
}),
|
||
prisma.conversation.count({
|
||
where: { userId }
|
||
})
|
||
])
|
||
|
||
return {
|
||
conversations,
|
||
total,
|
||
page,
|
||
totalPages: Math.ceil(total / limit)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 删除对话
|
||
*/
|
||
static async deleteConversation(conversationId: string, userId: string): Promise<boolean> {
|
||
const result = await prisma.conversation.deleteMany({
|
||
where: {
|
||
id: conversationId,
|
||
userId
|
||
}
|
||
})
|
||
|
||
return result.count > 0
|
||
}
|
||
|
||
/**
|
||
* 更新对话标题
|
||
*/
|
||
static async updateConversationTitle(
|
||
conversationId: string,
|
||
userId: string,
|
||
title: string
|
||
): Promise<boolean> {
|
||
const result = await prisma.conversation.updateMany({
|
||
where: {
|
||
id: conversationId,
|
||
userId
|
||
},
|
||
data: { title }
|
||
})
|
||
|
||
return result.count > 0
|
||
}
|
||
}
|