| .gitignore | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| AGENTS.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| CLAUDE.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/hk/NumericalCollection/config/DataAcquisitionConfiguration.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/hk/NumericalCollection/service/impl/NumericalServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/application.yml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/test/java/com/hk/NumericalCollection/DeviceReceivingApplicationTests.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| start.bat | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
.gitignore
¶Ô±ÈÐÂÎļþ @@ -0,0 +1 @@ /.idea/ AGENTS.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,34 @@ # Repository Guidelines These notes explain how to contribute to NumericalCollection safely and consistently. ## Project Structure & Module Organization The Spring Boot sources live in `src/main/java/com/hk/NumericalCollection`, split into `config`, `controller`, `service`, `mapper`, `entity`, `dto`, and `task`. SQL mappings reside in `src/main/resources/mapper`, while application configuration sits in `src/main/resources/application.yml`. Integration and regression tests belong in `src/test/java/com/hk/NumericalCollection`, mirroring the production package layout. Maven metadata and dependency management are handled in the root `pom.xml`. ## Build, Test, and Development Commands Run `mvn clean install` to resolve dependencies and build the shaded JAR. Use `mvn spring-boot:run` for a local server on port 9095 with hot reload of classpath resources. Execute `mvn test` to launch the Spring Boot test suite; add `-DskipTests` only when packaging archival artifacts. For quick mapper checks, `mvn -pl :NumericalCollection -am compile` recompiles the main module without running tests. ## Coding Style & Naming Conventions Target Java 8 with 4-space indentation and Unix line endings. Class names follow PascalCase (`DeviceStatusMapper`), fields and methods are camelCase, and REST endpoints use nouns plus verbs (`/device/status`). Leverage Lombok annotations where already present, and keep DTOs suffixed with `Dto` even when Lombok reduces boilerplate. Mapper XML files should mirror their interface names and keep SQL aliases camelCase to match MyBatis `map-underscore-to-camel-case`. ## Testing Guidelines Extend `spring-boot-starter-test` defaults; new tests should end with `Tests` and live alongside the production package. Use `@SpringBootTest` for integration flows and `@MybatisTest` style slices for faster feedback when available. Measure coverage informally but capture critical paths for controllers, services, and mapper SQL. æ³¨ï¼æäº¤å请æ¬å°è¿è¡å ¨é¨æµè¯ï¼é¿å å½±åå¢éè¿åº¦ã ## Commit & Pull Request Guidelines Write concise, descriptive commit messages such as `feat: add device throughput aggregation` or `fix(controller): handle empty status payload`. Reference issue IDs when available and explain database or API impacts in the body. Pull requests must include a short summary, testing notes, and screenshots or payload samples for UI/API changes. Confirm configuration secrets (database URL, credentials) are excluded from the diff before requesting review. ## Security & Configuration Tips Override production database credentials in `application.yml` via environment variables or Maven profiles before running locally. Shared logs and SQL captures must redact customer identifiers. Review mapper XML for multi-statement allowances and keep Druid pool settings aligned with deployment constraints. å¼å工使µç¨ é®é¢è§£å³æµç¨ 1. é¦å æèé®é¢ï¼é 读代ç åºä¸çç¸å ³æä»¶ï¼å¹¶å°è®¡ååå ¥ tasks/todo.md 2. 计ååºå å«å¯ä»¥å¾é宿çå¾ åäºé¡¹å表 3. å¼å§å·¥ä½åï¼ä¸æç¡®è®¤è®¡å 4. ç¶åå¼å§å¤çå¾ åäºé¡¹ï¼å®ææ¶æ è®°ä¸ºå®æ 5. æ¯ä¸æ¥é½æä¾é«å±æ¬¡çåå说æ 6. 使æ¯ä¸ªä»»å¡åä»£ç æ´æ¹å°½å¯è½ç®åï¼é¿å å¤§è§æ¨¡æå¤æçæ´æ¹ 7. æ¯ä¸ªæ´æ¹åºå°½å¯è½å°å°å½±å代ç ï¼ä¸å以ç®åæ§ä¸ºæ ¸å¿ 8. æåï¼å¨ todo.md æä»¶ä¸æ·»å 审æ¥é¨åï¼æ»ç»æåçæ´æ¹åå ¶ä»ç¸å ³ä¿¡æ¯ å¼ååå â¦ ä¸ææ°: ç»ä¸ææ°ã妿æéè¯¯ï¼æ¾å°æ ¹æ¬åå å¹¶ä¿®å¤å®ãä¸è¦ä½¿ç¨ä¸´æ¶ä¿®å¤ãä½ æ¯ä¸åé«çº§å¼å人åï¼ç»ä¸ææ°ã ⦠ç®åæ§: 使ææä¿®å¤åä»£ç æ´æ¹å°½å¯è½ç®åãå®ä»¬åªåºå½±åä¸ä»»å¡ç¸å ³çå¿ è¦ä»£ç ï¼ä¸åºå½±åå ¶ä»å 容ãåºå°½å¯è½å°å°å½±å代ç ãä½ çç®æ æ¯ä¸è¦å¼å ¥ä»»ä½é误ãä¸åé½å ³ä¹ç®åæ§ã CLAUDE.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,168 @@ # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview NumericalCollection is a Spring Boot 2.6.13 application that collects and synchronizes device metrics data from manufacturing equipment. It integrates with an Oracle database and external device APIs to fetch real-time device data, daily statistics, and production order information. The application runs scheduled tasks to poll device data and provides REST endpoints for manual synchronization. ## Build and Run Commands **Build the project:** ```bash mvn clean install ``` **Run the application locally:** ```bash mvn spring-boot:run ``` The server starts on port 9095 (configured in application.yml). **Run tests:** ```bash mvn test ``` **Compile without tests:** ```bash mvn compile -DskipTests ``` **Package for deployment:** ```bash mvn clean package -DskipTests ``` Produces `target/NumericalCollection.jar`. ## Architecture ### Core Package Structure - `config/` - Spring configuration classes, including DataAcquisitionConfiguration, MybatisPlusConfig, and result wrappers - `controller/` - REST controllers, primarily KMController which handles manual synchronization endpoints - `service/` and `service/impl/` - Business logic layer - `INumericalService` - Core service for device data retrieval and synchronization - `INumericalNoOrderService` - Service for device operations without order context (device list, real-time data, daily statistics) - `DeviceMetricsService` - Handles manual synchronization operations and PDF conversion - Entity-specific services follow naming pattern `{Entity}Service` (e.g., DeviceService, MesNumericalService) - `mapper/` - MyBatis-Plus mapper interfaces for database operations - `entity/` - JPA/MyBatis entities representing database tables - `dto/` - Data transfer objects for API requests/responses - `task/` - Scheduled task components, specifically ScheduledTasks for automated data collection ### Data Flow Architecture 1. **Scheduled Data Collection** (`ScheduledTasks.java`): - Every 2 minutes: Fetches real-time device data for main devices and BYCL devices (offset by 30 seconds) - Daily at 1 AM: Syncs production orders from Womdaa to MesOrderSelect - Daily at 2 AM: Collects previous day's device statistics - Weekly on Sunday: Cleans up old data (removes records older than 1 week) 2. **External API Integration**: - Uses OkHttp3 for HTTP calls to external device management systems - ApiService handles request/response serialization with Gson/FastJSON - Device data retrieved via `INumericalService` methods 3. **Database Layer**: - MyBatis-Plus with Oracle JDBC driver (ojdbc8) - Druid connection pool (5-30 connections) - XML-based SQL mappings in `src/main/resources/mapper/` - Automatic camelCase mapping enabled (`map-underscore-to-camel-case: true`) 4. **Manual Synchronization Endpoints** (`KMController`): - `/Numerical/manualSynchronization` - Sync device metrics for a specific order - `/Numerical/manualSynchronizationBycl` - Sync BYCL device metrics - `/Numerical/RefreshDev` and `/Numerical/RefreshDevBycl` - Refresh device data - `/Numerical/PdfToBase64` - Convert PDF reports to Base64 ### Key Dependencies - Spring Boot 2.6.13 (Java 8) - MyBatis-Plus 3.5.4 for database operations - Druid 1.2.16 for connection pooling - OkHttp 4.9.3 for HTTP client - Hutool 5.8.18 for utilities (date handling, etc.) - FastJSON 2.0.32 and Gson 2.8.9 for JSON processing - Apache POI 4.1.2 for Excel handling - PDFBox 2.0.27 for PDF operations - Lombok for boilerplate reduction ## Development Notes ### Database Configuration The application connects to Oracle database at 192.168.0.94:1521/orcl with credentials in `application.yml`. Override these for local development using environment variables or Spring profiles: ```bash mvn spring-boot:run -Dspring-boot.run.arguments="--spring.datasource.url=jdbc:oracle:thin:@localhost:1521/orcl --spring.datasource.username=user --spring.datasource.password=pass" ``` ### MyBatis Mapper Development - Mapper interfaces in `mapper/` package are auto-scanned via `@MapperScan` annotation - Corresponding XML files must be in `src/main/resources/mapper/` with matching names - SQL result columns use snake_case, automatically mapped to camelCase entity fields - Multi-statement execution is enabled in Druid configuration ### Service Layer Pattern Services extend `IService<Entity>` from MyBatis-Plus for CRUD operations. Implementations follow the pattern: ```java @Service @RequiredArgsConstructor public class EntityServiceImpl extends ServiceImpl<EntityMapper, Entity> implements EntityService ``` Use constructor injection via Lombok's `@RequiredArgsConstructor` for dependencies. ### Scheduled Task Development Add new scheduled methods to `ScheduledTasks.java` component. Cron expressions follow standard format. Ensure error handling wraps API calls in try-catch blocks as shown in existing tasks. ### Testing Considerations - Tests should extend Spring Boot test framework - Mock external API calls to avoid dependencies on external systems during testing - Test database operations using embedded H2 or test Oracle schema - Run full test suite before committing: `mvn clean test` ## Common Operations ### Adding a New Device Endpoint 1. Add method to `INumericalService` interface 2. Implement in corresponding `ServiceImpl` class 3. Add REST endpoint in `KMController` if manual trigger needed 4. Create/update mapper interface and XML for database operations 5. Add entity/DTO classes if new data structures needed ### Modifying Scheduled Tasks Edit `ScheduledTasks.java` and adjust cron expressions. Remember existing offsets: - Main device polling: every 2 minutes at :00 seconds - BYCL device polling: every 2 minutes at :30 seconds - Order sync: daily at 1 AM - Statistics collection: daily at 2 AM - Data cleanup: weekly Sunday at midnight ### Database Schema Changes 1. Apply schema changes to Oracle database 2. Update entity classes with new fields (use Lombok annotations) 3. Update mapper XML files with new column mappings 4. Regenerate any affected DTOs 5. Update service layer logic to handle new fields å¼å工使µç¨ é®é¢è§£å³æµç¨ 1. é¦å æèé®é¢ï¼é 读代ç åºä¸çç¸å ³æä»¶ï¼å¹¶å°è®¡ååå ¥ tasks/todo.md 2. 计ååºå å«å¯ä»¥å¾é宿çå¾ åäºé¡¹å表 3. å¼å§å·¥ä½åï¼ä¸æç¡®è®¤è®¡å 4. ç¶åå¼å§å¤çå¾ åäºé¡¹ï¼å®ææ¶æ è®°ä¸ºå®æ 5. æ¯ä¸æ¥é½æä¾é«å±æ¬¡çåå说æ 6. 使æ¯ä¸ªä»»å¡åä»£ç æ´æ¹å°½å¯è½ç®åï¼é¿å å¤§è§æ¨¡æå¤æçæ´æ¹ 7. æ¯ä¸ªæ´æ¹åºå°½å¯è½å°å°å½±å代ç ï¼ä¸å以ç®åæ§ä¸ºæ ¸å¿ 8. æåï¼å¨ todo.md æä»¶ä¸æ·»å 审æ¥é¨åï¼æ»ç»æåçæ´æ¹åå ¶ä»ç¸å ³ä¿¡æ¯ å¼ååå â¦ ä¸ææ°: ç»ä¸ææ°ã妿æéè¯¯ï¼æ¾å°æ ¹æ¬åå å¹¶ä¿®å¤å®ãä¸è¦ä½¿ç¨ä¸´æ¶ä¿®å¤ãä½ æ¯ä¸åé«çº§å¼å人åï¼ç»ä¸ææ°ã ⦠ç®åæ§: 使ææä¿®å¤åä»£ç æ´æ¹å°½å¯è½ç®åãå®ä»¬åªåºå½±åä¸ä»»å¡ç¸å ³çå¿ è¦ä»£ç ï¼ä¸åºå½±åå ¶ä»å 容ãåºå°½å¯è½å°å°å½±å代ç ãä½ çç®æ æ¯ä¸è¦å¼å ¥ä»»ä½é误ãä¸åé½å ³ä¹ç®åæ§ã src/main/java/com/hk/NumericalCollection/config/DataAcquisitionConfiguration.java
@@ -12,7 +12,7 @@ /** * APIåºç¡URL */ public static final String API_BASE_URL = "http://172.16.2.238:8100/lantingNewB/open"; public static final String API_BASE_URL = "http://172.100.1.114:8100/lantingNewB/open"; /** * è·åç¾ååæ®µURL src/main/java/com/hk/NumericalCollection/service/impl/NumericalServiceImpl.java
@@ -82,12 +82,20 @@ List<Device> deviceList = response.getList(); // æ¸ ç©ºidï¼è®©æ°æ®åºèªå¨çæ deviceList.forEach(d -> d.setId(null)); List<String> uidList = deviceList.stream().map(Device::getDevNo).collect(Collectors.toList()); LambdaUpdateWrapper<Device> wrapper = new LambdaUpdateWrapper<>(); wrapper.in(Device::getDevNo, uidList); deviceService.remove(wrapper); return deviceService.saveOrUpdateBatch(deviceList); // SQL Server æ¹éæå ¥å ¼å®¹æ§é®é¢ï¼æ¹ç¨éæ¡æå ¥ for (Device device : deviceList) { deviceService.save(device); } return true; } //为æå¤å¶ä¸ä»½è¿ä¸ªæ¹æ³åºæ¥ï¼æç¨å°çDEVICE_STATUSå®ä½ç±»æ¹ä¸ºDEVICE_STATUS_BYCLï¼MES_NUMERICALå®ä½æ¹ä¸ºMES_NUMERICAL_BYCLï¼å ¶ä»çé»è¾ä¸åå¹¶ç»ææ³¨é src/main/resources/application.yml
@@ -32,7 +32,7 @@ mybatis-plus: global-config: db-config: id-type: INPUT id-type: AUTO configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true src/test/java/com/hk/NumericalCollection/DeviceReceivingApplicationTests.java
@@ -54,16 +54,16 @@ @Test void getDeviceDayCount() throws IOException { DateTime oneWeekAgo = DateUtil.offsetDay(DateUtil.date(), -1); String format = DateUtil.format(oneWeekAgo, "yyyy-MM-dd"); try { List<DevMachine> list = devMachineService.list(); for (DevMachine s : list) { numericalService.getDeviceDayCount(s.getDevNo(), format); } } catch (IOException e) { throw new RuntimeException(e); } // DateTime oneWeekAgo = DateUtil.offsetDay(DateUtil.date(), -1); // String format = DateUtil.format(oneWeekAgo, "yyyy-MM-dd"); // try { // List<DevMachine> list = devMachineService.list(); // for (DevMachine s : list) { // numericalService.getDeviceDayCount(s.getDevNo(), format); // } // } catch (IOException e) { // throw new RuntimeException(e); // } // //numericalService.getDeviceDayCount("862858070704174_1", "2025-04-22"); } @@ -90,26 +90,17 @@ // numericalService.getDeviceRealTimeDataBycl("866042075016340"); List<DevMacBycl> list = devMacByclService.list(); list.forEach(s -> { try { numericalService.getDeviceRealTimeDataBycl(s.getDevNo()); } catch (Exception e) { throw new RuntimeException(e); } }); // List<DevMachine> list = devMachineService.list(); // list.forEach(s -> { // try { // numericalNoOrderService.getDeviceRealTimeData(s.getDevNo()); // } catch (Exception e) { // throw new RuntimeException(e); // } // }); } //deviceMetricsService.manualSynchronizationBycl(barcode) @Test public void get1() throws Exception { NumbericalDto barcode = new NumbericalDto(); barcode.setMachineNo("C05"); barcode.setOrderId(7890268L); deviceMetricsService.manualSynchronizationBycl(barcode); } @Test //@Test public void SoDeviceList() { try { boolean b = numericalService.SoDeviceList(); @@ -127,29 +118,9 @@ } /** * æµè¯è·åè®¾å¤æ éå表 */ @Test public void testGetDeviceErrorList() throws Exception { // 设置æµè¯åæ° String uid = "864606067274372"; // 设å¤ç¼å· String startDate = "2024-01-01"; // å¼å§æ¥æ String endDate = "2024-12-31"; // ç»ææ¥æ try { // è°ç¨æ¹æ³è·åè®¾å¤æ éå表 numericalNoOrderService.getDeviceErrorList(uid, startDate, endDate); System.out.println("è®¾å¤æ éå表è·åæå"); } catch (Exception e) { System.err.println("è®¾å¤æ éå表è·å失败: " + e.getMessage()); throw e; } } /** * æµè¯æ¹éè·åææè®¾å¤çæ éå表 */ @Test //@Test public void testGetAllDeviceErrorList() throws Exception { DateTime yesterday = DateUtil.yesterday(); DateTime startDateTime = DateUtil.parse(DateUtil.format(yesterday, "yyyy-MM-dd") + " 07:30:00"); start.bat
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ @echo off chcp 65001 >nul setlocal enabledelayedexpansion echo ======================================== echo NumericalCollection å¯å¨èæ¬ echo ======================================== echo. echo è¯·éæ©æ°æ®æºç¯å¢: echo [1] æµè¯ç¯å¢ (TEST_MES - 172.16.2.238) echo [2] ç产ç¯å¢ (请é ç½®çäº§æ°æ®åºä¿¡æ¯) echo. set /p choice=请è¾å ¥é项 (1/2): if "%choice%"=="1" ( set DB_URL=jdbc:sqlserver://172.16.2.238:12468;databaseName=TEST_MES;encrypt=false;trustServerCertificate=true set DB_USER=sa set DB_PASS=FuDa@2025 set ENV_NAME=æµè¯ç¯å¢ ) else if "%choice%"=="2" ( set DB_URL=jdbc:sqlserver://ç产æå¡å¨IP:端å£;databaseName=PROD_MES;encrypt=false;trustServerCertificate=true set DB_USER=prod_user set DB_PASS=prod_password set ENV_NAME=ç产ç¯å¢ ) else ( echo æ æé项ï¼ä½¿ç¨é»è®¤æµè¯ç¯å¢ set DB_URL=jdbc:sqlserver://172.16.2.238:12468;databaseName=TEST_MES;encrypt=false;trustServerCertificate=true set DB_USER=sa set DB_PASS=FuDa@2025 set ENV_NAME=æµè¯ç¯å¢ ) echo. echo å½åç¯å¢: %ENV_NAME% echo æ°æ®åºå°å: %DB_URL% echo. echo æ£å¨å¯å¨åºç¨... java -jar target/NumericalCollection.jar ^ --spring.datasource.url="%DB_URL%" ^ --spring.datasource.username=%DB_USER% ^ --spring.datasource.password=%DB_PASS% pause