chore: 以本地为准,上传全部并替换 GitHub

This commit is contained in:
卡若
2026-02-03 11:36:53 +08:00
parent 1219166526
commit b404bf546e
131 changed files with 37618 additions and 3930 deletions

315
app/api/ai-chat/route.ts Normal file
View File

@@ -0,0 +1,315 @@
/**
* AI 智能助手 API
* 支持自然语言查询用户数据
*/
import { NextRequest, NextResponse } from "next/server"
import { getMongoClient, intelligentSearch, queryFullProfile, getDatabaseStats } from "@/lib/mongodb"
// 消息类型
interface ChatMessage {
role: "user" | "assistant" | "system"
content: string
timestamp?: string
data?: any
}
// 解析用户意图
function parseIntent(message: string): { type: string; query?: string; params?: any } {
const msg = message.trim().toLowerCase()
// 查询手机号
const phoneMatch = message.match(/(?:查|查询|搜索|找)?[:\s]*(\+?86)?1[3-9]\d{9}/g)
if (phoneMatch) {
const phone = phoneMatch[0].replace(/[查询搜索找::\s]/g, '').replace(/^\+?86/, '')
return { type: "query_phone", query: phone }
}
// 查询 QQ
const qqMatch = message.match(/(?:qq|QQ)[:\s]*(\d{5,11})|(\d{5,11})\s*(?:qq|QQ)/i)
if (qqMatch) {
return { type: "query_qq", query: qqMatch[1] || qqMatch[2] }
}
// 系统状态
if (msg.includes("状态") || msg.includes("统计") || msg.includes("总量")) {
return { type: "system_status" }
}
// RFM 分析
if (msg.includes("rfm") || msg.includes("估值") || msg.includes("价值")) {
return { type: "rfm_analysis" }
}
// 高价值用户
if (msg.includes("高价值") || msg.includes("top") || msg.includes("排行")) {
const limitMatch = msg.match(/(\d+)/)
return { type: "high_value_users", params: { limit: limitMatch ? parseInt(limitMatch[1]) : 10 } }
}
// 帮助
if (msg.includes("帮助") || msg.includes("help") || msg === "?") {
return { type: "help" }
}
// 通用搜索
return { type: "search", query: message }
}
// 格式化用户数据
function formatUserData(user: any): string {
if (!user) return "未找到用户信息"
const lines: string[] = []
if (user.name) lines.push(`👤 姓名: ${user.name}`)
if (user.phone_masked) lines.push(`📱 手机: ${user.phone_masked}`)
if (user.qq) lines.push(`💬 QQ: ${user.qq}`)
if (user.gender) lines.push(`⚧ 性别: ${user.gender}`)
if (user.age_range) lines.push(`📅 年龄段: ${user.age_range}`)
if (user.province || user.city) lines.push(`📍 地区: ${user.province || ''}${user.city || ''}`)
if (user.evaluation_score || user.user_evaluation_score) {
lines.push(`⭐ 估值分: ${user.evaluation_score || user.user_evaluation_score}`)
}
if (user.user_level) lines.push(`🏆 等级: ${user.user_level}`)
if (user.carrier) lines.push(`📶 运营商: ${user.carrier}`)
if (user.tags && user.tags.length > 0) lines.push(`🏷️ 标签: ${user.tags.join(', ')}`)
return lines.join('\n')
}
// 处理 AI 聊天
async function processChat(message: string): Promise<ChatMessage> {
const startTime = Date.now()
const intent = parseIntent(message)
try {
switch (intent.type) {
case "query_phone": {
const result = await queryFullProfile(intent.query!)
if (result.valuation || result.qqPhone) {
const user = {
...result.valuation,
qq: result.qqPhone?.qq,
carrier: result.qqPhone?.运营商
}
return {
role: "assistant",
content: `🎯 手机号 ${intent.query} 查询结果:\n\n${formatUserData(user)}\n\n⏱ 查询耗时: ${Date.now() - startTime}ms`,
data: result
}
} else {
return {
role: "assistant",
content: `❌ 未找到手机号 ${intent.query} 的相关信息\n\n💡 提示: 请检查手机号是否正确11位数字`
}
}
}
case "query_qq": {
const client = await getMongoClient()
const qqDb = client.db("KR_腾讯")
let qqDoc = await qqDb.collection("QQ+手机").findOne({ qq: intent.query })
if (!qqDoc) {
qqDoc = await qqDb.collection("QQ+手机").findOne({ qq: parseInt(intent.query!) })
}
if (qqDoc) {
const phone = qqDoc.phone || qqDoc.
let userInfo = `🎯 QQ ${intent.query} 查询结果:\n\n`
userInfo += `💬 QQ: ${qqDoc.qq}\n`
userInfo += `📱 手机: ${phone ? phone.toString().replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') : '未知'}\n`
userInfo += `📊 QQ评分: ${qqDoc.QQ号评分 || 'N/A'}\n`
userInfo += `📊 手机评分: ${qqDoc. || 'N/A'}\n`
userInfo += `📍 地区: ${qqDoc. || ''}${qqDoc. || ''}\n`
userInfo += `📶 运营商: ${qqDoc. || 'N/A'}\n`
userInfo += `\n⏱ 查询耗时: ${Date.now() - startTime}ms`
return {
role: "assistant",
content: userInfo,
data: qqDoc
}
} else {
return {
role: "assistant",
content: `❌ 未找到 QQ ${intent.query} 的相关信息`
}
}
}
case "system_status": {
const stats = await getDatabaseStats()
return {
role: "assistant",
content: `📊 神射手系统状态\n\n` +
`🟢 连接状态: ${stats.connected ? '正常' : '异常'}\n` +
`📁 数据库数: ${stats.databases?.length || 0}\n` +
`📄 总记录数: ${(stats.totalDocuments / 1e8).toFixed(2)} 亿条\n` +
`💾 总数据量: ${(stats.totalSize / 1e9).toFixed(2)} GB\n` +
`⏱️ 响应延迟: ${stats.latency}ms`,
data: stats
}
}
case "rfm_analysis": {
const client = await getMongoClient()
const db = client.db("KR")
const pipeline = [
{ $group: { _id: "$user_level", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
]
const results = await db.collection("用户估值").aggregate(pipeline).toArray()
let content = `📈 RFM 用户分布统计\n\n`
let total = 0
results.forEach(r => {
const level = r._id || '未分级'
content += `${level}: ${(r.count / 10000).toFixed(1)}\n`
total += r.count
})
content += `\n📊 总用户数: ${(total / 10000).toFixed(1)}`
content += `\n⏱ 统计耗时: ${Date.now() - startTime}ms`
return {
role: "assistant",
content,
data: results
}
}
case "high_value_users": {
const limit = intent.params?.limit || 10
const client = await getMongoClient()
const db = client.db("KR")
const users = await db.collection("用户估值")
.find({ user_evaluation_score: { $exists: true } })
.sort({ user_evaluation_score: -1 })
.limit(limit)
.toArray()
let content = `🏆 高价值用户 TOP${limit}\n\n`
users.forEach((u, i) => {
const phone = u.phone?.replace(/(\+?86)?(\d{3})\d{4}(\d{4})/, '$2****$3') || '***'
content += `${i + 1}. ${u.name || '未知'} (${phone}) - 估值: ${u.user_evaluation_score}\n`
})
content += `\n⏱ 查询耗时: ${Date.now() - startTime}ms`
return {
role: "assistant",
content,
data: users
}
}
case "help": {
return {
role: "assistant",
content: `🎯 神射手 AI 助手使用指南\n\n` +
`📱 查询手机号:\n "查 13800138000" 或 "13800138000"\n\n` +
`💬 查询 QQ:\n "28533368 qq" 或 "qq 28533368"\n\n` +
`📊 系统状态:\n "系统状态" 或 "统计"\n\n` +
`📈 RFM 分析:\n "RFM分析" 或 "用户估值"\n\n` +
`🏆 高价值用户:\n "高价值用户 TOP10"\n\n` +
`💡 数据覆盖: 20亿+用户207GB数据`
}
}
case "search":
default: {
// 尝试智能搜索
const result = await intelligentSearch(intent.query || message, { limit: 5 })
if (result.total > 0) {
let content = `🔍 搜索结果 (共${result.total}条)\n\n`
result.users.slice(0, 5).forEach((u, i) => {
content += `${i + 1}. ${u.name || '未知'} - ${u.city || ''} - 估值: ${u.user_evaluation_score || 'N/A'}\n`
})
content += `\n⏱ 查询耗时: ${Date.now() - startTime}ms`
return {
role: "assistant",
content,
data: result
}
} else {
return {
role: "assistant",
content: `🤔 我不太理解 "${message}"\n\n` +
`💡 你可以尝试:\n` +
`- 查询手机号: "查 13800138000"\n` +
`- 查询QQ: "28533368 qq"\n` +
`- 输入 "帮助" 查看更多功能`
}
}
}
}
} catch (error: any) {
console.error("AI Chat 错误:", error)
return {
role: "assistant",
content: `⚠️ 查询出错: ${error.message}\n\n请稍后重试或检查数据库连接`
}
}
}
/**
* POST /api/ai-chat
* AI 对话接口
*/
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const { message, history = [] } = body
if (!message || !message.trim()) {
return NextResponse.json({
success: false,
error: "消息不能为空"
}, { status: 400 })
}
const response = await processChat(message)
response.timestamp = new Date().toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" })
return NextResponse.json({
success: true,
response
})
} catch (error: any) {
console.error("AI Chat API 错误:", error)
return NextResponse.json({
success: false,
error: error.message,
response: {
role: "assistant",
content: `⚠️ 服务暂时不可用: ${error.message}`,
timestamp: new Date().toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" })
}
}, { status: 500 })
}
}
/**
* GET /api/ai-chat
* 获取 AI 助手状态
*/
export async function GET() {
try {
const stats = await getDatabaseStats()
return NextResponse.json({
status: "online",
model: "神射手 AI v1.0",
capabilities: ["用户查询", "QQ查询", "RFM分析", "智能搜索"],
database: {
connected: stats.connected,
totalUsers: stats.totalDocuments,
latency: stats.latency
}
})
} catch (error: any) {
return NextResponse.json({
status: "degraded",
error: error.message
})
}
}