Files
promote/backend/scripts/generate-funnel-test-data.js
2025-03-11 00:36:22 +08:00

351 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 生成KOL合作转换漏斗测试数据的脚本
const { createClient } = require('@supabase/supabase-js');
const dotenv = require('dotenv');
const path = require('path');
// 加载环境变量
dotenv.config({ path: path.resolve(__dirname, '../.env') });
// 创建Supabase客户端
const supabaseUrl = process.env.SUPABASE_URL;
const supabaseKey = process.env.SUPABASE_KEY;
if (!supabaseUrl || !supabaseKey) {
console.error('缺少Supabase配置。请确保.env文件中包含SUPABASE_URL和SUPABASE_KEY');
process.exit(1);
}
const supabase = createClient(supabaseUrl, supabaseKey);
// 生成随机字符串
const generateRandomString = (length = 8) => {
return Math.random().toString(36).substring(2, length + 2);
};
// 生成随机日期
const generateRandomDate = (startDate, endDate) => {
const start = startDate.getTime();
const end = endDate.getTime();
const randomTime = start + Math.random() * (end - start);
return new Date(randomTime).toISOString();
};
// 生成随机数字
const generateRandomNumber = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
// 创建测试项目
const createTestProject = async () => {
console.log('创建测试项目...');
const projectName = `漏斗测试项目-${generateRandomString()}`;
const { data, error } = await supabase
.from('projects')
.insert({
name: projectName,
description: '这是一个用于测试KOL合作转换漏斗API的项目',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
})
.select()
.single();
if (error) {
console.error('创建测试项目失败:', error);
process.exit(1);
}
console.log(`测试项目创建成功: ${data.name} (ID: ${data.id})`);
return data.id;
};
// 创建测试KOL
const createTestInfluencers = async (count) => {
console.log(`创建${count}个测试KOL...`);
const platforms = ['instagram', 'youtube', 'tiktok', 'twitter', 'facebook'];
const influencers = [];
// 创建不同阶段的KOL
// 1. 认知阶段 - 所有KOL (100%)
// 2. 兴趣阶段 - 75%的KOL有内容
// 3. 考虑阶段 - 50%的KOL有高互动率
// 4. 意向阶段 - 30%的KOL有多篇内容
// 5. 评估阶段 - 20%的KOL有高浏览量
// 6. 购买阶段 - 10%的KOL是长期合作(3个月以上)
// 计算各阶段的KOL数量
const awarenessCount = count;
const interestCount = Math.floor(count * 0.75);
const considerationCount = Math.floor(count * 0.5);
const intentCount = Math.floor(count * 0.3);
const evaluationCount = Math.floor(count * 0.2);
const purchaseCount = Math.floor(count * 0.1);
// 创建所有KOL
for (let i = 0; i < count; i++) {
const platform = platforms[Math.floor(Math.random() * platforms.length)];
// 根据KOL所处阶段设置不同的创建日期
let createdAt;
if (i < purchaseCount) {
// 购买阶段 - 创建日期在3个月以前
createdAt = generateRandomDate(
new Date(Date.now() - 365 * 24 * 60 * 60 * 1000), // 1年前
new Date(Date.now() - 90 * 24 * 60 * 60 * 1000) // 3个月前
);
} else if (i < evaluationCount) {
// 评估阶段 - 创建日期在1-3个月之间
createdAt = generateRandomDate(
new Date(Date.now() - 90 * 24 * 60 * 60 * 1000), // 3个月前
new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // 1个月前
);
} else if (i < intentCount) {
// 意向阶段 - 创建日期在2周-1个月之间
createdAt = generateRandomDate(
new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), // 1个月前
new Date(Date.now() - 14 * 24 * 60 * 60 * 1000) // 2周前
);
} else if (i < considerationCount) {
// 考虑阶段 - 创建日期在1-2周之间
createdAt = generateRandomDate(
new Date(Date.now() - 14 * 24 * 60 * 60 * 1000), // 2周前
new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) // 1周前
);
} else if (i < interestCount) {
// 兴趣阶段 - 创建日期在3天-1周之间
createdAt = generateRandomDate(
new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // 1周前
new Date(Date.now() - 3 * 24 * 60 * 60 * 1000) // 3天前
);
} else {
// 认知阶段 - 创建日期在3天内
createdAt = generateRandomDate(
new Date(Date.now() - 3 * 24 * 60 * 60 * 1000), // 3天前
new Date() // 现在
);
}
influencers.push({
name: `测试KOL-${generateRandomString()}`,
platform,
profile_url: `https://${platform}.com/user${generateRandomString()}`,
followers_count: generateRandomNumber(1000, 1000000),
created_at: createdAt,
updated_at: new Date().toISOString()
});
}
const { data, error } = await supabase
.from('influencers')
.insert(influencers)
.select();
if (error) {
console.error('创建测试KOL失败:', error);
process.exit(1);
}
console.log(`${data.length}个测试KOL创建成功`);
return data;
};
// 将KOL添加到项目
const addInfluencersToProject = async (projectId, influencers) => {
console.log(`将KOL添加到项目 ${projectId}...`);
const projectInfluencers = influencers.map(influencer => ({
project_id: projectId,
influencer_id: influencer.id,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
}));
const { data, error } = await supabase
.from('project_influencers')
.insert(projectInfluencers)
.select();
if (error) {
console.error('将KOL添加到项目失败:', error);
process.exit(1);
}
console.log(`${data.length}个KOL成功添加到项目`);
return data;
};
// 创建测试内容
const createTestPosts = async (projectId, influencers) => {
console.log(`为项目 ${projectId} 创建测试内容...`);
const posts = [];
// 为不同阶段的KOL创建不同数量的内容
const awarenessCount = influencers.length;
const interestCount = Math.floor(influencers.length * 0.75);
const considerationCount = Math.floor(influencers.length * 0.5);
const intentCount = Math.floor(influencers.length * 0.3);
const evaluationCount = Math.floor(influencers.length * 0.2);
for (let i = 0; i < influencers.length; i++) {
const influencer = influencers[i];
// 根据KOL所处阶段创建不同数量的内容
let postCount;
if (i < evaluationCount) {
// 评估阶段 - 3-5篇内容
postCount = generateRandomNumber(3, 5);
} else if (i < intentCount) {
// 意向阶段 - 2-3篇内容
postCount = generateRandomNumber(2, 3);
} else if (i < considerationCount) {
// 考虑阶段 - 1-2篇内容
postCount = generateRandomNumber(1, 2);
} else if (i < interestCount) {
// 兴趣阶段 - 1篇内容
postCount = 1;
} else {
// 认知阶段 - 无内容
postCount = 0;
}
for (let j = 0; j < postCount; j++) {
const publishedAt = generateRandomDate(
new Date(Date.now() - 90 * 24 * 60 * 60 * 1000), // 3个月前
new Date() // 现在
);
posts.push({
project_id: projectId,
influencer_id: influencer.id,
platform: influencer.platform,
title: `测试内容-${generateRandomString()}`,
description: `这是KOL ${influencer.name} 的测试内容`,
post_url: `https://${influencer.platform}.com/post/${generateRandomString()}`,
published_at: publishedAt,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
});
}
}
if (posts.length === 0) {
console.log('没有创建任何内容');
return [];
}
const { data, error } = await supabase
.from('posts')
.insert(posts)
.select();
if (error) {
console.error('创建测试内容失败:', error);
process.exit(1);
}
console.log(`${data.length}篇测试内容创建成功`);
return data;
};
// 测试KOL合作转换漏斗API
const testConversionFunnelAPI = async (projectId) => {
console.log(`测试KOL合作转换漏斗API项目ID: ${projectId}...`);
try {
const url = `http://localhost:4000/api/analytics/project/${projectId}/conversion-funnel`;
console.log(`请求URL: ${url}`);
// 使用http模块发送请求
const http = require('http');
return new Promise((resolve, reject) => {
const req = http.get(url, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
if (res.statusCode !== 200) {
console.error(`API请求失败: ${res.statusCode}`);
reject(new Error(`API请求失败: ${res.statusCode}`));
return;
}
try {
const jsonData = JSON.parse(data);
console.log('API响应:');
console.log(JSON.stringify(jsonData, null, 2));
resolve(jsonData);
} catch (error) {
console.error('解析API响应失败:', error);
reject(error);
}
});
});
req.on('error', (error) => {
console.error('请求出错:', error);
reject(error);
});
req.end();
});
} catch (error) {
console.error('测试API失败:', error);
console.log('请确保后端服务器正在运行并且可以访问API端点');
console.log('运行命令: cd /Users/liam/code/promote/backend && npm run dev');
}
};
// 主函数
const main = async () => {
try {
// 创建测试项目
const projectId = await createTestProject();
// 创建测试KOL - 创建100个KOL以便有足够的数据来测试漏斗的各个阶段
const influencers = await createTestInfluencers(100);
// 将KOL添加到项目
await addInfluencersToProject(projectId, influencers);
// 创建测试内容
await createTestPosts(projectId, influencers);
console.log('\n测试数据生成完成!');
console.log(`项目ID: ${projectId}`);
console.log('KOL数量: 100');
console.log('内容数量: 根据KOL所处阶段不同');
console.log('\n漏斗阶段分布:');
console.log('- 认知阶段 (Awareness): 100个KOL (100%)');
console.log('- 兴趣阶段 (Interest): 75个KOL (75%)');
console.log('- 考虑阶段 (Consideration): 50个KOL (50%)');
console.log('- 意向阶段 (Intent): 30个KOL (30%)');
console.log('- 评估阶段 (Evaluation): 20个KOL (20%)');
console.log('- 购买阶段 (Purchase): 10个KOL (10%)');
console.log('\n现在您可以使用以下命令测试KOL合作转换漏斗API:');
console.log(`curl http://localhost:4000/api/analytics/project/${projectId}/conversion-funnel`);
console.log('\n或者在浏览器中访问Swagger UI:');
console.log('http://localhost:4000/swagger');
// 尝试测试API
console.log('\n尝试测试API...');
await testConversionFunnelAPI(projectId);
} catch (error) {
console.error('测试数据生成过程中出错:', error);
process.exit(1);
}
};
// 运行主函数
main();