|
@@ -447,10 +447,10 @@ public class DatabaseInitializer implements CommandLineRunner {
|
|
|
"status TINYINT DEFAULT 1 COMMENT '状态:0禁用1启用', " +
|
|
"status TINYINT DEFAULT 1 COMMENT '状态:0禁用1启用', " +
|
|
|
"created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
"created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
"updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
"updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
- "INDEX idx_game_code (game_code), " +
|
|
|
|
|
- "INDEX idx_status (status)" +
|
|
|
|
|
- ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
|
|
|
|
|
-);
|
|
|
|
|
|
|
+"INDEX idx_game_code (game_code), " +
|
|
|
|
|
+"INDEX idx_status (status)" +
|
|
|
|
|
+") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// 执行创建表SQL
|
|
// 执行创建表SQL
|
|
|
for (String sql : createTableSQLs) {
|
|
for (String sql : createTableSQLs) {
|
|
@@ -1199,7 +1199,7 @@ log.info("已添加template_id列到tasks表");
|
|
|
log.warn("检查/添加个人信息补充字段失败: {}", e.getMessage());
|
|
log.warn("检查/添加个人信息补充字段失败: {}", e.getMessage());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Phase 0: 汐福俱乐部 — 服务商字段
|
|
|
|
|
|
|
+ // Phase 0: 浠艾福俱乐部 — 服务商字段
|
|
|
try {
|
|
try {
|
|
|
Integer exists = jdbcTemplate.queryForObject(
|
|
Integer exists = jdbcTemplate.queryForObject(
|
|
|
"SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = 'vendor_type'",
|
|
"SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = 'vendor_type'",
|
|
@@ -1210,9 +1210,9 @@ log.info("已添加template_id列到tasks表");
|
|
|
jdbcTemplate.execute("ALTER TABLE users ADD COLUMN vendor_reject_reason VARCHAR(500) DEFAULT NULL COMMENT '审核拒绝原因'");
|
|
jdbcTemplate.execute("ALTER TABLE users ADD COLUMN vendor_reject_reason VARCHAR(500) DEFAULT NULL COMMENT '审核拒绝原因'");
|
|
|
jdbcTemplate.execute("ALTER TABLE users ADD COLUMN is_family_admin TINYINT DEFAULT 0 COMMENT '是否家庭管理员'");
|
|
jdbcTemplate.execute("ALTER TABLE users ADD COLUMN is_family_admin TINYINT DEFAULT 0 COMMENT '是否家庭管理员'");
|
|
|
jdbcTemplate.execute("ALTER TABLE users ADD COLUMN vendor_info VARCHAR(2000) DEFAULT NULL COMMENT '服务商资质信息(JSON)'");
|
|
jdbcTemplate.execute("ALTER TABLE users ADD COLUMN vendor_info VARCHAR(2000) DEFAULT NULL COMMENT '服务商资质信息(JSON)'");
|
|
|
- log.info("已添加汐福俱乐部服务商字段到users表");
|
|
|
|
|
|
|
+ log.info("已添加浠艾福俱乐部服务商字段到users表");
|
|
|
} else {
|
|
} else {
|
|
|
- log.info("汐福俱乐部服务商字段已存在,跳过");
|
|
|
|
|
|
|
+ log.info("浠艾福俱乐部服务商字段已存在,跳过");
|
|
|
}
|
|
}
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.warn("检查/添加服务商字段失败: {}", e.getMessage());
|
|
log.warn("检查/添加服务商字段失败: {}", e.getMessage());
|
|
@@ -1230,7 +1230,7 @@ log.info("已添加template_id列到tasks表");
|
|
|
log.warn("迁移规划师到服务商体系失败: {}", e.getMessage());
|
|
log.warn("迁移规划师到服务商体系失败: {}", e.getMessage());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ==================== Phase 1: 汐福俱乐部商品系统 ====================
|
|
|
|
|
|
|
+ // ==================== Phase 1: 浠艾福俱乐部商品系统 ====================
|
|
|
|
|
|
|
|
// 商品表
|
|
// 商品表
|
|
|
try {
|
|
try {
|
|
@@ -1332,6 +1332,336 @@ log.info("已添加template_id列到tasks表");
|
|
|
log.warn("Product 种子数据初始化失败: {}", e.getMessage());
|
|
log.warn("Product 种子数据初始化失败: {}", e.getMessage());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // ==================== Phase 2: 内容区块可见性配置 ====================
|
|
|
|
|
+
|
|
|
|
|
+ // 内容区块配置表
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute(
|
|
|
|
|
+ "CREATE TABLE IF NOT EXISTS content_sections (" +
|
|
|
|
|
+ " id BIGINT AUTO_INCREMENT PRIMARY KEY," +
|
|
|
|
|
+ " page_key VARCHAR(50) NOT NULL," +
|
|
|
|
|
+ " section_key VARCHAR(50) NOT NULL," +
|
|
|
|
|
+ " title VARCHAR(100)," +
|
|
|
|
|
+ " allowed_roles VARCHAR(255) DEFAULT '[\"anonymous\"]'," +
|
|
|
|
|
+ " sort_order INT DEFAULT 0," +
|
|
|
|
|
+ " status VARCHAR(20) DEFAULT 'active'," +
|
|
|
|
|
+ " created_at DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
|
|
+ " updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
|
|
+ ")"
|
|
|
|
|
+ );
|
|
|
|
|
+ log.info("content_sections 表已创建");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建 content_sections 表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ContentSection 种子数据
|
|
|
|
|
+ try {
|
|
|
|
|
+ insertContentSectionSeed("mind", "func_entries", "功能入口", "[\"anonymous\"]", 1);
|
|
|
|
|
+ insertContentSectionSeed("mind", "daily_tip", "每日心理", "[\"anonymous\"]", 2);
|
|
|
|
|
+ insertContentSectionSeed("mind", "recommended_reading", "推荐阅读", "[\"anonymous\"]", 3);
|
|
|
|
|
+ insertContentSectionSeed("mind", "premium_content", "会员专属内容", "[\"parent\",\"teacher\"]", 4);
|
|
|
|
|
+ insertContentSectionSeed("body", "func_entries", "功能入口", "[\"anonymous\"]", 1);
|
|
|
|
|
+ insertContentSectionSeed("body", "daily_stats", "今日数据", "[\"anonymous\"]", 2);
|
|
|
|
|
+ insertContentSectionSeed("body", "health_tips", "健康小贴士", "[\"anonymous\"]", 3);
|
|
|
|
|
+ insertContentSectionSeed("body", "teacher_tips", "规划师推荐", "[\"teacher\"]", 4);
|
|
|
|
|
+ log.info("ContentSection 种子数据已加载");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("ContentSection 种子数据初始化失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 文章内容系统种子数据 ====================
|
|
|
|
|
+
|
|
|
|
|
+ // 文章分类种子数据
|
|
|
|
|
+ try {
|
|
|
|
|
+ Integer catCount = jdbcTemplate.queryForObject(
|
|
|
|
|
+ "SELECT COUNT(*) FROM article_categories WHERE id IN (1,2,3,4,5)", Integer.class);
|
|
|
|
|
+ if (catCount == null || catCount == 0) {
|
|
|
|
|
+ jdbcTemplate.execute("INSERT IGNORE INTO article_categories (id, name, icon, color, sort_order, status) VALUES " +
|
|
|
|
|
+ "(1, '心理健康', '🧠', '#5B9BD5', 1, 1), " +
|
|
|
|
|
+ "(2, '情绪管理', '💖', '#FF6B35', 2, 1), " +
|
|
|
|
|
+ "(3, '亲子教育', '👨👩👧👦', '#4CAF50', 3, 1), " +
|
|
|
|
|
+ "(4, '学习力', '📚', '#FFD700', 4, 1), " +
|
|
|
|
|
+ "(5, '专注力', '🎯', '#8D6E63', 5, 1)");
|
|
|
|
|
+ log.info("文章分类种子数据已加载");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("文章分类种子数据初始化失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 分佣裂变系统 ====================
|
|
|
|
|
+
|
|
|
|
|
+ // 迁移: users表添加推荐人字段
|
|
|
|
|
+ try {
|
|
|
|
|
+ Integer exists = jdbcTemplate.queryForObject(
|
|
|
|
|
+ "SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = 'referrer_id'",
|
|
|
|
|
+ Integer.class);
|
|
|
|
|
+ if (exists == null || exists == 0) {
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE users ADD COLUMN referrer_id BIGINT DEFAULT NULL COMMENT '推荐人ID'");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE users ADD COLUMN referral_code VARCHAR(32) DEFAULT NULL COMMENT '个人邀请码'");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE users ADD INDEX idx_referral_code (referral_code)");
|
|
|
|
|
+ log.info("已添加分佣字段到users表");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.info("分佣金字段已存在,跳过");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("检查/添加分佣金字段失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 迁移: products表添加利润率字段
|
|
|
|
|
+ try {
|
|
|
|
|
+ Integer exists = jdbcTemplate.queryForObject(
|
|
|
|
|
+ "SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'products' AND COLUMN_NAME = 'profit_rate'",
|
|
|
|
|
+ Integer.class);
|
|
|
|
|
+ if (exists == null || exists == 0) {
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE products ADD COLUMN profit_rate DECIMAL(5,2) DEFAULT 0.00 COMMENT '平台利润率(%)'");
|
|
|
|
|
+ log.info("已添加profit_rate列到products表");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.info("profit_rate列已存在,跳过");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("检查/添加profit_rate列失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 新表: commission_records (佣金记录)
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS commission_records (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "order_id BIGINT NOT NULL COMMENT '订单ID', " +
|
|
|
|
|
+ "order_type VARCHAR(32) NOT NULL COMMENT '订单类型: membership/product/assessment/package', " +
|
|
|
|
|
+ "referrer_id BIGINT NOT NULL COMMENT '推荐人ID', " +
|
|
|
|
|
+ "buyer_id BIGINT NOT NULL COMMENT '购买人ID', " +
|
|
|
|
|
+ "commission_type VARCHAR(16) NOT NULL COMMENT '佣金类型: member/profit', " +
|
|
|
|
|
+ "order_amount DECIMAL(10,2) NOT NULL COMMENT '订单金额', " +
|
|
|
|
|
+ "profit_rate DECIMAL(5,2) DEFAULT 0.00 COMMENT '利润率(%)', " +
|
|
|
|
|
+ "commission_amount DECIMAL(10,2) NOT NULL COMMENT '佣金金额', " +
|
|
|
|
|
+ "status VARCHAR(16) NOT NULL DEFAULT 'settled' COMMENT '状态: pending/settled', " +
|
|
|
|
|
+ "remark VARCHAR(255) DEFAULT NULL, " +
|
|
|
|
|
+ "created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ "INDEX idx_referrer (referrer_id), " +
|
|
|
|
|
+ "INDEX idx_buyer (buyer_id), " +
|
|
|
|
|
+ "INDEX idx_order (order_id, order_type)" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
|
|
|
|
|
+ log.info("已创建commission_records表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建commission_records表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 新表: withdrawal_requests (提现申请)
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS withdrawal_requests (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "user_id BIGINT NOT NULL COMMENT '用户ID', " +
|
|
|
|
|
+ "amount DECIMAL(10,2) NOT NULL COMMENT '提现金额', " +
|
|
|
|
|
+ "account_info TEXT COMMENT '账户信息(JSON)', " +
|
|
|
|
|
+ "status VARCHAR(16) NOT NULL DEFAULT 'pending' COMMENT '状态: pending/approved/rejected', " +
|
|
|
|
|
+ "audit_by BIGINT DEFAULT NULL COMMENT '审核人ID', " +
|
|
|
|
|
+ "audit_at DATETIME DEFAULT NULL COMMENT '审核时间', " +
|
|
|
|
|
+ "remark VARCHAR(255) DEFAULT NULL COMMENT '审核备注', " +
|
|
|
|
|
+ "created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ "INDEX idx_user (user_id), " +
|
|
|
|
|
+ "INDEX idx_status (status)" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
|
|
|
|
|
+ log.info("已创建withdrawal_requests表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建withdrawal_requests表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 文章内容系统 ====================
|
|
|
|
|
+
|
|
|
|
|
+ // 文章分类表
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS article_categories (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "name VARCHAR(50) NOT NULL COMMENT '分类名', " +
|
|
|
|
|
+ "icon VARCHAR(20) DEFAULT '' COMMENT '图标emoji', " +
|
|
|
|
|
+ "color VARCHAR(20) DEFAULT '#5B9BD5' COMMENT '标识色', " +
|
|
|
|
|
+ "sort_order INT DEFAULT 0 COMMENT '排序', " +
|
|
|
|
|
+ "status TINYINT DEFAULT 1 COMMENT '1启用/0禁用'" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章分类'");
|
|
|
|
|
+ log.info("已创建article_categories表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建article_categories表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 文章表
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS articles (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "category_id BIGINT DEFAULT 0 COMMENT '所属分类ID', " +
|
|
|
|
|
+ "title VARCHAR(200) NOT NULL COMMENT '标题', " +
|
|
|
|
|
+ "summary VARCHAR(500) DEFAULT '' COMMENT '摘要', " +
|
|
|
|
|
+ "cover_image VARCHAR(500) DEFAULT '' COMMENT '封面图URL', " +
|
|
|
|
|
+ "content LONGTEXT COMMENT '富文本内容', " +
|
|
|
|
|
+ "tags VARCHAR(200) DEFAULT '' COMMENT '标签JSON数组', " +
|
|
|
|
|
+ "author VARCHAR(100) DEFAULT '浠艾福' COMMENT '作者', " +
|
|
|
|
|
+ "read_time INT DEFAULT 0 COMMENT '预计阅读分钟数', " +
|
|
|
|
|
+ "related_dimensions VARCHAR(100) DEFAULT '' COMMENT '关联五维JSON数组', " +
|
|
|
|
|
+ "visibility VARCHAR(20) DEFAULT 'public' COMMENT '浏览权限:public/login/private', " +
|
|
|
|
|
+ "visible_to TEXT COMMENT '私密指定人群JSON', " +
|
|
|
|
|
+ "status VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/published/archived', " +
|
|
|
|
|
+ "is_featured TINYINT DEFAULT 0 COMMENT '1精选/0普通', " +
|
|
|
|
|
+ "published_at DATETIME DEFAULT NULL COMMENT '发布时间', " +
|
|
|
|
|
+ "view_count INT DEFAULT 0 COMMENT '浏览次数', " +
|
|
|
|
|
+ "created_by BIGINT DEFAULT 0 COMMENT '发布人adminID', " +
|
|
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章'");
|
|
|
|
|
+ log.info("已创建articles表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建articles表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 迁移: articles表补充新字段(兼容旧表)
|
|
|
|
|
+ try {
|
|
|
|
|
+ Integer colExists = jdbcTemplate.queryForObject(
|
|
|
|
|
+ "SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'articles' AND COLUMN_NAME = 'visibility'",
|
|
|
|
|
+ Integer.class);
|
|
|
|
|
+ if (colExists == null || colExists == 0) {
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE articles ADD COLUMN visibility VARCHAR(20) DEFAULT 'public' COMMENT '浏览权限:public/login/private' AFTER related_dimensions");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE articles ADD COLUMN visible_to TEXT COMMENT '私密指定人群JSON' AFTER visibility");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE articles ADD COLUMN tags VARCHAR(200) DEFAULT '' COMMENT '标签JSON数组' AFTER content");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE articles ADD COLUMN related_dimensions VARCHAR(100) DEFAULT '' COMMENT '关联五维JSON数组' AFTER read_time");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE articles ADD COLUMN is_featured TINYINT DEFAULT 0 COMMENT '1精选/0普通' AFTER status");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE articles ADD COLUMN published_at DATETIME DEFAULT NULL COMMENT '发布时间' AFTER is_featured");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE articles ADD COLUMN view_count INT DEFAULT 0 COMMENT '浏览次数' AFTER published_at");
|
|
|
|
|
+ jdbcTemplate.execute("ALTER TABLE articles ADD COLUMN created_by BIGINT DEFAULT 0 COMMENT '发布人adminID' AFTER view_count");
|
|
|
|
|
+ log.info("已迁移articles表补充字段");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.info("articles表字段已完整,跳过迁移");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("articles表字段迁移失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 五维能量系统(账本模式) ====================
|
|
|
|
|
+
|
|
|
|
|
+ // 维度定义表
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute(
|
|
|
|
|
+ "CREATE TABLE IF NOT EXISTS energy_dimension (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "code VARCHAR(16) NOT NULL UNIQUE COMMENT '维度代码: body/mind/wisdom/action/wealth', " +
|
|
|
|
|
+ "name VARCHAR(20) NOT NULL COMMENT '维度名称: 身/心/智/行/富', " +
|
|
|
|
|
+ "icon VARCHAR(16) COMMENT '图标emoji', " +
|
|
|
|
|
+ "element VARCHAR(10) COMMENT '五行元素: 土/火/金/木/水', " +
|
|
|
|
|
+ "sort_order INT DEFAULT 0 COMMENT '显示顺序', " +
|
|
|
|
|
+ "status TINYINT DEFAULT 1 COMMENT '1启用/0禁用', " +
|
|
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='能量维度定义表'"
|
|
|
|
|
+ );
|
|
|
|
|
+ log.info("已创建energy_dimension表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建energy_dimension表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 服务-维度比例配置表
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute(
|
|
|
|
|
+ "CREATE TABLE IF NOT EXISTS energy_source_config (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "source_type VARCHAR(32) NOT NULL COMMENT '来源类型: task/activity/course/product/consultation', " +
|
|
|
|
|
+ "source_id BIGINT NOT NULL COMMENT '来源业务表ID', " +
|
|
|
|
|
+ "source_name VARCHAR(200) COMMENT '冗余名称', " +
|
|
|
|
|
+ "dimension_id BIGINT NOT NULL COMMENT '维度ID', " +
|
|
|
|
|
+ "ratio DECIMAL(5,4) NOT NULL COMMENT '占比如0.6000=60%', " +
|
|
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ "INDEX idx_source (source_type, source_id)" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务-维度比例配置表'"
|
|
|
|
|
+ );
|
|
|
|
|
+ log.info("已创建energy_source_config表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建energy_source_config表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 能量流水表
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute(
|
|
|
|
|
+ "CREATE TABLE IF NOT EXISTS energy_log (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "child_id BIGINT NOT NULL COMMENT '孩子ID', " +
|
|
|
|
|
+ "dimension_id BIGINT NOT NULL COMMENT '维度ID', " +
|
|
|
|
|
+ "amount INT NOT NULL COMMENT '变动量(正=获得,负=消耗)', " +
|
|
|
|
|
+ "balance_after INT NOT NULL COMMENT '变动后余额', " +
|
|
|
|
|
+ "source_type VARCHAR(32) COMMENT '来源类型: task/product/medical_report/daily_record', " +
|
|
|
|
|
+ "source_id BIGINT COMMENT '来源ID', " +
|
|
|
|
|
+ "ref_id BIGINT COMMENT '关联旧流水ID(覆盖时标记)', " +
|
|
|
|
|
+ "expires_at DATETIME COMMENT '过期时间(空=永不过期)', " +
|
|
|
|
|
+ "description VARCHAR(500) COMMENT '描述', " +
|
|
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ "INDEX idx_child_dim (child_id, dimension_id), " +
|
|
|
|
|
+ "INDEX idx_created (created_at), " +
|
|
|
|
|
+ "INDEX idx_source (source_type, source_id)" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='能量流水表'"
|
|
|
|
|
+ );
|
|
|
|
|
+ log.info("已创建energy_log表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建energy_log表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 维度余额表
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute(
|
|
|
|
|
+ "CREATE TABLE IF NOT EXISTS energy_balance (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "child_id BIGINT NOT NULL COMMENT '孩子ID', " +
|
|
|
|
|
+ "dimension_id BIGINT NOT NULL COMMENT '维度ID', " +
|
|
|
|
|
+ "balance INT DEFAULT 0 COMMENT '当前能量值(可为负)', " +
|
|
|
|
|
+ "total_earned INT DEFAULT 0 COMMENT '累计获得', " +
|
|
|
|
|
+ "total_spent INT DEFAULT 0 COMMENT '累计消耗', " +
|
|
|
|
|
+ "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ "UNIQUE KEY uk_child_dim (child_id, dimension_id)" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='维度余额表'"
|
|
|
|
|
+ );
|
|
|
|
|
+ log.info("已创建energy_balance表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建energy_balance表失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 维度种子数据(按相生链: 智→富→行→心→身)
|
|
|
|
|
+ try {
|
|
|
|
|
+ Integer dimCount = jdbcTemplate.queryForObject(
|
|
|
|
|
+ "SELECT COUNT(*) FROM energy_dimension", Integer.class);
|
|
|
|
|
+ if (dimCount == null || dimCount == 0) {
|
|
|
|
|
+ jdbcTemplate.execute("INSERT INTO energy_dimension (code, name, icon, element, sort_order, status) VALUES " +
|
|
|
|
|
+ "('mind', '心', '🔥', '火', 4, 1), " +
|
|
|
|
|
+ "('body', '身', '🌏', '土', 5, 1), " +
|
|
|
|
|
+ "('wisdom', '智', '⚔️', '金', 1, 1), " +
|
|
|
|
|
+ "('action', '行', '🌿', '木', 3, 1), " +
|
|
|
|
|
+ "('wealth', '富', '💧', '水', 2, 1)");
|
|
|
|
|
+ log.info("能量维度种子数据已初始化");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("初始化能量维度种子数据失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 为已有商品插入默认比例配置(与Product.domain一致)
|
|
|
|
|
+ try {
|
|
|
|
|
+ Integer productConfigCount = jdbcTemplate.queryForObject(
|
|
|
|
|
+ "SELECT COUNT(*) FROM energy_source_config WHERE source_type = 'product'", Integer.class);
|
|
|
|
|
+ if (productConfigCount == null || productConfigCount == 0) {
|
|
|
|
|
+ String[][] domainMapping = {
|
|
|
|
|
+ {"action", "action"}, {"mind", "mind"}, {"body", "body"},
|
|
|
|
|
+ {"wisdom", "wisdom"}, {"wealth", "wealth"}
|
|
|
|
|
+ };
|
|
|
|
|
+ for (String[] mapping : domainMapping) {
|
|
|
|
|
+ jdbcTemplate.execute(
|
|
|
|
|
+ "INSERT INTO energy_source_config (source_type, source_id, source_name, dimension_id, ratio) " +
|
|
|
|
|
+ "SELECT 'product', p.id, p.name, d.id, 1.0000 " +
|
|
|
|
|
+ "FROM products p " +
|
|
|
|
|
+ "JOIN energy_dimension d ON d.code = '" + mapping[1] + "' " +
|
|
|
|
|
+ "WHERE p.domain = '" + mapping[0] + "' " +
|
|
|
|
|
+ "AND NOT EXISTS (" +
|
|
|
|
|
+ " SELECT 1 FROM energy_source_config esc " +
|
|
|
|
|
+ " WHERE esc.source_type = 'product' AND esc.source_id = p.id" +
|
|
|
|
|
+ ")"
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("已有商品能量比例配置已初始化");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("初始化商品能量比例配置失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
log.info("数据库迁移完成");
|
|
log.info("数据库迁移完成");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1816,4 +2146,17 @@ try {
|
|
|
name, desc, price, type, domain, memberEligible);
|
|
name, desc, price, type, domain, memberEligible);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ private void insertContentSectionSeed(String pageKey, String sectionKey, String title,
|
|
|
|
|
+ String allowedRoles, int sortOrder) {
|
|
|
|
|
+ Integer count = jdbcTemplate.queryForObject(
|
|
|
|
|
+ "SELECT COUNT(*) FROM content_sections WHERE page_key = ? AND section_key = ?",
|
|
|
|
|
+ Integer.class, pageKey, sectionKey);
|
|
|
|
|
+ if (count == null || count == 0) {
|
|
|
|
|
+ jdbcTemplate.update(
|
|
|
|
|
+ "INSERT INTO content_sections (page_key, section_key, title, allowed_roles, sort_order, status, created_at, updated_at) " +
|
|
|
|
|
+ "VALUES (?, ?, ?, ?, ?, 'active', NOW(), NOW())",
|
|
|
|
|
+ pageKey, sectionKey, title, allowedRoles, sortOrder);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|