Browse Source

采集程序

王波 5 tháng trước cách đây
commit
e18011cc79

+ 219 - 0
pom.xml

@@ -0,0 +1,219 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.example</groupId>
+    <artifactId>DataAcquisition</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <name>Archetype - DataAcquisition</name>
+    <url>http://maven.apache.org</url>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.3.7.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <properties>
+        <java.version>1.8</java.version> <!-- 或您正在使用的 Java 版本 -->
+    </properties>
+
+    <dependencies>
+        <!-- Spring Boot 依赖项 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <scope>runtime</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- 数据库驱动 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>1.2.11</version>
+        </dependency>
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.oracle.database.jdbc</groupId>
+            <artifactId>ojdbc8</artifactId>
+            <version>19.7.0.0</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.xerial</groupId>
+            <artifactId>sqlite-jdbc</artifactId>
+            <version>3.36.0.3</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.taosdata.jdbc</groupId>
+            <artifactId>taos-jdbcdriver</artifactId>
+            <version>3.2.2</version>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!-- MyBatis Plus -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-generator</artifactId>
+            <version>3.3.2</version>
+            <scope>test</scope> <!-- 如果生成器只在测试时使用 -->
+        </dependency>
+
+        <!-- 其他依赖项 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>2.0.40</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.16.20</version>
+            <scope>provided</scope> <!-- 如果在编译时生成代码,但在运行时不需要 -->
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity-engine-core</artifactId>
+            <version>2.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.netflix.feign</groupId>
+            <artifactId>feign-core</artifactId>
+            <version>8.18.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.netflix.feign</groupId>
+            <artifactId>feign-jackson</artifactId>
+            <version>8.18.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>1.6.2</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-core</artifactId>
+            <version>5.8.16</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-ui</artifactId>
+            <version>1.7.0</version> <!-- 请确保使用最新版本 -->
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+            <version>4.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+            <version>2.3.32</version>
+        </dependency>
+        <dependency>
+            <groupId>org.example</groupId>
+            <artifactId>lcm-commons</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.haifengl</groupId>
+            <artifactId>smile-core</artifactId>
+            <version>2.6.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-generator</artifactId>
+            <version>3.3.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.xerial</groupId>
+            <artifactId>sqlite-jdbc</artifactId>
+            <version>3.39.3.0</version>
+        </dependency>
+        <!-- JSON.org 的 JSON 库 -->
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>20231013</version> <!-- 请根据需要选择版本 -->
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.15.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.15.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>2.15.2</version>
+        </dependency>
+        <!-- 测试依赖项 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <!-- 添加必要的插件,如 spring-boot-maven-plugin 用于打包和运行 Spring Boot 应用 -->
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 37 - 0
src/main/java/com/acquisition/DataAcquisitionApplication.java

@@ -0,0 +1,37 @@
+package com.acquisition;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.system.ApplicationHome;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.Environment;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import static org.reflections.Reflections.log;
+
+@SpringBootApplication
+public class DataAcquisitionApplication {
+    public static void main(String[] args) throws UnknownHostException {
+        ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(DataAcquisitionApplication.class, args);
+
+        Environment env = configurableApplicationContext.getEnvironment();
+        String ip = InetAddress.getLocalHost().getHostAddress();
+        String port = env.getProperty("server.port");
+        String path = env.getProperty("server.servlet.context-path");
+        ApplicationHome home = new ApplicationHome(DataAcquisitionApplication.class);
+        String filePath = home.getSource().getParentFile().getAbsolutePath();
+
+        //        createFolder();
+
+        log.info("\n-------------------------------------------------------------------\n\t" +
+                "经济运行系统启动成功,访问路径如下:\n\t" +
+                "本地路径: \t\thttp://localhost:" + port + path + "\n\t" +
+                "网络地址: \t\thttp://" + ip + ":" + port + path + "\n\t" +
+                "API文档: \t\thttp://" + ip + ":" + port + path + "/swagger-ui.html\n" +
+                "-----------------------------------------------------------------------");
+        log.info(filePath);
+        System.out.println("Hello World!");
+    }
+}

+ 128 - 0
src/main/java/com/acquisition/config/ExcelImporter.java

@@ -0,0 +1,128 @@
+package com.acquisition.config;
+
+
+import com.acquisition.mapper.auto.DataAcquisitionMapper;
+import com.acquisition.model.auto.DataAcquisition;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.List;
+@Component
+public class ExcelImporter {
+
+    @Autowired
+    private DataAcquisitionMapper dataAcquisitionMapper;
+
+    /**
+     * 配置总表数据导入读取Excel文件
+     * @param folderPath
+     * @throws Exception
+     */
+    public void importExcelToDatabase(String folderPath) throws Exception {
+        // 文件夹路径
+        File folder = new File(folderPath);
+        if (!folder.exists()) {
+            System.out.println("文件夹不存在:" + folderPath);
+            return;
+        }
+
+        // 清空表数据
+        clearTable();
+
+        // 遍历文件夹中的 Excel 文件
+        for (File file : folder.listFiles()) {
+            if (file.isFile() && file.getName().endsWith(".xlsx")) {
+                System.out.println("处理文件:" + file.getName());
+
+                // 读取 Excel 文件
+                FileInputStream fis = new FileInputStream(file);
+                Workbook workbook = new XSSFWorkbook(fis);
+                Sheet sheet = workbook.getSheetAt(0);
+
+                // 解析 Excel 数据
+                List<DataAcquisition> dataList = new ArrayList<>();
+                for (int i = 1; i <= sheet.getLastRowNum(); i++) {
+                    Row row = sheet.getRow(i);
+                    if (row == null) continue;
+
+                    DataAcquisition data = new DataAcquisition();
+                    data.setIec104Addr(parseInteger(getCellValue(row.getCell(0))));
+                    data.setIec104Xmax(parseInteger(getCellValue(row.getCell(1))));
+                    data.setIec104Xmin(parseInteger(getCellValue(row.getCell(2))));
+                    data.setIec104Coeff(parseInteger(getCellValue(row.getCell(3))));
+                    data.setIec104Base(parseInteger(getCellValue(row.getCell(4))));
+                    data.setGyfpAddr(parseInteger(getCellValue(row.getCell(5))));
+                    data.setGyfpValid(parseInteger(getCellValue(row.getCell(6))));
+                    data.setGyfpCoeff(parseInteger(getCellValue(row.getCell(7))));
+                    data.setGyfpBase(parseInteger(getCellValue(row.getCell(8))));
+                    data.setGyfp2Addr(parseInteger(getCellValue(row.getCell(9))));
+                    data.setGyfp2Valid(parseInteger(getCellValue(row.getCell(10))));
+                    data.setGyfp2Coeff(parseInteger(getCellValue(row.getCell(11))));
+                    data.setGyfp2Base(parseInteger(getCellValue(row.getCell(12))));
+                    data.setMongoKey(getCellValue(row.getCell(13))); // 字符串类型
+                    data.setDescribe(getCellValue(row.getCell(14))); // 字符串类型
+                    dataList.add(data);
+                }
+
+                // 将数据批量插入到数据库
+                if (!dataList.isEmpty()) {
+                    dataList.forEach(dataAcquisitionMapper::insert);
+                }
+
+                // 关闭 Excel 工作簿
+                workbook.close();
+                fis.close();
+                System.out.println("文件处理完成:" + file.getName());
+            }
+        }
+    }
+
+
+
+    /**
+     * 清空表数据
+     */
+    private void clearTable() {
+        System.out.println("清空表数据...");
+        dataAcquisitionMapper.delete(null); // 使用 MyBatis-Plus 提供的 delete 方法清空表
+        System.out.println("表数据已清空!");
+    }
+
+    private String getCellValue(Cell cell) {
+        if (cell == null) {
+            return null;
+        }
+        switch (cell.getCellType()) {
+            case STRING:
+                return cell.getStringCellValue();
+            case NUMERIC:
+                // 检查是否为整数
+                if (cell.getNumericCellValue() % 1 == 0) {
+                    return String.valueOf((int) cell.getNumericCellValue());
+                } else {
+                    return String.valueOf(cell.getNumericCellValue());
+                }
+            case BOOLEAN:
+                return String.valueOf(cell.getBooleanCellValue());
+            case FORMULA:
+                return cell.getCellFormula();
+            default:
+                return null;
+        }
+    }
+
+    private Integer parseInteger(String value) {
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            return null; // 如果无法解析,返回 null
+        }
+    }
+
+
+}

+ 95 - 0
src/main/java/com/acquisition/config/FileUtils.java

@@ -0,0 +1,95 @@
+package com.acquisition.config;
+
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public class FileUtils {
+
+    // 读取 Excel 中指定列的数据
+
+    public static List<String> readExcelColumn(String excelPath, int columnIndex) throws Exception {
+        List<String> columnData = new ArrayList<>();
+
+        try (FileInputStream fis = new FileInputStream(excelPath);
+             Workbook workbook = new XSSFWorkbook(fis)) {
+            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表
+            int firstRow = sheet.getFirstRowNum();
+            int lastRow = sheet.getLastRowNum();
+
+            for (int i = firstRow; i <= lastRow; i++) {
+                Row row = sheet.getRow(i);
+                String cellValue = "";
+                if(row != null){
+                    Cell cell = row.getCell(columnIndex);
+                    cellValue =  getCellValueAsString(cell);
+                }
+                columnData.add(cellValue);
+            }
+        }
+        return columnData;
+    }
+
+    private static String getCellValueAsString(Cell cell) {
+        if (cell == null || cell.getCellType() == CellType.BLANK) {
+            return "无";
+        }
+
+        switch (cell.getCellType()) {
+            case STRING:
+                return cell.getStringCellValue().trim();
+            case NUMERIC:
+                if (DateUtil.isCellDateFormatted(cell)) {
+                    return cell.getDateCellValue().toString().trim();
+                }else{
+                    return String.valueOf(cell.getNumericCellValue()).trim();
+                }
+            case BOOLEAN:
+                return String.valueOf(cell.getBooleanCellValue()).trim();
+            case FORMULA:
+                return cell.getCellFormula().trim();
+            default:
+                return cell.toString().trim();
+        }
+    }
+    public static void createDirectory(String directoryPath) throws IOException {
+        Path path = Paths.get(directoryPath);
+        if (!Files.exists(path)) {
+            Files.createDirectories(path);
+        }
+    }
+
+    public static void copyFolderContent(String sourceDir, String targetDir) throws IOException {
+        Path sourcePath = Paths.get(sourceDir);
+        Path targetPath = Paths.get(targetDir);
+
+        if (!Files.exists(sourcePath) || !Files.isDirectory(sourcePath)) {
+            System.err.println("源目录不存在或不是目录: " + sourceDir);
+            return; // 源目录不存在或不是目录,则直接返回
+        }
+
+        Files.walk(sourcePath).forEach(source -> {
+                    Path target = targetPath.resolve(sourcePath.relativize(source));
+                    try {
+                        if (Files.isDirectory(source)) {
+                            if(!Files.exists(target)){
+                                Files.createDirectories(target);
+                            }
+                        } else {
+                            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+                        }
+                    }catch (IOException ex){
+                        System.err.println("拷贝文件失败, 源文件: " + source + ", 目标文件: " + target + " " + ex.getMessage());
+                    }
+                }
+        );
+    }
+}

+ 154 - 0
src/main/java/com/acquisition/config/GeneratorCodeConfig.java

@@ -0,0 +1,154 @@
+package com.acquisition.config;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+
+import java.util.Scanner;
+
+/**
+ *@ClassName GeneratorCodeConfig
+ *@Description 自动生成mybatisplus的相关代码
+ *@Author 谢生杰
+ *@Date 2020/9/25 18:26
+ *@Version 1.0
+ **/
+public class GeneratorCodeConfig {
+    public static String scanner(String tip) {
+        Scanner scanner = new Scanner(System.in);
+        StringBuilder help = new StringBuilder();
+        help.append("请输入" + tip + ":");
+        System.out.println(help.toString());
+        if (scanner.hasNext()) {
+            String ipt = scanner.next();
+            if (StringUtils.isNotEmpty(ipt)) {
+                return ipt;
+            }
+        }
+        throw new MybatisPlusException("请输入正确的" + tip + "!");
+    }
+
+    public static void main(String[] args) {
+        // 代码生成器
+        AutoGenerator mpg = new AutoGenerator();
+
+        // 全局配置
+        GlobalConfig gc = new GlobalConfig();
+        String projectPath = System.getProperty("user.dir");
+        gc.setOutputDir(projectPath+ "/src/main/java");
+        gc.setAuthor("wang");
+        gc.setOpen(false);
+        //实体属性 Swagger2 注解
+        gc.setSwagger2(false);
+        mpg.setGlobalConfig(gc);
+
+        // 数据源配置
+        DataSourceConfig dsc = new DataSourceConfig();
+        /*dsc.setUrl("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true");
+        dsc.setDriverName("com.mysql.jdbc.Driver");
+        dsc.setUsername("root");
+        dsc.setPassword("root");
+        mpg.setDataSource(dsc);*/
+//        dsc.setDriverName("oracle.jdbc.driver.OracleDriver");
+//        dsc.setUsername("gdprod");
+//        dsc.setPassword("gd123");
+//        dsc.setUrl("jdbc:oracle:thin:@10.83.68.165:1521:gdsj");
+
+        dsc.setDriverName("org.postgresql.Driver");
+        dsc.setUsername("postgres");
+        dsc.setPassword("gyeepd@123");
+        dsc.setUrl("jdbc:postgresql://123.60.219.66:5432/power_lcm");
+//        dsc.setDriverName("org.postgresql.Driver");
+//        dsc.setUsername("postgres");
+//        dsc.setPassword("postgres");
+//        dsc.setUrl("jdbc:postgresql://192.168.11.248:5432/IMS_NEM_SD");
+//        dsc.setUrl("jdbc:postgresql://124.70.75.91:5432/jn_test");
+//        dsc.setUsername("postgres");
+//        dsc.setPassword("gd123");
+        mpg.setDataSource(dsc);
+
+
+
+        // 包配置
+        PackageConfig pc = new PackageConfig();
+//        pc.setModuleName(scanner("模块名"));
+        pc.setParent("com.acquisition");
+        pc.setEntity("model.auto");
+        pc.setMapper("mapper.auto");
+        pc.setService("service.auto");
+        pc.setServiceImpl("service.auto.impl");
+        mpg.setPackageInfo(pc);
+
+        // 自定义配置
+//        InjectionConfig cfg = new InjectionConfig() {
+//            @Override
+//            public void initMap() {
+//                // to do nothing
+//            }
+//        };
+
+        // 如果模板引擎是 freemarker
+//        String templatePath = "/templates/mapper.xml.ftl";
+        // 如果模板引擎是 velocity
+        // String templatePath = "/templates/mapper.xml.vm";
+
+        // 自定义输出配置
+//        List<FileOutConfig> focList = new ArrayList<>();
+        // 自定义配置会被优先输出
+//        focList.add(new FileOutConfig(templatePath) {
+//            @Override
+//            public String outputFile(TableInfo tableInfo) {
+//                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
+//                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+//                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
+//            }
+//        });
+        /*
+        cfg.setFileCreate(new IFileCreate() {
+            @Override
+            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
+                // 判断自定义文件夹是否需要创建
+                checkDir("调用默认方法创建的目录");
+                return false;
+            }
+        });
+        */
+//        cfg.setFileOutConfigList(focList);
+//        mpg.setCfg(cfg);
+
+        // 配置模板
+        TemplateConfig templateConfig = new TemplateConfig();
+
+        // 配置自定义输出模板
+        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
+        // templateConfig.setEntity("templates/entity2.java");
+        // templateConfig.setService();
+        // templateConfig.setController();
+
+        templateConfig.setXml(null);
+        mpg.setTemplate(templateConfig);
+
+        // 策略配置
+        StrategyConfig strategy = new StrategyConfig();
+        strategy.setNaming(NamingStrategy.underline_to_camel);
+        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
+        strategy.setSuperEntityClass("com.baomidou.mybatisplus.extension.activerecord.Model");
+        strategy.setEntityLombokModel(true);
+        strategy.setRestControllerStyle(true);
+
+        strategy.setEntityLombokModel(true);
+        // 公共父类
+//        strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController");
+        // 写于父类中的公共字段
+//        strategy.setSuperEntityColumns("id");
+        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
+        strategy.setControllerMappingHyphenStyle(true);
+        strategy.setTablePrefix(pc.getModuleName() + "_");
+        mpg.setStrategy(strategy);
+        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
+        mpg.execute();
+    }
+}

+ 113 - 0
src/main/java/com/acquisition/controller/DataAcquisitionController.java

@@ -0,0 +1,113 @@
+package com.acquisition.controller;
+
+import com.acquisition.service.DataAcquisition.DataAcquisitionService;
+import com.acquisition.service.DataAcquisition.FileProcessorConfigService;
+import com.acquisition.service.DataAcquisition.FileProcessorService;
+import com.acquisition.service.auto.impl.DataAcquisitionServiceImpl;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 前端控制器
+ * </p>
+ *
+ * @author wang
+ * @since 2025-01-07
+ */
+@RestController
+@RequestMapping("//data-acquisition")
+public class DataAcquisitionController {
+
+    @Autowired
+    private DataAcquisitionServiceImpl dataAcquisitionService;
+
+    @Autowired
+    private DataAcquisitionService dataService;
+
+    @Autowired
+    private FileProcessorService fileProcessorService;
+
+    @Autowired
+    private FileProcessorConfigService configService;
+
+    /**
+     * 总表数据自动导入。
+     *
+     * @return 导入完成信息
+     */
+    @GetMapping("/import")
+    @Operation(summary = "总表数据自动导入", description = "执行总表数据的自动导入任务")
+    @ApiResponse(responseCode = "200", description = "成功返回导入完成信息",
+            content = @Content(mediaType = "text/plain",
+                    schema = @Schema(implementation = String.class)))
+    public String importData() {
+        dataAcquisitionService.importDataFromExcel();
+        return "数据导入完成!";
+    }
+
+
+    /**
+     * 可选列导出SQLite。
+     *
+     * @param columns 需要导出的字段列表
+     * @return 导出完成信息
+     * @throws Exception 如果导出过程中出现问题
+     */
+    @GetMapping("/export-to-sqlite")
+    @Operation(summary = "可选列导出SQLite", description = "根据指定的字段导出数据到SQLite数据库")
+    @ApiResponse(responseCode = "200", description = "成功返回导出完成信息",
+            content = @Content(mediaType = "text/plain",
+                    schema = @Schema(implementation = String.class)))
+    public String exportToSQLite(
+            @Parameter(description = "需要导出的字段名称列表", required = true)
+            @RequestParam List<String> columns) throws Exception {
+        dataService.export(columns);
+        return "数据已导出";
+    }
+
+
+    /**
+     * 创建data文件并复制demo文件。
+     *
+     * @return 完成信息
+     * @throws Exception 如果处理文件时出现错误
+     */
+    @GetMapping("/fileprocess")
+    @Operation(summary = "创建data文件并复制demo文件", description = "执行创建data文件并复制demo文件")
+    @ApiResponse(responseCode = "200", description = "成功返回完成信息",
+            content = @Content(mediaType = "text/plain",
+                    schema = @Schema(implementation = String.class)))
+    public String fileprocess() throws Exception {
+        fileProcessorService.processFiles();
+        return "文件夹创建已完成";
+    }
+
+    /**
+     * 数据自动采集。
+     *
+     * @return 完成信息
+     * @throws Exception 如果处理文件时出现错误
+     */
+    @GetMapping("/fileprocessconfig")
+    @Operation(summary = "数据自动采集配置", description = "数据自动采集配置")
+    @ApiResponse(responseCode = "200", description = "成功返回完成信息",
+            content = @Content(mediaType = "text/plain",
+                    schema = @Schema(implementation = String.class)))
+    public String fileprocessconfig() throws Exception {
+        configService.processFiles();
+        return "数据自动配置已完成";
+    }
+
+}

+ 18 - 0
src/main/java/com/acquisition/mapper/auto/DataAcquisitionMapper.java

@@ -0,0 +1,18 @@
+package com.acquisition.mapper.auto;
+
+import com.acquisition.model.auto.DataAcquisition;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author wang
+ * @since 2025-01-07
+ */
+@Mapper
+public interface DataAcquisitionMapper extends BaseMapper<DataAcquisition> {
+
+}

+ 201 - 0
src/main/java/com/acquisition/model/auto/DataAcquisition.java

@@ -0,0 +1,201 @@
+package com.acquisition.model.auto;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wang
+ * @since 2025-01-07
+ */
+@Data
+@TableName("data_acquisition")
+@EqualsAndHashCode(callSuper = true)
+public class DataAcquisition extends Model {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("iec104_addr")
+    private Integer iec104Addr;
+
+    @TableField("iec104_xmax")
+    private Integer iec104Xmax;
+
+    @TableField("iec104_xmin")
+    private Integer iec104Xmin;
+
+    @TableField("iec104_coeff")
+    private Integer iec104Coeff;
+
+    @TableField("iec104_base")
+    private Integer iec104Base;
+
+    @TableField("gyfp_addr")
+    private Integer gyfpAddr;
+
+    @TableField("gyfp_valid")
+    private Integer gyfpValid;
+
+    @TableField("gyfp_coeff")
+    private Integer gyfpCoeff;
+
+    @TableField("gyfp_base")
+    private Integer gyfpBase;
+
+    @TableField("gyfp2_addr")
+    private Integer gyfp2Addr;
+
+    @TableField("gyfp2_valid")
+    private Integer gyfp2Valid;
+
+    @TableField("gyfp2_coeff")
+    private Integer gyfp2Coeff;
+
+    @TableField("gyfp2_base")
+    private Integer gyfp2Base;
+
+    @TableField("mongo_key")
+    private String mongoKey;
+
+    @TableField("describe")
+    private String describe;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getIec104Addr() {
+        return iec104Addr;
+    }
+
+    public void setIec104Addr(Integer iec104Addr) {
+        this.iec104Addr = iec104Addr;
+    }
+
+    public Integer getIec104Xmax() {
+        return iec104Xmax;
+    }
+
+    public void setIec104Xmax(Integer iec104Xmax) {
+        this.iec104Xmax = iec104Xmax;
+    }
+
+    public Integer getIec104Xmin() {
+        return iec104Xmin;
+    }
+
+    public void setIec104Xmin(Integer iec104Xmin) {
+        this.iec104Xmin = iec104Xmin;
+    }
+
+    public Integer getIec104Coeff() {
+        return iec104Coeff;
+    }
+
+    public void setIec104Coeff(Integer iec104Coeff) {
+        this.iec104Coeff = iec104Coeff;
+    }
+
+    public Integer getIec104Base() {
+        return iec104Base;
+    }
+
+    public void setIec104Base(Integer iec104Base) {
+        this.iec104Base = iec104Base;
+    }
+
+    public Integer getGyfpAddr() {
+        return gyfpAddr;
+    }
+
+    public void setGyfpAddr(Integer gyfpAddr) {
+        this.gyfpAddr = gyfpAddr;
+    }
+
+    public Integer getGyfpValid() {
+        return gyfpValid;
+    }
+
+    public void setGyfpValid(Integer gyfpValid) {
+        this.gyfpValid = gyfpValid;
+    }
+
+    public Integer getGyfpCoeff() {
+        return gyfpCoeff;
+    }
+
+    public void setGyfpCoeff(Integer gyfpCoeff) {
+        this.gyfpCoeff = gyfpCoeff;
+    }
+
+    public Integer getGyfpBase() {
+        return gyfpBase;
+    }
+
+    public void setGyfpBase(Integer gyfpBase) {
+        this.gyfpBase = gyfpBase;
+    }
+
+    public Integer getGyfp2Addr() {
+        return gyfp2Addr;
+    }
+
+    public void setGyfp2Addr(Integer gyfp2Addr) {
+        this.gyfp2Addr = gyfp2Addr;
+    }
+
+    public Integer getGyfp2Valid() {
+        return gyfp2Valid;
+    }
+
+    public void setGyfp2Valid(Integer gyfp2Valid) {
+        this.gyfp2Valid = gyfp2Valid;
+    }
+
+    public Integer getGyfp2Coeff() {
+        return gyfp2Coeff;
+    }
+
+    public void setGyfp2Coeff(Integer gyfp2Coeff) {
+        this.gyfp2Coeff = gyfp2Coeff;
+    }
+
+    public Integer getGyfp2Base() {
+        return gyfp2Base;
+    }
+
+    public void setGyfp2Base(Integer gyfp2Base) {
+        this.gyfp2Base = gyfp2Base;
+    }
+
+    public String getMongoKey() {
+        return mongoKey;
+    }
+
+    public void setMongoKey(String mongoKey) {
+        this.mongoKey = mongoKey;
+    }
+
+    public String getDescribe() {
+        return describe;
+    }
+
+    public void setDescribe(String describe) {
+        this.describe = describe;
+    }
+}

+ 120 - 0
src/main/java/com/acquisition/service/DataAcquisition/DataAcquisitionService.java

@@ -0,0 +1,120 @@
+package com.acquisition.service.DataAcquisition;
+
+import com.acquisition.mapper.auto.DataAcquisitionMapper;
+import com.acquisition.model.auto.DataAcquisition;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.util.Collections;
+import java.util.List;
+
+@Service
+public class DataAcquisitionService {
+    @Autowired
+    private DataAcquisitionMapper dataAcquisitionMapper;
+
+    /**
+     * 动态选择列导出sqlite表
+     *
+     * @param columns
+     * @return
+     * @throws Exception
+     */
+    public String export(List<String> columns) throws Exception {
+        // 将列名组成的字符串传递给 SQL 查询
+        String columnList = String.join(",", columns);
+
+        // 动态构建 SQL 查询
+        List<DataAcquisition> dataList = dataAcquisitionMapper.selectList(new QueryWrapper<DataAcquisition>()
+                .select(columns.toArray(new String[0]))); // 动态选择列
+
+        // 设置文件路径,目标路径为桌面上的 data_acquisition/sqlite 文件夹
+        String sqliteFilePath = System.getProperty("user.home") + "\\Desktop\\data_acquisition\\sqlite\\keytable.sqlite3";
+
+        // 确保目标文件夹存在
+        File folder = new File(System.getProperty("user.home") + "\\Desktop\\data_acquisition\\sqlite");
+        if (!folder.exists()) {
+            folder.mkdirs();  // 如果文件夹不存在,则创建它
+        }
+
+        try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + sqliteFilePath)) {
+            // 创建表的 SQL 语句,根据用户输入的列生成表结构
+            StringBuilder createTableSQL = new StringBuilder("CREATE TABLE IF NOT EXISTS key_table (");
+
+            // 获取 DataAcquisition 类中的字段类型来构造 SQL 表
+            for (String column : columns) {
+                // 将列名从下划线格式转换为驼峰命名法
+                String camelCaseColumn = convertToCamelCase(column);
+                Field field = DataAcquisition.class.getDeclaredField(camelCaseColumn);  // 获取对应字段
+                String fieldType = getSQLType(field.getType()); // 获取 SQL 数据类型
+                createTableSQL.append(column).append(" ").append(fieldType).append(", ");
+            }
+            createTableSQL.setLength(createTableSQL.length() - 2);  // 删除最后一个多余的逗号
+            createTableSQL.append(")");
+
+            conn.createStatement().execute(createTableSQL.toString());
+
+            // 动态生成插入语句
+            String insertSQL = "INSERT INTO key_table (" + columnList + ") VALUES (" +
+                    String.join(",", Collections.nCopies(columns.size(), "?")) + ")";
+            try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {
+                for (DataAcquisition data : dataList) {
+                    for (int i = 0; i < columns.size(); i++) {
+                        // 根据列名动态构造 getter 方法名(转换下划线为驼峰格式)
+                        String getterMethodName = "get" + capitalizeFirstLetter(convertToCamelCase(columns.get(i)));
+                        Object value = data.getClass().getMethod(getterMethodName).invoke(data);
+                        pstmt.setObject(i + 1, value);
+                    }
+                    pstmt.addBatch(); // 批量插入
+                }
+                pstmt.executeBatch(); // 执行批量插入
+            }
+            return "数据已成功导出到 SQLite 文件:" + sqliteFilePath;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return "导出失败: " + e.getMessage();
+        }
+    }
+
+
+    // 工具方法:将下划线格式转换为驼峰命名法
+    private String convertToCamelCase(String str) {
+        String[] parts = str.split("_");
+        StringBuilder camelCaseString = new StringBuilder(parts[0].toLowerCase());
+        for (int i = 1; i < parts.length; i++) {
+            camelCaseString.append(parts[i].substring(0, 1).toUpperCase())
+                    .append(parts[i].substring(1).toLowerCase());
+        }
+        return camelCaseString.toString();
+    }
+
+    // 工具方法:处理字段名,确保_后第一字母大写
+    private String capitalizeFirstLetter(String str) {
+        if (str == null || str.isEmpty()) {
+            return str;
+        }
+        return str.substring(0, 1).toUpperCase() + str.substring(1);
+    }
+
+    // 获取字段的 SQL 数据类型
+    private String getSQLType(Class<?> clazz) {
+        if (clazz == Integer.class || clazz == int.class) {
+            return "INTEGER";
+        } else if (clazz == String.class) {
+            return "TEXT";
+        } else if (clazz == Double.class || clazz == double.class) {
+            return "REAL";
+        } else if (clazz == Boolean.class || clazz == boolean.class) {
+            return "INTEGER";
+        } else if (clazz == java.util.Date.class) {
+            return "TEXT";
+        }
+        return "TEXT";
+    }
+}

+ 504 - 0
src/main/java/com/acquisition/service/DataAcquisition/FileProcessorConfigService.java

@@ -0,0 +1,504 @@
+package com.acquisition.service.DataAcquisition;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.io.*;
+import java.nio.file.*;
+import java.sql.*;
+import java.util.*;
+
+@Service
+public class FileProcessorConfigService {
+
+    private final String collectionServiceDir;
+
+    // 构造方法中初始化路径
+    public FileProcessorConfigService() {
+        this.collectionServiceDir = System.getProperty("user.home") + "\\Desktop\\CollectionService";
+    }
+
+    /**
+     * 处理数据文件
+     *
+     * @throws Exception 如果处理文件时出现错误
+     */
+
+    public void processFiles() throws Exception {
+        // 读取配置Excel文件
+        List<List<String>> configData = configreadConfigExcel(collectionServiceDir + "\\demo\\config.xlsx");
+
+        // 从第1行开始遍历配置数据,i从0开始
+        for (int i = 1; i < configData.size(); i++) {  // i从0开始
+            List<String> rowData = configData.get(i); // 当前行数据
+            String folderNamecj = rowData.get(6); // 第一行第6列数据
+            String folderNamezf = rowData.get(14); // 第一行第14列数据
+            String folderNameredis = rowData.get(20); // 第一行第20列数据
+            String folderNamefs = rowData.get(22); // 第一行第22列数据
+            String folderNamejs = rowData.get(25); // 第一行第25列数据
+
+            String dataFolderPathcj = collectionServiceDir + "\\data" + (i) + "\\" + folderNamecj; // data1, data2, ...
+            String dataFolderPathzf = collectionServiceDir + "\\data" + (i) + "\\" + folderNamezf;
+            String dataFolderPathredis = collectionServiceDir + "\\data" + (i) + "\\" + folderNameredis;
+            String dataFolderPathfs = collectionServiceDir + "\\data" + (i) + "\\" + folderNamefs;
+            String dataFolderPathjs = collectionServiceDir + "\\data" + (i) + "\\" + folderNamejs;
+
+            // 获取该行对应的配置总表路径
+            String configExcelPath = collectionServiceDir + "\\data" + (i) + "\\配置总表.xlsx";
+
+            // 1. 读取配置总表.xlsx中的数据并生成sqlite3文件
+            List<List<String>> configExcelData = readConfigExcel(configExcelPath);
+
+            // 获取并传递需要的列数据给generateKeyTableFile方法
+            // 处理采集第2列到第10列的数据
+            if (!folderNamecj.equals("无")) {
+                cjmodifyJsonConfigFile(dataFolderPathcj, "wormholed.json", folderNamecj, rowData.get(28)); // 修改json文件,使用第28列数据作为插件
+                JsonpluginFile(dataFolderPathcj, rowData.get(28) + ".json", rowData.get(7), rowData.get(9), rowData.get(13), rowData.get(11));
+                generateKeyTableFile(dataFolderPathcj, configExcelData, 2, 10); // 读取第2列到第10列数据
+            }
+            //处理转发第11列到第19列的数据
+            if (!folderNamezf.equals("无")) {
+                modifyJsonConfigFile(dataFolderPathzf, "wormholed.json", folderNamezf); // 修改json文件
+                zfJsonpluginFile(dataFolderPathzf, null, rowData.get(15), rowData.get(16), rowData.get(17));
+                generateKeyTableFile(dataFolderPathzf, configExcelData, 11, 19); // 读取第11列到第19列数据
+            }
+            //处理redis第20列到第24列的数据
+            if (!folderNameredis.equals("无")) {
+                modifyJsonConfigFile(dataFolderPathredis, "wormholed.json", folderNameredis); // 修改json文件,修改pwd为第14列
+                redisJsonpluginFile(dataFolderPathredis, rowData.get(19), rowData.get(27));
+                generateKeyTableFile(dataFolderPathredis, configExcelData, 20, 24); // 读取20列到第24列的数据
+            }
+            //处理发送第25列到第29列的数据
+            if (!folderNamefs.equals("无")) {
+                modifyJsonConfigFile(dataFolderPathfs, "wormholed.json", folderNamefs); // 修改json文件,修改pwd为第14列
+                fsJsonpluginFile(dataFolderPathfs, rowData.get(23), rowData.get(24));
+                generateKeyTableFile(dataFolderPathfs, configExcelData, 25, 29); // 读取第25列到第29列的数据
+            }
+            //处理接收第30列到第34列的数据
+            if (!folderNamejs.equals("无")) {
+                modifyJsonConfigFile(dataFolderPathjs, "wormholed.json", folderNamejs); // 修改json文件,修改pwd为第14列
+                jsJsonpluginFile(dataFolderPathjs, rowData.get(26));
+                generateKeyTableFile(dataFolderPathjs, configExcelData, 30, 34); // 读取第30列到第34列的数据
+            }
+
+        }
+    }
+
+
+    //读取Excel文件中的数据
+    public List<List<String>> configreadConfigExcel(String excelPath) throws Exception {
+        List<List<String>> data = new ArrayList<>();
+
+        try (FileInputStream fis = new FileInputStream(excelPath);
+             Workbook workbook = new XSSFWorkbook(fis)) {
+            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表
+            int maxColumn = getMaxColumnCount(sheet);  // 获取最大列数
+
+            for (Row row : sheet) {
+                List<String> rowData = new ArrayList<>();
+                if (row != null) {  // 添加非空检查
+                    for (int i = 0; i < maxColumn; i++) {
+                        Cell cell = row.getCell(i);
+                        String cellValue = getCellValueAsString(cell);
+                        rowData.add(cellValue);
+                    }
+                } else {
+                    for (int i = 0; i < maxColumn; i++) {
+                        rowData.add("无");
+                    }
+                }
+
+                data.add(rowData);
+            }
+        }
+        return data;
+    }
+
+    // 获取最大列数
+    private int getMaxColumnCount(Sheet sheet) {
+        int maxColumn = 0;
+        for (Row row : sheet) {
+            if (row != null) {
+                maxColumn = Math.max(maxColumn, row.getLastCellNum());
+            }
+        }
+        return maxColumn;
+    }
+
+
+    private String getCellValueAsString(Cell cell) {
+        if (cell == null || cell.getCellType() == CellType.BLANK) {
+            return "无";
+        }
+
+        switch (cell.getCellType()) {
+            case STRING:
+                return cell.getStringCellValue().trim();
+            case NUMERIC:
+                if (DateUtil.isCellDateFormatted(cell)) {
+                    return cell.getDateCellValue().toString().trim();
+                } else {
+                    return String.valueOf(cell.getNumericCellValue()).trim();
+                }
+            case BOOLEAN:
+                return String.valueOf(cell.getBooleanCellValue()).trim();
+            case FORMULA:
+                return cell.getCellFormula().trim();
+            default:
+                return cell.toString().trim();
+        }
+    }
+
+    //读取Excel文件
+    public List<List<String>> readConfigExcel(String excelPath) throws Exception {
+        List<List<String>> data = new ArrayList<>();
+
+        // 通过 FileInputStream 读取 Excel 文件
+        try (FileInputStream fis = new FileInputStream(excelPath);
+             Workbook workbook = new XSSFWorkbook(fis)) {
+
+            // 获取第一个工作表
+            Sheet sheet = workbook.getSheetAt(0);
+
+            // 遍历每一行
+            for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {  // 采用getPhysicalNumberOfRows来提高效率
+                Row row = sheet.getRow(i);
+
+                if (row == null) continue;  // 跳过空行
+
+                List<String> rowData = new ArrayList<>();
+
+                // 遍历每个单元格
+                for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {  // 采用getPhysicalNumberOfCells来提高效率
+                    Cell cell = row.getCell(j);
+                    if (cell == null) {
+                        rowData.add("");  // 如果单元格为空,添加空字符串
+                    } else {
+                        switch (cell.getCellType()) {
+                            case STRING:
+                                rowData.add(cell.getStringCellValue().trim());
+                                break;
+                            case NUMERIC:
+                                rowData.add(String.valueOf(cell.getNumericCellValue()).trim());
+                                break;
+                            case BOOLEAN:
+                                rowData.add(String.valueOf(cell.getBooleanCellValue()).trim());
+                                break;
+                            default:
+                                rowData.add("");  // 对于其他类型的单元格返回空字符串
+                        }
+                    }
+                }
+
+                // 将读取到的行数据添加到数据列表中
+                data.add(rowData);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new Exception("Error reading Excel file: " + e.getMessage());
+        }
+
+        return data;
+    }
+
+
+    // 生成keytable.sqlite3文件
+    private void generateKeyTableFile(String dataFolderPath, List<List<String>> configExcelData, int startCol, int endCol) throws Exception {
+        // 提取指定列范围的数据
+        List<List<String>> dataToWrite = new ArrayList<>();
+
+        // 从configExcelData中获取第startCol到endCol列的数据
+        for (List<String> row : configExcelData) {
+            // 只取指定范围的列
+            List<String> rowData = row.subList(startCol, endCol + 1); // 提取列范围的数据
+            dataToWrite.add(rowData);
+        }
+
+        // 根据提取的数据生成sqlite3文件
+        String keytableDir = dataFolderPath + "\\keytable";
+        File keytableDirFile = new File(keytableDir);
+        if (!keytableDirFile.exists()) {
+            keytableDirFile.mkdir(); // 创建 keytable 目录
+        }
+
+        String sqliteFilePath = keytableDir + "\\keytable.sqlite3";
+        // 写入SQLite数据库
+        writeToSQLite(dataToWrite, sqliteFilePath);
+    }
+
+
+    // 写入SQLite数据库
+    private void writeToSQLite(List<List<String>> data, String sqliteFilePath) {
+        try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + sqliteFilePath)) {
+            // 获取列名(假设第一行是列名)
+            List<String> columnNames = data.get(0); // 第一行作为列名
+
+            // 创建表格
+            String createTableSQL = "CREATE TABLE IF NOT EXISTS keytable (";
+
+            // 检查每列的数据类型
+            for (int i = 0; i < columnNames.size(); i++) {
+                String columnType = "TEXT"; // 默认列类型为 TEXT
+
+                // 遍历当前列的所有数据来检查是否包含数字
+                for (int rowIdx = 1; rowIdx < data.size(); rowIdx++) { // 从第二行开始检查数据
+                    String cellValue = data.get(rowIdx).get(i).trim();
+                    // 如果列中任何数据是数字,将列的数据类型设置为 INTEGER
+                    if (cellValue.matches("-?\\d+(\\.\\d+)?")) { // 允许整数或浮动数字
+                        columnType = "INTEGER";
+                        break;
+                    }
+                }
+
+                createTableSQL += columnNames.get(i) + " " + columnType; // 使用原始列名和类型
+                if (i < columnNames.size() - 1) {
+                    createTableSQL += ", ";
+                }
+            }
+            createTableSQL += ");";
+
+            // 执行创建表格语句
+            try (Statement stmt = conn.createStatement()) {
+                stmt.execute(createTableSQL);
+            }
+
+            // 插入数据
+            StringBuilder insertSQL = new StringBuilder("INSERT INTO keytable VALUES (");
+            for (int i = 0; i < columnNames.size() - 1; i++) {
+                insertSQL.append("?, ");
+            }
+            insertSQL.append("?);"); // 最后一列不需要逗号
+
+            try (PreparedStatement pstmt = conn.prepareStatement(insertSQL.toString())) {
+                for (int rowIdx = 1; rowIdx < data.size(); rowIdx++) { // 从第二行开始处理数据
+                    List<String> row = data.get(rowIdx);
+                    for (int colIdx = 0; colIdx < row.size(); colIdx++) {
+                        String value = row.get(colIdx).trim();
+
+                        // 判断值是否为数字并设定相应的数据类型
+                        if (value.matches("-?\\d+(\\.\\d+)?")) {
+                            // 如果是浮动数字,转换为整数
+                            try {
+                                double numericValue = Double.parseDouble(value);
+                                // 如果是浮动数字,四舍五入并转为整数
+                                if (numericValue % 1 != 0) {
+                                    pstmt.setInt(colIdx + 1, (int) Math.round(numericValue)); // 插入整数
+                                } else {
+                                    pstmt.setInt(colIdx + 1, (int) numericValue); // 插入整数
+                                }
+                            } catch (NumberFormatException e) {
+                                pstmt.setString(colIdx + 1, value); // 如果无法解析为数字,插入为字符串
+                            }
+                        } else {
+                            pstmt.setString(colIdx + 1, value); // 插入文本
+                        }
+                    }
+                    pstmt.addBatch(); // 添加批处理
+                }
+                pstmt.executeBatch(); // 执行批量插入
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    // 修改采集wormholed.json文件
+    public void cjmodifyJsonConfigFile(String folderPath, String jsonFileName, String pwdData, String pluginData) throws IOException {
+        String jsonFilePath = folderPath + "/config/" + jsonFileName;
+        String content = new String(Files.readAllBytes(Paths.get(jsonFilePath)));
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 使用 Jackson 将 JSON 解析为 LinkedHashMap,保留顺序
+        LinkedHashMap<String, Object> orderedJsonMap = mapper.readValue(content, LinkedHashMap.class);
+
+
+        // 修改指定部分数据
+        // 修改 engine 部分
+        Object engineObj = orderedJsonMap.get("engine");
+        if (engineObj instanceof LinkedHashMap) {
+            LinkedHashMap<String, Object> engine = (LinkedHashMap<String, Object>) engineObj;
+            engine.put("pwd", "/home/GYEE/service/" + pwdData);
+        }
+
+        // 修改 ci 部分
+        Object ciObj = orderedJsonMap.get("ci");
+        if (ciObj instanceof LinkedHashMap) {
+            LinkedHashMap<String, Object> ci = (LinkedHashMap<String, Object>) ciObj;
+            ci.put("plugin", pluginData + ".so");
+            ci.put("config", pluginData + ".json");
+        }
+
+        // 使用 Jackson 将 LinkedHashMap 写入文件,保持格式化和顺序
+        mapper.writeValue(Paths.get(jsonFilePath).toFile(), orderedJsonMap);
+
+    }
+
+
+    // 采集plugin.json文件目录
+    public void JsonpluginFile(String folderPath, String jsonFileName, String ipData, String portData, String gyfpip, String gyfpport) throws IOException {
+        //采集104或者modbusJSON地址
+        String jsonFilePath = folderPath + "/plugin/" + jsonFileName;
+        //采集gyfp文件地址
+        String gyfpFilePath = folderPath + "/plugin/" + "libplugingyfp.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改采集第一个 JSON 文件
+        modifyJsonFile(mapper, jsonFilePath, ipData, portData, null);
+        // 读取并修改采集第二个 JSON 文件
+        modifyJsonFile(mapper, gyfpFilePath, gyfpip, gyfpport, null);
+
+        // 根据 jsonFileName 删除对应的文件
+        deleteFileByFileName(folderPath, jsonFileName);
+
+    }
+
+    // 转发plugin.json文件目录
+    public void zfJsonpluginFile(String folderPath, String ipData, String portData, String gyfpip, String gyfpport) throws IOException {
+
+        //转发gyfp文件地址
+        String zfFilePath = folderPath + "/plugin/" + "libplugingyfp.json";
+        //转发gyfp2文件地址
+        String zf2FilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改转发gyfp JSON 文件
+        modifyJsonFile(mapper, zfFilePath, ipData, portData, null);
+        // 读取并修改转发gyfp2 JSON 文件
+        modifyJsonFile(mapper, zf2FilePath, gyfpip, gyfpport, null);
+
+    }
+
+    // redis plugin.json文件目录
+    public void redisJsonpluginFile(String folderPath, String portData, String dbid) throws IOException {
+
+        //redis gyfp2文件地址
+        String redisFilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+        //redis-redis文件地址
+        String redis2FilePath = folderPath + "/plugin/" + "libpluginredis.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改redis gyfp JSON 文件
+        modifyJsonFile(mapper, redisFilePath, null, portData, null);
+        // 读取并修改redis redis JSON 文件
+        modifyJsonFile(mapper, redis2FilePath, null, null, dbid);
+
+    }
+
+    // 发送plugin.json文件目录
+    public void fsJsonpluginFile(String folderPath, String ipData, String portData) throws IOException {
+
+        //fs gyfp2文件地址
+        String fsFilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改fs gyfp2 JSON 文件
+        modifyJsonFile(mapper, fsFilePath, ipData, portData, null);
+
+    }
+
+    // 接收plugin.json文件目录
+    public void jsJsonpluginFile(String folderPath, String portData) throws IOException {
+
+        //js gyfp2文件地址
+        String fsFilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改fs gyfp2 JSON 文件
+        modifyJsonFile(mapper, fsFilePath, null, portData, null);
+
+    }
+
+    //修改plugin文件夹json文件
+    private void modifyJsonFile(ObjectMapper mapper, String filePath, String ipData, String portData, String dbid) throws IOException {
+        String content = new String(Files.readAllBytes(Paths.get(filePath)));
+        // 使用 Jackson 将 JSON 解析为 LinkedHashMap,保留顺序
+        LinkedHashMap<String, Object> orderedJsonMap = mapper.readValue(content, LinkedHashMap.class);
+
+        // 修改指定部分数据
+        // 修改 ip 部分
+        if (orderedJsonMap.containsKey("ip") && ipData != null && !ipData.equals("无")) {
+            orderedJsonMap.put("ip", ipData);
+        }
+
+        // 修改 dbid 部分
+        if (orderedJsonMap.containsKey("dbid") && dbid != null && !dbid.equals("无")) {
+            orderedJsonMap.put("dbid", dbid);
+        }
+
+
+        // 修改 port 部分
+        if (orderedJsonMap.containsKey("port") && portData != null && !portData.equals("无")) {
+            try {
+                double doublePort = Double.parseDouble(portData);
+                orderedJsonMap.put("port", (int) doublePort);
+            } catch (NumberFormatException e) {
+                System.err.println("转换port为int类型失败,使用默认值0 " + filePath + " " + e.getMessage());
+                orderedJsonMap.put("port", 0);
+            }
+
+        }
+        // 使用 Jackson 将 LinkedHashMap 写入文件,保持格式化和顺序
+        mapper.writeValue(Paths.get(filePath).toFile(), orderedJsonMap);
+
+    }
+
+    //采集有两种-执行删除plugin中json文件
+    private void deleteFileByFileName(String folderPath, String jsonFileName) {
+        Path filePathToDelete = null;
+        if ("libplugin104.json".equals(jsonFileName)) {
+            filePathToDelete = Paths.get(folderPath, "plugin", "libpluginmodbus.json");
+        } else {
+            filePathToDelete = Paths.get(folderPath, "plugin", "libplugin104.json");
+        }
+
+        try {
+            Files.delete(filePathToDelete);
+            System.out.println("成功删除文件:" + filePathToDelete);
+        } catch (NoSuchFileException e) {
+            System.err.println("文件不存在,删除失败:" + filePathToDelete + " " + e.getMessage());
+        } catch (IOException e) {
+            System.err.println("删除文件失败:" + filePathToDelete + " " + e.getMessage());
+        }
+    }
+
+    //修改除采集外其它四个目录wormholed文件
+    public void modifyJsonConfigFile(String folderPath, String jsonFileName, String pwdData) throws IOException {
+        String jsonFilePath = folderPath + "/config/" + jsonFileName;
+        String content = new String(Files.readAllBytes(Paths.get(jsonFilePath)));
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 使用 Jackson 将 JSON 解析为 LinkedHashMap,保留顺序
+        LinkedHashMap<String, Object> orderedJsonMap = mapper.readValue(content, LinkedHashMap.class);
+
+        // 修改 engine 部分
+        Object engineObj = orderedJsonMap.get("engine");
+        if (engineObj instanceof LinkedHashMap) {
+            LinkedHashMap<String, Object> engine = (LinkedHashMap<String, Object>) engineObj;
+            engine.put("pwd", "/home/GYEE/service/" + pwdData);
+        }
+
+        // 使用 Jackson 将 LinkedHashMap 写入文件,保持格式化和顺序
+        mapper.writeValue(Paths.get(jsonFilePath).toFile(), orderedJsonMap);
+
+    }
+
+}

+ 66 - 0
src/main/java/com/acquisition/service/DataAcquisition/FileProcessorService.java

@@ -0,0 +1,66 @@
+package com.acquisition.service.DataAcquisition;
+
+import com.acquisition.config.FileUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class FileProcessorService {
+
+    private final String collectionServiceDir;
+
+    public FileProcessorService() {
+        // 动态获取用户桌面的路径
+        this.collectionServiceDir = System.getProperty("user.home") + "/Desktop/CollectionService";
+    }
+
+
+    /**
+     * 创建data文件并复制demo文件
+     *
+     * @throws Exception
+     */
+    public void processFiles() throws Exception {
+        String configExcelPath = collectionServiceDir + "/demo/config.xlsx";
+
+        // 各字段列索引
+        int[] columnIndexes = {6, 14, 20, 22, 25}; // 对应采集服务名、三区转发服务等
+
+        String[] sourceFolders = {
+                "gyee_syz_cj",
+                "gyee_syz_zf",
+                "gyee_syz_redis",
+                "gyee_syz_fs",
+                "gyee_syz_js"
+        };
+        Map<String, Boolean> copiedDirs = new HashMap<>();
+        // 读取每列数据并处理
+        for (int i = 0; i < columnIndexes.length; i++) {
+            List<String> folderNames = FileUtils.readExcelColumn(configExcelPath, columnIndexes[i]);
+
+            for (int j = 1; j < folderNames.size(); j++) {
+                String folderName = folderNames.get(j);
+                // 如果数据为空或为“无”,跳过当前行
+                if (StringUtils.isBlank(folderName) || "无".equals(folderName)) {
+                    continue;
+                }
+                String targetDir = collectionServiceDir + "/data" + (j) + "/" + folderName;
+                if (!copiedDirs.containsKey(targetDir)) {
+                    FileUtils.createDirectory(targetDir);
+                    String sourceDir = collectionServiceDir + "/demo/" + sourceFolders[i];
+                    FileUtils.copyFolderContent(sourceDir, targetDir);
+                    copiedDirs.put(targetDir, true);
+                }
+            }
+        }
+    }
+}

+ 16 - 0
src/main/java/com/acquisition/service/IDataAcquisitionService.java

@@ -0,0 +1,16 @@
+package com.acquisition.service;
+
+import com.acquisition.model.auto.DataAcquisition;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author wang
+ * @since 2025-01-07
+ */
+public interface IDataAcquisitionService extends IService<DataAcquisition> {
+
+}

+ 36 - 0
src/main/java/com/acquisition/service/auto/impl/DataAcquisitionServiceImpl.java

@@ -0,0 +1,36 @@
+package com.acquisition.service.auto.impl;
+
+import com.acquisition.config.ExcelImporter;
+import com.acquisition.model.auto.DataAcquisition;
+import com.acquisition.mapper.auto.DataAcquisitionMapper;
+import com.acquisition.service.IDataAcquisitionService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 服务实现类
+ * </p>
+ *
+ * @author wang
+ * @since 2025-01-07
+ */
+@Service
+public class DataAcquisitionServiceImpl extends ServiceImpl<DataAcquisitionMapper, DataAcquisition> implements IDataAcquisitionService {
+    @Autowired
+    private ExcelImporter excelImporter;
+
+    /**
+     * 配置总表数据导入
+     */
+    public void importDataFromExcel() {
+        String folderPath = System.getProperty("user.home") + "\\Desktop\\data_acquisition"; // Windows 桌面路径
+        try {
+            excelImporter.importExcelToDatabase(folderPath);
+            System.out.println("数据导入成功!");
+        } catch (Exception e) {
+            System.err.println("数据导入失败:" + e.getMessage());
+        }
+    }
+}

+ 63 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,63 @@
+server:
+  port: 6060
+  servlet:
+    context-path: /
+
+spring:
+  application:
+    name: DataAcquisition
+  main:
+    allow-bean-definition-overriding: true # 当遇到同样名字的时候,是否允许覆盖注册
+
+  # 数据源配置
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driver-class-name: org.postgresql.Driver
+    dynamic:
+      primary: master
+      strict: false
+      datasource:
+        master:
+#          url: jdbc:postgresql://localhost:5432/power_forecast
+          url: jdbc:postgresql://123.60.219.66:5432/power_lcm
+          username: postgres
+#          password: gd123
+          password: gyeepd@123
+    druid:
+      max-active: 10
+      initial-size: 1
+      min-idle: 1
+      max-wait: 60000
+      time-between-eviction-runs-millis: 60000
+      min-evictable-idle-time-millis: 300000
+      test-while-idle: true
+      test-on-borrow: false
+      test-on-return: false
+
+  servlet:
+    multipart:
+      enabled: true
+      file-size-threshold: 2KB
+      max-file-size: 200MB
+      max-request-size: 215MB
+
+mybatis-plus:
+  configuration:
+    map-underscore-to-camel-case: true
+    auto-mapping-behavior: full
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+    # 如果需要按名称映射枚举,请使用EnumTypeHandler
+    # default-enum-type-handler: org.apache.ibatis.type.EnumTypeHandler
+  mapper-locations: classpath*:mapper/**/*Mapper.xml
+  global-config:
+    db-config:
+      id-type: assign_uuid
+      logic-not-delete-value: 1
+      logic-delete-value: 0
+  type-aliases-package: DataAcquisition.model.auto,com.gyee.jinneng_kpi.model.auto
+  type-enums-package: DataAcquisition.config
+
+logging:
+  level:
+    root: info
+    DataAcquisition: debug

+ 4 - 0
src/main/resources/application.yml

@@ -0,0 +1,4 @@
+spring:
+  profiles:
+    active: dev
+