taxonomy.js
9.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/**
* 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,
};