chore: 以本地为准,强制同步全部内容
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
/**
|
||||
* RFM 分析 API
|
||||
* 支持 MongoDB 真实数据 + 内存计算
|
||||
*/
|
||||
|
||||
import { NextResponse } from "next/server"
|
||||
import { analyzeUser, type AnalyzeInput } from "@/services/rfm-engine"
|
||||
import { analyzeUserRFM } from "@/services/rfm-mongodb-service"
|
||||
import { generateText } from "ai"
|
||||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
/**
|
||||
* 可选 AI 标签增强:
|
||||
* - 使用 AI SDK (generateText + openai("gpt-4o")),符合统一标准 [^1]
|
||||
* - 无 OPENAI_API_KEY 时自动跳过,保持稳定
|
||||
* 可选 AI 标签增强
|
||||
*/
|
||||
async function aiTagging(chat_logs?: string[]) {
|
||||
const text = (chat_logs ?? []).slice(0, 8).join("。")
|
||||
@@ -33,13 +37,38 @@ export async function POST(req: Request) {
|
||||
const body = await req.json()
|
||||
const inputs: AnalyzeInput[] = Array.isArray(body) ? body : [body]
|
||||
const useAI = (Array.isArray(body) ? (body as any).useAI : (body as any)?.useAI) ?? false
|
||||
const useMongoData = (body as any)?.useMongoData ?? true
|
||||
|
||||
const results = []
|
||||
|
||||
for (const input of inputs) {
|
||||
const base = analyzeUser(input)
|
||||
let base: any
|
||||
let source = 'memory'
|
||||
|
||||
// 尝试从 MongoDB 获取真实数据
|
||||
if (useMongoData && input.user_id) {
|
||||
// 如果 user_id 是手机号格式,尝试从 MongoDB 查询
|
||||
const phone = input.user_id.replace(/\D/g, '')
|
||||
if (/^1[3-9]\d{9}$/.test(phone)) {
|
||||
const mongoResult = await analyzeUserRFM(phone)
|
||||
if (mongoResult.found) {
|
||||
base = mongoResult.data
|
||||
source = 'mongodb'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 MongoDB 没有数据,使用内存计算
|
||||
if (!base) {
|
||||
base = analyzeUser(input)
|
||||
source = 'memory'
|
||||
}
|
||||
|
||||
// AI 标签增强
|
||||
if (useAI) {
|
||||
const ai = await aiTagging(input.chat_logs)
|
||||
if (ai) {
|
||||
base.tags = base.tags || {}
|
||||
base.tags.emotion = ai.emotion ?? base.tags.emotion
|
||||
base.tags.intent = ai.intent ?? base.tags.intent
|
||||
if (Array.isArray(ai.behavior)) {
|
||||
@@ -47,10 +76,55 @@ export async function POST(req: Request) {
|
||||
}
|
||||
}
|
||||
}
|
||||
results.push(base)
|
||||
|
||||
results.push({ ...base, source })
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true, data: results })
|
||||
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ success: false, error: e?.message || "Invalid input" }, { status: 400 })
|
||||
console.error('RFM analyze error:', e)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: e?.message || "Invalid input"
|
||||
}, { status: 400 })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET 方法:按手机号查询用户 RFM
|
||||
*/
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const phone = searchParams.get('phone')
|
||||
|
||||
if (!phone) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: '请提供手机号参数'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
const result = await analyzeUserRFM(phone)
|
||||
|
||||
if (!result.found) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: '未找到该用户'
|
||||
}, { status: 404 })
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: result.data,
|
||||
source: 'mongodb'
|
||||
})
|
||||
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: e?.message || "查询失败"
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,51 @@
|
||||
/**
|
||||
* RFM 标签获取 API
|
||||
* 对接 MongoDB 真实数据
|
||||
*/
|
||||
|
||||
import { NextResponse } from "next/server"
|
||||
import { getRFMTagsDistribution } from "@/services/rfm-mongodb-service"
|
||||
import { getUserTags } from "@/services/rfm-engine"
|
||||
|
||||
/**
|
||||
* GET /api/rfm/get_tags
|
||||
* 获取标签分布或指定用户的标签
|
||||
*/
|
||||
export async function GET(req: Request) {
|
||||
const url = new URL(req.url)
|
||||
const userId = url.searchParams.get("user_id")
|
||||
if (!userId) {
|
||||
return NextResponse.json({ success: false, error: "missing user_id" }, { status: 400 })
|
||||
try {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const userId = searchParams.get('user_id')
|
||||
|
||||
// 如果指定用户,返回用户标签
|
||||
if (userId) {
|
||||
const userTags = getUserTags(userId)
|
||||
if (userTags) {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: userTags.tags,
|
||||
source: 'memory'
|
||||
})
|
||||
}
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: '未找到该用户标签'
|
||||
}, { status: 404 })
|
||||
}
|
||||
|
||||
// 否则返回标签分布
|
||||
const distribution = await getRFMTagsDistribution()
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: distribution,
|
||||
source: 'mongodb'
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('Get tags error:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
}, { status: 500 })
|
||||
}
|
||||
const data = getUserTags(userId)
|
||||
return NextResponse.json({ success: true, data })
|
||||
}
|
||||
|
||||
@@ -1,7 +1,54 @@
|
||||
/**
|
||||
* RFM 分组统计 API
|
||||
* 对接 MongoDB 真实数据
|
||||
*/
|
||||
|
||||
import { NextResponse } from "next/server"
|
||||
import { getMongoRFMGroupSummary } from "@/services/rfm-mongodb-service"
|
||||
import { getGroupSummary } from "@/services/rfm-engine"
|
||||
|
||||
export async function GET() {
|
||||
const data = getGroupSummary()
|
||||
return NextResponse.json({ success: true, data })
|
||||
try {
|
||||
// 尝试从 MongoDB 获取真实数据
|
||||
const mongoData = await getMongoRFMGroupSummary()
|
||||
|
||||
if (mongoData.totalUsers > 0) {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: {
|
||||
gradeCount: mongoData.gradeCount,
|
||||
valueCount: mongoData.valueCount,
|
||||
lifecycleCount: {}, // MongoDB 暂无此字段
|
||||
totalUsers: mongoData.totalUsers,
|
||||
avgScore: mongoData.avgScore
|
||||
},
|
||||
source: 'mongodb'
|
||||
})
|
||||
}
|
||||
|
||||
// 回退到内存数据
|
||||
const memData = getGroupSummary()
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: memData,
|
||||
source: 'memory'
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('RFM group summary error:', error)
|
||||
|
||||
// 返回默认数据
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: {
|
||||
gradeCount: { S: 0, A: 0, B: 0, C: 0, D: 0 },
|
||||
valueCount: { '高': 0, '中': 0, '低': 0 },
|
||||
lifecycleCount: {},
|
||||
totalUsers: 0,
|
||||
avgScore: 0
|
||||
},
|
||||
source: 'fallback',
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user