const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() // 基础 15 品类 + 扩展关键词(覆盖剩余 68 条线索的常见标题模式) const EXTENDED_CATEGORIES = { '钢材': ['钢', '钢管', '钢板', '钢筋', '型材', '铜覆', '热镀锌', '塔筒', '金属', '圆线', '钢绞线', '角钢'], '混凝土': ['混凝土', '商混', '商品砼', '水泥', '砂浆', '砼', '灌浆料'], '阀门': ['阀门', '闸阀', '球阀', '蝶阀', '截止阀', '止回阀', '调节阀', '控制阀', '节流装置', '旁路'], '管材': ['管材', '管道', 'PVC', 'PE管', '镀锌管', '无缝管', '螺旋管', '给水管', '铸铁管', '膨胀节', '地砖', '面砖'], '仪表': ['仪表', '仪器', '传感器', '变送器', '流量计', '压力表', '温度计', '标准孔板', '文丘里', '监测', '监测站', '监测设备'], '电机': ['电机', '电动机', '减速机', '减速器', '变频', '电气系统'], '水泵': ['水泵', '离心泵', '潜污泵', '消防泵', '排污泵', '循环泵'], '变压器': ['变压器', '箱变', '干式变', '油浸变', '电力变压器', '换流站'], '电线电缆': ['电缆', '电线', '导线', '电力线', '控制电缆', '光缆', '架空线'], '配电箱': ['配电箱', '配电柜', '配电盘'], '开关': ['开关', '断路器', '接触器', '继电器', '熔断器', '隔离开关'], '风机': ['风机', '通风机', '排风机', '轴流风机', '离心风机'], '灯具': ['灯具', '照明灯', '路灯', '防爆灯', 'LED灯', '太阳能灯'], '涂料': ['涂料', '油漆', '防腐漆', '防火涂料', '乳胶漆', '防水涂料', '化学药剂', '聚氯化铝'], '防火门': ['防火门', '防火卷帘', '防火窗', '钢质防火', '木质防火'], '标识标牌': ['标识', '标牌', '广告', '安全标准化'], '电梯': ['电梯', '扶梯', '升降机'], '油料': ['柴油', '汽油', '润滑油', '油料'], '环保设备': ['空气净化', '净化设备', '除尘', '废气'], '网络设备': ['网络', '服务器', '计算机', '交换机', 'SVDU', '工作站'], '消防器材': ['消防', '灭火', '阻燃', '防火材料'], '施工设备': ['盾构', '钻爆', '登高车', '平台', '备品备件', '台车'], '石材': ['石材', '大理石', '花岗岩', '块石', '戈壁料'], '土工材料': ['土工布', '两布一膜', '土工膜', '防水板', '隔墙板'], '杂品': ['零星', '小五金', '棉被', '三防布', '安全培训', '化学药剂', '介质'], '工程服务': ['服务', '劳务', '可行性研究', '地质', '技术测评', '运维', '管理', '设计', '评估'], '设备配件': ['配件', '配套设备', '螺栓', '拉伸机', '设备', '汽机', '氢气储存', '压力容器', '生产线'], } async function main() { const emptyLeads = await prisma.lead.findMany({ where: { OR: [{ category: null }, { category: '' }] }, select: { id: true, title: true }, }) console.log(`空品类线索: ${emptyLeads.length} 条`) let filled = 0 const remaining = [] for (const lead of emptyLeads) { let matched = null for (const [cat, keywords] of Object.entries(EXTENDED_CATEGORIES)) { if (keywords.some((kw) => lead.title.includes(kw))) { matched = cat break } } if (matched) { await prisma.lead.update({ where: { id: lead.id }, data: { category: matched } }) filled++ } else { remaining.push(lead) } } console.log(`扩展关键词匹配: ${filled} 条`) console.log(`仍需人工: ${remaining.length} 条`) if (remaining.length > 0) { console.log('\n--- 需要人工判断的标题 ---') remaining.forEach((l, i) => console.log(`${i + 1}. ${l.title}`)) } // 新增扩展品类到 ProductCategory 表 const newCats = Object.keys(EXTENDED_CATEGORIES).filter( (c) => !['防火门', '配电箱', '电线电缆', '阀门', '钢材', '涂料', '混凝土', '变压器', '水泵', '风机', '管材', '开关', '灯具', '仪表', '电机'].includes(c), ) for (const catName of newCats) { await prisma.productCategory.upsert({ where: { name: catName }, update: { keywords: JSON.stringify(EXTENDED_CATEGORIES[catName]) }, create: { name: catName, keywords: JSON.stringify(EXTENDED_CATEGORIES[catName]) }, }) } console.log(`\n已新增/更新 ${newCats.length} 个扩展品类到 ProductCategory`) } main() .catch((e) => { console.error(e) process.exit(1) }) .finally(() => prisma.$disconnect())