|
|
@@ -5245,9 +5245,65 @@ try {
|
|
|
runMigration80();
|
|
|
runMigration81();
|
|
|
runMigration82();
|
|
|
- runMigration83();
|
|
|
- runMigration84();
|
|
|
- runMigration85();
|
|
|
+ runMigration86();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void runMigration81() {
|
|
|
+
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS product_dimension_mapping (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "product_id BIGINT NOT NULL COMMENT '商品 ID', " +
|
|
|
+ "dimension_code VARCHAR(32) NOT NULL COMMENT '维度:body/wisdom/mind/action/wealth', " +
|
|
|
+ "match_score INT DEFAULT 100 COMMENT '匹配度 0-100', " +
|
|
|
+ "match_reason VARCHAR(200) COMMENT '匹配原因', " +
|
|
|
+ "tags VARCHAR(500) COMMENT '推荐标签 JSON', " +
|
|
|
+ "enabled TINYINT DEFAULT 1, " +
|
|
|
+ "created_at DATETIME, " +
|
|
|
+ "updated_at DATETIME, " +
|
|
|
+ "INDEX idx_product (product_id), " +
|
|
|
+ "INDEX idx_dimension (dimension_code) " +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品维度关联表'");
|
|
|
+ log.info("已创建 product_dimension_mapping 表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建 product_dimension_mapping 表失败:{}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS ai_conversation_summary (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "user_id BIGINT NOT NULL COMMENT '用户ID', " +
|
|
|
+ "conversation_id VARCHAR(100) NOT NULL COMMENT 'Dify会话ID', " +
|
|
|
+ "summary_text TEXT COMMENT '对话摘要文本', " +
|
|
|
+ "summary_tokens INT DEFAULT 0 COMMENT '摘要token数', " +
|
|
|
+ "message_count INT DEFAULT 0 COMMENT '本次对话消息数', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "INDEX idx_conversation (conversation_id), " +
|
|
|
+ "INDEX idx_user (user_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI对话摘要'");
|
|
|
+ log.info("已创建ai_conversation_summary表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建ai_conversation_summary表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS ai_user_facts (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "user_id BIGINT NOT NULL COMMENT '用户ID', " +
|
|
|
+ "fact_key VARCHAR(100) NOT NULL COMMENT '事实键', " +
|
|
|
+ "fact_value VARCHAR(500) COMMENT '事实值', " +
|
|
|
+ "source_conversation VARCHAR(100) COMMENT '来源会话ID', " +
|
|
|
+ "confidence DECIMAL(3,2) DEFAULT 1.00 COMMENT '置信度0-1', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', " +
|
|
|
+ "INDEX idx_user_key (user_id, fact_key), " +
|
|
|
+ "INDEX idx_conversation (source_conversation)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI用户关键事实'");
|
|
|
+ log.info("已创建ai_user_facts表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建ai_user_facts表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
|
|
|
// 迁移 81: products 表添加 recommendation_tags 字段
|
|
|
ensureColumn("products", "recommendation_tags", "VARCHAR(500) COMMENT '推荐标签 JSON' AFTER domain");
|
|
|
@@ -5322,27 +5378,6 @@ try {
|
|
|
} catch (Exception e) { /* 表已存在忽略 */ }
|
|
|
}
|
|
|
|
|
|
- private void runMigration81() {
|
|
|
- try {
|
|
|
- jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS product_dimension_mapping (" +
|
|
|
- "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
- "product_id BIGINT NOT NULL COMMENT '商品 ID', " +
|
|
|
- "dimension_code VARCHAR(32) NOT NULL COMMENT '维度:body/wisdom/mind/action/wealth', " +
|
|
|
- "match_score INT DEFAULT 100 COMMENT '匹配度 0-100', " +
|
|
|
- "match_reason VARCHAR(200) COMMENT '匹配原因', " +
|
|
|
- "tags VARCHAR(500) COMMENT '推荐标签 JSON', " +
|
|
|
- "enabled TINYINT DEFAULT 1, " +
|
|
|
- "created_at DATETIME, " +
|
|
|
- "updated_at DATETIME, " +
|
|
|
- "INDEX idx_product (product_id), " +
|
|
|
- "INDEX idx_dimension (dimension_code) " +
|
|
|
- ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品维度关联表'");
|
|
|
- log.info("已创建 product_dimension_mapping 表");
|
|
|
- } catch (Exception e) {
|
|
|
- log.warn("创建 product_dimension_mapping 表失败:{}", e.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private void runMigration82() {
|
|
|
try {
|
|
|
jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS ai_conversation_summary (" +
|
|
|
@@ -5380,94 +5415,148 @@ try {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void runMigration83() {
|
|
|
- // 迁移83: activities/products/articles添加dimension_weights JSON列(五维权重百分比)
|
|
|
- ensureColumn("activities", "dimension_weights",
|
|
|
- "JSON DEFAULT NULL COMMENT '{\"body\":0,\"mind\":0,\"wisdom\":0,\"action\":0,\"wealth\":0}'");
|
|
|
- ensureColumn("products", "dimension_weights",
|
|
|
- "JSON DEFAULT NULL COMMENT '{\"body\":0,\"mind\":0,\"wisdom\":0,\"action\":0,\"wealth\":0}'");
|
|
|
- ensureColumn("articles", "dimension_weights",
|
|
|
- "JSON DEFAULT NULL COMMENT '{\"body\":0,\"mind\":0,\"wisdom\":0,\"action\":0,\"wealth\":0}'");
|
|
|
- }
|
|
|
+ private void runMigration86() {
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS supply_hierarchy (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "system_id BIGINT NOT NULL COMMENT '供应商体系ID', " +
|
|
|
+ "parent_id BIGINT NOT NULL COMMENT '上级供应商ID', " +
|
|
|
+ "child_id BIGINT NOT NULL COMMENT '下级供应商ID', " +
|
|
|
+ "level INT DEFAULT 1 COMMENT '层级深度', " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'active', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
+ "UNIQUE KEY uk_system_parent_child (system_id, parent_id, child_id), " +
|
|
|
+ "KEY idx_system_child (system_id, child_id), " +
|
|
|
+ "KEY idx_parent (parent_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商上下级关系表'");
|
|
|
+ log.info("已创建supply_hierarchy表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建supply_hierarchy表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
|
|
|
- private void runMigration84() {
|
|
|
- // 迁移84: 存量数据回填 — 根据dimension_code/domain/relatedDimensions初始化dimension_weights
|
|
|
try {
|
|
|
- int actCount = jdbcTemplate.queryForObject(
|
|
|
- "SELECT COUNT(*) FROM activities WHERE dimension_code IS NOT NULL AND dimension_code != '' AND dimension_weights IS NULL",
|
|
|
- Integer.class);
|
|
|
- if (actCount > 0) {
|
|
|
- jdbcTemplate.update(
|
|
|
- "UPDATE activities SET dimension_weights = " +
|
|
|
- "JSON_OBJECT(" +
|
|
|
- " 'body', IF(dimension_code='body',100,0)," +
|
|
|
- " 'mind', IF(dimension_code='mind',100,0)," +
|
|
|
- " 'wisdom', IF(dimension_code='wisdom',100,0)," +
|
|
|
- " 'action', IF(dimension_code='action',100,0)," +
|
|
|
- " 'wealth', IF(dimension_code='wealth',100,0)" +
|
|
|
- ") WHERE dimension_code IS NOT NULL AND dimension_code != '' AND dimension_weights IS NULL");
|
|
|
- log.info("已回填{}条activities的dimension_weights", actCount);
|
|
|
- }
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS supply_hierarchy_change_request (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "system_id BIGINT NOT NULL, " +
|
|
|
+ "applicant_id BIGINT NOT NULL COMMENT '申请人ID', " +
|
|
|
+ "target_parent_id BIGINT NOT NULL COMMENT '目标上级ID', " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'pending', " +
|
|
|
+ "reason VARCHAR(500), " +
|
|
|
+ "reject_reason VARCHAR(500), " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "reviewed_at DATETIME, " +
|
|
|
+ "reviewed_by BIGINT, " +
|
|
|
+ "KEY idx_system_applicant (system_id, applicant_id), " +
|
|
|
+ "KEY idx_status (status)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商更换上级申请表'");
|
|
|
+ log.info("已创建supply_hierarchy_change_request表");
|
|
|
} catch (Exception e) {
|
|
|
- log.warn("回填activities.dimension_weights失败: {}", e.getMessage());
|
|
|
+ log.warn("创建supply_hierarchy_change_request表失败: {}", e.getMessage());
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- int prodCount = jdbcTemplate.queryForObject(
|
|
|
- "SELECT COUNT(*) FROM products WHERE domain IS NOT NULL AND domain != '' AND dimension_weights IS NULL",
|
|
|
- Integer.class);
|
|
|
- if (prodCount > 0) {
|
|
|
- jdbcTemplate.update(
|
|
|
- "UPDATE products SET dimension_weights = " +
|
|
|
- "JSON_OBJECT(" +
|
|
|
- " 'body', IF(domain='body',100,0)," +
|
|
|
- " 'mind', IF(domain='mind',100,0)," +
|
|
|
- " 'wisdom', IF(domain='wisdom',100,0)," +
|
|
|
- " 'action', IF(domain='action',100,0)," +
|
|
|
- " 'wealth', IF(domain='wealth',100,0)" +
|
|
|
- ") WHERE domain IS NOT NULL AND domain != '' AND dimension_weights IS NULL");
|
|
|
- log.info("已回填{}条products的dimension_weights", prodCount);
|
|
|
- }
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS butler_profiles (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "user_id BIGINT NOT NULL, " +
|
|
|
+ "tier VARCHAR(10), " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'pending', " +
|
|
|
+ "member_count INT DEFAULT 0, " +
|
|
|
+ "max_members INT DEFAULT 50, " +
|
|
|
+ "annual_fee_l1 BIGINT, " +
|
|
|
+ "annual_fee_l2 BIGINT, " +
|
|
|
+ "description TEXT, " +
|
|
|
+ "certificates TEXT, " +
|
|
|
+ "reject_reason VARCHAR(500), " +
|
|
|
+ "commission_rate_l1 INT DEFAULT 1000, " +
|
|
|
+ "commission_rate_l2 INT DEFAULT 5000, " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
+ "approved_at DATETIME, " +
|
|
|
+ "UNIQUE KEY uk_user_id (user_id), " +
|
|
|
+ "INDEX idx_status (status), " +
|
|
|
+ "INDEX idx_tier (tier)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管家服务提供商档案'");
|
|
|
+ log.info("已创建butler_profiles表");
|
|
|
} catch (Exception e) {
|
|
|
- log.warn("回填products.dimension_weights失败: {}", e.getMessage());
|
|
|
+ log.warn("创建butler_profiles表失败: {}", e.getMessage());
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- int artCount = jdbcTemplate.queryForObject(
|
|
|
- "SELECT COUNT(*) FROM articles WHERE related_dimensions IS NOT NULL AND related_dimensions != '' AND dimension_weights IS NULL",
|
|
|
- Integer.class);
|
|
|
- if (artCount > 0) {
|
|
|
- jdbcTemplate.update("UPDATE articles SET dimension_weights = JSON_OBJECT(" +
|
|
|
- "'body', IF(INSTR(COALESCE(related_dimensions,''),'body')>0 OR INSTR(COALESCE(related_dimensions,''),'身')>0, 100, 0)," +
|
|
|
- "'mind', IF(INSTR(COALESCE(related_dimensions,''),'mind')>0 OR INSTR(COALESCE(related_dimensions,''),'心')>0, 100, 0)," +
|
|
|
- "'wisdom', IF(INSTR(COALESCE(related_dimensions,''),'wisdom')>0 OR INSTR(COALESCE(related_dimensions,''),'智')>0, 100, 0)," +
|
|
|
- "'action', IF(INSTR(COALESCE(related_dimensions,''),'action')>0 OR INSTR(COALESCE(related_dimensions,''),'行')>0, 100, 0)," +
|
|
|
- "'wealth', IF(INSTR(COALESCE(related_dimensions,''),'wealth')>0 OR INSTR(COALESCE(related_dimensions,''),'富')>0, 100, 0)" +
|
|
|
- ") WHERE related_dimensions IS NOT NULL AND related_dimensions != '' AND dimension_weights IS NULL");
|
|
|
- log.info("已回填{}条articles的dimension_weights", artCount);
|
|
|
- }
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS butler_service_records (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "butler_id BIGINT NOT NULL, " +
|
|
|
+ "member_user_id BIGINT NOT NULL, " +
|
|
|
+ "subscription_id BIGINT, " +
|
|
|
+ "service_type VARCHAR(20) NOT NULL, " +
|
|
|
+ "amount_p BIGINT NOT NULL, " +
|
|
|
+ "platform_fee_p BIGINT DEFAULT 0, " +
|
|
|
+ "butler_amount_p BIGINT DEFAULT 0, " +
|
|
|
+ "member_tier VARCHAR(10), " +
|
|
|
+ "year_month VARCHAR(7), " +
|
|
|
+ "remark VARCHAR(500), " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "INDEX idx_butler_id (butler_id), " +
|
|
|
+ "INDEX idx_member_user_id (member_user_id), " +
|
|
|
+ "INDEX idx_year_month (year_month)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管家服务记录'");
|
|
|
+ log.info("已创建butler_service_records表");
|
|
|
} catch (Exception e) {
|
|
|
- log.warn("回填articles.dimension_weights失败: {}", e.getMessage());
|
|
|
+ log.warn("创建butler_service_records表失败: {}", e.getMessage());
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- private void runMigration85() {
|
|
|
- // 迁移85: 创建dimension_weights表(管理端保存维度权重使用)
|
|
|
try {
|
|
|
- jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS dimension_weights (" +
|
|
|
- "id BIGINT AUTO_INCREMENT PRIMARY KEY," +
|
|
|
- "target_type VARCHAR(20) NOT NULL COMMENT '目标类型: activity/product/article'," +
|
|
|
- "target_id BIGINT NOT NULL COMMENT '目标ID'," +
|
|
|
- "dimension VARCHAR(20) NOT NULL COMMENT '维度: body/mind/wisdom/action/wealth'," +
|
|
|
- "weight INT DEFAULT 0 COMMENT '权重百分比'," +
|
|
|
- "enabled TINYINT(1) DEFAULT 0 COMMENT '是否启用'," +
|
|
|
- "created_at DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
- "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
|
|
|
- "INDEX idx_target (target_type, target_id)" +
|
|
|
- ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='维度权重表'");
|
|
|
- log.info("已创建dimension_weights表");
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS butler_commission_settlements (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "butler_id BIGINT NOT NULL, " +
|
|
|
+ "year_month VARCHAR(7) NOT NULL, " +
|
|
|
+ "member_count INT DEFAULT 0, " +
|
|
|
+ "annual_base_amount_p BIGINT DEFAULT 0, " +
|
|
|
+ "annual_butler_amount_p BIGINT DEFAULT 0, " +
|
|
|
+ "annual_platform_amount_p BIGINT DEFAULT 0, " +
|
|
|
+ "per_session_total_p BIGINT DEFAULT 0, " +
|
|
|
+ "per_session_platform_total_p BIGINT DEFAULT 0, " +
|
|
|
+ "per_session_butler_total_p BIGINT DEFAULT 0, " +
|
|
|
+ "total_butler_amount_p BIGINT DEFAULT 0, " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'pending', " +
|
|
|
+ "settled_at DATETIME, " +
|
|
|
+ "settled_by BIGINT, " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "UNIQUE KEY uk_butler_month (butler_id, year_month), " +
|
|
|
+ "INDEX idx_status (status), " +
|
|
|
+ "INDEX idx_year_month (year_month)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管家月度佣金结算单'");
|
|
|
+ log.info("已创建butler_commission_settlements表");
|
|
|
} catch (Exception e) {
|
|
|
- log.warn("创建dimension_weights表失败: {}", e.getMessage());
|
|
|
+ log.warn("创建butler_commission_settlements表失败: {}", e.getMessage());
|
|
|
}
|
|
|
+
|
|
|
+try {
|
|
|
+ jdbcTemplate.execute("ALTER TABLE users ADD COLUMN butler_status VARCHAR(20)");
|
|
|
+ jdbcTemplate.execute("ALTER TABLE users ADD COLUMN butler_info TEXT");
|
|
|
+ jdbcTemplate.execute("ALTER TABLE users ADD COLUMN butler_approved_at DATETIME");
|
|
|
+ log.info("已添加 butler 相关列到 users 表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移 86: 创建 butler_assignments 表(会员 - 管家分配记录)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS butler_assignments (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "family_id BIGINT NOT NULL COMMENT '家庭 ID', " +
|
|
|
+ "butler_user_id BIGINT NOT NULL COMMENT '管家用户 ID', " +
|
|
|
+ "subscription_id BIGINT COMMENT '关联订阅 ID', " +
|
|
|
+ "level VARCHAR(10) NOT NULL COMMENT '订阅级别 L1/L2', " +
|
|
|
+ "assigned_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "UNIQUE KEY uk_family_assignment (family_id), " +
|
|
|
+ "INDEX idx_butler_user_id (butler_user_id), " +
|
|
|
+ "INDEX idx_subscription_id (subscription_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员 - 管家分配记录'");
|
|
|
+ log.info("已创建 butler_assignments 表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建 butler_assignments 表失败:{}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
}
|
|
|
}
|