|
@@ -8561,4 +8561,149 @@ private void runMigration100() {
|
|
|
// 迁移225: articles 添加 growth_category 列(成长分类筛选,Article 实体已含字段,生产库缺列导致 Unknown column 'growth_category')
|
|
// 迁移225: articles 添加 growth_category 列(成长分类筛选,Article 实体已含字段,生产库缺列导致 Unknown column 'growth_category')
|
|
|
ensureColumn("articles", "growth_category", "VARCHAR(50) DEFAULT NULL COMMENT '成长分类'");
|
|
ensureColumn("articles", "growth_category", "VARCHAR(50) DEFAULT NULL COMMENT '成长分类'");
|
|
|
}
|
|
}
|
|
|
|
|
+ private void seedFullRegionData() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Integer count = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM streets WHERE level = 1", Integer.class);
|
|
|
|
|
+ if (count != null && count >= 20) {
|
|
|
|
|
+ log.info("全国省市区数据已存在({}个省份),跳过导入", count);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("检查省份数据失败,跳过全量导入: {}", e.getMessage());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ org.springframework.core.io.Resource resource = resourceLoader.getResource("classpath:region_data.json");
|
|
|
|
|
+ if (!resource.exists()) {
|
|
|
|
|
+ log.warn("region_data.json 不存在,跳过全量省市区数据导入");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ String content = new String(StreamUtils.copyToByteArray(resource.getInputStream()), StandardCharsets.UTF_8);
|
|
|
|
|
+ com.alibaba.fastjson.JSONArray provinces = com.alibaba.fastjson.JSON.parseArray(content);
|
|
|
|
|
+
|
|
|
|
|
+ for (int pi = 0; pi < provinces.size(); pi++) {
|
|
|
|
|
+ com.alibaba.fastjson.JSONObject prov = provinces.getJSONObject(pi);
|
|
|
|
|
+ String provName = prov.getString("name");
|
|
|
|
|
+ String provCode = prov.getString("code");
|
|
|
|
|
+
|
|
|
|
|
+ java.sql.Connection conn = jdbcTemplate.getDataSource().getConnection();
|
|
|
|
|
+ java.sql.PreparedStatement ps = conn.prepareStatement(
|
|
|
|
|
+ "INSERT INTO streets (province, province_code, full_name, level, parent_id, sort_order) VALUES (?, ?, ?, 1, NULL, ?)",
|
|
|
|
|
+ java.sql.Statement.RETURN_GENERATED_KEYS
|
|
|
|
|
+ );
|
|
|
|
|
+ ps.setString(1, provName);
|
|
|
|
|
+ ps.setString(2, provCode);
|
|
|
|
|
+ ps.setString(3, provName);
|
|
|
|
|
+ ps.setInt(4, pi + 1);
|
|
|
|
|
+ ps.executeUpdate();
|
|
|
|
|
+ java.sql.ResultSet rs = ps.getGeneratedKeys();
|
|
|
|
|
+ long provId = 0;
|
|
|
|
|
+ if (rs.next()) provId = rs.getLong(1);
|
|
|
|
|
+ rs.close();
|
|
|
|
|
+ ps.close();
|
|
|
|
|
+
|
|
|
|
|
+ com.alibaba.fastjson.JSONArray cities = prov.getJSONArray("cities");
|
|
|
|
|
+ if (cities == null) continue;
|
|
|
|
|
+
|
|
|
|
|
+ for (int ci = 0; ci < cities.size(); ci++) {
|
|
|
|
|
+ com.alibaba.fastjson.JSONObject city = cities.getJSONObject(ci);
|
|
|
|
|
+ String cityName = city.getString("name");
|
|
|
|
|
+ String cityCode = city.getString("code");
|
|
|
|
|
+
|
|
|
|
|
+ java.sql.PreparedStatement ps2 = conn.prepareStatement(
|
|
|
|
|
+ "INSERT INTO streets (province, province_code, city, city_code, full_name, level, parent_id, sort_order) VALUES (?, ?, ?, ?, ?, 2, ?, ?)",
|
|
|
|
|
+ java.sql.Statement.RETURN_GENERATED_KEYS
|
|
|
|
|
+ );
|
|
|
|
|
+ ps2.setString(1, provName);
|
|
|
|
|
+ ps2.setString(2, provCode);
|
|
|
|
|
+ ps2.setString(3, cityName);
|
|
|
|
|
+ ps2.setString(4, cityCode);
|
|
|
|
|
+ ps2.setString(5, provName + cityName);
|
|
|
|
|
+ ps2.setLong(6, provId);
|
|
|
|
|
+ ps2.setInt(7, ci + 1);
|
|
|
|
|
+ ps2.executeUpdate();
|
|
|
|
|
+ java.sql.ResultSet rs2 = ps2.getGeneratedKeys();
|
|
|
|
|
+ long cityId = 0;
|
|
|
|
|
+ if (rs2.next()) cityId = rs2.getLong(1);
|
|
|
|
|
+ rs2.close();
|
|
|
|
|
+ ps2.close();
|
|
|
|
|
+
|
|
|
|
|
+ com.alibaba.fastjson.JSONArray districts = city.getJSONArray("districts");
|
|
|
|
|
+ if (districts == null) continue;
|
|
|
|
|
+
|
|
|
|
|
+ for (int di = 0; di < districts.size(); di++) {
|
|
|
|
|
+ com.alibaba.fastjson.JSONObject dist = districts.getJSONObject(di);
|
|
|
|
|
+ String distName = dist.getString("name");
|
|
|
|
|
+ String distCode = dist.getString("code");
|
|
|
|
|
+
|
|
|
|
|
+ java.sql.PreparedStatement ps3 = conn.prepareStatement(
|
|
|
|
|
+ "INSERT INTO streets (province, province_code, city, city_code, district, district_code, full_name, level, parent_id, sort_order) VALUES (?, ?, ?, ?, ?, ?, ?, 3, ?, ?)",
|
|
|
|
|
+ java.sql.Statement.RETURN_GENERATED_KEYS
|
|
|
|
|
+ );
|
|
|
|
|
+ ps3.setString(1, provName);
|
|
|
|
|
+ ps3.setString(2, provCode);
|
|
|
|
|
+ ps3.setString(3, cityName);
|
|
|
|
|
+ ps3.setString(4, cityCode);
|
|
|
|
|
+ ps3.setString(5, distName);
|
|
|
|
|
+ ps3.setString(6, distCode);
|
|
|
|
|
+ ps3.setString(7, provName + cityName + distName);
|
|
|
|
|
+ ps3.setLong(8, cityId);
|
|
|
|
|
+ ps3.setInt(9, di + 1);
|
|
|
|
|
+ ps3.executeUpdate();
|
|
|
|
|
+ ps3.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ conn.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("全国省市区数据导入完成:{}省/{}市/{}区", provinces.size(), 0, 0);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("导入全国省市区数据失败: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 迁移226: 创建 family_platform_balance 表 + family_platform_balance_log 表 + products.points_multiplier 列
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute(
|
|
|
|
|
+ "CREATE TABLE IF NOT EXISTS family_platform_balance (" +
|
|
|
|
|
+ " id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ " family_id BIGINT NOT NULL COMMENT '家庭ID', " +
|
|
|
|
|
+ " total_earned INT DEFAULT 0 COMMENT '累计获得', " +
|
|
|
|
|
+ " available INT DEFAULT 0 COMMENT '可用余额', " +
|
|
|
|
|
+ " frozen INT DEFAULT 0 COMMENT '冻结(提现审核中)', " +
|
|
|
|
|
+ " withdrawn INT DEFAULT 0 COMMENT '已提现', " +
|
|
|
|
|
+ " exchanged INT DEFAULT 0 COMMENT '已兑换', " +
|
|
|
|
|
+ " created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ " updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ " UNIQUE KEY uk_family (family_id)" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭平台积分池余额'"
|
|
|
|
|
+ );
|
|
|
|
|
+ log.info("已创建family_platform_balance表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建family_platform_balance表失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute(
|
|
|
|
|
+ "CREATE TABLE IF NOT EXISTS family_platform_balance_log (" +
|
|
|
|
|
+ " id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ " family_id BIGINT NOT NULL COMMENT '家庭ID', " +
|
|
|
|
|
+ " type VARCHAR(20) NOT NULL COMMENT 'earn/spend/freeze/unfreeze/withdraw/adjust/migration', " +
|
|
|
|
|
+ " amount INT NOT NULL COMMENT '变动数量', " +
|
|
|
|
|
+ " balance_after INT NOT NULL COMMENT '变动后可用余额', " +
|
|
|
|
|
+ " ref_type VARCHAR(50) COMMENT 'product_order/referral_dist/activity/withdrawal/adjust/migration/refund', " +
|
|
|
|
|
+ " ref_id BIGINT COMMENT '关联业务ID', " +
|
|
|
|
|
+ " remark VARCHAR(255) COMMENT '备注', " +
|
|
|
|
|
+ " created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
+ " INDEX idx_family (family_id), " +
|
|
|
|
|
+ " INDEX idx_ref (ref_type, ref_id)" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭平台积分流水'"
|
|
|
|
|
+ );
|
|
|
|
|
+ log.info("已创建family_platform_balance_log表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("创建family_platform_balance_log表失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ ensureColumn("products", "points_multiplier", "DECIMAL(4,2) NOT NULL DEFAULT 1.00 COMMENT '平台积分倍数,1元=1积分×倍数'");
|
|
|
|
|
+ log.info("已添加products.points_multiplier列");
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|