#!/usr/bin/env node /** * 完整测试数据初始化脚本 * 用于开发环境创建完整的测试数据 */ const mysql = require('mysql2/promise'); const bcrypt = require('bcryptjs'); const config = require('../config/env'); async function initCompleteTestData() { let connection; try { console.log('🚀 开始初始化完整测试数据...'); // 创建数据库连接 const dbConfig = { host: config.mysql.host, port: config.mysql.port, user: config.mysql.user, password: config.mysql.password, database: config.mysql.database, charset: config.mysql.charset, timezone: config.mysql.timezone }; connection = await mysql.createConnection(dbConfig); console.log('✅ 数据库连接成功'); // 清理现有测试数据(可选) console.log('🧹 清理现有测试数据...'); const tablesToClean = [ 'refunds', 'payments', 'orders', 'travel_registrations', 'travel_plans', 'animal_claims', 'animals', 'flowers', 'merchants', 'users', 'admins', 'email_verifications', 'password_resets', 'login_attempts' ]; for (const table of tablesToClean) { try { await connection.execute(`DELETE FROM ${table} WHERE id > 0`); await connection.execute(`ALTER TABLE ${table} AUTO_INCREMENT = 1`); console.log(` 清理表: ${table}`); } catch (error) { console.log(` 跳过表: ${table} (${error.message})`); } } // 1. 插入管理员数据 console.log('👨‍💼 插入管理员数据...'); const adminPassword = await bcrypt.hash('admin123', 10); const managerPassword = await bcrypt.hash('manager123', 10); await connection.execute(` INSERT INTO admins (username, password, email, nickname, role, status) VALUES ('admin', ?, 'admin@jiebanke.com', '超级管理员', 'super_admin', 1), ('manager', ?, 'manager@jiebanke.com', '运营经理', 'admin', 1), ('operator', ?, 'operator@jiebanke.com', '运营专员', 'operator', 1) `, [adminPassword, managerPassword, await bcrypt.hash('operator123', 10)]); console.log(' ✅ 管理员数据插入完成'); // 2. 插入用户数据 console.log('👥 插入用户数据...'); const userPassword = await bcrypt.hash('user123', 10); const farmerPassword = await bcrypt.hash('farmer123', 10); const merchantPassword = await bcrypt.hash('merchant123', 10); await connection.execute(` INSERT INTO users (username, password_hash, email, phone, real_name, user_type, status, balance, points) VALUES ('tourist1', ?, 'tourist1@jiebanke.com', '13800138001', '张三', 'tourist', 'active', 1000.00, 100), ('tourist2', ?, 'tourist2@jiebanke.com', '13800138002', '李四', 'tourist', 'active', 500.00, 50), ('farmer1', ?, 'farmer1@jiebanke.com', '13800138003', '王农夫', 'farmer', 'active', 2000.00, 200), ('farmer2', ?, 'farmer2@jiebanke.com', '13800138004', '赵农民', 'farmer', 'active', 1500.00, 150), ('merchant1', ?, 'merchant1@jiebanke.com', '13800138005', '刘老板', 'merchant', 'active', 5000.00, 500), ('merchant2', ?, 'merchant2@jiebanke.com', '13800138006', '陈经理', 'merchant', 'active', 3000.00, 300) `, [userPassword, userPassword, farmerPassword, farmerPassword, merchantPassword, merchantPassword]); console.log(' ✅ 用户数据插入完成'); // 3. 插入商家数据 console.log('🏪 插入商家数据...'); await connection.execute(` INSERT INTO merchants (user_id, business_name, business_type, description, address, contact_phone, status) VALUES (5, '山水农家乐', 'restaurant', '提供正宗农家菜和住宿服务', '北京市密云区某某村', '13800138005', 'approved'), (6, '绿野仙踪度假村', 'hotel', '生态度假村,环境优美', '河北省承德市某某镇', '13800138006', 'approved') `); console.log(' ✅ 商家数据插入完成'); // 4. 插入动物数据 console.log('🐷 插入动物数据...'); await connection.execute(` INSERT INTO animals (name, type, breed, age, weight, gender, description, price, daily_cost, farmer_id, status) VALUES ('小花', 'pig', '土猪', 6, 50.5, 'female', '健康活泼的小母猪', 800.00, 5.00, 3, 'available'), ('大黄', 'chicken', '土鸡', 8, 2.5, 'male', '散养公鸡,肉质鲜美', 120.00, 2.00, 3, 'available'), ('小白', 'sheep', '绵羊', 12, 35.0, 'female', '温顺的小绵羊', 600.00, 4.00, 4, 'available'), ('老黑', 'cow', '黄牛', 24, 300.0, 'male', '强壮的耕牛', 2000.00, 10.00, 4, 'available'), ('小灰', 'rabbit', '肉兔', 3, 1.8, 'female', '可爱的小兔子', 80.00, 1.50, 3, 'available') `); console.log(' ✅ 动物数据插入完成'); // 5. 插入鲜花数据 console.log('🌸 插入鲜花数据...'); await connection.execute(` INSERT INTO flowers (name, category, color, description, price, stock_quantity, farmer_id, status) VALUES ('红玫瑰', 'rose', '红色', '经典红玫瑰,象征爱情', 15.00, 100, 3, 'available'), ('白百合', 'lily', '白色', '纯洁的白百合,适合送礼', 25.00, 50, 3, 'available'), ('黄郁金香', 'tulip', '黄色', '明亮的黄郁金香', 20.00, 80, 4, 'available'), ('向日葵', 'sunflower', '黄色', '阳光般的向日葵', 12.00, 120, 4, 'available'), ('粉康乃馨', 'carnation', '粉色', '温馨的粉色康乃馨', 18.00, 90, 3, 'available') `); console.log(' ✅ 鲜花数据插入完成'); // 6. 插入旅行计划数据 console.log('✈️ 插入旅行计划数据...'); await connection.execute(` INSERT INTO travel_plans (title, description, destination, start_date, end_date, max_participants, price_per_person, created_by, status) VALUES ('密云水库生态游', '体验密云水库的自然风光,品尝农家美食', '北京密云', '2024-05-01', '2024-05-03', 20, 299.00, 5, 'published'), ('承德避暑山庄文化游', '探访承德避暑山庄,了解清朝历史文化', '河北承德', '2024-06-15', '2024-06-17', 15, 599.00, 6, 'published'), ('农场体验亲子游', '带孩子体验农场生活,学习农业知识', '北京郊区', '2024-07-01', '2024-07-02', 25, 199.00, 3, 'published') `); console.log(' ✅ 旅行计划数据插入完成'); // 7. 插入动物认领数据 console.log('🐾 插入动物认领数据...'); await connection.execute(` INSERT INTO animal_claims (claim_no, animal_id, user_id, claim_reason, claim_duration, total_amount, status, start_date, end_date) VALUES ('AC202401001', 1, 1, '想体验养猪的乐趣', 30, 950.00, 'approved', '2024-04-01', '2024-04-30'), ('AC202401002', 2, 2, '孩子喜欢小鸡', 15, 150.00, 'pending', '2024-04-15', '2024-04-29'), ('AC202401003', 3, 1, '认领小羊作为宠物', 60, 840.00, 'approved', '2024-03-01', '2024-04-29') `); console.log(' ✅ 动物认领数据插入完成'); // 8. 插入旅行报名数据 console.log('📝 插入旅行报名数据...'); await connection.execute(` INSERT INTO travel_registrations (travel_plan_id, user_id, participants, message, emergency_contact, emergency_phone, status) VALUES (1, 1, 2, '期待这次旅行', '张三妻子', '13900139001', 'approved'), (1, 2, 1, '第一次参加农家游', '李四父亲', '13900139002', 'pending'), (2, 1, 3, '全家一起出游', '张三妻子', '13900139001', 'approved'), (3, 2, 2, '带孩子体验农场', '李四妻子', '13900139003', 'pending') `); console.log(' ✅ 旅行报名数据插入完成'); // 9. 插入订单数据 console.log('📦 插入订单数据...'); await connection.execute(` INSERT INTO orders (order_no, user_id, type, related_id, title, total_amount, final_amount, status, payment_status) VALUES ('ORD202401001', 1, 'animal_claim', 1, '认领小花猪30天', 950.00, 950.00, 'completed', 'paid'), ('ORD202401002', 2, 'animal_claim', 2, '认领大黄鸡15天', 150.00, 150.00, 'pending', 'unpaid'), ('ORD202401003', 1, 'travel', 1, '密云水库生态游 2人', 598.00, 598.00, 'completed', 'paid'), ('ORD202401004', 1, 'flower', 1, '红玫瑰 10支', 150.00, 150.00, 'completed', 'paid') `); console.log(' ✅ 订单数据插入完成'); // 10. 插入支付数据 console.log('💳 插入支付数据...'); await connection.execute(` INSERT INTO payments (payment_no, order_id, user_id, amount, payment_method, status, paid_amount, paid_at) VALUES ('PAY202401001', 1, 1, 950.00, 'wechat', 'paid', 950.00, '2024-04-01 10:30:00'), ('PAY202401002', 3, 1, 598.00, 'alipay', 'paid', 598.00, '2024-04-02 14:20:00'), ('PAY202401003', 4, 1, 150.00, 'wechat', 'paid', 150.00, '2024-04-03 16:45:00') `); console.log(' ✅ 支付数据插入完成'); // 统计插入的数据 console.log('\n📊 数据统计:'); const tables = ['admins', 'users', 'merchants', 'animals', 'flowers', 'travel_plans', 'animal_claims', 'travel_registrations', 'orders', 'payments']; for (const table of tables) { try { const [rows] = await connection.execute(`SELECT COUNT(*) as count FROM ${table}`); console.log(` ${table}: ${rows[0].count} 条记录`); } catch (error) { console.log(` ${table}: 表不存在或查询失败`); } } console.log('\n🎉 完整测试数据初始化完成!'); console.log('📋 测试账号信息:'); console.log(' 管理员账号:'); console.log(' admin / admin123 (超级管理员)'); console.log(' manager / manager123 (运营经理)'); console.log(' operator / operator123 (运营专员)'); console.log(' 用户账号:'); console.log(' tourist1 / user123 (游客)'); console.log(' tourist2 / user123 (游客)'); console.log(' farmer1 / farmer123 (农户)'); console.log(' farmer2 / farmer123 (农户)'); console.log(' merchant1 / merchant123 (商家)'); console.log(' merchant2 / merchant123 (商家)'); } catch (error) { console.error('❌ 初始化测试数据失败:', error.message); if (error.code === 'ER_NO_SUCH_TABLE') { console.log('💡 提示: 请先运行数据库结构创建脚本'); } throw error; } finally { if (connection) { await connection.end(); console.log('🔒 数据库连接已关闭'); } } } // 如果是直接运行此文件,则执行初始化 if (require.main === module) { initCompleteTestData() .then(() => { console.log('✅ 脚本执行成功'); process.exit(0); }) .catch((error) => { console.error('❌ 脚本执行失败:', error.message); process.exit(1); }); } module.exports = { initCompleteTestData };