funel data
This commit is contained in:
311
backend/scripts/insert-test-data.js
Normal file
311
backend/scripts/insert-test-data.js
Normal file
@@ -0,0 +1,311 @@
|
||||
require('dotenv').config();
|
||||
const { Pool } = require('pg');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
// 创建PostgreSQL连接池
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
});
|
||||
|
||||
// 生成随机日期,在指定天数范围内
|
||||
function randomDate(daysBack = 30) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - Math.floor(Math.random() * daysBack));
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
// 生成随机数字,在指定范围内
|
||||
function randomNumber(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
// 插入测试项目数据
|
||||
async function insertTestProjects(count = 5) {
|
||||
console.log(`开始插入${count}个测试项目...`);
|
||||
|
||||
const projectNames = [
|
||||
'夏季新品推广', '618电商活动', '品牌周年庆', '新产品发布会',
|
||||
'冬季促销活动', '跨年营销', '校园推广', '明星代言合作',
|
||||
'社交媒体挑战赛', '用户生成内容活动'
|
||||
];
|
||||
|
||||
const projectDescriptions = [
|
||||
'推广夏季新品系列,提高品牌知名度',
|
||||
'618电商大促活动,提升销售转化',
|
||||
'品牌成立周年庆典,增强品牌忠诚度',
|
||||
'新产品线上发布会,扩大产品影响力',
|
||||
'冬季产品促销活动,刺激季节性消费',
|
||||
'跨年营销活动,提升品牌曝光',
|
||||
'针对大学生群体的校园推广活动',
|
||||
'与明星合作的品牌代言项目',
|
||||
'社交媒体平台的用户参与挑战活动',
|
||||
'鼓励用户创建与品牌相关内容的活动'
|
||||
];
|
||||
|
||||
const statuses = ['active', 'completed', 'archived'];
|
||||
|
||||
try {
|
||||
const client = await pool.connect();
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const nameIndex = i % projectNames.length;
|
||||
const descIndex = i % projectDescriptions.length;
|
||||
const statusIndex = i % statuses.length;
|
||||
|
||||
const projectId = uuidv4();
|
||||
const startDate = randomDate(60);
|
||||
const endDate = new Date(new Date(startDate).getTime() + (30 * 24 * 60 * 60 * 1000)).toISOString();
|
||||
|
||||
await client.query(
|
||||
`INSERT INTO public.projects
|
||||
(id, name, description, status, start_date, end_date, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
|
||||
[
|
||||
projectId,
|
||||
projectNames[nameIndex],
|
||||
projectDescriptions[descIndex],
|
||||
statuses[statusIndex],
|
||||
startDate,
|
||||
endDate,
|
||||
new Date().toISOString(),
|
||||
new Date().toISOString()
|
||||
]
|
||||
);
|
||||
|
||||
console.log(`已插入项目: ${projectNames[nameIndex]}`);
|
||||
}
|
||||
|
||||
client.release();
|
||||
console.log(`成功插入${count}个测试项目`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('插入测试项目失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 插入测试网红数据
|
||||
async function insertTestInfluencers(count = 10) {
|
||||
console.log(`开始插入${count}个测试网红...`);
|
||||
|
||||
const influencerNames = [
|
||||
'张小明', '李华', '王芳', '刘星', '陈晓',
|
||||
'Emma Wong', 'Jack Chen', 'Sophia Liu', 'Noah Zhang', 'Olivia Wang',
|
||||
'김민준', '이지은', '박서준', '최수지', '정우성'
|
||||
];
|
||||
|
||||
const platforms = ['youtube', 'instagram', 'tiktok', 'twitter', 'facebook'];
|
||||
|
||||
try {
|
||||
const client = await pool.connect();
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const nameIndex = i % influencerNames.length;
|
||||
const platformIndex = i % platforms.length;
|
||||
const platform = platforms[platformIndex];
|
||||
|
||||
const influencerId = uuidv4();
|
||||
const externalId = `${platform}_${Math.random().toString(36).substring(2, 10)}`;
|
||||
const followersCount = randomNumber(1000, 1000000);
|
||||
const videoCount = randomNumber(10, 500);
|
||||
|
||||
await client.query(
|
||||
`INSERT INTO public.influencers
|
||||
(influencer_id, name, platform, profile_url, external_id, followers_count, video_count, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
|
||||
[
|
||||
influencerId,
|
||||
influencerNames[nameIndex],
|
||||
platform,
|
||||
`https://${platform}.com/${externalId}`,
|
||||
externalId,
|
||||
followersCount,
|
||||
videoCount,
|
||||
new Date().toISOString(),
|
||||
new Date().toISOString()
|
||||
]
|
||||
);
|
||||
|
||||
console.log(`已插入网红: ${influencerNames[nameIndex]} (${platform})`);
|
||||
}
|
||||
|
||||
client.release();
|
||||
console.log(`成功插入${count}个测试网红`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('插入测试网红失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 关联项目和网红
|
||||
async function associateProjectsAndInfluencers() {
|
||||
console.log('开始关联项目和网红...');
|
||||
|
||||
try {
|
||||
const client = await pool.connect();
|
||||
|
||||
// 获取所有项目
|
||||
const projectsResult = await client.query('SELECT id FROM public.projects');
|
||||
const projects = projectsResult.rows;
|
||||
|
||||
// 获取所有网红
|
||||
const influencersResult = await client.query('SELECT influencer_id FROM public.influencers');
|
||||
const influencers = influencersResult.rows;
|
||||
|
||||
if (projects.length === 0 || influencers.length === 0) {
|
||||
console.log('没有找到项目或网红数据,无法创建关联');
|
||||
client.release();
|
||||
return false;
|
||||
}
|
||||
|
||||
const statuses = ['active', 'inactive', 'completed'];
|
||||
let associationsCount = 0;
|
||||
|
||||
// 为每个项目随机关联1-5个网红
|
||||
for (const project of projects) {
|
||||
const numInfluencers = randomNumber(1, 5);
|
||||
const shuffledInfluencers = [...influencers].sort(() => 0.5 - Math.random());
|
||||
const selectedInfluencers = shuffledInfluencers.slice(0, numInfluencers);
|
||||
|
||||
for (const influencer of selectedInfluencers) {
|
||||
const statusIndex = randomNumber(0, statuses.length - 1);
|
||||
|
||||
try {
|
||||
await client.query(
|
||||
`INSERT INTO public.project_influencers
|
||||
(id, project_id, influencer_id, status, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)`,
|
||||
[
|
||||
uuidv4(),
|
||||
project.id,
|
||||
influencer.influencer_id,
|
||||
statuses[statusIndex],
|
||||
new Date().toISOString(),
|
||||
new Date().toISOString()
|
||||
]
|
||||
);
|
||||
|
||||
associationsCount++;
|
||||
} catch (error) {
|
||||
// 可能是唯一约束冲突,忽略错误继续
|
||||
console.log(`关联已存在或发生错误: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
client.release();
|
||||
console.log(`成功创建${associationsCount}个项目-网红关联`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('关联项目和网红失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 插入测试帖子数据
|
||||
async function insertTestPosts(postsPerInfluencer = 3) {
|
||||
console.log(`开始为每个网红插入${postsPerInfluencer}个测试帖子...`);
|
||||
|
||||
const postTitles = [
|
||||
'新品开箱视频', '使用体验分享', '产品评测', '购物分享',
|
||||
'日常VLOG', '挑战视频', '教程分享', '合作推广',
|
||||
'直播回放', '问答视频'
|
||||
];
|
||||
|
||||
const postDescriptions = [
|
||||
'今天为大家带来新品开箱,这款产品真的太赞了!',
|
||||
'使用一周后的真实体验分享,优缺点都告诉你',
|
||||
'专业评测:性能、外观、性价比全面分析',
|
||||
'本月最值得购买的好物推荐,不容错过',
|
||||
'跟我一起度过充实的一天,生活记录分享',
|
||||
'参与最新网络挑战,太有趣了',
|
||||
'详细教程:如何正确使用这款产品',
|
||||
'与品牌合作的特别内容,限时优惠',
|
||||
'错过直播的朋友可以看回放啦',
|
||||
'回答粉丝提问,解答产品使用疑惑'
|
||||
];
|
||||
|
||||
try {
|
||||
const client = await pool.connect();
|
||||
|
||||
// 获取所有网红
|
||||
const influencersResult = await client.query('SELECT influencer_id, platform FROM public.influencers');
|
||||
const influencers = influencersResult.rows;
|
||||
|
||||
if (influencers.length === 0) {
|
||||
console.log('没有找到网红数据,无法创建帖子');
|
||||
client.release();
|
||||
return false;
|
||||
}
|
||||
|
||||
let postsCount = 0;
|
||||
|
||||
// 为每个网红创建帖子
|
||||
for (const influencer of influencers) {
|
||||
for (let i = 0; i < postsPerInfluencer; i++) {
|
||||
const titleIndex = randomNumber(0, postTitles.length - 1);
|
||||
const descIndex = randomNumber(0, postDescriptions.length - 1);
|
||||
const publishedDate = randomDate(30);
|
||||
|
||||
const postId = uuidv4();
|
||||
const postUrl = `https://${influencer.platform}.com/post/${Math.random().toString(36).substring(2, 10)}`;
|
||||
|
||||
await client.query(
|
||||
`INSERT INTO public.posts
|
||||
(post_id, influencer_id, platform, post_url, title, description, published_at, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
|
||||
[
|
||||
postId,
|
||||
influencer.influencer_id,
|
||||
influencer.platform,
|
||||
postUrl,
|
||||
postTitles[titleIndex],
|
||||
postDescriptions[descIndex],
|
||||
publishedDate,
|
||||
new Date().toISOString(),
|
||||
new Date().toISOString()
|
||||
]
|
||||
);
|
||||
|
||||
postsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
client.release();
|
||||
console.log(`成功插入${postsCount}个测试帖子`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('插入测试帖子失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 主函数
|
||||
async function main() {
|
||||
console.log('开始插入测试数据...');
|
||||
|
||||
try {
|
||||
// 插入测试项目
|
||||
await insertTestProjects(5);
|
||||
|
||||
// 插入测试网红
|
||||
await insertTestInfluencers(15);
|
||||
|
||||
// 关联项目和网红
|
||||
await associateProjectsAndInfluencers();
|
||||
|
||||
// 插入测试帖子
|
||||
await insertTestPosts(5);
|
||||
|
||||
console.log('所有测试数据插入完成!');
|
||||
} catch (error) {
|
||||
console.error('插入测试数据过程中发生错误:', error);
|
||||
} finally {
|
||||
// 关闭连接池
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
// 执行主函数
|
||||
main();
|
||||
Reference in New Issue
Block a user