"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.initDatabase = exports.checkDatabaseConnection = exports.createSampleData = exports.initSupabaseFunctions = exports.initClickHouseTables = exports.initSupabaseTables = void 0; const supabase_1 = __importDefault(require("./supabase")); const clickhouse_1 = __importDefault(require("./clickhouse")); const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); /** * 初始化 Supabase (PostgreSQL) 数据库表 */ const initSupabaseTables = async () => { try { console.log('开始初始化 Supabase 数据表...'); // 创建用户扩展表 await supabase_1.default.rpc('create_user_profiles_if_not_exists'); // 创建项目表 await supabase_1.default.rpc('create_projects_table_if_not_exists'); // 创建网红(影响者)表 await supabase_1.default.rpc('create_influencers_table_if_not_exists'); // 创建项目-网红关联表 await supabase_1.default.rpc('create_project_influencers_table_if_not_exists'); // 创建帖子表 await supabase_1.default.rpc('create_posts_table_if_not_exists'); // 创建评论表 await supabase_1.default.rpc('create_comments_table_if_not_exists'); // 创建项目评论表 await supabase_1.default.rpc('create_project_comments_table_if_not_exists'); console.log('Supabase 数据表初始化完成'); return true; } catch (error) { console.error('初始化 Supabase 数据表失败:', error); return false; } }; exports.initSupabaseTables = initSupabaseTables; /** * 初始化 ClickHouse 数据库表 */ const initClickHouseTables = async () => { try { console.log('开始初始化 ClickHouse 数据表...'); // 创建事件表 await clickhouse_1.default.query({ query: ` CREATE TABLE IF NOT EXISTS events ( event_id UUID DEFAULT generateUUIDv4(), project_id UUID, influencer_id UUID, post_id UUID NULL, platform String, event_type Enum( 'follower_change' = 1, 'post_like_change' = 2, 'post_view_change' = 3, 'click' = 4, 'comment' = 5, 'share' = 6, 'project_comment' = 7 ), metric_value Int64, event_metadata String, timestamp DateTime DEFAULT now() ) ENGINE = MergeTree() PARTITION BY toYYYYMM(timestamp) ORDER BY (platform, influencer_id, post_id, event_type, timestamp) ` }); // 创建统计视图 - 按天统计 await clickhouse_1.default.query({ query: ` CREATE MATERIALIZED VIEW IF NOT EXISTS daily_stats ENGINE = SummingMergeTree() PARTITION BY toYYYYMM(date) ORDER BY (date, platform, influencer_id, event_type) AS SELECT toDate(timestamp) AS date, platform, influencer_id, event_type, SUM(metric_value) AS total_value, COUNT(*) AS event_count FROM events GROUP BY date, platform, influencer_id, event_type ` }); // 创建统计视图 - 按月统计 await clickhouse_1.default.query({ query: ` CREATE MATERIALIZED VIEW IF NOT EXISTS monthly_stats ENGINE = SummingMergeTree() ORDER BY (month, platform, influencer_id, event_type) AS SELECT toStartOfMonth(timestamp) AS month, platform, influencer_id, event_type, SUM(metric_value) AS total_value, COUNT(*) AS event_count FROM events GROUP BY month, platform, influencer_id, event_type ` }); // 创建帖子互动统计视图 await clickhouse_1.default.query({ query: ` CREATE MATERIALIZED VIEW IF NOT EXISTS post_interaction_stats ENGINE = SummingMergeTree() ORDER BY (post_id, event_type, date) AS SELECT post_id, event_type, toDate(timestamp) AS date, SUM(metric_value) AS value, COUNT(*) AS count FROM events WHERE post_id IS NOT NULL GROUP BY post_id, event_type, date ` }); // 创建项目互动统计视图 await clickhouse_1.default.query({ query: ` CREATE MATERIALIZED VIEW IF NOT EXISTS project_interaction_stats ENGINE = SummingMergeTree() ORDER BY (project_id, event_type, date) AS SELECT project_id, event_type, toDate(timestamp) AS date, SUM(metric_value) AS value, COUNT(*) AS count FROM events WHERE project_id IS NOT NULL AND event_type = 'project_comment' GROUP BY project_id, event_type, date ` }); console.log('ClickHouse 数据表初始化完成'); return true; } catch (error) { console.error('初始化 ClickHouse 数据表失败:', error); return false; } }; exports.initClickHouseTables = initClickHouseTables; /** * 初始化 Supabase 存储函数 */ const initSupabaseFunctions = async () => { try { console.log('开始初始化 Supabase 存储过程...'); // 创建用户简档表的存储过程 await supabase_1.default.rpc('create_function_create_user_profiles_if_not_exists'); // 创建项目表的存储过程 await supabase_1.default.rpc('create_function_create_projects_table_if_not_exists'); // 创建网红表的存储过程 await supabase_1.default.rpc('create_function_create_influencers_table_if_not_exists'); // 创建项目-网红关联表的存储过程 await supabase_1.default.rpc('create_function_create_project_influencers_table_if_not_exists'); // 创建帖子表的存储过程 await supabase_1.default.rpc('create_function_create_posts_table_if_not_exists'); // 创建评论表的存储过程 await supabase_1.default.rpc('create_function_create_comments_table_if_not_exists'); // 创建项目评论表的存储过程 await supabase_1.default.rpc('create_function_create_project_comments_table_if_not_exists'); // 创建评论相关的SQL函数 console.log('创建评论相关的SQL函数...'); const commentsSQL = await promises_1.default.readFile(path_1.default.join(__dirname, 'supabase-comments-functions.sql'), 'utf8'); // 使用Supabase执行SQL const { error: commentsFunctionsError } = await supabase_1.default.rpc('pgclient_execute', { query: commentsSQL }); if (commentsFunctionsError) { console.error('创建评论SQL函数失败:', commentsFunctionsError); } else { console.log('评论SQL函数创建成功'); } console.log('Supabase 存储过程初始化完成'); return true; } catch (error) { console.error('初始化 Supabase 存储过程失败:', error); return false; } }; exports.initSupabaseFunctions = initSupabaseFunctions; /** * 创建测试数据 */ const createSampleData = async () => { try { console.log('开始创建测试数据...'); // 创建测试用户 const { data: user, error: userError } = await supabase_1.default.auth.admin.createUser({ email: 'test@example.com', password: 'password123', user_metadata: { full_name: '测试用户' } }); if (userError) { console.error('创建测试用户失败:', userError); return false; } // 创建测试项目 const { data: project, error: projectError } = await supabase_1.default .from('projects') .insert({ name: '测试营销活动', description: '这是一个测试营销活动', created_by: user.user.id }) .select() .single(); if (projectError) { console.error('创建测试项目失败:', projectError); return false; } // 创建项目评论 await supabase_1.default .from('project_comments') .insert([ { project_id: project.id, user_id: user.user.id, content: '这是对项目的一条测试评论', sentiment_score: 0.8 }, { project_id: project.id, user_id: user.user.id, content: '这个项目很有前景', sentiment_score: 0.9 }, { project_id: project.id, user_id: user.user.id, content: '需要关注这个项目的进展', sentiment_score: 0.7 } ]); // 创建测试网红 const platforms = ['youtube', 'instagram', 'tiktok']; const influencers = []; for (let i = 1; i <= 10; i++) { const platform = platforms[Math.floor(Math.random() * platforms.length)]; const { data: influencer, error: influencerError } = await supabase_1.default .from('influencers') .insert({ name: `测试网红 ${i}`, platform, profile_url: `https://${platform}.com/user${i}`, external_id: `user_${platform}_${i}`, followers_count: Math.floor(Math.random() * 1000000) + 1000, video_count: Math.floor(Math.random() * 500) + 10 }) .select() .single(); if (influencerError) { console.error(`创建测试网红 ${i} 失败:`, influencerError); continue; } influencers.push(influencer); // 将网红添加到项目 await supabase_1.default .from('project_influencers') .insert({ project_id: project.id, influencer_id: influencer.influencer_id }); // 为每个网红创建 3-5 个帖子 const postCount = Math.floor(Math.random() * 3) + 3; for (let j = 1; j <= postCount; j++) { const { data: post, error: postError } = await supabase_1.default .from('posts') .insert({ influencer_id: influencer.influencer_id, platform, post_url: `https://${platform}.com/user${i}/post${j}`, title: `测试帖子 ${j} - 由 ${influencer.name} 发布`, description: `这是一个测试帖子的描述 ${j}`, published_at: new Date(Date.now() - Math.floor(Math.random() * 30) * 24 * 60 * 60 * 1000).toISOString() }) .select() .single(); if (postError) { console.error(`创建测试帖子 ${j} 失败:`, postError); continue; } // 为每个帖子创建 2-10 个评论 const commentCount = Math.floor(Math.random() * 9) + 2; for (let k = 1; k <= commentCount; k++) { await supabase_1.default .from('comments') .insert({ post_id: post.post_id, user_id: user.user.id, content: `这是对帖子 ${post.title} 的测试评论 ${k}`, sentiment_score: (Math.random() * 2 - 1) // -1 到 1 之间的随机数 }); } // 创建 ClickHouse 事件数据 // 粉丝变化事件 await clickhouse_1.default.query({ query: ` INSERT INTO events ( project_id, influencer_id, platform, event_type, metric_value, event_metadata ) VALUES (?, ?, ?, 'follower_change', ?, ?) `, values: [ project.id, influencer.influencer_id, platform, Math.floor(Math.random() * 1000) - 200, // -200 到 800 之间的随机数 JSON.stringify({ source: 'api_crawler' }) ] }); // 帖子点赞变化事件 await clickhouse_1.default.query({ query: ` INSERT INTO events ( project_id, influencer_id, post_id, platform, event_type, metric_value, event_metadata ) VALUES (?, ?, ?, ?, 'post_like_change', ?, ?) `, values: [ project.id, influencer.influencer_id, post.post_id, platform, Math.floor(Math.random() * 500) + 10, // 10 到 510 之间的随机数 JSON.stringify({ source: 'api_crawler' }) ] }); // 帖子观看数变化事件 await clickhouse_1.default.query({ query: ` INSERT INTO events ( project_id, influencer_id, post_id, platform, event_type, metric_value, event_metadata ) VALUES (?, ?, ?, ?, 'post_view_change', ?, ?) `, values: [ project.id, influencer.influencer_id, post.post_id, platform, Math.floor(Math.random() * 5000) + 100, // 100 到 5100 之间的随机数 JSON.stringify({ source: 'api_crawler' }) ] }); // 互动事件 const interactionTypes = ['click', 'comment', 'share']; const interactionType = interactionTypes[Math.floor(Math.random() * interactionTypes.length)]; await clickhouse_1.default.query({ query: ` INSERT INTO events ( project_id, influencer_id, post_id, platform, event_type, metric_value, event_metadata ) VALUES (?, ?, ?, ?, ?, ?, ?) `, values: [ project.id, influencer.influencer_id, post.post_id, platform, interactionType, 1, JSON.stringify({ ip: '192.168.1.' + Math.floor(Math.random() * 255), user_agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' }) ] }); } } // 创建项目评论事件 for (let i = 1; i <= 5; i++) { await clickhouse_1.default.query({ query: ` INSERT INTO events ( project_id, event_type, metric_value, event_metadata ) VALUES (?, 'project_comment', ?, ?) `, values: [ project.id, 1, JSON.stringify({ user_id: user.user.id, timestamp: new Date().toISOString(), comment: `项目评论事件 ${i}` }) ] }); } console.log('测试数据创建完成'); return true; } catch (error) { console.error('创建测试数据失败:', error); return false; } }; exports.createSampleData = createSampleData; /** * 检查数据库连接 */ const checkDatabaseConnection = async () => { try { console.log('检查数据库连接...'); // 检查 Supabase 连接 try { // 仅检查连接是否正常,不执行实际查询 const { data, error } = await supabase_1.default.auth.getSession(); if (error) { console.error('Supabase 连接测试失败:', error); return false; } console.log('Supabase 连接正常'); } catch (supabaseError) { console.error('Supabase 连接测试失败:', supabaseError); return false; } // 检查 ClickHouse 连接 try { // 使用简单查询代替ping方法 const result = await clickhouse_1.default.query({ query: 'SELECT 1' }); console.log('ClickHouse 连接正常'); } catch (error) { console.error('ClickHouse 连接测试失败:', error); return false; } console.log('数据库连接检查完成,所有连接均正常'); return true; } catch (error) { console.error('数据库连接检查失败:', error); return false; } }; exports.checkDatabaseConnection = checkDatabaseConnection; /** * 初始化数据库 - 此函数现在仅作为手动初始化的入口点 * 只有通过管理API明确调用时才会执行实际的初始化 */ const initDatabase = async () => { try { console.log('开始数据库初始化...'); console.log('警告: 此操作将修改数据库结构,请确保您知道自己在做什么'); // 初始化 Supabase 函数 await (0, exports.initSupabaseFunctions)(); // 初始化 Supabase 表 await (0, exports.initSupabaseTables)(); // 初始化 ClickHouse 表 await (0, exports.initClickHouseTables)(); console.log('数据库初始化完成'); return true; } catch (error) { console.error('数据库初始化失败:', error); return false; } }; exports.initDatabase = initDatabase;