| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- #!/usr/bin/env node
- /**
- * 区域数据CSV转SQL导入脚本
- * 将 docs/省市区.csv 转换为 area_data 表的 INSERT 语句
- * 使用方法: node docs/generate-area-sql.mjs
- */
- import fs from 'fs';
- import path from 'path';
- import { fileURLToPath } from 'url';
- // 获取当前目录
- const __filename = fileURLToPath(import.meta.url);
- const __dirname = path.dirname(__filename);
- // 文件路径
- const csvFilePath = path.join(__dirname, '省市区.csv');
- const outputSqlPath = path.join(__dirname, 'area_data_init.sql');
- // 读取CSV文件
- function readCSV(filePath) {
- try {
- const content = fs.readFileSync(filePath, 'utf-8');
- return content.trim().split('\n');
- } catch (error) {
- console.error('读取CSV文件失败:', error.message);
- process.exit(1);
- }
- }
- // 解析CSV行
- function parseCSVLine(line) {
- // 处理包含逗号的字段
- const parts = line.split(',');
- if (parts.length !== 3) {
- console.warn('跳过格式不正确的行:', line);
- return null;
- }
-
- const [id, parentId, name] = parts;
- return {
- id: parseInt(id.trim()),
- parentId: parseInt(parentId.trim()) || null,
- name: name.trim()
- };
- }
- // 生成SQL语句
- function generateSQLStatements(data) {
- const statements = [
- '-- 区域数据初始化脚本',
- '-- 来源: docs/省市区.csv',
- '-- 生成时间: ' + new Date().toISOString(),
- '',
- '-- 清空现有数据(可选)',
- '-- TRUNCATE TABLE area_data;',
- '',
- '-- 插入区域数据',
- 'INSERT INTO area_data (id, parent_id, name, created_at, updated_at) VALUES'
- ];
- const values = data.map(item =>
- ` (${item.id}, ${item.parentId === 0 ? 'NULL' : item.parentId}, '${escapeString(item.name)}', NOW(), NOW())`
- );
- statements.push(values.join(',\n'));
- statements.push(';');
-
- return statements.join('\n');
- }
- // 转义SQL字符串
- function escapeString(str) {
- return str.replace(/'/g, "''");
- }
- // 验证数据完整性
- function validateData(data) {
- const ids = new Set();
- const parentIds = new Set();
-
- for (const item of data) {
- if (ids.has(item.id)) {
- console.warn(`重复的ID: ${item.id}`);
- }
- ids.add(item.id);
-
- if (item.parentId !== null && item.parentId !== 0) {
- parentIds.add(item.parentId);
- }
- }
-
- // 检查所有parentId是否都存在对应的记录
- for (const parentId of parentIds) {
- if (!ids.has(parentId)) {
- console.warn(`父ID不存在: ${parentId}`);
- }
- }
-
- console.log(`总计 ${data.length} 条区域数据`);
- console.log(`顶级区域数量: ${data.filter(item => item.parentId === 0 || item.parentId === null).length}`);
- }
- // 主函数
- function main() {
- console.log('开始生成区域数据SQL文件...');
-
- // 检查CSV文件是否存在
- if (!fs.existsSync(csvFilePath)) {
- console.error('CSV文件不存在:', csvFilePath);
- process.exit(1);
- }
-
- // 读取并解析CSV
- const lines = readCSV(csvFilePath);
-
- // 跳过表头
- const header = lines[0];
- if (header !== 'aId,aFId,aName') {
- console.warn('CSV文件格式可能不正确,表头不匹配');
- }
-
- const data = [];
- for (let i = 1; i < lines.length; i++) {
- const line = lines[i].trim();
- if (line) {
- const item = parseCSVLine(line);
- if (item) {
- data.push(item);
- }
- }
- }
-
- // 验证数据
- validateData(data);
-
- // 生成SQL
- const sql = generateSQLStatements(data);
-
- // 写入SQL文件
- try {
- fs.writeFileSync(outputSqlPath, sql, 'utf-8');
- console.log('SQL文件已生成:', outputSqlPath);
- console.log('文件大小:', (fs.statSync(outputSqlPath).size / 1024).toFixed(2), 'KB');
- } catch (error) {
- console.error('写入SQL文件失败:', error.message);
- process.exit(1);
- }
-
- // 生成使用说明
- console.log('\n使用说明:');
- console.log('1. 运行: node docs/generate-area-sql.mjs');
- console.log('2. 执行生成的SQL文件: mysql -u username -p database < docs/area_data_init.sql');
- console.log('3. 或者直接在数据库管理工具中执行SQL内容');
- }
- // 执行主函数
- if (import.meta.url === `file://${process.argv[1]}`) {
- main();
- }
- export {
- readCSV,
- parseCSVLine,
- generateSQLStatements,
- validateData
- };
|