const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() const KNOWN_CATEGORIES = new Set([ '防火门', '配电箱', '电线电缆', '阀门', '钢材', '涂料', '混凝土', '变压器', '水泵', '风机', '管材', '开关', '灯具', '仪表', '电机', ]) const EXPLANATION_PREFIX = /^(让我|用户|我需要|好的|现在|首先|分析|根据|对于|这条|这个|考虑|我们|这里|注意|提示|重要|关键|总结|综上|该|其|它|他们|这些|那些|由于|因为|所以|因此|需要|可能|应该|可以|建议|希望|要求|必须)/ function cleanCategory(raw) { if (!raw) return '' let s = String(raw).trim() s = s.replace(/[\s\S]*?<\/think>/g, '').trim() s = s.replace(/\*\*/g, '').trim() s = s.replace(/^["「『]+|["」』]+$/g, '').trim() const lines = s.split('\n').map((l) => l.trim()).filter((l) => l) for (const line of lines) { if (EXPLANATION_PREFIX.test(line)) continue if (line.length > 20) continue if (line.includes(',') || line.includes('。') || line.includes(':') || line.includes(':')) continue if (line.includes(' - ') || line.includes(' – ') || line.includes('--')) { const parts = line.split(/\s*[-–]\s*/).map((p) => p.trim()).filter((p) => p) for (const p of parts) { if (KNOWN_CATEGORIES.has(p)) return p const m = p.match(/^([\u4e00-\u9fa5]{2,6})$/) if (m && !EXPLANATION_PREFIX.test(p)) return m[1] } continue } const cleaned = line.replace(/^[\d]+[\.、::]\s*/, '').trim() if (!cleaned || cleaned.length > 10) continue if (KNOWN_CATEGORIES.has(cleaned)) return cleaned const m = cleaned.match(/^([\u4e00-\u9fa5]{2,6})$/) if (m && !EXPLANATION_PREFIX.test(m[1])) return m[1] } return '' } async function main() { const leads = await prisma.lead.findMany({ where: { NOT: { category: null } }, select: { id: true, category: true }, }) console.log(`共 ${leads.length} 条有品类的线索`) let fixed = 0 let cleared = 0 for (const lead of leads) { const cleaned = cleanCategory(lead.category) if (cleaned !== lead.category) { await prisma.lead.update({ where: { id: lead.id }, data: { category: cleaned } }) if (cleaned === '') cleared++ else fixed++ } } console.log(`修正: ${fixed}, 清空: ${cleared}`) const remaining = await prisma.lead.count({ where: { OR: [{ category: null }, { category: '' }] } }) console.log(`剩余空品类: ${remaining}`) const dist = await prisma.lead.groupBy({ by: ['category'], where: { NOT: { category: '' } }, _count: true, orderBy: { _count: { category: 'desc' } }, take: 30, }) console.log('品类分布:') dist.forEach((d) => console.log(` ${d.category}: ${d._count}`)) } main() .catch((e) => { console.error(e) process.exit(1) }) .finally(() => prisma.$disconnect())