|
|
@@ -5245,64 +5245,9 @@ try {
|
|
|
runMigration80();
|
|
|
runMigration81();
|
|
|
runMigration82();
|
|
|
- }
|
|
|
-
|
|
|
- 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());
|
|
|
- }
|
|
|
+ runMigration83();
|
|
|
+ runMigration84();
|
|
|
+ runMigration85();
|
|
|
|
|
|
// 迁移 81: products 表添加 recommendation_tags 字段
|
|
|
ensureColumn("products", "recommendation_tags", "VARCHAR(500) COMMENT '推荐标签 JSON' AFTER domain");
|
|
|
@@ -5377,6 +5322,27 @@ 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 (" +
|
|
|
@@ -5413,4 +5379,95 @@ try {
|
|
|
log.warn("创建ai_user_facts表失败: {}", e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ 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 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);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("回填activities.dimension_weights失败: {}", 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);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("回填products.dimension_weights失败: {}", 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);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("回填articles.dimension_weights失败: {}", 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表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建dimension_weights表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|