taxonomy.js 9.94 KB
/**
 * taxonomy.js — 三维标签分类体系
 *
 * Role × Scene × Platform 生产力场景分类
 * 预定义 + 支持运行时扩展
 */

// ═══════════════════════════════════════════
//  角色 (Role)
// ═══════════════════════════════════════════
const ROLES = [
  { id: 'marketer',   name: '运营',       nameEn: 'Marketer',         icon: '📢' },
  { id: 'designer',   name: '设计师',     nameEn: 'Designer',         icon: '🎨' },
  { id: 'developer',  name: '开发者',     nameEn: 'Developer',        icon: '💻' },
  { id: 'writer',     name: '内容创作者', nameEn: 'Writer',           icon: '✍️' },
  { id: 'analyst',    name: '数据分析师', nameEn: 'Analyst',          icon: '📊' },
  { id: 'pm',         name: '产品经理',   nameEn: 'Product Manager',  icon: '📋' },
  { id: 'sales',      name: '销售',       nameEn: 'Sales',            icon: '💰' },
  { id: 'support',    name: '客服',       nameEn: 'Support',          icon: '🎧' },
  { id: 'researcher', name: '研究员',     nameEn: 'Researcher',       icon: '🔬' },
  { id: 'educator',   name: '教育者',     nameEn: 'Educator',         icon: '🎓' },
];

// ═══════════════════════════════════════════
//  场景 (Scene)
// ═══════════════════════════════════════════
const SCENES = [
  { id: 'video_creation',    name: '视频创作',   nameEn: 'Video Creation',      icon: '🎬' },
  { id: 'content_writing',   name: '内容写作',   nameEn: 'Content Writing',     icon: '📝' },
  { id: 'data_analysis',     name: '数据分析',   nameEn: 'Data Analysis',       icon: '📈' },
  { id: 'social_operation',  name: '社媒运营',   nameEn: 'Social Operation',    icon: '📱' },
  { id: 'ad_creative',       name: '广告创意',   nameEn: 'Ad Creative',         icon: '🎯' },
  { id: 'customer_outreach', name: '客户触达',   nameEn: 'Customer Outreach',   icon: '📧' },
  { id: 'code_develop',      name: '代码开发',   nameEn: 'Code Development',    icon: '🔧' },
  { id: 'testing_qa',        name: '测试QA',     nameEn: 'Testing & QA',        icon: '🧪' },
  { id: 'search_scraping',   name: '搜索抓取',   nameEn: 'Search & Scraping',   icon: '🔍' },
  { id: 'design_asset',      name: '设计素材',   nameEn: 'Design Assets',       icon: '🖼️' },
  { id: 'automation',        name: '流程自动化', nameEn: 'Automation',          icon: '🤖' },
  { id: 'translation',       name: '翻译本地化', nameEn: 'Translation',         icon: '🌐' },
  { id: 'report_gen',        name: '报告生成',   nameEn: 'Report Generation',   icon: '📄' },
  { id: 'ecommerce_ops',     name: '电商运营',   nameEn: 'E-Commerce Ops',      icon: '🛒' },
];

// ═══════════════════════════════════════════
//  平台 (Platform)
// ═══════════════════════════════════════════
const PLATFORMS = [
  { id: 'youtube',      name: 'YouTube',    icon: '📺' },
  { id: 'tiktok',       name: 'TikTok',     icon: '🎵' },
  { id: 'instagram',    name: 'Instagram',  icon: '📷' },
  { id: 'twitter',      name: 'Twitter/X',  icon: '🐦' },
  { id: 'wechat',       name: '微信',       icon: '💬' },
  { id: 'xiaohongshu',  name: '小红书',     icon: '📕' },
  { id: 'douyin',       name: '抖音',       icon: '🎶' },
  { id: 'bilibili',     name: 'B站',        icon: '📹' },
  { id: 'linkedin',     name: 'LinkedIn',   icon: '🔗' },
  { id: 'github',       name: 'GitHub',     icon: '🐙' },
  { id: 'shopify',      name: 'Shopify',    icon: '🛍️' },
  { id: 'amazon',       name: 'Amazon',     icon: '📦' },
  { id: 'email',        name: 'Email',      icon: '📨' },
  { id: 'slack',        name: 'Slack',      icon: '💼' },
  { id: 'general',      name: '通用',       icon: '🌐' },
];

// ═══════════════════════════════════════════
//  关键词 → 标签映射(用于自动打标)
// ═══════════════════════════════════════════
const ROLE_KEYWORDS = {
  marketer:   ['运营', '营销', 'marketing', 'campaign', 'promotion', 'growth', 'seo', 'sem'],
  designer:   ['设计', 'design', 'ui', 'ux', 'creative', 'figma', 'photoshop', 'illustrator', 'graphic', '素材'],
  developer:  ['开发', '代码', 'code', 'coding', 'develop', 'api', 'sdk', 'debug', 'git', 'deploy', 'test', 'build'],
  writer:     ['写作', '创作', 'write', 'writing', 'content', 'article', 'blog', 'novel', 'copy', 'text'],
  analyst:    ['分析', '数据', 'data', 'analysis', 'analytics', 'report', 'statistics', 'chart', 'dashboard'],
  pm:         ['产品', 'product', 'requirement', 'prd', 'roadmap', 'backlog', 'user story'],
  sales:      ['销售', 'sales', 'crm', 'lead', 'deal', 'pipeline', 'prospect', 'outreach'],
  support:    ['客服', 'support', 'ticket', 'helpdesk', 'faq', 'service', 'customer service'],
  researcher: ['研究', 'research', 'paper', 'literature', 'academic', 'survey', 'study'],
  educator:   ['教育', 'education', 'course', 'tutorial', 'teaching', 'learning', 'training'],
};

const SCENE_KEYWORDS = {
  video_creation:    ['video', '视频', 'clip', 'reel', 'short', 'animation', 'subtitle', 'thumbnail'],
  content_writing:   ['write', 'writing', '写作', 'article', 'blog', 'copy', 'text', 'seo', 'novel', '内容'],
  data_analysis:     ['data', '数据', 'analysis', 'analytics', 'chart', 'report', 'csv', 'excel', 'statistics'],
  social_operation:  ['social', '社交', '社媒', 'post', 'comment', 'follower', 'engagement', '舆情'],
  ad_creative:       ['ad', '广告', 'creative', 'banner', 'campaign', 'landing', 'cta'],
  customer_outreach: ['email', '邮件', 'outreach', 'cold', 'newsletter', 'dm', 'message'],
  code_develop:      ['code', '代码', 'develop', 'api', 'sdk', 'build', 'deploy', 'debug', 'refactor'],
  testing_qa:        ['test', '测试', 'qa', 'e2e', 'unit', 'integration', 'bug', 'regression'],
  search_scraping:   ['search', '搜索', 'scrape', 'crawl', 'fetch', 'parse', 'web', 'dom', '抓取', '爬虫'],
  design_asset:      ['design', '设计', 'asset', 'icon', 'illustration', 'mockup', 'template', '素材'],
  automation:        ['automation', '自动化', 'workflow', 'cron', 'schedule', 'pipeline', 'ci', 'cd'],
  translation:       ['translate', '翻译', 'localize', 'i18n', 'l10n', 'language', '本地化'],
  report_gen:        ['report', '报告', 'summary', 'brief', 'document', 'ppt', 'slide', '文档'],
  ecommerce_ops:     ['ecommerce', '电商', 'shop', 'product', 'inventory', 'price', 'listing', '商品'],
};

const PLATFORM_KEYWORDS = {
  youtube:     ['youtube', 'yt'],
  tiktok:      ['tiktok', 'tt'],
  instagram:   ['instagram', 'ig', 'insta'],
  twitter:     ['twitter', 'tweet', 'x.com'],
  wechat:      ['wechat', '微信', 'weixin'],
  xiaohongshu: ['xiaohongshu', '小红书', 'xhs', 'red'],
  douyin:      ['douyin', '抖音'],
  bilibili:    ['bilibili', 'b站', 'b站'],
  linkedin:    ['linkedin'],
  github:      ['github', 'gitlab', 'gitee'],
  shopify:     ['shopify'],
  amazon:      ['amazon', 'aws'],
  email:       ['email', 'mail', 'smtp', 'newsletter'],
  slack:       ['slack', 'discord', 'feishu', '飞书', 'telegram', 'whatsapp'],
};

// ═══════════════════════════════════════════
//  自动打标函数
// ═══════════════════════════════════════════

/**
 * 根据 Skill metadata 自动推断三维标签
 * @param {object} skill — { skillName, description, domain, keywords, tags, ... }
 * @returns {{ roles: string[], scenes: string[], platforms: string[] }}
 */
function autoTag(skill) {
  const text = [
    skill.skillName || '',
    skill.description || '',
    skill.domain || '',
    ...(skill.keywords || []),
    ...(skill.tags || []),
  ].join(' ').toLowerCase();

  const roles = _matchKeywords(text, ROLE_KEYWORDS, 1);
  const scenes = _matchKeywords(text, SCENE_KEYWORDS, 1);
  const platforms = _matchKeywords(text, PLATFORM_KEYWORDS, 1);

  // 默认值
  if (roles.length === 0) roles.push('developer');
  if (scenes.length === 0) scenes.push('code_develop');
  if (platforms.length === 0) platforms.push('general');

  return { roles, scenes, platforms };
}

/**
 * 关键词匹配 — 返回匹配度超过阈值的所有分类
 */
function _matchKeywords(text, keywordMap, minHits = 1) {
  const results = [];
  for (const [id, keywords] of Object.entries(keywordMap)) {
    const hits = keywords.filter(kw => text.includes(kw)).length;
    if (hits >= minHits) {
      results.push({ id, hits });
    }
  }
  // 按匹配数降序
  results.sort((a, b) => b.hits - a.hits);
  return results.map(r => r.id);
}

/**
 * 兼容旧的 scene 字段 → 新的 scenes 数组
 */
function migrateOldScene(skill) {
  if (skill.scene && (!skill.scenes || skill.scenes.length === 0)) {
    // 旧 scene ID → 新 scenes 映射
    const OLD_TO_NEW = {
      search_scraping: 'search_scraping',
      data_analysis: 'data_analysis',
      content_gen: 'content_writing',
      automation: 'automation',
      social_media: 'social_operation',
      communication: 'customer_outreach',
      ecommerce: 'ecommerce_ops',
      dev_tools: 'code_develop',
    };
    const newScene = OLD_TO_NEW[skill.scene] || skill.scene;
    skill.scenes = [newScene];
  }
  return skill;
}

module.exports = {
  ROLES,
  SCENES,
  PLATFORMS,
  ROLE_KEYWORDS,
  SCENE_KEYWORDS,
  PLATFORM_KEYWORDS,
  autoTag,
  migrateOldScene,
};