229 lines
6.1 KiB
TypeScript
229 lines
6.1 KiB
TypeScript
|
|
// 数据字典和映射规则管理
|
||
|
|
// 根据需求文档中的要求,创建动态维护的数据字典
|
||
|
|
|
||
|
|
export interface DataField {
|
||
|
|
name: string
|
||
|
|
type: "string" | "number" | "boolean" | "date" | "json" | "array"
|
||
|
|
description: string
|
||
|
|
isRequired: boolean
|
||
|
|
isPII: boolean // 个人身份信息标识
|
||
|
|
isIdentityKey: boolean // 身份识别关键字段
|
||
|
|
isAIFeature: boolean // 用于AI分析的特征字段
|
||
|
|
isDistributionKey: boolean // 用于分销/返点计算的关联字段
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface SourceMapping {
|
||
|
|
sourceSystem: string
|
||
|
|
sourceField: string
|
||
|
|
targetField: string
|
||
|
|
transformRule?: string
|
||
|
|
validationRule?: string
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface DataDictionary {
|
||
|
|
coreFields: Record<string, DataField>
|
||
|
|
unifiedTags: string[]
|
||
|
|
unifiedAttributes: Record<string, DataField>
|
||
|
|
sourceMappings: Record<string, SourceMapping[]>
|
||
|
|
}
|
||
|
|
|
||
|
|
// 核心数据字典定义
|
||
|
|
export const DATA_DICTIONARY: DataDictionary = {
|
||
|
|
coreFields: {
|
||
|
|
userId: {
|
||
|
|
name: "userId",
|
||
|
|
type: "string",
|
||
|
|
description: "全局唯一用户ID",
|
||
|
|
isRequired: true,
|
||
|
|
isPII: false,
|
||
|
|
isIdentityKey: true,
|
||
|
|
isAIFeature: false,
|
||
|
|
isDistributionKey: true,
|
||
|
|
},
|
||
|
|
username: {
|
||
|
|
name: "username",
|
||
|
|
type: "string",
|
||
|
|
description: "用户名",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: true,
|
||
|
|
isIdentityKey: true,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
email: {
|
||
|
|
name: "email",
|
||
|
|
type: "string",
|
||
|
|
description: "邮箱地址",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: true,
|
||
|
|
isIdentityKey: true,
|
||
|
|
isAIFeature: false,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
phone: {
|
||
|
|
name: "phone",
|
||
|
|
type: "string",
|
||
|
|
description: "手机号码",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: true,
|
||
|
|
isIdentityKey: true,
|
||
|
|
isAIFeature: false,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
fullName: {
|
||
|
|
name: "fullName",
|
||
|
|
type: "string",
|
||
|
|
description: "真实姓名",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: true,
|
||
|
|
isIdentityKey: true,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
gender: {
|
||
|
|
name: "gender",
|
||
|
|
type: "string",
|
||
|
|
description: "性别",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: false,
|
||
|
|
isIdentityKey: false,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
birthDate: {
|
||
|
|
name: "birthDate",
|
||
|
|
type: "date",
|
||
|
|
description: "出生日期",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: true,
|
||
|
|
isIdentityKey: false,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
city: {
|
||
|
|
name: "city",
|
||
|
|
type: "string",
|
||
|
|
description: "所在城市",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: false,
|
||
|
|
isIdentityKey: false,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
province: {
|
||
|
|
name: "province",
|
||
|
|
type: "string",
|
||
|
|
description: "所在省份",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: false,
|
||
|
|
isIdentityKey: false,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
unifiedTags: [
|
||
|
|
"高价值客户",
|
||
|
|
"新用户",
|
||
|
|
"活跃用户",
|
||
|
|
"流失风险",
|
||
|
|
"科技爱好者",
|
||
|
|
"内容创作者",
|
||
|
|
"90后",
|
||
|
|
"00后",
|
||
|
|
"北京地区",
|
||
|
|
"上海地区",
|
||
|
|
"游戏爱好者",
|
||
|
|
"旅游达人",
|
||
|
|
"美食家",
|
||
|
|
],
|
||
|
|
unifiedAttributes: {
|
||
|
|
totalSpend: {
|
||
|
|
name: "totalSpend",
|
||
|
|
type: "number",
|
||
|
|
description: "总消费金额",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: false,
|
||
|
|
isIdentityKey: false,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: true,
|
||
|
|
},
|
||
|
|
lastActiveDays: {
|
||
|
|
name: "lastActiveDays",
|
||
|
|
type: "number",
|
||
|
|
description: "最后活跃天数",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: false,
|
||
|
|
isIdentityKey: false,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
contentPreference: {
|
||
|
|
name: "contentPreference",
|
||
|
|
type: "array",
|
||
|
|
description: "内容偏好",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: false,
|
||
|
|
isIdentityKey: false,
|
||
|
|
isAIFeature: true,
|
||
|
|
isDistributionKey: false,
|
||
|
|
},
|
||
|
|
distributionLevel: {
|
||
|
|
name: "distributionLevel",
|
||
|
|
type: "number",
|
||
|
|
description: "分销层级",
|
||
|
|
isRequired: false,
|
||
|
|
isPII: false,
|
||
|
|
isIdentityKey: false,
|
||
|
|
isAIFeature: false,
|
||
|
|
isDistributionKey: true,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
sourceMappings: {
|
||
|
|
douyin: [
|
||
|
|
{ sourceSystem: "douyin", sourceField: "openid", targetField: "userId", transformRule: "prefix_dy_" },
|
||
|
|
{ sourceSystem: "douyin", sourceField: "nickname", targetField: "username" },
|
||
|
|
{ sourceSystem: "douyin", sourceField: "avatar", targetField: "avatarUrl" },
|
||
|
|
],
|
||
|
|
xiaohongshu: [
|
||
|
|
{ sourceSystem: "xiaohongshu", sourceField: "openid", targetField: "userId", transformRule: "prefix_xhs_" },
|
||
|
|
{ sourceSystem: "xiaohongshu", sourceField: "nickname", targetField: "username" },
|
||
|
|
],
|
||
|
|
cunkebao_form: [
|
||
|
|
{ sourceSystem: "cunkebao_form", sourceField: "name", targetField: "fullName" },
|
||
|
|
{ sourceSystem: "cunkebao_form", sourceField: "phone", targetField: "phone" },
|
||
|
|
{ sourceSystem: "cunkebao_form", sourceField: "email", targetField: "email" },
|
||
|
|
],
|
||
|
|
touchkebao_call: [
|
||
|
|
{ sourceSystem: "touchkebao_call", sourceField: "phone_number", targetField: "phone" },
|
||
|
|
{ sourceSystem: "touchkebao_call", sourceField: "call_time", targetField: "lastContactTime" },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取字段映射规则
|
||
|
|
export function getFieldMapping(sourceSystem: string, sourceField: string): SourceMapping | undefined {
|
||
|
|
const mappings = DATA_DICTIONARY.sourceMappings[sourceSystem]
|
||
|
|
return mappings?.find((mapping) => mapping.sourceField === sourceField)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取身份识别关键字段
|
||
|
|
export function getIdentityKeyFields(): string[] {
|
||
|
|
return Object.entries(DATA_DICTIONARY.coreFields)
|
||
|
|
.filter(([_, field]) => field.isIdentityKey)
|
||
|
|
.map(([name, _]) => name)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取AI特征字段
|
||
|
|
export function getAIFeatureFields(): string[] {
|
||
|
|
return Object.entries(DATA_DICTIONARY.coreFields)
|
||
|
|
.filter(([_, field]) => field.isAIFeature)
|
||
|
|
.map(([name, _]) => name)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取分销关联字段
|
||
|
|
export function getDistributionKeyFields(): string[] {
|
||
|
|
return Object.entries(DATA_DICTIONARY.coreFields)
|
||
|
|
.filter(([_, field]) => field.isDistributionKey)
|
||
|
|
.map(([name, _]) => name)
|
||
|
|
}
|