// 身份识别与合并服务 // 实现基于数据字典标识的关键字段的匹配逻辑 import { getIdentityKeyFields } from "@/lib/data-dictionary" export interface IdentityMatch { userId: string confidence: number matchedFields: string[] matchType: "exact" | "fuzzy" | "partial" } export interface UserIdentity { userId: string identityFields: Record } export class IdentityService { private static instance: IdentityService private userIdentities: Map = new Map() private constructor() { // 初始化一些模拟数据 this.initializeMockData() } public static getInstance(): IdentityService { if (!IdentityService.instance) { IdentityService.instance = new IdentityService() } return IdentityService.instance } private initializeMockData() { // 模拟已存在的用户身份数据 const mockUsers = [ { userId: "user_global_id_1", identityFields: { phone: "13800138000", email: "zhangsan@example.com", username: "zhangsan", fullName: "张三", }, }, { userId: "user_global_id_2", identityFields: { phone: "13912345678", email: "lisi@example.com", username: "lisi", fullName: "李四", }, }, ] mockUsers.forEach((user) => { this.userIdentities.set(user.userId, user) }) } // 根据输入数据查找匹配的用户身份 public async findMatchingIdentity(inputData: Record): Promise { const identityKeyFields = getIdentityKeyFields() const matches: IdentityMatch[] = [] for (const [userId, userIdentity] of this.userIdentities) { const matchResult = this.calculateMatch(inputData, userIdentity.identityFields, identityKeyFields) if (matchResult.confidence > 0) { matches.push({ userId, ...matchResult, }) } } // 按置信度排序 return matches.sort((a, b) => b.confidence - a.confidence) } // 计算匹配度 private calculateMatch( inputData: Record, existingData: Record, keyFields: string[], ): { confidence: number; matchedFields: string[]; matchType: "exact" | "fuzzy" | "partial" } { const matchedFields: string[] = [] let exactMatches = 0 let fuzzyMatches = 0 let totalFields = 0 for (const field of keyFields) { if (inputData[field] && existingData[field]) { totalFields++ if (this.isExactMatch(inputData[field], existingData[field])) { exactMatches++ matchedFields.push(field) } else if (this.isFuzzyMatch(inputData[field], existingData[field])) { fuzzyMatches++ matchedFields.push(field) } } } if (totalFields === 0) { return { confidence: 0, matchedFields: [], matchType: "partial" } } const confidence = (exactMatches * 1.0 + fuzzyMatches * 0.7) / totalFields let matchType: "exact" | "fuzzy" | "partial" = "partial" if (exactMatches > 0 && fuzzyMatches === 0) { matchType = "exact" } else if (exactMatches > 0 || fuzzyMatches > 0) { matchType = "fuzzy" } return { confidence, matchedFields, matchType } } // 精确匹配 private isExactMatch(value1: any, value2: any): boolean { if (typeof value1 === "string" && typeof value2 === "string") { return value1.toLowerCase().trim() === value2.toLowerCase().trim() } return value1 === value2 } // 模糊匹配 private isFuzzyMatch(value1: any, value2: any): boolean { if (typeof value1 === "string" && typeof value2 === "string") { const str1 = value1.toLowerCase().trim() const str2 = value2.toLowerCase().trim() // 简单的相似度计算 const similarity = this.calculateStringSimilarity(str1, str2) return similarity > 0.8 } return false } // 计算字符串相似度 private calculateStringSimilarity(str1: string, str2: string): number { const longer = str1.length > str2.length ? str1 : str2 const shorter = str1.length > str2.length ? str2 : str1 if (longer.length === 0) { return 1.0 } const editDistance = this.levenshteinDistance(longer, shorter) return (longer.length - editDistance) / longer.length } // 计算编辑距离 private levenshteinDistance(str1: string, str2: string): number { const matrix = [] for (let i = 0; i <= str2.length; i++) { matrix[i] = [i] } for (let j = 0; j <= str1.length; j++) { matrix[0][j] = j } for (let i = 1; i <= str2.length; i++) { for (let j = 1; j <= str1.length; j++) { if (str2.charAt(i - 1) === str1.charAt(j - 1)) { matrix[i][j] = matrix[i - 1][j - 1] } else { matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1) } } } return matrix[str2.length][str1.length] } // 创建新的用户身份 public async createNewIdentity(inputData: Record): Promise { const userId = `user_global_id_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` const identityKeyFields = getIdentityKeyFields() const identityFields: Record = {} identityKeyFields.forEach((field) => { if (inputData[field]) { identityFields[field] = inputData[field] } }) this.userIdentities.set(userId, { userId, identityFields, }) return userId } // 更新用户身份信息 public async updateIdentity(userId: string, updateData: Record): Promise { const existingIdentity = this.userIdentities.get(userId) if (existingIdentity) { const identityKeyFields = getIdentityKeyFields() identityKeyFields.forEach((field) => { if (updateData[field]) { existingIdentity.identityFields[field] = updateData[field] } }) this.userIdentities.set(userId, existingIdentity) } } // 合并用户身份 public async mergeIdentities(primaryUserId: string, secondaryUserId: string): Promise { const primaryIdentity = this.userIdentities.get(primaryUserId) const secondaryIdentity = this.userIdentities.get(secondaryUserId) if (primaryIdentity && secondaryIdentity) { // 合并身份字段,优先保留主身份的数据 Object.keys(secondaryIdentity.identityFields).forEach((field) => { if (!primaryIdentity.identityFields[field] && secondaryIdentity.identityFields[field]) { primaryIdentity.identityFields[field] = secondaryIdentity.identityFields[field] } }) this.userIdentities.set(primaryUserId, primaryIdentity) this.userIdentities.delete(secondaryUserId) } } }