From 79adde03ab8f304240673fbc1cd843185cf621f2 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期二, 07 四月 2026 16:40:12 +0800
Subject: [PATCH] 新增加交通监管服务

---
 xp-robotaxi-traffic-control-boot/src/test/java/com/ruoyi/account/RuoYiAccountApplicationTests.java                      |   30 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java           |   83 ++
 xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages_zh_CN.properties                                      |    0 
 xp-robotaxi-traffic-control-boot/xp-robotaxi-vehicle-convoy-boot.iml                                                    |    9 
 xp-robotaxi-traffic-control-boot/pom.xml                                                                                |  214 +++++
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ThreadLocalSHA1.java                    |   26 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java                 |   83 ++
 xp-robotaxi-traffic-control-boot/src/main/resources/application-local.properties                                        |  104 ++
 xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages.properties                                            |    0 
 pom.xml                                                                                                                 |    1 
 xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml.bak                                                     |  222 ++++++
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HexUtil.java                            |   36 +
 xp-robotaxi-traffic-control-boot/src/main/resources/mybatis-config.xml                                                  |   25 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ResourceUtil.java                       |   82 ++
 xp-robotaxi-traffic-control-boot/Dockerfile                                                                             |   16 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/DataUpdateHandlerConfig.java          |   71 +
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java               |   29 
 xp-robotaxi-traffic-control-boot/src/main/resources/seata.conf                                                          |    7 
 xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java                   |    4 
 xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java                                |    1 
 xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml                                                         |  222 ++++++
 xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages_en_US.properties                                      |    0 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HMACSHA1.java                           |   35 
 xp-robotaxi-map-boot/src/main/resources/bootstrap.yml                                                                   |  148 ++++
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SignatureUtils.java                     |  114 +++
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/DecodingException.java                       |   17 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java |  139 +++
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SHA1Util.java                           |  118 +++
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/constant/I18nKeyConstant.java                |   69 +
 xp-robotaxi-order-boot/src/main/resources/bootstrap.yml                                                                 |    1 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MultipartFilterConfig.java            |   64 +
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/TransactionConfiguration.java         |   27 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java               |   59 +
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/enums/SignatureType.java                     |   15 
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MybatisPlusConfig.java                |   51 +
 35 files changed, 2,120 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 46a9729..5130865 100644
--- a/pom.xml
+++ b/pom.xml
@@ -267,6 +267,7 @@
         <module>xp-robotaxi-vehicle-convoy-boot</module>
         <module>xp-robotaxi-job-boot</module>
         <module>xp-robotaxi-file-boot</module>
+        <module>xp-robotaxi-traffic-control-boot</module>
     </modules>
     <packaging>pom</packaging>
 
diff --git a/xp-robotaxi-map-boot/src/main/resources/bootstrap.yml b/xp-robotaxi-map-boot/src/main/resources/bootstrap.yml
index 36fdb64..bfcf8c0 100644
--- a/xp-robotaxi-map-boot/src/main/resources/bootstrap.yml
+++ b/xp-robotaxi-map-boot/src/main/resources/bootstrap.yml
@@ -12,4 +12,150 @@
     allow-circular-references: true
   profiles:
     # 环境配置
-    active: local
+    active: dev
+  #    active: prod
+---
+spring:
+  config:
+    activate:
+      on-profile: dev
+  cloud:
+    nacos:
+      discovery:
+        # 服务注册地址
+        server-addr: 192.168.110.80:8848
+        service: ${spring.application.name}
+        group: DEFAULT_GROUP
+        namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+        username: nacos
+        password: nacos
+        ip: 192.168.110.85
+      config:
+        # 配置中心地址
+        server-addr: 192.168.110.80:8848
+        namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+        group: DEFAULT_GROUP
+        name: ${spring.application.name}
+        username: nacos
+        password: nacos
+        # 配置文件格式
+        file-extension: yml
+        # 共享配置
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+---
+seata:
+  enabled: true
+  application-id: ${spring.application.name}
+  tx-service-group: seata_tx_group    #此处配置自定义的seata事务分组名称
+  enable-auto-data-source-proxy: false    #关闭数据库代理
+  service:
+    vgroup-mapping:
+      seata_tx_group: default
+  data-source-proxy-mode: AT
+  config:
+    type: nacos
+    nacos:
+      # 开发环境
+      server-addr: 192.168.110.80:8848
+      namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+      group: DEFAULT_GROUP
+      data-id: seata-server.properties
+      username: nacos
+      password: nacos
+      # 生产环境
+  #      server-addr: 192.168.0.137:8848,192.168.0.123:8848
+  #      namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+  #      group: DEFAULT_GROUP
+  #      data-id: seata-server.properties
+  #      username: nacos
+  #      password: nacos
+  registry:
+    type: nacos
+    nacos:
+      application: seata-server
+      # 开发环境
+      server-addr: 192.168.110.80:8848
+      namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+      group: DEFAULT_GROUP
+      username: nacos
+      password: nacos
+      # 生产环境
+  #      server-addr: 192.168.0.137:8848,192.168.0.123:8848
+  #      namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+  #      group: DEFAULT_GROUP
+  #      username: nacos
+  #      password: nacos
+  cloud:
+    nacos:
+      discovery:
+        # 开发环境
+        server-addr: 192.168.110.80:8848
+        namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+        group: DEFAULT_GROUP
+        application: seata-server #Nacos 中 Seata 名称
+        username: nacos
+        password: nacos
+        # 生产环境
+    #        server-addr: 192.168.0.137:8848,192.168.0.123:8848
+    #        namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+    #        group: DEFAULT_GROUP
+    #        application: seata-server #Nacos 中 Seata 名称
+    #        username: nacos
+    #        password: nacos
+    sentinel:
+      transport:
+        dashboard: 192.168.0.137:8080  #  Sentinel控制台地址
+      eager: true
+---
+spring:
+  config:
+    activate:
+      on-profile: prod
+  cloud:
+    nacos:
+      discovery:
+        # 服务注册地址
+        server-addr: 192.168.0.137:8848,192.168.0.123:8848
+        service: ${spring.application.name}
+        group: DEFAULT_GROUP
+        namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+        username: nacos
+        password: nacos
+      config:
+        # 配置中心地址
+        server-addr: 192.168.0.137:8848,192.168.0.123:8848
+        namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+        username: nacos
+        password: nacos
+        group: DEFAULT_GROUP
+        name: ${spring.application.name}
+        # 配置文件格式
+        file-extension: yml
+        # 共享配置
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+---
+spring:
+  config:
+    activate:
+      on-profile: test
+  cloud:
+    nacos:
+      discovery:
+        # 服务注册地址
+        server-addr: 127.0.0.1:8848
+        service: ${spring.application.name}
+        group: DEFAULT_GROUP
+        namespace: 96712c7a-480b-4f40-b783-39f00f3b33ce
+      config:
+        # 配置中心地址
+        server-addr: 127.0.0.1:8848
+        namespace: 96712c7a-480b-4f40-b783-39f00f3b33ce
+        group: DEFAULT_GROUP
+        name: ${spring.application.name}
+        # 配置文件格式
+        file-extension: yml
+        # 共享配置
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
\ No newline at end of file
diff --git a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java
index 5e9f636..c578622 100644
--- a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java
+++ b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java
@@ -457,4 +457,8 @@
 
     }
 
+
+
+
+
 }
diff --git a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
index 5c7422e..365703f 100644
--- a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
+++ b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -137,7 +137,6 @@
      * @param firstElement 队列第一个元素
      */
     private void orderProcess(String quoteName, String firstElement) {
-        System.out.println("进入处理环节");
         XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null);
         String orderId = firstElement.split("_")[0];
         String lonLat = firstElement.split("_")[1];
diff --git a/xp-robotaxi-order-boot/src/main/resources/bootstrap.yml b/xp-robotaxi-order-boot/src/main/resources/bootstrap.yml
index e4631d7..73d792f 100644
--- a/xp-robotaxi-order-boot/src/main/resources/bootstrap.yml
+++ b/xp-robotaxi-order-boot/src/main/resources/bootstrap.yml
@@ -29,6 +29,7 @@
         namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
         username: nacos
         password: nacos
+        ip: 192.168.110.85
       config:
         # 配置中心地址
         server-addr: 192.168.110.80:8848
diff --git a/xp-robotaxi-traffic-control-boot/Dockerfile b/xp-robotaxi-traffic-control-boot/Dockerfile
new file mode 100644
index 0000000..f598f98
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/Dockerfile
@@ -0,0 +1,16 @@
+FROM registry.logan.xiaopeng.local/logancloud/logan-base:1.1.4-rc1-J1.8.0_372
+LABEL maintainer="Linzhaoming <linzm2@xiaopeng.com>"
+
+ENV JAVA_OPTS="-Xmx3072m -Xms1024m -XX:NewRatio=1 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 \
+-XX:+UseCMSInitiatingOccupancyOnly -XX:ReservedCodeCacheSize=128M -XX:ParallelGCThreads=2 \
+-XX:+ExplicitGCInvokesConcurrent -Duser.timezone=Asia/Shanghai"
+
+ENTRYPOINT [ "sh", "-c", "java $APP_OPTS $JMX_OPTS $JAVA_OPTS $GCLOG_OPTS -Djava.security.egd=file:/dev/./urandom -jar xp-robotaxi-vehicle-convoy-boot.jar" ]
+
+WORKDIR /home/xpmotors/local
+
+RUN mkdir -p /data/log/app/xp-robotaxi-vehicle-convoy-boot /data/tomcat && chown -R xpmotors:xpmotors /data/log/app/xp-robotaxi-vehicle-convoy-boot /data/tomcat
+
+COPY target/xp-robotaxi-vehicle-convoy-boot-*-exec.jar /home/xpmotors/local/xp-robotaxi-vehicle-convoy-boot.jar
+
+USER xpmotors
diff --git a/xp-robotaxi-traffic-control-boot/pom.xml b/xp-robotaxi-traffic-control-boot/pom.xml
new file mode 100644
index 0000000..349b4f1
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/pom.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>com.xiaopeng</groupId>
+        <artifactId>robotaxi</artifactId>
+        <version>0.1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>xp-robotaxi-traffic-control-boot</artifactId>
+
+    <description>
+        xp-modules-trafficControl交通监管模块
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-loadbalancer</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${swagger.fox.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.xiaopeng</groupId>
+            <artifactId>xp-common-log</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.xiaopeng</groupId>
+            <artifactId>xp-common-swagger</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.xiaopeng</groupId>
+            <artifactId>xp-robotaxi-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>${druid.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.xiaopeng</groupId>
+            <artifactId>unified-verification</artifactId>
+            <version>1.5.2-v2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
+            <version>5.2.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.yaml</groupId>
+                    <artifactId>snakeyaml</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-transaction-base-seata-at</artifactId>
+            <version>5.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+            <version>1.33</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>2.25.3</version>
+        </dependency>
+        <!-- easypoi -->
+        <!-- Apache POI 核心依赖 -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>5.2.3</version>
+        </dependency>
+
+        <!-- Apache POI OOXML 支持(用于 .xlsx 文件) -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>5.2.3</version>
+        </dependency>
+
+        <!-- Apache POI XMLBeans(可选,用于复杂 XML 处理) -->
+        <dependency>
+            <groupId>org.apache.xmlbeans</groupId>
+            <artifactId>xmlbeans</artifactId>
+            <version>5.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.afterturn</groupId>
+            <artifactId>easypoi-base</artifactId>
+            <version>4.4.0</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>cn.afterturn</groupId>
+            <artifactId>easypoi-web</artifactId>
+            <version>4.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.afterturn</groupId>
+            <artifactId>easypoi-annotation</artifactId>
+            <version>4.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.xiaopeng.logan</groupId>
+            <artifactId>xp-evi-oss-sdk</artifactId>
+            <version>1.0.1-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+            <resource>
+                <directory>lib</directory>
+                <targetPath>/BOOT-INF/lib/</targetPath>
+                <includes>
+                    <include>**/*.jar</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/java</directory>
+                <includes>
+                    <include>**/*.xml</include>
+                </includes>
+                <filtering>false</filtering>
+            </resource>
+        </resources>
+    </build>
+</project>
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/DecodingException.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/DecodingException.java
new file mode 100644
index 0000000..a1416fd
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/DecodingException.java
@@ -0,0 +1,17 @@
+package com.xiaopeng.trafficControl;
+
+/**
+ * 解码处理异常类</br>
+ */
+public class DecodingException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+
+	public DecodingException(String message) {
+		super(message);
+	}
+
+	public DecodingException(Throwable cause) {
+		super(cause);
+	}
+
+}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java
new file mode 100644
index 0000000..e9fe0df
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java
@@ -0,0 +1,29 @@
+package com.xiaopeng.trafficControl;
+
+import com.xiaopeng.common.security.annotation.EnableCustomConfig;
+import com.xiaopeng.common.security.annotation.EnableRyFeignClients;
+import com.xiaopeng.common.swagger.annotation.EnableCustomSwagger2;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * 交通监管模块
+ */
+@EnableCustomConfig
+@MapperScan({"com.xiaopeng.trafficControl.mapper"})
+@EnableCustomSwagger2
+@EnableRyFeignClients
+@SpringBootApplication
+@EnableScheduling//开启定时任务
+@ServletComponentScan
+@EnableTransactionManagement//开启事务
+public class TrafficControlApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(TrafficControlApplication.class, args);
+        System.out.println("(♥◠‿◠)ノ゙  交通监管模块启动成功   ლ(´ڡ`ლ)゙  \n");
+    }
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/DataUpdateHandlerConfig.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/DataUpdateHandlerConfig.java
new file mode 100644
index 0000000..cc030b6
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/DataUpdateHandlerConfig.java
@@ -0,0 +1,71 @@
+package com.xiaopeng.trafficControl.config;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.xiaopeng.common.core.utils.StringUtils;
+import com.xiaopeng.common.security.utils.SecurityUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.context.annotation.Configuration;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author xiaochen
+ * @ClassName DataUpdateInterceptor
+ * @Description 数据更新操作处理
+ * @date 2021-12-15
+ * <p>
+ * 注意,之前在此处注入了 JwtTokenUtils
+ * <p>
+ * 造成spring循环依赖,项目支棱不起来
+ */
+@Slf4j
+@Configuration
+public class DataUpdateHandlerConfig implements MetaObjectHandler {
+
+    /**
+     * 新增数据执行
+     *
+     * @param metaObject
+     */
+    @Override
+    public void insertFill(MetaObject metaObject) {
+        String userName = "";
+        try{
+            //  获取登录信息
+            userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
+            log.info("DataUpdateInterceptor insertFill");
+        } catch (Exception e) {
+            log.error("DataUpdateInterceptor insertFill error:{}", e.getMessage());
+        }
+        if (StringUtils.isNotBlank(userName)) {
+            this.setFieldValByName("createBy", userName, metaObject);
+            this.setFieldValByName("updateBy", userName, metaObject);
+        } else {
+            this.setFieldValByName("createBy", userName, metaObject);
+            this.setFieldValByName("updateBy", userName, metaObject);
+        }
+        this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
+        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
+    }
+
+    /**
+     * 修改数据执行
+     *
+     * @param metaObject
+     */
+    @Override
+    public void updateFill(MetaObject metaObject) {
+        String userName = "";
+        try{
+            //  获取登录信息
+            userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
+            log.info("DataUpdateInterceptor insertFill");
+        } catch (Exception e) {
+            log.error("DataUpdateInterceptor insertFill error:{}", e.getMessage());
+        }
+        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
+        this.setFieldValByName("updateBy", userName, metaObject);
+
+    }
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java
new file mode 100644
index 0000000..37ce6c2
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java
@@ -0,0 +1,59 @@
+package com.xiaopeng.trafficControl.config;
+
+import org.springframework.boot.autoconfigure.context.MessageSourceProperties;
+import org.springframework.context.MessageSource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.ResourceBundleMessageSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.LocaleResolver;
+
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+
+
+/**
+ * 国际化配置
+ */
+@Configuration
+public class MessageLocalConfig {
+
+    @Bean
+    public MessageSourceProperties messageSourceProperties() {
+        MessageSourceProperties properties = new MessageSourceProperties();
+        properties.setBasename("i18n/messages");
+        properties.setEncoding(StandardCharsets.UTF_8);
+        properties.setFallbackToSystemLocale(false);
+        properties.setCacheDuration(Duration.ofSeconds(-1));
+        properties.setAlwaysUseMessageFormat(false);
+        properties.setUseCodeAsDefaultMessage(true);
+        return properties;
+    }
+
+    @Bean
+    public MessageSource messageSource(MessageSourceProperties properties) {
+        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
+        if (StringUtils.hasText(properties.getBasename())) {
+            messageSource.setBasenames(StringUtils
+                    .commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
+        }
+        if (properties.getEncoding() != null) {
+            messageSource.setDefaultEncoding(properties.getEncoding().name());
+        }
+        messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
+        Duration cacheDuration = properties.getCacheDuration();
+        if (cacheDuration != null) {
+            messageSource.setCacheMillis(cacheDuration.toMillis());
+        }
+        messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
+        messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
+        return messageSource;
+    }
+
+
+    @Bean//注册国际化组件
+    public LocaleResolver localeResolver(){
+        return new MyLocaleResolver();
+    }
+
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MultipartFilterConfig.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MultipartFilterConfig.java
new file mode 100644
index 0000000..3810404
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MultipartFilterConfig.java
@@ -0,0 +1,64 @@
+package com.xiaopeng.trafficControl.config;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+
+/**
+ * 修复 multipart 文件上传被 ReplaceRequestFilter 破坏的问题。
+ * <p>
+ * ReplaceRequestFilter(来自 request-wrapper jar,logan-starter-core 传递依赖)
+ * 会读取 request 的 InputStream 来包装请求体,导致后续 Spring 解析 multipart 时
+ * 抛出 "Stream closed" 异常。
+ * <p>
+ * 解决方案:注册一个高优先级 Filter,对 multipart 请求提前触发 Servlet 容器的
+ * multipart 解析(通过调用 request.getParts()),使文件数据被缓存到临时文件中。
+ * 这样即使后续 ReplaceRequestFilter 消费了 InputStream,multipart 数据仍然可用。
+ */
+@Slf4j
+@Configuration
+public class MultipartFilterConfig {
+
+    private static final String MULTIPART = "multipart/";
+    @Bean
+    public FilterRegistrationBean<Filter> earlyMultipartParsingFilter() {
+        FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
+        registration.setFilter(new EarlyMultipartParsingFilter());
+        registration.addUrlPatterns("/*");
+        // 确保在 ReplaceRequestFilter 之前执行
+        registration.setOrder(Integer.MIN_VALUE + 10);
+        registration.setName("earlyMultipartParsingFilter");
+        return registration;
+    }
+    /**
+     * 在 filter 链最前面对 multipart 请求提前解析,
+     * 让 Tomcat 将文件数据缓存到磁盘,避免后续 filter 消费 InputStream 导致 Stream closed。
+     */
+    static class EarlyMultipartParsingFilter implements Filter {
+        @Override
+        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+                throws IOException, ServletException {
+            if (request instanceof HttpServletRequest) {
+                HttpServletRequest httpRequest = (HttpServletRequest) request;
+                String contentType = httpRequest.getContentType();
+                if (contentType != null && contentType.toLowerCase().startsWith(MULTIPART)) {
+                    // 提前触发 multipart 解析,Tomcat 会将 parts 缓存
+                    try {
+                        httpRequest.getParts();
+                    } catch (Exception e) {
+                        log.warn("Early multipart parsing failed, will retry later: {}", e.getMessage());
+                    }
+                }
+            }
+            chain.doFilter(request, response);
+        }
+    }
+
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java
new file mode 100644
index 0000000..f23bb21
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java
@@ -0,0 +1,83 @@
+package com.xiaopeng.trafficControl.config;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.LocaleResolver;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.Locale;
+
+public class MyLocaleResolver implements LocaleResolver {
+
+    @Override
+    public Locale resolveLocale(HttpServletRequest request) {
+        //1=中文,2=英文,3=印尼文
+        //1=Chinese, 2=English, 3=Indonesian.
+        String language = getQueryParams(request, "language");
+
+        Locale locale = null;
+        if (StringUtils.isEmpty(language)) {
+            locale = Locale.getDefault();
+            language = "1";
+        }
+        //如果请求不为空
+        //If the request is not empty.
+        if(!StringUtils.isEmpty(language)){
+            if (language.equals("1")) {
+                locale = new Locale("zh", "CN");
+            } else if (language.equals("2")) {
+                locale = new Locale("en", "US");
+            }
+        }
+        return locale;
+    }
+
+    @Override
+    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
+    }
+
+
+    public String getQueryParams(HttpServletRequest request, String key) {
+        try {
+            String method = request.getMethod();
+            if("POST".equals(method)){
+                String parameter = request.getParameter(key);
+                if(!StringUtils.isEmpty(parameter)){
+                    return parameter;
+                }
+                Object attribute = request.getAttribute(key);
+                if(null != attribute){
+                    return attribute.toString();
+                }
+                StringBuffer sb = new StringBuffer();
+                ServletInputStream inputStream = request.getInputStream();
+                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
+                String s;
+                while ((s = bufferedReader.readLine()) != null){
+                    sb.append(s);
+                }
+                bufferedReader.close();
+                inputStream.close();
+                JSONObject jsonObject = JSON.parseObject(sb.toString());
+                return jsonObject.getString(key);
+            }else{
+                String parameter = request.getParameter(key);
+                if(!StringUtils.isEmpty(parameter)){
+                    return parameter;
+                }
+                Object attribute = request.getAttribute(key);
+                if(null != attribute){
+                    return attribute.toString();
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MybatisPlusConfig.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..4642647
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MybatisPlusConfig.java
@@ -0,0 +1,51 @@
+package com.xiaopeng.trafficControl.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author xiaochen
+ * @ClassName MybatisPlusConfig
+ * @Description MybatisPlus相关配置
+ * @date 2020-09-22 11:22、
+ * 直接以实现类作为bean的注入(有事务管理的类)
+ * @EnableTransactionManagement(proxyTargetClass = true)
+ */
+@Configuration
+public class MybatisPlusConfig {
+    private final DataUpdateHandlerConfig dataUpdateHandler;
+
+    @Autowired
+    public MybatisPlusConfig(DataUpdateHandlerConfig dataUpdateHandler) {
+        this.dataUpdateHandler = dataUpdateHandler;
+    }
+
+    /**
+     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
+     */
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        return interceptor;
+    }
+
+    /**
+     * 自动填充功能
+     *
+     * @return
+     */
+    @Bean
+    public GlobalConfig globalConfig() {
+        GlobalConfig globalConfig = new GlobalConfig();
+        globalConfig.setMetaObjectHandler(dataUpdateHandler);
+        return globalConfig;
+    }
+
+
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/TransactionConfiguration.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/TransactionConfiguration.java
new file mode 100644
index 0000000..a814162
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/TransactionConfiguration.java
@@ -0,0 +1,27 @@
+package com.xiaopeng.trafficControl.config;
+
+import javax.sql.DataSource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * 分布式事务配置
+ */
+@Configuration
+@EnableTransactionManagement
+public class TransactionConfiguration {
+
+    @Bean
+    public PlatformTransactionManager txManager(final DataSource dataSource) {
+        return new DataSourceTransactionManager(dataSource);
+    }
+
+    @Bean
+    public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
+        return new JdbcTemplate(dataSource);
+    }
+}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java
new file mode 100644
index 0000000..a2da7be
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java
@@ -0,0 +1,83 @@
+package com.xiaopeng.trafficControl.config.log;
+
+import com.alibaba.fastjson2.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+/**
+ * Feign 调用日志切面
+ *
+ * <p>拦截所有带 @FeignClient 注解的接口方法,记录:
+ * <ul>
+ *   <li>调用的接口类名 + 方法名</li>
+ *   <li>入参(JSON 序列化)</li>
+ *   <li>出参(JSON 序列化)</li>
+ *   <li>耗时(ms)</li>
+ *   <li>异常信息(含完整堆栈)</li>
+ * </ul>
+ */
+@Slf4j
+@Aspect
+@Component
+public class FeignLoggingAspect {
+
+    /**
+     * 拦截所有带 @FeignClient 注解的接口的所有方法
+     */
+    @Around("within(@org.springframework.cloud.openfeign.FeignClient *)")
+    public Object logFeignCall(ProceedingJoinPoint pjp) throws Throwable {
+        return doLog(pjp);
+    }
+
+    private Object doLog(ProceedingJoinPoint pjp) throws Throwable {
+        MethodSignature signature = (MethodSignature) pjp.getSignature();
+        Method method = signature.getMethod();
+        // 使用接口声明类名,避免打印动态代理类名(如 $Proxy270)
+        String className = signature.getDeclaringType().getSimpleName();
+        String methodName = method.getName();
+        String fullMethod = className + "#" + methodName;
+
+        Object[] args = pjp.getArgs();
+        String argsJson = safeToJson(args);
+
+        log.info("[Feign] >>> 调用开始 | method={} | args={}", fullMethod, argsJson);
+
+        long start = System.currentTimeMillis();
+        try {
+            Object result = pjp.proceed();
+            long elapsed = System.currentTimeMillis() - start;
+            String resultJson = safeToJson(result);
+            log.info("[Feign] <<< 调用成功 | method={} | elapsed={}ms | result={}", fullMethod, elapsed, resultJson);
+            return result;
+        } catch (Throwable ex) {
+            long elapsed = System.currentTimeMillis() - start;
+            log.error("[Feign] <<< 调用异常 | method={} | elapsed={}ms | error={} | args={}",
+                    fullMethod, elapsed, ex.getMessage(), argsJson, ex);
+            throw ex;
+        }
+    }
+
+    /**
+     * 安全序列化为 JSON,避免序列化失败导致日志切面本身抛异常
+     */
+    private String safeToJson(Object obj) {
+        if (obj == null) {
+            return "null";
+        }
+        try {
+            if (obj instanceof Object[]) {
+                return JSON.toJSONString(Arrays.asList((Object[]) obj));
+            }
+            return JSON.toJSONString(obj);
+        } catch (Exception e) {
+            return "[序列化失败: " + obj.getClass().getSimpleName() + "]";
+        }
+    }
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java
new file mode 100644
index 0000000..5c46133
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java
@@ -0,0 +1,139 @@
+package com.xiaopeng.trafficControl.config.log;
+
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+import org.springframework.web.util.ContentCachingResponseWrapper;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 请求/响应日志过滤器
+ * 打印:traceId、method、uri、queryString、请求体、响应状态、耗时、响应体
+ */
+@Slf4j
+@Component
+@Order(Ordered.HIGHEST_PRECEDENCE + 10)
+public class RequestResponseLoggingFilter extends OncePerRequestFilter {
+
+    /** 不打印 body 的路径前缀(健康检查、actuator 等) */
+    private static final Set<String> EXCLUDE_PATHS = new HashSet<>(Arrays.asList(
+            "/actuator", "/healthcheck", "/health", "/prometheus"
+    ));
+
+    /** 只对这些 Content-Type 打印 body(避免打印二进制流) */
+    private static final Set<String> LOGGABLE_CONTENT_TYPES = new HashSet<>(Arrays.asList(
+            MediaType.APPLICATION_JSON_VALUE,
+            MediaType.APPLICATION_JSON_UTF8_VALUE,
+            MediaType.TEXT_PLAIN_VALUE,
+            MediaType.TEXT_XML_VALUE,
+            MediaType.APPLICATION_XML_VALUE,
+            "application/x-www-form-urlencoded"
+    ));
+
+    private static final int MAX_BODY_LENGTH = 2000;
+
+    @Override
+    protected boolean shouldNotFilter(HttpServletRequest request) {
+        String uri = request.getRequestURI();
+        return EXCLUDE_PATHS.stream().anyMatch(uri::startsWith);
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+                                    FilterChain chain) throws ServletException, IOException {
+        // 初始化 MDC(Filter 先于 Interceptor 执行,在此统一设置)
+        String traceId = request.getHeader("X-Trace-Id");
+        if (traceId == null || traceId.isEmpty()) {
+            traceId = java.util.UUID.randomUUID().toString().replace("-", "");
+        }
+        MDC.put("traceId",    traceId);
+        MDC.put("clientIp",   getClientIp(request));
+        MDC.put("requestUri", request.getRequestURI());
+        response.setHeader("X-Trace-Id", traceId);
+
+        ContentCachingRequestWrapper reqWrapper  = new ContentCachingRequestWrapper(request);
+        ContentCachingResponseWrapper respWrapper = new ContentCachingResponseWrapper(response);
+
+        long start = System.currentTimeMillis();
+        try {
+            chain.doFilter(reqWrapper, respWrapper);
+        } finally {
+            long cost = System.currentTimeMillis() - start;
+            logRequest(reqWrapper);
+            logResponse(respWrapper, cost);
+            // 必须把响应体写回,否则客户端收不到数据
+            respWrapper.copyBodyToResponse();
+            MDC.clear();
+        }
+    }
+
+    private String getClientIp(HttpServletRequest request) {
+        String ip = request.getHeader("X-Forwarded-For");
+        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
+            return ip.split(",")[0].trim();
+        }
+        ip = request.getHeader("X-Real-IP");
+        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
+            return ip;
+        }
+        return request.getRemoteAddr();
+    }
+
+    private void logRequest(ContentCachingRequestWrapper request) {
+        String traceId = MDC.get("traceId");
+        String uri     = request.getRequestURI();
+        String query   = request.getQueryString();
+        String method  = request.getMethod();
+        String body    = extractBody(request.getContentAsByteArray(), request.getContentType());
+
+        log.info(">>> [{}] {} {}{} | body={}",
+                traceId,
+                method,
+                uri,
+                query != null ? "?" + query : "",
+                body);
+    }
+
+    private void logResponse(ContentCachingResponseWrapper response, long cost) {
+        String traceId = MDC.get("traceId");
+        int    status  = response.getStatus();
+        String body    = extractBody(response.getContentAsByteArray(), response.getContentType());
+
+        log.info("<<< [{}] status={} cost={}ms | body={}",
+                traceId, status, cost, body);
+    }
+
+    private String extractBody(byte[] bodyBytes, String contentType) {
+        if (bodyBytes == null || bodyBytes.length == 0) {
+            return "";
+        }
+        if (!isLoggableContentType(contentType)) {
+            return "[binary, " + bodyBytes.length + " bytes]";
+        }
+        String body = new String(bodyBytes, StandardCharsets.UTF_8);
+        if (body.length() > MAX_BODY_LENGTH) {
+            body = body.substring(0, MAX_BODY_LENGTH) + "...(truncated)";
+        }
+        return body;
+    }
+
+    private boolean isLoggableContentType(String contentType) {
+        if (contentType == null) return true;
+        String ct = contentType.toLowerCase();
+        return LOGGABLE_CONTENT_TYPES.stream().anyMatch(ct::contains);
+    }
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/constant/I18nKeyConstant.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/constant/I18nKeyConstant.java
new file mode 100644
index 0000000..dff7880
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/constant/I18nKeyConstant.java
@@ -0,0 +1,69 @@
+package com.xiaopeng.trafficControl.constant;
+
+/**
+ * @author MiTao
+ * @date 2026-02-06 17:34
+ * 国际化消息键常量
+ *
+ */
+public interface I18nKeyConstant {
+    //========== 小程序业务流程 ==========
+    String ORDER_NOT_EXISTS = "order.not.exists";
+    String VEHICLE_NOT_EXISTS = "vehicle.not.exists";
+
+    // ========== 车辆导入相关 ==========
+    String VEHICLE_IMPORT_FAILED = "vehicle.import.failed";
+    String VEHICLE_IMPORT_DATA_EMPTY = "vehicle.import.data.empty";
+    String VEHICLE_IMPORT_FIELDS_REQUIRED = "vehicle.import.fields.required";
+
+    // ========== 车队删除相关 ==========
+    String FLEET_DELETE_HAS_BOUND_VEHICLE_OR_USER = "fleet.delete.has.bound.vehicle.or.user";
+
+    // ========== 车辆运营相关 ==========
+    String VEHICLE_OPERATION_INFO_INCOMPLETE = "vehicle.operation.info.incomplete";
+    String VEHICLE_BATCH_OPERATION_CONDITION_NOT_MET = "vehicle.batch.operation.condition.not.met";
+    String VEHICLE_TIME_EXPIRED = "vehicle.time.expired";
+
+    // ========== 车队相关 ==========
+    String FLEET_OPERATION_USER_BOUND_V1 = "fleet.operation.user.bound.v1";
+    String FLEET_OPERATION_USER_BOUND_2 = "fleet.operation.user.bound.v2";
+    String FLEET_VEHICLE_BOUND_V1 = "fleet.vehicle.bound.v1";
+    String FLEET_VEHICLE_BOUND_V2 = "fleet.vehicle.bound.v2";
+
+    // ========== 车辆开关车门 ==========
+    String VEHICLE_NOT_P_GEAR = "vehicle.not.p.gear";
+    String VEHICLE_DISTANCE_TOO_LONG = "vehicle.distance.too.long";
+
+
+    // ========== 车辆温度控制 ==========
+    String VEHICLE_TEMPERATURE_UP = "vehicle.temperature.up";
+
+    String VEHICLE_TEMPERATURE_DOWN = "vehicle.temperature.down";
+
+    // ========== 车辆新增/编辑校验 ==========
+    String VEHICLE_CODE_INVALID = "vehicle.code.invalid";
+    String VEHICLE_CODE_EXISTS = "vehicle.code.exists";
+    String VEHICLE_VIN_INVALID = "vehicle.vin.invalid";
+    String VEHICLE_VIN_EXISTS = "vehicle.vin.exists";
+    String VEHICLE_PLATE_INVALID = "vehicle.plate.invalid";
+    String VEHICLE_PLATE_EXISTS = "vehicle.plate.exists";
+    String VEHICLE_COLOR_INVALID = "vehicle.color.invalid";
+    String VEHICLE_ELECTRONIC_NOT_EXISTS = "vehicle.electronic.not.exists";
+
+    // ========== 车辆导入校验 ==========
+    String VEHICLE_IMPORT_VALIDATE_FAIL = "vehicle.import.validate.fail";
+    String VEHICLE_IMPORT_CODE_INVALID = "vehicle.import.code.invalid";
+    String VEHICLE_IMPORT_VIN_INVALID = "vehicle.import.vin.invalid";
+    String VEHICLE_IMPORT_PLATE_INVALID = "vehicle.import.plate.invalid";
+    String VEHICLE_IMPORT_COLOR_INVALID = "vehicle.import.color.invalid";
+    String VEHICLE_IMPORT_CODE_DUPLICATE = "vehicle.import.code.duplicate";
+    String VEHICLE_IMPORT_VIN_DUPLICATE = "vehicle.import.vin.duplicate";
+    String VEHICLE_IMPORT_PLATE_DUPLICATE = "vehicle.import.plate.duplicate";
+    String VEHICLE_IMPORT_CODE_EXISTS = "vehicle.import.code.exists";
+    String VEHICLE_IMPORT_VIN_EXISTS = "vehicle.import.vin.exists";
+    String VEHICLE_IMPORT_PLATE_EXISTS = "vehicle.import.plate.exists";
+
+    // ========== 车辆删除相关 ==========
+    String VEHICLE_DELETE_HAS_BOUND_FLEET = "vehicle.delete.has.bound.fleet";
+
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/enums/SignatureType.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/enums/SignatureType.java
new file mode 100644
index 0000000..d1871c4
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/enums/SignatureType.java
@@ -0,0 +1,15 @@
+package com.xiaopeng.trafficControl.enums;
+
+/** 签名类型枚举 */
+public enum SignatureType {
+	MD5("MD5"), SHA1("SHA1"), SHA256("SHA256");
+	private String value;
+
+	private SignatureType(String value) {
+		this.value = value;
+	}
+
+	public String getValue() {
+		return value;
+	}
+}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HMACSHA1.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HMACSHA1.java
new file mode 100644
index 0000000..b2d23d9
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HMACSHA1.java
@@ -0,0 +1,35 @@
+package com.xiaopeng.trafficControl.util;
+
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+public class HMACSHA1 {
+	
+	private static final String MAC_NAME = "HmacSHA1";
+	private static final String ENCODING = "UTF-8";
+	
+	/**
+	 * 使用 HMAC-SHA1 签名方法对对encryptText进行签名
+	 *
+	 * @param encryptText 被签名的字符串
+	 * @param encryptKey  密钥
+	 * @return
+	 * @throws Exception
+	 */
+	public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception {
+		byte[] data = encryptKey.getBytes(ENCODING);
+		// 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
+		Mac mac = Mac.getInstance(MAC_NAME);
+		SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
+		// 生成一个指定 Mac 算法 的 Mac 对象
+		// 用给定密钥初始化 Mac 对象
+		mac.init(secretKey);
+		
+		byte[] text = encryptText.getBytes(ENCODING);
+		// 完成 Mac 操作
+		return mac.doFinal(text);
+	}
+	
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HexUtil.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HexUtil.java
new file mode 100644
index 0000000..b845c1d
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HexUtil.java
@@ -0,0 +1,36 @@
+package com.xiaopeng.trafficControl.util;
+
+import com.xiaopeng.trafficControl.DecodingException;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+
+
+/**
+ * 与字节16进制相关的工具类<br/>
+ */
+public class HexUtil {
+	/** 将十六进制字符串转成字节数组 */
+	public static byte[] toHexBytes(String hexText) {
+		try {
+			return Hex.decodeHex(hexText.toCharArray());
+		} catch (DecoderException e) {
+			throw new DecodingException(e);
+		}
+	}
+
+	/** 将字节数组转成十六进制字符串(字母小写) */
+	public static String toLowerCase(byte[] hex) {
+		return new String(Hex.encodeHex(hex, true));
+	}
+
+	/** 将字节数组转成十六进制字符串(字母大写) */
+	public static String toUpperCase(byte[] hex) {
+		return new String(Hex.encodeHex(hex, false));
+	}
+
+	/** 将字节数组转成整数 */
+	public static int hashToInt(byte[] hash) {
+		return (int) (hash[3] << 24 | hash[2] << 16 | hash[1] << 8 | hash[0]);
+	}
+
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ResourceUtil.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ResourceUtil.java
new file mode 100644
index 0000000..162dda6
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ResourceUtil.java
@@ -0,0 +1,82 @@
+package com.xiaopeng.trafficControl.util;
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.net.URL;
+
+/**
+ * 资源工具类
+ * @author binghuoliu
+ * 
+ */
+public class ResourceUtil {
+
+	/**
+	 * 读取classpath下的文件<br>
+	 * 读取classpath下的文件 一般用于读取classpath下的配置文件,注意读取的配置文件路径是相对传入参数clazz的load入路径. 例:<br>
+	 * ClassTest c1;//假设c1是从/usr/local/classpath/ 载入<br>
+	 * ClassTest c2;//假设c2是从/home/classpath/ 载入<br>
+	 * ............<br>
+	 * loadConfigFile("a.xml",c1.class);//从/usr/local/classpath1/下寻找a.xml<br>
+	 * loadConfigFile("a.xml",c2.class);//从/home/classpath/下寻找a.xml<br>
+	 * @param resource 资源路径
+	 * @param clazz
+	 * @return InputStream 文件的inputstram,如果找不到则返回null
+	 */
+	@SuppressWarnings("unchecked")
+	public static InputStream loadConfigFile(String resource, Class clazz) {
+		ClassLoader classLoader = null;
+		try {
+			Method method = Thread.class.getMethod("getContextClassLoader");
+			classLoader = (ClassLoader) method.invoke(Thread.currentThread());
+		} catch (Exception e) {
+			throw new RuntimeException("loadConfigFile error: ", e);
+		}
+		if (classLoader == null) {
+			classLoader = clazz.getClassLoader();
+		}
+		try {
+			if (classLoader != null) {
+				URL url = classLoader.getResource(resource);
+				if (url == null) {
+					System.out.println("Can not find resource:" + resource);
+					return null;
+				}
+				if (url.toString().startsWith("jar:file:")) {
+					System.out.println("Get resource \"" + resource + "\" from jar:\t" + url.toString());
+					return clazz.getResourceAsStream(resource.startsWith("/") ? resource : "/" + resource);
+				} else {
+					System.out.println("Get resource \"" + resource + "\" from:\t" + url.toString());
+					return new FileInputStream(new File(url.toURI()));
+				}
+			}
+		} catch (Exception e) {
+			throw new RuntimeException("loadConfigFile error: ", e);
+		}
+		return null;
+	}
+
+	/**
+	 * 释放资源(有异常抛出)
+	 * @param closeable
+	 * @throws IOException
+	 */
+	public static void close(Closeable closeable) throws IOException {
+		if (closeable != null) {
+			closeable.close();
+		}
+	}
+
+	/**
+	 * 以优雅的形式释放资源(内部吃掉了异常)
+	 * @param closeable
+	 */
+	public static void closeGracefully(Closeable closeable) {
+		if (closeable != null) {
+			try {
+				closeable.close();
+			} catch (IOException e) {
+			}
+		}
+	}
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SHA1Util.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SHA1Util.java
new file mode 100644
index 0000000..d123471
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SHA1Util.java
@@ -0,0 +1,118 @@
+package com.xiaopeng.trafficControl.util;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * 该API支持线程安全<br/>
+ */
+public class SHA1Util {
+	// --------------------------计算SHA1大写字符串----------------------------------------------
+	/**
+	 * 计算出文件的SHA1大写字符串
+	 * 
+	 * @param file
+	 * @return
+	 * @throws IOException
+	 */
+	public static String getSHA1UpperString(File file) throws IOException {
+		return HexUtil.toUpperCase(getSHA1Bytes(file));
+	}
+
+	/**
+	 * 计算出SHA1后十六进制结果(大写)
+	 * 
+	 * @param s
+	 * @return
+	 */
+	public static String getSHA1UpperString(String s) {
+		try {
+			return getSHA1UpperString(s.getBytes("UTF-8"));
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * 计算出SHA1后十六进制结果(大写)
+	 * 
+	 * @param bytes
+	 * @return
+	 */
+	public static String getSHA1UpperString(byte[] bytes) {
+		return HexUtil.toUpperCase(getSHA1Bytes(bytes));
+	}
+
+	// --------------------------计算SHA1小写字符串----------------------------------------------
+	/**
+	 * 计算出文件的SHA1小写字符串
+	 * 
+	 * @param file
+	 * @return
+	 * @throws IOException
+	 */
+	public static String getSHA1LowerString(File file) throws IOException {
+		return HexUtil.toLowerCase(getSHA1Bytes(file));
+	}
+
+	/**
+	 * 计算出SHA1后十六进制结果(小写)
+	 * 
+	 * @param s
+	 * @return
+	 */
+	public static String getSHA1LowerString(String s) {
+		try {
+			return getSHA1LowerString(s.getBytes("UTF-8"));
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * 计算出SHA1后十六进制结果(小写)
+	 * 
+	 * @param bytes
+	 * @return
+	 */
+	public static String getSHA1LowerString(byte[] bytes) {
+		return HexUtil.toLowerCase(getSHA1Bytes(bytes));
+	}
+
+	// ------------------------计算出SHA1的byte[]------------------------------------------------
+	public static byte[] getSHA1Bytes(byte[] bytes) {
+		ThreadLocalSHA1.current().update(bytes);
+		return ThreadLocalSHA1.current().digest();
+	}
+
+	public static byte[] getSHA1Bytes(File file) throws IOException {
+		FileInputStream in = null;
+		FileChannel ch = null;
+		try {
+			in = new FileInputStream(file);
+			ch = in.getChannel();
+
+			MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
+
+			ThreadLocalSHA1.current().update(byteBuffer);
+			return ThreadLocalSHA1.current().digest();
+		} finally {
+			ResourceUtil.closeGracefully(ch);
+			ResourceUtil.closeGracefully(in);
+		}
+	}
+
+	// ------------------------------------------------------------------------
+	public static boolean checkPassword(String originContent, String sha1Content) {
+		String s = getSHA1LowerString(originContent);
+		return s.equals(sha1Content);
+	}
+
+	// ------------------------------------------------------------------------
+	
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SignatureUtils.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SignatureUtils.java
new file mode 100644
index 0000000..950e47c
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SignatureUtils.java
@@ -0,0 +1,114 @@
+package com.xiaopeng.trafficControl.util;
+
+import com.xiaopeng.unifiedverification.util.md5.MD5Util;
+import com.xiaopeng.unifiedverification.util.sha256.SHA256Util;
+import com.xiaopeng.trafficControl.enums.SignatureType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class SignatureUtils {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SignatureUtils.class);
+
+    /**
+     * 通用签名方法,签名算法为SHA1<br/>
+     * 签名原文拼装规则:<br/>
+     * ①paraMap按key的自然排序,并按key1+value1+key2+value2的规则拼接,中间无分隔符<br/>
+     * ②在第①步骤组装的String前面追加appid的值<br/>
+     * ③在第①步骤组装的String后面追加appSecret的值<br/>
+     *
+     * @param appId     业务系统唯一标识
+     * @param paraMap   所需要传递的参数map
+     * @param appSecret 分配给业务系统的秘钥
+     * @return
+     */
+    public static String getSignatureSHA1(String appId, Map<String, String> paraMap, String appSecret) {
+        return getSignature(appId, paraMap, appSecret, SignatureType.SHA1);
+    }
+
+    /**
+     * 通用签名方法<br/>
+     * 签名原文拼装规则:<br/>
+     * ①paraMap按key的自然排序,并按key1+value1+key2+value2的规则拼接,中间无分隔符<br/>
+     * ②在第①步骤组装的String前面追加appid的值<br/>
+     * ③在第①步骤组装的String后面追加appSecret的值<br/>
+     *
+     * @param appId         业务系统唯一标识
+     * @param paraMap       所需要传递的参数map
+     * @param appSecret     分配给业务系统的秘钥
+     * @param signatureType 签名算法类型(参考SignatureType)
+     * @return
+     */
+    public static String getSignature(String appId, Map<String, String> paraMap, String appSecret,
+                                      SignatureType signatureType) {
+        String originStr = buildAllSignatureOriginStr(appId, paraMap, appSecret);
+        LOGGER.info("originStr: {}", originStr);
+        return getSignature(originStr, signatureType);
+    }
+
+    // ------------------------------------------------------------------------------------------
+
+    /**
+     * 构造计算签名的完整消息内容<br/>
+     */
+    public static String buildAllSignatureOriginStr(String appId, Map<String, String> paraMap, String appSecret) {
+        StringBuilder sb = new StringBuilder(128);
+        String result = sb.append(appId).append(buildMiddleSignatureOriginStr(paraMap)).append(appSecret).toString(); // 用于签名的原文
+
+        return result;
+    }
+
+    /**
+     * 构造计算签名的中间消息内容<br/>
+     */
+    public static String buildMiddleSignatureOriginStr(Map<String, String> map) {
+        if (map.isEmpty()) {
+            return "";
+        }
+
+        Map<String, String> treeMap = new TreeMap<String, String>(new Comparator<String>() {
+            public int compare(String obj1, String obj2) {
+                // 升序排序
+                return obj1.compareTo(obj2);
+            }
+        });
+
+        treeMap.putAll(map);
+
+        Iterator<Map.Entry<String, String>> iter = treeMap.entrySet().iterator();
+        StringBuilder stringBuilder = new StringBuilder(128);
+
+        while (iter.hasNext()) {
+            Map.Entry<String, String> entry = iter.next();
+
+            stringBuilder.append(entry.getKey()).append(entry.getValue());
+        }
+
+        return stringBuilder.toString();
+    }
+
+    /**
+     * 计算签名
+     *
+     * @param originStr
+     *            用于签名的原始内容
+     * @param signatureType
+     *            签名算法类型(参考SignatureType)
+     * @return 签名值
+     */
+    public static String getSignature(String originStr, SignatureType signatureType) {
+        if (SignatureType.MD5 == signatureType) {
+            return MD5Util.getMD5LowerString(originStr);
+        } else if (SignatureType.SHA1 == signatureType) {
+            return SHA1Util.getSHA1LowerString(originStr);
+        } else if (SignatureType.SHA256 == signatureType) {
+            return SHA256Util.getSHA256LowerString(originStr);
+        } else { // 默认用SHA1
+            return SHA1Util.getSHA1LowerString(originStr);
+        }
+    }
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ThreadLocalSHA1.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ThreadLocalSHA1.java
new file mode 100644
index 0000000..9907197
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ThreadLocalSHA1.java
@@ -0,0 +1,26 @@
+package com.xiaopeng.trafficControl.util;
+
+import java.security.MessageDigest;
+
+/**
+ * SHA1算法计算散列值的ThreadLocal,避免多线程场景下的线程安全问题<br/>
+ */
+public class ThreadLocalSHA1 {
+	private static final ThreadLocal<MessageDigest> localFormat = new ThreadLocal<MessageDigest>() {
+		protected MessageDigest initialValue() {
+			try {
+				return MessageDigest.getInstance("SHA1");
+			} catch (Exception e) {
+				System.err.println(SHA1Util.class.getName() + "初始化失败,MessageDigest不支持SHA1Util。");
+				e.printStackTrace();
+
+				return null;
+			}
+		};
+	};
+
+	/** 获取当前线程对应的实例 */
+	public static MessageDigest current() {
+		return localFormat.get();
+	}
+}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/application-local.properties b/xp-robotaxi-traffic-control-boot/src/main/resources/application-local.properties
new file mode 100644
index 0000000..347eecd
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/application-local.properties
@@ -0,0 +1,104 @@
+spring.autoconfigure.exclude=com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
+spring.shardingsphere.props.sql.show=true
+spring.shardingsphere.props.show-sql=true
+spring.shardingsphere.datasource.names=xp0
+spring.shardingsphere.datasource.xp0.type=com.alibaba.druid.pool.DruidDataSource
+spring.shardingsphere.datasource.xp0.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.shardingsphere.datasource.xp0.url=jdbc:mysql://pc-bp1o444934f546768po.rwlb.rds.aliyuncs.com:3306/xp_rt_maintenance?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+spring.shardingsphere.datasource.xp0.username=xp_rt_maintenance
+spring.shardingsphere.datasource.xp0.password=gWgoAv_bi02um8sN
+spring.shardingsphere.datasource.xp0.druid.initial-size=10
+spring.shardingsphere.datasource.xp0.druid.min-idle=10
+spring.shardingsphere.datasource.xp0.druid.max-active=100
+spring.shardingsphere.datasource.xp0.druid.max-wait=60000
+spring.shardingsphere.datasource.xp0.druid.time-between-eviction-runs-millis=60000
+spring.shardingsphere.datasource.xp0.druid.min-evictable-idle-time-millis=300000
+spring.shardingsphere.datasource.xp0.druid.validation-query=SELECT 1
+spring.shardingsphere.datasource.xp0.druid.test-while-idle=true
+spring.shardingsphere.datasource.xp0.druid.test-on-borrow=false
+spring.shardingsphere.datasource.xp0.druid.test-on-return=false
+spring.shardingsphere.datasource.xp0.druid.pool-prepared-statements=true
+spring.shardingsphere.datasource.xp0.druid.max-pool-prepared-statement-per-connection-size=20
+spring.shardingsphere.datasource.xp0.druid.filters=stat,wall,log4j
+spring.shardingsphere.datasource.xp0.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
+spring.shardingsphere.datasource.xp0.druid.remove-abandoned=true
+spring.shardingsphere.datasource.xp0.druid.remove-abandoned-timeout=1800
+spring.shardingsphere.datasource.xp0.druid.log-abandoned=true
+spring.shardingsphere.datasource.xp0.druid.stat-view-servlet.enabled=true
+spring.shardingsphere.datasource.xp0.druid.stat-view-servlet.url-pattern=/druid/*
+spring.shardingsphere.datasource.xp0.druid.stat-view-servlet.login-username=admin
+spring.shardingsphere.datasource.xp0.druid.stat-view-servlet.login-password=admin
+spring.shardingsphere.datasource.xp0.druid.stat-view-servlet.reset-enable=false
+spring.shardingsphere.datasource.xp0.druid.wall.config.multi-statement-allow=false
+spring.shardingsphere.rules.sharding.tables.xp_charging_record.actual-data-nodes=xp0.xp_charging_record_$->{0..9}
+spring.shardingsphere.rules.sharding.tables.xp_charging_record.table-strategy.standard.sharding-column=vehicle_id
+spring.shardingsphere.rules.sharding.tables.xp_charging_record.table-strategy.standard.sharding-algorithm-name=xp-charging-record-inline
+spring.shardingsphere.rules.sharding.tables.xp_charging_record.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_charging_record.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_clock_in.actual-data-nodes=xp0.xp_clock_in_$->{0..9}
+spring.shardingsphere.rules.sharding.tables.xp_clock_in.table-strategy.standard.sharding-column=app_user_id
+spring.shardingsphere.rules.sharding.tables.xp_clock_in.table-strategy.standard.sharding-algorithm-name=xp-clock-in-inline
+spring.shardingsphere.rules.sharding.tables.xp_clock_in.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_clock_in.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_task.actual-data-nodes=xp0.xp_task_$->{0..19}
+spring.shardingsphere.rules.sharding.tables.xp_task.table-strategy.standard.sharding-column=vehicle_id
+spring.shardingsphere.rules.sharding.tables.xp_task.table-strategy.standard.sharding-algorithm-name=xp-task-inline
+spring.shardingsphere.rules.sharding.tables.xp_task.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_task.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail.actual-data-nodes=xp0.xp_task_handle_detail_$->{0..19}
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail.table-strategy.standard.sharding-column=task_id
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail.table-strategy.standard.sharding-algorithm-name=xp-task-handle-detail-inline
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail_routine.actual-data-nodes=xp0.xp_task_handle_detail_routine_$->{0..19}
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail_routine.table-strategy.standard.sharding-column=task_id
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail_routine.table-strategy.standard.sharding-algorithm-name=xp-task-handle-detail-routine-inline
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail_routine.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_task_handle_detail_routine.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_detection.actual-data-nodes=xp0.xp_vehicle_detection_$->{0..9}
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_detection.table-strategy.standard.sharding-column=task_id
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_detection.table-strategy.standard.sharding-algorithm-name=xp-vehicle-detection-inline
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_detection.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_detection.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_preparation.actual-data-nodes=xp0.xp_vehicle_preparation_$->{0..9}
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_preparation.table-strategy.standard.sharding-column=task_id
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_preparation.table-strategy.standard.sharding-algorithm-name=xp-vehicle-preparation-inline
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_preparation.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_preparation.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_repair.actual-data-nodes=xp0.xp_vehicle_repair_$->{0..9}
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_repair.table-strategy.standard.sharding-column=task_id
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_repair.table-strategy.standard.sharding-algorithm-name=xp-vehicle-repair-inline
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_repair.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_vehicle_repair.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_work_order.actual-data-nodes=xp0.xp_work_order_$->{0..9}
+spring.shardingsphere.rules.sharding.tables.xp_work_order.table-strategy.standard.sharding-column=feedback_user_phone
+spring.shardingsphere.rules.sharding.tables.xp_work_order.table-strategy.standard.sharding-algorithm-name=xp-work-order-inline
+spring.shardingsphere.rules.sharding.tables.xp_work_order.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_work_order.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.tables.xp_work_order_log.actual-data-nodes=xp0.xp_work_order_log_$->{0..19}
+spring.shardingsphere.rules.sharding.tables.xp_work_order_log.table-strategy.standard.sharding-column=work_order_id
+spring.shardingsphere.rules.sharding.tables.xp_work_order_log.table-strategy.standard.sharding-algorithm-name=xp-work-order-log-inline
+spring.shardingsphere.rules.sharding.tables.xp_work_order_log.key-generate-strategy.column=id
+spring.shardingsphere.rules.sharding.tables.xp_work_order_log.key-generate-strategy.key-generator-name=snowflake
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-charging-record-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-charging-record-inline.props.algorithm-expression=xp_charging_record_${vehicle_id % 20}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-clock-in-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-clock-in-inline.props.algorithm-expression=xp_clock_in_${app_user_id % 10}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-task-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-task-inline.props.algorithm-expression=xp_task_${vehicle_id % 20}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-task-handle-detail-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-task-handle-detail-inline.props.algorithm-expression=xp_task_handle_detail_${task_id % 20}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-task-handle-detail-routine-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-task-handle-detail-routine-inline.props.algorithm-expression=xp_task_handle_detail_routine_${task_id % 20}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-vehicle-detection-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-vehicle-detection-inline.props.algorithm-expression=xp_vehicle_detection_${task_id % 10}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-vehicle-preparation-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-vehicle-preparation-inline.props.algorithm-expression=xp_vehicle_preparation_${task_id % 10}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-vehicle-repair-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-vehicle-repair-inline.props.algorithm-expression=xp_vehicle_repair_${task_id % 10}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-work-order-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-work-order-inline.props.algorithm-expression=xp_work_order_${feedback_user_phone % 10}
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-work-order-log-inline.type=INLINE
+spring.shardingsphere.rules.sharding.sharding-algorithms.xp-work-order-log-inline.props.algorithm-expression=xp_work_order_log_${work_order_id % 20}
+spring.shardingsphere.rules.sharding.key-generators.snowflake.type=SNOWFLAKE
+seata.enabled=false
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages.properties b/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages.properties
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages_en_US.properties b/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages_en_US.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages_en_US.properties
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages_zh_CN.properties b/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages_zh_CN.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/i18n/messages_zh_CN.properties
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml b/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml
new file mode 100644
index 0000000..eca5fcc
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 -->
+<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
+<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
+<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
+<configuration  scan="true" scanPeriod="10 seconds">
+	<contextName>logback</contextName>
+	
+	<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
+	<property name="log.path" value="/data/log/app/ruoyi-account"/>
+	
+	<!--0. 日志格式和颜色渲染 -->
+	<!-- 彩色日志依赖的渲染类 -->
+	<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
+	<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
+	<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
+	<!-- 彩色日志格式 -->
+	<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
+	
+	<!--1. 输出到控制台-->
+	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+		<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
+		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+			<level>debug</level>
+		</filter>
+		<encoder>
+			<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
+			<!-- 设置字符集 -->
+			<charset>UTF-8</charset>
+		</encoder>
+	</appender>
+	
+	<!--2. 输出到文档-->
+	<!-- 2.1 level为 DEBUG 日志,时间滚动输出  -->
+	<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/debug.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<!-- 日志归档 -->
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档只记录debug级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>debug</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<!-- 2.2 level为 INFO 日志,时间滚动输出  -->
+	<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/info.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<!-- 每天日志归档路径以及格式 -->
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档只记录info级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>info</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<!-- 2.3 level为 WARN 日志,时间滚动输出  -->
+	<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/warn.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档只记录warn级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>warn</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<!-- 2.4 level为 ERROR 日志,时间滚动输出  -->
+	<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/error.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档只记录ERROR级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>ERROR</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件  -->
+	<appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/all.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>DEBUG</level>
+			<onMatch>DENY</onMatch>
+			<onMismatch>ACCEPT</onMismatch>
+		</filter>
+	</appender>
+	
+	<!--
+		<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
+		以及指定<appender>。<logger>仅有一个name属性,
+		一个可选的level和一个可选的addtivity属性。
+		name:用来指定受此logger约束的某一个包或者具体的某一个类。
+		level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
+			  还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。
+			  如果未设置此属性,那么当前logger将会继承上级的级别。
+		addtivity:是否向上级logger传递打印信息。默认是true。
+		<logger name="org.springframework.web" level="info"/>
+		<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
+	-->
+	
+	<!--
+		root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
+		level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
+		不能设置为INHERITED或者同义词NULL。默认是DEBUG
+		可以包含零个或多个元素,标识这个appender将会添加到这个logger。
+	-->
+	
+	<!-- 4  最终的策略:
+				 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)-->
+	<springProfile name="dev">
+		<root level="info">
+			<appender-ref ref="CONSOLE" />
+			<appender-ref ref="DEBUG_FILE" />
+			<appender-ref ref="INFO_FILE" />
+			<appender-ref ref="WARN_FILE" />
+			<appender-ref ref="ERROR_FILE" />
+			<appender-ref ref="ALL_FILE" />
+		</root>
+		<logger name="com.stylefeng.guns.modular.system.dao" level="debug"/>
+	</springProfile>
+	
+	<springProfile name="test">
+		<root level="info">
+			<appender-ref ref="CONSOLE" />
+			<appender-ref ref="DEBUG_FILE" />
+			<appender-ref ref="INFO_FILE" />
+			<appender-ref ref="WARN_FILE" />
+			<appender-ref ref="ERROR_FILE" />
+			<appender-ref ref="ALL_FILE" />
+		</root>
+	</springProfile>
+	
+	<springProfile name="prod">
+		<root level="info">
+			<!-- 生产环境最好不配置console写文件 -->
+			<appender-ref ref="DEBUG_FILE" />
+			<appender-ref ref="INFO_FILE" />
+			<appender-ref ref="WARN_FILE" />
+			<appender-ref ref="ERROR_FILE" />
+			<appender-ref ref="ALL_FILE" />
+		</root>
+	</springProfile>
+
+</configuration>
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml.bak b/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml.bak
new file mode 100644
index 0000000..14a129a
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml.bak
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 -->
+<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
+<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
+<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
+<configuration  scan="true" scanPeriod="10 seconds">
+	<contextName>logback</contextName>
+	
+	<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使"${}"来使用变量。 -->
+	<property name="log.path" value="/data/log/app/ruoyi-account"/>
+	
+	<!--0. 日志格式和颜色渲染 -->
+	<!-- 彩色日志依赖的渲染类 -->
+	<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
+	<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
+	<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
+	<!-- 彩色日志格式 -->
+	<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
+	
+	<!--1. 输出到控制台-->
+	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+		<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
+		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+			<level>debug</level>
+		</filter>
+		<encoder>
+			<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
+			<!-- 设置字符集 -->
+			<charset>UTF-8</charset>
+		</encoder>
+	</appender>
+	
+	<!--2. 输出到文档-->
+	<!-- 2.1 level为 DEBUG 日志,时间滚动输出  -->
+	<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/debug.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<!-- 日志归档 -->
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档只记录debug级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>debug</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<!-- 2.2 level为 INFO 日志,时间滚动输出  -->
+	<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/info.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<!-- 每天日志归档路径以及格式 -->
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档只记录info级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>info</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<!-- 2.3 level为 WARN 日志,时间滚动输出  -->
+	<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/warn.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档只记录warn级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>warn</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<!-- 2.4 level为 ERROR 日志,时间滚动输出  -->
+	<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/error.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档只记录ERROR级别的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>ERROR</level>
+			<onMatch>ACCEPT</onMatch>
+			<onMismatch>DENY</onMismatch>
+		</filter>
+	</appender>
+	
+	<!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件  -->
+	<appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<!-- 正在记录的日志文档的路径及文档名 -->
+		<file>${log.path}/all.log</file>
+		<!--日志文档输出格式-->
+		<encoder>
+			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+			<charset>UTF-8</charset> <!-- 此处设置字符集 -->
+		</encoder>
+		<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<maxFileSize>100MB</maxFileSize>
+			</timeBasedFileNamingAndTriggeringPolicy>
+			<!--日志文档保留天数-->
+			<maxHistory>15</maxHistory>
+		</rollingPolicy>
+		<!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 -->
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+			<level>DEBUG</level>
+			<onMatch>DENY</onMatch>
+			<onMismatch>ACCEPT</onMismatch>
+		</filter>
+	</appender>
+	
+	<!--
+		<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
+		以及指定<appender>。<logger>仅有一个name属性,
+		一个可选的level和一个可选的addtivity属性。
+		name:用来指定受此logger约束的某一个包或者具体的某一个类。
+		level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
+			  还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。
+			  如果未设置此属性,那么当前logger将会继承上级的级别。
+		addtivity:是否向上级logger传递打印信息。默认是true。
+		<logger name="org.springframework.web" level="info"/>
+		<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
+	-->
+	
+	<!--
+		root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
+		level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
+		不能设置为INHERITED或者同义词NULL。默认是DEBUG
+		可以包含零个或多个元素,标识这个appender将会添加到这个logger。
+	-->
+	
+	<!-- 4  最终的策略:
+				 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)-->
+	<springProfile name="dev">
+		<root level="info">
+			<appender-ref ref="CONSOLE" />
+			<appender-ref ref="DEBUG_FILE" />
+			<appender-ref ref="INFO_FILE" />
+			<appender-ref ref="WARN_FILE" />
+			<appender-ref ref="ERROR_FILE" />
+			<appender-ref ref="ALL_FILE" />
+		</root>
+		<logger name="com.stylefeng.guns.modular.system.dao" level="debug"/>
+	</springProfile>
+	
+	<springProfile name="test">
+		<root level="info">
+			<appender-ref ref="CONSOLE" />
+			<appender-ref ref="DEBUG_FILE" />
+			<appender-ref ref="INFO_FILE" />
+			<appender-ref ref="WARN_FILE" />
+			<appender-ref ref="ERROR_FILE" />
+			<appender-ref ref="ALL_FILE" />
+		</root>
+	</springProfile>
+	
+	<springProfile name="prod">
+		<root level="info">
+			<!-- 生产环境最好不配置console写文件 -->
+			<appender-ref ref="DEBUG_FILE" />
+			<appender-ref ref="INFO_FILE" />
+			<appender-ref ref="WARN_FILE" />
+			<appender-ref ref="ERROR_FILE" />
+			<appender-ref ref="ALL_FILE" />
+		</root>
+	</springProfile>
+
+</configuration>
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/mybatis-config.xml b/xp-robotaxi-traffic-control-boot/src/main/resources/mybatis-config.xml
new file mode 100644
index 0000000..53c5587
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/mybatis-config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration  PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+
+    <settings>
+        <!-- 打印查询语句 不会写入到日志文件中-->
+        <setting name="logImpl" value="STDOUT_LOGGING"/>
+        <!--<setting name="logImpl" value="LOG4J" />-->
+        <!-- 控制全局缓存(二级缓存),按美团技术团队的说法,尽量别用缓存机制 emmmm.... -->
+        <setting name="cacheEnabled" value="true"/>
+        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
+        <!-- <setting name="lazyLoadingEnabled" value="true"/> -->
+        <setting name="mapUnderscoreToCamelCase" value="true"/><!--是否将map下划线方式转为驼峰式命名-->
+        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
+        <!-- <setting name="aggressiveLazyLoading" value="false"/>-->
+        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
+        <!--<setting name="proxyFactory" value="CGLIB" />-->
+        <!-- 关于mybatis的一二级缓存 请参照:https://tech.meituan.com/2018/01/19/mybatis-cache.html -->
+        <!-- 一级缓存范围默认:SESSION ,此范围在复杂应用场景中可能会出现脏读数据-->
+        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
+        <!--<setting name="localCacheScope" value="STATEMENT"/>-->
+        <setting name="localCacheScope" value="STATEMENT"/>
+    </settings>
+
+</configuration>
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/seata.conf b/xp-robotaxi-traffic-control-boot/src/main/resources/seata.conf
new file mode 100644
index 0000000..21e4919
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/seata.conf
@@ -0,0 +1,7 @@
+# seata.conf
+shardingsphere.transaction.seata.at.enable = true
+shardingsphere.transaction.seata.tx.timeout = 60
+client {
+    application.id = "xp-robotaxi-vehicle-convoy-boot"  # 与spring.application.name一致
+    transaction.service.group = "seata_tx_group"
+}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/test/java/com/ruoyi/account/RuoYiAccountApplicationTests.java b/xp-robotaxi-traffic-control-boot/src/test/java/com/ruoyi/account/RuoYiAccountApplicationTests.java
new file mode 100644
index 0000000..9302669
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/test/java/com/ruoyi/account/RuoYiAccountApplicationTests.java
@@ -0,0 +1,30 @@
+//package com.ruoyi.account;
+//
+//import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+//import com.ruoyi.common.security.service.TokenService;
+//import com.ruoyi.system.api.model.LoginUserApplet;
+//import org.junit.jupiter.api.Test;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.boot.test.context.SpringBootTest;
+//
+//import java.util.HashMap;
+//import java.util.Map;
+//
+//@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = RuoYiAccountApplication.class)
+//public class RuoYiAccountApplicationTests {
+//	@Autowired
+//	private TokenService tokenService;
+//
+//	@Test
+//	public void test(){
+//		LoginUserApplet loginUserApplet = new LoginUserApplet();
+//		loginUserApplet.setUserId(1839480334642704385L);
+//		loginUserApplet.setUserIdStr("1839480334642704385");
+//		loginUserApplet.setName("158****3127");
+//		loginUserApplet.setPhone("15828353127");
+//		loginUserApplet.setAvatar("");
+//		loginUserApplet.setAddress("");
+//		Map<String, Object> tokenInfos = new HashMap<>();
+//		System.err.println(tokenService.createTokenApplet(loginUserApplet));
+//	}
+//}
diff --git a/xp-robotaxi-traffic-control-boot/xp-robotaxi-vehicle-convoy-boot.iml b/xp-robotaxi-traffic-control-boot/xp-robotaxi-vehicle-convoy-boot.iml
new file mode 100644
index 0000000..68a9707
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/xp-robotaxi-vehicle-convoy-boot.iml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4">
+  <component name="AdditionalModuleElements">
+    <content url="file://$MODULE_DIR$" dumb="true">
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+    </content>
+  </component>
+</module>
\ No newline at end of file

--
Gitblit v1.7.1