From 4aeb1f73626337630674518d6ea03992b0952d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B1=95=E9=B9=8F?= Date: Wed, 19 Nov 2025 17:00:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(VIP=E5=8C=B9=E9=85=8D):=20=E6=94=B9?= =?UTF-8?q?=E8=BF=9BVIP=E5=AE=A2=E6=88=B7=E6=89=8B=E6=9C=BA=E5=8F=B7?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E7=AE=97=E6=B3=95=E5=B9=B6=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=E8=B0=83=E8=AF=95=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 引入基于分数的匹配机制,为不同匹配策略分配权重 添加匹配分数阈值控制有效匹配 增强调试面板显示更多匹配细节和统计信息 --- index.php | 174 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 134 insertions(+), 40 deletions(-) diff --git a/index.php b/index.php index a716755..ced1ffc 100644 --- a/index.php +++ b/index.php @@ -1082,6 +1082,7 @@ $packages_json = json_encode(array_map(function($package) { // 找出所有可能匹配的VIP客户 const potentialMatches = []; let matchedVIP = null; + let bestMatchScore = 0; for (const vip of window.allVIPCustomers) { if (!vip.phone) continue; @@ -1091,40 +1092,75 @@ $packages_json = json_encode(array_map(function($package) { console.log('检查VIP:', vip.customer_name, '手机号:', vipPhone, '标准化后:', normalizedVIPPhone); - // 多种匹配策略 - const isMatch = - // 精确匹配 - vipPhone === phone || - normalizedVIPPhone === normalizedInput || - // 包含匹配 - vipPhone.includes(phone) || - phone.includes(vipPhone) || - normalizedVIPPhone.includes(normalizedInput) || - normalizedInput.includes(normalizedVIPPhone) || - // 后几位匹配(常用于隐私保护) - (normalizedInput.length >= 4 && normalizedVIPPhone.endsWith(normalizedInput)); + // 计算匹配分数 + let matchScore = 0; - if (isMatch) { - console.log('找到匹配:', vip.customer_name, vipPhone); + // 精确匹配(最高优先级) + if (vipPhone === phone) { + matchScore = 100; + } else if (normalizedVIPPhone === normalizedInput) { + matchScore = 95; + } + // 包含匹配(中等优先级) + else if (vipPhone.includes(phone)) { + matchScore = 90; + } else if (phone.includes(vipPhone)) { + matchScore = 85; + } else if (normalizedVIPPhone.includes(normalizedInput)) { + matchScore = 80; + } else if (normalizedInput.includes(normalizedVIPPhone)) { + matchScore = 75; + } + // 后几位匹配(低优先级) + else if (normalizedInput.length >= 4 && normalizedVIPPhone.endsWith(normalizedInput)) { + matchScore = 70; + } + // 前几位匹配 + else if (normalizedInput.length >= 4 && normalizedVIPPhone.startsWith(normalizedInput)) { + matchScore = 65; + } + // 部分匹配(最低优先级) + else if (normalizedVIPPhone.includes(normalizedInput.substring(normalizedInput.length - 4))) { + matchScore = 60; + } else if (normalizedInput.length >= 6 && normalizedVIPPhone.includes(normalizedInput.substring(0, 6))) { + matchScore = 55; + } + + // 如果找到更好的匹配,更新匹配结果 + if (matchScore > bestMatchScore) { + bestMatchScore = matchScore; matchedVIP = vip; - break; // 找到第一个匹配就返回 + console.log('找到更好的匹配:', vip.customer_name, vipPhone, '分数:', matchScore); } // 记录潜在匹配供调试 - if (normalizedVIPPhone.includes(normalizedInput.substring(normalizedInput.length - 3)) || - normalizedInput.includes(normalizedVIPPhone.substring(normalizedVIPPhone.length - 3))) { - potentialMatches.push({name: vip.customer_name, phone: vipPhone}); + if (matchScore >= 50 && matchScore < bestMatchScore) { + potentialMatches.push({name: vip.customer_name, phone: vipPhone, score: matchScore}); + } else if (normalizedVIPPhone.includes(normalizedInput.substring(normalizedInput.length - 3)) || + normalizedInput.includes(normalizedVIPPhone.substring(normalizedVIPPhone.length - 3))) { + potentialMatches.push({name: vip.customer_name, phone: vipPhone, score: 40}); } } - console.log('潜在匹配列表:', potentialMatches); - console.log('最终匹配结果:', matchedVIP); + // 根据分数过滤潜在匹配,只保留分数较高的 + potentialMatches.sort((a, b) => (b.score || 0) - (a.score || 0)); - if (matchedVIP) { + console.log('潜在匹配列表:', potentialMatches); + console.log('最终匹配结果:', matchedVIP, '匹配分数:', bestMatchScore); + + // 设置最小匹配分数阈值 + const MIN_MATCH_SCORE = 55; + + // 只有当匹配分数足够高时才认为是有效匹配 + const isEffectiveMatch = matchedVIP && bestMatchScore >= MIN_MATCH_SCORE; + + if (isEffectiveMatch) { + console.log('确认有效匹配,分数:', bestMatchScore); // 显示VIP客户提示 tipDiv.innerHTML = ` 👑 检测到VIP客户!
该手机号属于 VIP客户:${matchedVIP.customer_name}
+ 匹配度: ${bestMatchScore}分
@@ -1136,12 +1172,17 @@ $packages_json = json_encode(array_map(function($package) { let message = '💡 提示:未找到该手机号的VIP客户
'; message += '如果此客户是VIP客户,请检查手机号是否正确'; - // 如果有潜在匹配,添加提示 + // 如果有潜在匹配,添加提示并显示匹配分数 if (potentialMatches.length > 0) { message += '

可能相关的VIP客户:
'; potentialMatches.slice(0, 3).forEach(vip => { - message += `- ${vip.name} (${vip.phone})
`; + const scoreText = vip.score ? ` (匹配度: ${vip.score}分)` : ''; + message += `- ${vip.name} (${vip.phone})${scoreText}
`; }); + } else if (matchedVIP && bestMatchScore > 0) { + // 如果有低分数匹配,也显示出来 + message += `

相似手机号的VIP客户:
`; + message += `- ${matchedVIP.customer_name} (${matchedVIP.phone}) (匹配度: ${bestMatchScore}分)
`; } tipDiv.innerHTML = message; @@ -1149,13 +1190,17 @@ $packages_json = json_encode(array_map(function($package) { tipDiv.style.display = 'block'; } - // 记录到调试面板 - logSearchToDebugPanel(phone, matchedVIP, potentialMatches); - + // 增强的调试日志 console.log('--- 结束检查手机号 ---'); + console.log('检查总结: 输入手机号=', phone, '标准化后=', normalizedInput, 'VIP客户总数=', window.allVIPCustomers.length, '有效匹配=', isEffectiveMatch); - // 记录到调试面板 - logSearchToDebugPanel(phone, matchedVIP, potentialMatches); + // 记录到调试面板,包含更详细的信息 + logSearchToDebugPanel(phone, matchedVIP, potentialMatches, { + normalizedInput, + matchScore: bestMatchScore, + isEffectiveMatch, + vipCount: window.allVIPCustomers.length + }); } // VIP客户搜索调试面板 @@ -1232,33 +1277,82 @@ $packages_json = json_encode(array_map(function($package) { } // 记录搜索历史到调试面板 - function logSearchToDebugPanel(phone, result, potentialMatches) { + function logSearchToDebugPanel(phone, result, potentialMatches, searchInfo = {}) { const historyElem = document.getElementById('debug-search-history'); if (!historyElem) return; const timestamp = new Date().toLocaleTimeString(); + const { normalizedInput, matchScore, isEffectiveMatch, vipCount } = searchInfo; const logEntry = document.createElement('div'); - logEntry.style.cssText = 'border-bottom: 1px solid #eee; padding: 5px 0;'; + logEntry.style.cssText = 'border-bottom: 1px solid #eee; padding: 8px 0; font-size: 12px;'; - let resultHtml = '未匹配'; - if (result) { - resultHtml = `匹配成功: ${result.customer_name} (${result.phone})`; + // 构建日志内容 + let logContent = ` +
[${timestamp}] 搜索: ${phone}
+ `; + + // 添加详细信息 + if (normalizedInput) { + logContent += ` +
标准化: ${normalizedInput}
+ `; } - logEntry.innerHTML = ` -
[${timestamp}] 搜索: ${phone}
-
结果: ${resultHtml}
- `; + if (vipCount !== undefined) { + logContent += ` +
数据库中VIP客户数: ${vipCount}
+ `; + } + + // 显示匹配结果 + let resultHtml = '未匹配'; + if (isEffectiveMatch !== undefined) { + if (isEffectiveMatch && result) { + resultHtml = `匹配成功: ${result.customer_name} (${result.phone})`; + if (matchScore !== undefined) { + logContent += ` +
结果: ${resultHtml}
+
匹配度: ${matchScore}分
+ `; + } else { + logContent += ` +
结果: ${resultHtml}
+ `; + } + } else { + if (result && matchScore !== undefined) { + resultHtml = `相似匹配: ${result.customer_name} (${result.phone}) (匹配度: ${matchScore}分)`; + } + logContent += ` +
结果: ${resultHtml}
+ `; + } + } else if (result) { + // 兼容旧版本调用 + resultHtml = `匹配成功: ${result.customer_name} (${result.phone})`; + logContent += ` +
结果: ${resultHtml}
+ `; + } else { + logContent += ` +
结果: ${resultHtml}
+ `; + } // 如果有潜在匹配,也显示出来 if (potentialMatches && potentialMatches.length > 0) { let potentialHtml = '
潜在匹配: '; - potentialHtml += potentialMatches.slice(0, 2).map(v => `${v.name} (${v.phone})`).join(', '); + potentialHtml += potentialMatches.slice(0, 2).map(v => { + const scoreText = v.score ? ` (${v.score}分)` : ''; + return `${v.name} (${v.phone})${scoreText}`; + }).join(', '); if (potentialMatches.length > 2) potentialHtml += '...'; potentialHtml += '
'; - logEntry.innerHTML += potentialHtml; + logContent += potentialHtml; } + logEntry.innerHTML = logContent; + // 添加到历史的顶部 if (historyElem.firstChild) { historyElem.insertBefore(logEntry, historyElem.firstChild); @@ -1267,7 +1361,7 @@ $packages_json = json_encode(array_map(function($package) { } // 限制历史记录数量 - while (historyElem.children.length > 10) { + while (historyElem.children.length > 20) { historyElem.removeChild(historyElem.lastChild); } }