吉安感知网项目-后端
rain
2026-02-09 66bfbdb9251c22ffa2b5f05595a76a3547a2f5eb
Merge remote-tracking branch 'origin/master'
102 files modified
16 files added
3128 ■■■■ changed files
drone-auth/docker-compose-prod.yml 2 ●●● patch | view | raw | blame | history
drone-auth/docker-compose-test.yml 2 ●●● patch | view | raw | blame | history
drone-auth/src/main/resources/log/logback-prod.xml 9 ●●●●● patch | view | raw | blame | history
drone-auth/src/main/resources/log/logback-test.xml 9 ●●●●● patch | view | raw | blame | history
drone-common/src/main/java/org/sxkj/common/constant/LauncherConstant.java 2 ●●● patch | view | raw | blame | history
drone-common/src/main/java/org/sxkj/common/utils/HeaderUtils.java 22 ●●●●● patch | view | raw | blame | history
drone-ops/drone-flow/src/main/resources/log/logback-dev.xml 113 ●●●●● patch | view | raw | blame | history
drone-ops/drone-flow/src/main/resources/log/logback-prod.xml 222 ●●●●● patch | view | raw | blame | history
drone-ops/drone-flow/src/main/resources/log/logback-test.xml 222 ●●●●● patch | view | raw | blame | history
drone-ops/drone-log/docker-compose-prod.yml 2 ●●● patch | view | raw | blame | history
drone-ops/drone-log/docker-compose-test.yml 2 ●●● patch | view | raw | blame | history
drone-ops/drone-log/src/main/resources/log/logback-prod.xml 9 ●●●●● patch | view | raw | blame | history
drone-ops/drone-log/src/main/resources/log/logback-test.xml 9 ●●●●● patch | view | raw | blame | history
drone-ops/drone-resource/docker-compose-prod.yml 2 ●●● patch | view | raw | blame | history
drone-ops/drone-resource/docker-compose-test.yml 2 ●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/mapper/AttachMapper.xml 2 ●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java 13 ●●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/FileServiceImpl.java 4 ●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/resources/application-dev.yml 33 ●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/resources/application.yml 32 ●●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/resources/log/logback-prod.xml 8 ●●●● patch | view | raw | blame | history
drone-ops/drone-resource/src/main/resources/log/logback-test.xml 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/docker-compose-prod.yml 2 ●●● patch | view | raw | blame | history
drone-service/drone-fw/docker-compose-test.yml 2 ●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/controller/FwPoliceStationController.java 33 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwAreaDivideMapper.java 23 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwAreaDivideMapper.xml 53 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwDefenseSceneManageMapper.java 10 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwDefenseSceneManageMapper.xml 41 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwDefenseSceneMapper.java 6 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwDefenseSceneMapper.xml 13 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/param/FwAreaDivideListParam.java 73 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/param/FwDefenseSceneManagePageParam.java 3 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/IFwAreaDivideService.java 8 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/IFwDefenseSceneManageService.java 10 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/impl/FwAreaDivideServiceImpl.java 187 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/impl/FwDefenseSceneManageServiceImpl.java 15 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/impl/FwDefenseSceneServiceImpl.java 177 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/cockpit/service/impl/CockpitServiceImpl.java 26 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/mapper/FwTaskScheduleMapper.xml 6 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/service/impl/FwEffectEvalServiceImpl.java 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/service/impl/FwTaskScheduleServiceImpl.java 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/controller/FwDeviceController.java 10 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/mapper/FwDeviceMapper.java 2 ●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/mapper/FwDeviceMapper.xml 57 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/service/impl/FwDeviceMaintainPlanServiceImpl.java 11 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/service/impl/FwDeviceScrapServiceImpl.java 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/service/impl/FwDeviceServiceImpl.java 53 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/vo/CockpitFwDeviceVO.java 10 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/vo/FwDeviceVO.java 3 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/dto/FwDroneFlightRecordDTO.java 12 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/mapper/FwDroneAlarmRecordMapper.xml 19 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/mapper/FwDroneFlightRecordMapper.xml 25 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/param/FwDroneAlarmRecordExportParam.java 3 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/param/FwDroneFlightRecordExportParam.java 3 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/service/impl/FwDroneAlarmRecordServiceImpl.java 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/service/impl/FwDroneFlightRecordServiceImpl.java 13 ●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/resources/log/logback-prod.xml 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-fw/src/main/resources/log/logback-test.xml 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/docker-compose-prod.yml 6 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/docker-compose-test.yml 3 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/common/IdParam.java 3 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/mapper/GdFlyerMapper.xml 1 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/service/impl/GdFlyerServiceImpl.java 15 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/implement/service/impl/GdImplementListServiceImpl.java 5 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/orderdata/service/impl/GdApplicationInnovationServiceImpl.java 31 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/orderdata/service/impl/GdDataEvaluationServiceImpl.java 16 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/orderdata/service/impl/GdDataObjectionServiceImpl.java 6 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/orderdata/service/impl/GdSupplyDemandServiceImpl.java 12 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdManageDevicePayloadController.java 137 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdPatrolTaskController.java 2 ●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdTaskResultController.java 2 ●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdManageDevicePayloadDTO.java 34 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdXingtuPayloadListDTO.java 23 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdXingtuPilotListDTO.java 4 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdManageDevicePayloadEntity.java 64 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/enums/PatrolTaskStatusEnum.java 1 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/excel/GdManageDevicePayloadExcel.java 80 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdManageDeviceMapper.xml 11 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdManageDevicePayloadMapper.java 52 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdManageDevicePayloadMapper.xml 37 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.java 8 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.xml 14 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdTaskResultMapper.xml 2 ●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/GdManageDevicePageParam.java 5 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/scheduler/GdXingtuDeviceScheduler.java 1 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdManageDevicePayloadService.java 52 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdPatrolTaskService.java 7 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdTaskResultService.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDevicePayloadServiceImpl.java 54 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDeviceServiceImpl.java 122 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdOperationalRevenueServiceImpl.java 7 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java 125 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdTaskResultServiceImpl.java 44 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdWorkOrderFlowServiceImpl.java 13 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdWorkOrderServiceImpl.java 6 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdManageDevicePayloadVO.java 50 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/wrapper/GdManageDevicePayloadWrapper.java 50 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/resources/log/logback-prod.xml 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/resources/log/logback-test.xml 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/docker-compose-prod.yml 4 ●●●● patch | view | raw | blame | history
drone-service/drone-system/docker-compose-test.yml 3 ●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/controller/DeptController.java 11 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/controller/ExternalController.java 160 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/controller/RoleController.java 4 ●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/controller/UserController.java 32 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/excel/DeptImportExcel.java 8 ●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/mapper/RegionMapper.xml 4 ●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/service/IUserService.java 7 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/service/impl/DeptServiceImpl.java 14 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/service/impl/UserServiceImpl.java 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/resources/log/logback-prod.xml 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/resources/log/logback-test.xml 9 ●●●●● patch | view | raw | blame | history
drone-task/drone-odm/docker-compose-prod.yml 2 ●●● patch | view | raw | blame | history
drone-task/drone-odm/docker-compose-test.yml 2 ●●● patch | view | raw | blame | history
drone-task/drone-odm/src/main/resources/log/logback-prod.xml 9 ●●●●● patch | view | raw | blame | history
drone-task/drone-odm/src/main/resources/log/logback-test.xml 9 ●●●●● patch | view | raw | blame | history
pom.xml 10 ●●●●● patch | view | raw | blame | history
drone-auth/docker-compose-prod.yml
@@ -9,7 +9,7 @@
    ports:
      - "8100:8100"
    volumes:
      - /data/log/auth:/data/log/auth
      - /data/log/auth:/data/logs/drone-auth
    # 设置环境变量
    environment:
      - SPRING_PROFILES_ACTIVE=prod
drone-auth/docker-compose-test.yml
@@ -9,7 +9,7 @@
    ports:
      - "8100:8100"
    volumes:
      - /data/log/auth:/data/log/auth
      - /data/log/auth:/data/logs/drone-auth
    # 设置环境变量
    environment:
      - SPRING_PROFILES_ACTIVE=test
drone-auth/src/main/resources/log/logback-prod.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/auth/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/auth/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/auth/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/auth/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-auth/src/main/resources/log/logback-test.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/auth/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/auth/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/auth/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/auth/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-common/src/main/java/org/sxkj/common/constant/LauncherConstant.java
@@ -43,7 +43,7 @@
    /**
     * nacos prod 地址
     */
    String NACOS_PROD_ADDR = "127.0.0.1:8899";
    String NACOS_PROD_ADDR = "172.19.118.191:8899";
    String NACOS_LOCAL_ADDR = "192.168.1.227:8848";
    /**
drone-common/src/main/java/org/sxkj/common/utils/HeaderUtils.java
@@ -192,6 +192,28 @@
    }
    /**
     * 处理区域代码,提取最后一组并补零到12位
     *
     * @param areaCode 原始区域代码,可能包含多个以逗号分隔的代码
     * @return 处理后的区域代码,补零到12位
     */
    public static String processAreaCode(String areaCode) {
        if (areaCode != null && !areaCode.isEmpty()) {
            // 分割区域代码并只取最后一组
            String[] codes = areaCode.split(",");
            if (codes.length > 0) {
                // 取最后一组并去除空格
                String lastCode = codes[codes.length - 1].trim();
                if (!lastCode.isEmpty()) {
                    // 补零到12位
                    return lastCode + "000000000000".substring(lastCode.length());
                }
            }
        }
        return areaCode;
    }
    /**
     * 获取当前HttpServletRequest对象
     *
     * @return HttpServletRequest对象,可能为null
drone-ops/drone-flow/src/main/resources/log/logback-dev.xml
New file
@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" debug="false">
    <!-- 自定义参数监听 -->
    <contextListener class="org.springblade.core.log.listener.LoggerStartupListener"/>
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <!-- 彩色日志依赖的渲染类 -->
    <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}}"/>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>
    <if condition='property("ELK_MODE").toUpperCase().contains("TRUE")'>
        <then>
            <!-- 推送日志至elk -->
            <appender name="STDOUT_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
                <destination>${DESTINATION}</destination>
                <!-- 日志输出编码 -->
                <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                    <providers>
                        <timestamp>
                            <timeZone>UTC</timeZone>
                        </timestamp>
                        <pattern>
                            <pattern>
                                {
                                "traceId": "%X{traceId}",
                                "requestId": "%X{requestId}",
                                "accountId": "%X{accountId}",
                                "tenantId": "%X{tenantId}",
                                "logLevel": "%level",
                                "serviceName": "${springAppName:-SpringApp}",
                                "pid": "${PID:-}",
                                "thread": "%thread",
                                "class": "%logger{40}",
                                "line":"%L",
                                "message": "%message"
                                }
                            </pattern>
                        </pattern>
                        <mdc/>
                        <stackTrace/>
                    </providers>
                </encoder>
            </appender>
        </then>
    </if>
    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="${STDOUT_APPENDER}"/>
    </root>
    <logger name="net.sf.ehcache" level="INFO"/>
    <logger name="druid.sql" level="INFO"/>
    <!-- MyBatis log configure -->
    <logger name="com.apache.ibatis" level="INFO"/>
    <logger name="org.mybatis.spring" level="INFO"/>
    <logger name="java.sql.Connection" level="INFO"/>
    <logger name="java.sql.Statement" level="INFO"/>
    <logger name="java.sql.PreparedStatement" level="INFO"/>
    <!-- 减少部分debug日志 -->
    <logger name="druid.sql" level="INFO"/>
    <logger name="org.apache.shiro" level="INFO"/>
    <logger name="org.mybatis.spring" level="INFO"/>
    <logger name="org.springframework" level="INFO"/>
    <logger name="org.springframework.context" level="WARN"/>
    <logger name="org.springframework.beans" level="WARN"/>
    <logger name="com.baomidou.mybatisplus" level="INFO"/>
    <logger name="org.apache.ibatis.io" level="INFO"/>
    <logger name="org.apache.velocity" level="INFO"/>
    <logger name="org.eclipse.jetty" level="INFO"/>
    <logger name="io.undertow" level="INFO"/>
    <logger name="org.xnio.nio" level="INFO"/>
    <logger name="org.thymeleaf" level="INFO"/>
    <logger name="springfox.documentation" level="INFO"/>
    <logger name="org.hibernate.validator" level="INFO"/>
    <logger name="com.netflix.loadbalancer" level="INFO"/>
    <logger name="com.netflix.hystrix" level="INFO"/>
    <logger name="com.netflix.zuul" level="INFO"/>
    <logger name="de.codecentric" level="INFO"/>
    <!-- cache INFO -->
    <logger name="net.sf.ehcache" level="INFO"/>
    <logger name="org.springframework.cache" level="INFO"/>
    <!-- cloud -->
    <logger name="org.apache.http" level="INFO"/>
    <logger name="com.netflix.discovery" level="INFO"/>
    <logger name="com.netflix.eureka" level="INFO"/>
    <!-- 业务日志 -->
    <Logger name="org.springblade" level="INFO"/>
    <Logger name="org.springblade.core.tenant" level="INFO"/>
    <Logger name="org.springblade.core.version" level="INFO"/>
    <!-- 减少nacos日志 -->
    <logger name="com.alibaba.nacos" level="ERROR"/>
</configuration>
drone-ops/drone-flow/src/main/resources/log/logback-prod.xml
New file
@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" debug="false">
    <!-- 自定义参数监听 -->
    <contextListener class="org.springblade.core.log.listener.LoggerStartupListener"/>
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <!-- 彩色日志依赖的渲染类 -->
    <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="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 生成日志文件 DEBUG -->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
            <totalSizeCap>1GB</totalSizeCap>
            <!-- maxFileSize:这是活动文件的大小,默认值是100MB-->
            <maxFileSize>100MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 生成日志文件 INFO -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
            <totalSizeCap>1GB</totalSizeCap>
            <!-- maxFileSize:这是活动文件的大小,默认值是100MB-->
            <maxFileSize>30MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 生成日志文件 warn 级别 -->
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
            <totalSizeCap>1GB</totalSizeCap>
            <!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成5KB看效果 -->
            <maxFileSize>10MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 生成日志文件 -->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
            <totalSizeCap>1GB</totalSizeCap>
            <!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成5KB看效果 -->
            <maxFileSize>10MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <if condition='property("ELK_MODE").toUpperCase().contains("TRUE")'>
        <then>
            <!-- 推送日志至elk -->
            <appender name="INFO_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
                <destination>${DESTINATION}</destination>
                <!-- 日志输出编码 -->
                <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                    <providers>
                        <timestamp>
                            <timeZone>UTC</timeZone>
                        </timestamp>
                        <pattern>
                            <pattern>
                                {
                                "traceId": "%X{traceId}",
                                "requestId": "%X{requestId}",
                                "accountId": "%X{accountId}",
                                "tenantId": "%X{tenantId}",
                                "logLevel": "%level",
                                "serviceName": "${springAppName:-SpringApp}",
                                "pid": "${PID:-}",
                                "thread": "%thread",
                                "class": "%logger{40}",
                                "line":"%L",
                                "message": "%message"
                                }
                            </pattern>
                        </pattern>
                        <mdc/>
                        <stackTrace/>
                    </providers>
                </encoder>
                <!-- 打印日志级别 -->
                <filter class="ch.qos.logback.classic.filter.LevelFilter">
                    <level>INFO</level>
                    <onMatch>ACCEPT</onMatch>
                    <onMismatch>DENY</onMismatch>
                </filter>
            </appender>
            <!-- 推送日志至elk -->
            <appender name="ERROR_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
                <destination>${DESTINATION}</destination>
                <!-- 日志输出编码 -->
                <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                    <providers>
                        <timestamp>
                            <timeZone>UTC</timeZone>
                        </timestamp>
                        <pattern>
                            <pattern>
                                {
                                "traceId": "%X{traceId}",
                                "requestId": "%X{requestId}",
                                "accountId": "%X{accountId}",
                                "tenantId": "%X{tenantId}",
                                "logLevel": "%level",
                                "serviceName": "${springAppName:-SpringApp}",
                                "pid": "${PID:-}",
                                "thread": "%thread",
                                "class": "%logger{40}",
                                "line":"%L",
                                "message": "%message"
                                }
                            </pattern>
                        </pattern>
                        <mdc/>
                        <stackTrace/>
                    </providers>
                </encoder>
                <!-- 打印日志级别 -->
                <filter class="ch.qos.logback.classic.filter.LevelFilter">
                    <level>ERROR</level>
                    <onMatch>ACCEPT</onMatch>
                    <onMismatch>DENY</onMismatch>
                </filter>
            </appender>
        </then>
    </if>
    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="${INFO_APPENDER}"/>
        <appender-ref ref="${ERROR_APPENDER}"/>
    </root>
    <logger name="net.sf.ehcache" level="INFO"/>
    <logger name="druid.sql" level="INFO"/>
    <!-- 减少nacos日志 -->
    <logger name="com.alibaba.nacos" level="ERROR"/>
    <logger name="com.dji.sample" level="DEBUG">
        <appender-ref ref="ERROR"/>
        <appender-ref ref="INFO"/>
        <appender-ref ref="DEBUG"/>
    </logger>
</configuration>
drone-ops/drone-flow/src/main/resources/log/logback-test.xml
New file
@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" debug="false">
    <!-- 自定义参数监听 -->
    <contextListener class="org.springblade.core.log.listener.LoggerStartupListener"/>
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <!-- 彩色日志依赖的渲染类 -->
    <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="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 生成日志文件 DEBUG -->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
            <totalSizeCap>1GB</totalSizeCap>
            <!-- maxFileSize:这是活动文件的大小,默认值是100MB-->
            <maxFileSize>100MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 生成日志文件 INFO -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
            <totalSizeCap>1GB</totalSizeCap>
            <!-- maxFileSize:这是活动文件的大小,默认值是100MB-->
            <maxFileSize>30MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 生成日志文件 warn 级别 -->
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
            <totalSizeCap>1GB</totalSizeCap>
            <!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成5KB看效果 -->
            <maxFileSize>10MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 生成日志文件 -->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
            <totalSizeCap>1GB</totalSizeCap>
            <!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成5KB看效果 -->
            <maxFileSize>10MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <if condition='property("ELK_MODE").toUpperCase().contains("TRUE")'>
        <then>
            <!-- 推送日志至elk -->
            <appender name="INFO_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
                <destination>${DESTINATION}</destination>
                <!-- 日志输出编码 -->
                <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                    <providers>
                        <timestamp>
                            <timeZone>UTC</timeZone>
                        </timestamp>
                        <pattern>
                            <pattern>
                                {
                                "traceId": "%X{traceId}",
                                "requestId": "%X{requestId}",
                                "accountId": "%X{accountId}",
                                "tenantId": "%X{tenantId}",
                                "logLevel": "%level",
                                "serviceName": "${springAppName:-SpringApp}",
                                "pid": "${PID:-}",
                                "thread": "%thread",
                                "class": "%logger{40}",
                                "line":"%L",
                                "message": "%message"
                                }
                            </pattern>
                        </pattern>
                        <mdc/>
                        <stackTrace/>
                    </providers>
                </encoder>
                <!-- 打印日志级别 -->
                <filter class="ch.qos.logback.classic.filter.LevelFilter">
                    <level>INFO</level>
                    <onMatch>ACCEPT</onMatch>
                    <onMismatch>DENY</onMismatch>
                </filter>
            </appender>
            <!-- 推送日志至elk -->
            <appender name="ERROR_LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
                <destination>${DESTINATION}</destination>
                <!-- 日志输出编码 -->
                <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                    <providers>
                        <timestamp>
                            <timeZone>UTC</timeZone>
                        </timestamp>
                        <pattern>
                            <pattern>
                                {
                                "traceId": "%X{traceId}",
                                "requestId": "%X{requestId}",
                                "accountId": "%X{accountId}",
                                "tenantId": "%X{tenantId}",
                                "logLevel": "%level",
                                "serviceName": "${springAppName:-SpringApp}",
                                "pid": "${PID:-}",
                                "thread": "%thread",
                                "class": "%logger{40}",
                                "line":"%L",
                                "message": "%message"
                                }
                            </pattern>
                        </pattern>
                        <mdc/>
                        <stackTrace/>
                    </providers>
                </encoder>
                <!-- 打印日志级别 -->
                <filter class="ch.qos.logback.classic.filter.LevelFilter">
                    <level>ERROR</level>
                    <onMatch>ACCEPT</onMatch>
                    <onMismatch>DENY</onMismatch>
                </filter>
            </appender>
        </then>
    </if>
    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="${INFO_APPENDER}"/>
        <appender-ref ref="${ERROR_APPENDER}"/>
    </root>
    <logger name="net.sf.ehcache" level="INFO"/>
    <logger name="druid.sql" level="INFO"/>
    <!-- 减少nacos日志 -->
    <logger name="com.alibaba.nacos" level="ERROR"/>
    <logger name="com.dji.sample" level="DEBUG">
        <appender-ref ref="ERROR"/>
        <appender-ref ref="INFO"/>
        <appender-ref ref="DEBUG"/>
    </logger>
</configuration>
drone-ops/drone-log/docker-compose-prod.yml
@@ -9,7 +9,7 @@
    ports:
      - "8103:8103"
    volumes:
      - /app/logs/log:/data/log/log
      - /app/logs/log:/data/logs/drone-log
    # 设置环境变量
    environment:
      - SPRING_PROFILES_ACTIVE=prod
drone-ops/drone-log/docker-compose-test.yml
@@ -9,7 +9,7 @@
    ports:
      - "8103:8103"
    volumes:
      - /data/log/log:/data/log/log
      - /data/log/log:/data/logs/drone-log
    # 设置环境变量
    environment:
      - SPRING_PROFILES_ACTIVE=test
drone-ops/drone-log/src/main/resources/log/logback-prod.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/log/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/log/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/log/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/log/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-ops/drone-log/src/main/resources/log/logback-test.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/log/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/log/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/log/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/log/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-ops/drone-resource/docker-compose-prod.yml
@@ -9,7 +9,7 @@
    ports:
      - "8010:8010"
    volumes:
      - /app/logs/resource:/data/log/resource
      - /app/logs/resource:/data/logs/drone-resource
      - /app/data/docker-data/docker/volumes:/app/data/docker-data/docker/volumes
      - /data/temp:/data/temp
      - /app/data/temp:/app/data/temp
drone-ops/drone-resource/docker-compose-test.yml
@@ -9,7 +9,7 @@
    ports:
      - "8010:8010"
    volumes:
      - /data/log/resource:/data/log/resource
      - /data/log/resource:/data/logs/drone-resource
      - /software/data/odm-data/docker/volumes:/software/data/odm-data/docker/volumes
      - /data/temp:/data/temp
      - /data/temp/zip:/data/temp/zip
drone-ops/drone-resource/src/main/java/org/sxkj/resource/mapper/AttachMapper.xml
@@ -25,7 +25,7 @@
        select
            ba.*,
            bd.dept_name,
            ifnull(ba.nick_name,ba.original_name) nickName
            coalesce(ba.nick_name,ba.original_name) nickName
        from
            blade_attach ba
        left join
drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java
@@ -116,9 +116,11 @@
    @Override
    public IPage<AttachVO> selectAttachPage(IPage<AttachVO> page, AttachPageParam attach) {
        // 创建部门
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        attach.setDeptList(deptList);
          List<AttachVO> attachVOS   = baseMapper.selectAttachPage(page, attach);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            attach.setDeptList(deptList);
        }
        List<AttachVO> attachVOS = baseMapper.selectAttachPage(page, attach);
        return page.setRecords(attachVOS);
    }
@@ -783,7 +785,8 @@
    /**
     * 下载附件
     * @param param 下载参数
     *
     * @param param        下载参数
     * @param outputStream 输出流
     * @return
     * @throws IOException
@@ -878,7 +881,7 @@
        } catch (Exception e) {
            log.error("创建zip文件失败", e);
            return false;
        }finally {
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.flush();
drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/FileServiceImpl.java
@@ -55,9 +55,9 @@
    @Autowired
    private IFileMapper mapper;
    @Value("${mio.out-net-file-address}")
    @Value("${oss.endpoint}")
    private String fileAddress;
    @Value("${mio.bucket}")
    @Value("${oss.bucket-name}")
    private String bucket;
    @Autowired
    private AttachMapper attachMapper;
drone-ops/drone-resource/src/main/resources/application-dev.yml
@@ -11,19 +11,22 @@
      zipPreFix: ${odm.down.temp.zipPreFix}
      zipBasePath: ${odm.down.temp.zipBasePath}
#oss默认配置
oss:
  enable: true
  provider: minio
  endpoint: http://192.168.1.204:9000
  external-endpoint: http://192.168.1.204:9000
  access-key: ztzfminio
  secret-key: ztzfminio
  bucket: jaxm
  expire: 3600
  region: us-east-1
  object-dir-prefix:
  out-net-file-address: http://192.168.1.204:9000
  minio-path: http://192.168.1.204:9000
#服务器minio地址
media:
  server-address: D:\software\minio\minio_data\jaxm
  #开启oss配置
  enabled: true
  #开启oss类型
  #minio、s3、qiniu、alioss、huaweiobs、tencentcos
  name: minio
  #租户模式
  tenant-mode: true
  #oss服务地址
  endpoint: http://218.202.104.82:39000
  #minio转换服务地址,用于内网上传后将返回地址改为转换的外网地址
  transform-endpoint: http://218.202.104.82:39000
  #访问key
  access-key: admin
  #密钥key
  secret-key: geovis@123
  #存储桶
  bucket-name: jian-bucket
drone-ops/drone-resource/src/main/resources/application.yml
@@ -2,39 +2,7 @@
server:
  port: 8010
#oss默认配置
oss:
  #开启oss配置
  enabled: true
  #开启oss类型
  #minio、s3、qiniu、alioss、huaweiobs、tencentcos
  name: minio
  #租户模式
  tenant-mode: true
  #oss服务地址
  endpoint: http://192.168.1.204:9000
  #minio转换服务地址,用于内网上传后将返回地址改为转换的外网地址
  transform-endpoint: http://192.168.1.204:9000
  #访问key
  access-key: ztzfminio
  #密钥key
  secret-key: ztzfminio
  #存储桶
  bucket-name: jaxm
blade:
  mybatis-plus:
    page-limit: 2000
mio:
  enable: true
  provider: minio
  endpoint: http://139.196.74.78:9000
  external-endpoint: http://139.196.74.78:9000
  access-key: sxkj
  secret-key: sxkj2024
  bucket: cloud-bucket
  expire: 3600
  region: us-east-1
  object-dir-prefix:
  out-net-file-address: https://wrj.shuixiongit.com/minio
  minio-path: http://wrj.shuixiongit.com:8088
drone-ops/drone-resource/src/main/resources/log/logback-prod.xml
@@ -31,7 +31,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/resource/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +54,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/resource/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +77,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/resource/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +100,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/resource/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-ops/drone-resource/src/main/resources/log/logback-test.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/resource/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/resource/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/resource/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/resource/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-service/drone-fw/docker-compose-prod.yml
@@ -9,7 +9,7 @@
    ports:
      - "8101:8101"
    volumes:
      - /app/logs/fw:/data/log/fw
      - /app/logs/fw:/data/logs/drone-fw
      - /software/service/liscense:/software/service/liscense
    # 设置环境变量
    environment:
drone-service/drone-fw/docker-compose-test.yml
@@ -9,7 +9,7 @@
    ports:
      - "8101:8101"
    volumes:
      - /data/log/fw:/data/log/fw
      - /data/logs/fw:/data/logs/drone-fw
      - /software/service/liscense:/software/service/liscense
    # 设置环境变量
    environment:
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/controller/FwPoliceStationController.java
@@ -74,19 +74,6 @@
        FwPoliceStationEntity detail = fwPoliceStationService.getById(id);
        return R.data(FwPoliceStationWrapper.build().entityVO(detail));
    }
    // /**
    // * 派出所信息表 分页
    // */
    // @GetMapping("/list")
    // @ApiOperationSupport(order = 2)
    // @ApiOperation(value = "分页", notes = "传入fwPoliceStation")
    // public R<IPage<FwPoliceStationVO>> list(@ApiIgnore @RequestParam Map<String,
    // Object> fwPoliceStation, Query query) {
    // IPage<FwPoliceStationEntity> pages =
    // fwPoliceStationService.page(Condition.getPage(query),
    // Condition.getQueryWrapper(fwPoliceStation, FwPoliceStationEntity.class));
    // return R.data(FwPoliceStationWrapper.build().pageVO(pages));
    // }
    /**
     * 派出所信息表 列表
@@ -111,26 +98,6 @@
            param);
        return R.data(pages);
    }
    // /**
    // * 派出所信息表 新增
    // */
    // @PostMapping("/save")
    // @ApiOperationSupport(order = 4)
    // @ApiOperation(value = "新增", notes = "传入fwPoliceStation")
    // public R save(@Valid @RequestBody FwPoliceStationEntity fwPoliceStation) {
    // return R.status(fwPoliceStationService.save(fwPoliceStation));
    // }
    //
    // /**
    // * 派出所信息表 修改
    // */
    // @PostMapping("/update")
    // @ApiOperationSupport(order = 5)
    // @ApiOperation(value = "修改", notes = "传入fwPoliceStation")
    // public R update(@Valid @RequestBody FwPoliceStationEntity fwPoliceStation) {
    // return R.status(fwPoliceStationService.updateById(fwPoliceStation));
    // }
    /**
     * 派出所信息表 新增或修改
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwAreaDivideMapper.java
@@ -19,6 +19,7 @@
import org.sxkj.fw.area.dto.FwAreaDivideDTO;
import org.sxkj.fw.area.dto.FwAreaDivideStatisticsDTO;
import org.sxkj.fw.area.entity.FwAreaDivideEntity;
import org.sxkj.fw.area.param.FwAreaDivideListParam;
import org.sxkj.fw.area.vo.FwAreaDivideVO;
import org.sxkj.fw.area.vo.FwAreaDivideStatisticsVO;
import org.sxkj.fw.area.vo.FwDefenseSceneVO;
@@ -49,15 +50,10 @@
    /**
     * 列表
     *
     * @param filterSelected
     * @param sceneId
     * @param param
     * @return
     */
    List<FwAreaDivideVO> selectFwAreaDivideList(@Param("filterSelected") Integer filterSelected,
        @Param("sceneId") Long sceneId,
        @Param("areaTypeKeyList") List<String> areaTypeKeyList,
        @Param("isSetSceneManage") Integer isSetSceneManage,
        @Param("flyTime") java.time.LocalDateTime flyTime);
    List<FwAreaDivideVO> selectFwAreaDivideList(FwAreaDivideListParam param);
    /**
     * 根据设备ID获取区域
@@ -132,4 +128,17 @@
     */
    List<FwAreaDivideExcel> exportFwAreaDivide(@Param("ew") Wrapper<FwAreaDivideEntity> queryWrapper);
    /**
     *
     * @param param
     * @return
     */
    List<FwAreaDivideVO> selectFwAreaDivideListCockpit(FwAreaDivideListParam param);
    /**
     *
     * @param areaId
     * @return
     */
    boolean checkAreaBindScene(Long areaId);
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwAreaDivideMapper.xml
@@ -101,7 +101,13 @@
        from ja_fw_area_divide ad
        left join ja_fw_police_station ps on ps.id = ad.police_station_id and ps.is_deleted = 0
        <where>
            ad.is_deleted = 0
                ad.is_deleted = 0
            <if test="deptList != null and deptList.size > 0">
                and ad.create_dept in
                <foreach collection="deptList" item="deptId" open="(" separator="," close=")">
                    #{deptId}
                </foreach>
            </if>
            <if test="isSetSceneManage != null and isSetSceneManage == 1">
                and exists (
                    select 1
@@ -300,7 +306,7 @@
                    from ja_fw_effect_eval ee
                    join ja_fw_device d on d.id = ee.device_id and d.is_deleted = 0
                    where ee.is_deleted = 0
                      and ee.counter_effect = 'success'
                      and ee.counter_effect = '1'
                      and find_in_set(d.id, replace(ad.device_ids, ' ', ''))
                )
            end as counter_success_count
@@ -454,6 +460,49 @@
        FROM ja_fw_area_divide ${ew.customSqlSegment}
    </select>
    <select id="selectFwAreaDivideListCockpit" resultType="org.sxkj.fw.area.vo.FwAreaDivideVO">
        select
        ad.*,
        ps.station_name as police_station_name,
        ps.contact_person as police_station_contact_person,
        ps.contact_phone as police_station_contact_phone
        from ja_fw_area_divide ad
        left join ja_fw_police_station ps on ps.id = ad.police_station_id and ps.is_deleted = 0
        inner join (
                SELECT
                    d.id
                FROM
                    ja_fw_device d
                WHERE
                    d.is_deleted = 0
                    AND d.is_enabled = 1
                    AND d.final_outbound_area IS NOT NULL
                <if test="regionCode != null and regionCode != ''">
                    and ( d.final_outbound_area_code like concat(#{regionCode},'%')
                    <if test="currentDeptId != null and currentDeptId != '' ">
                        or d.id in (
                        SELECT device_id FROM ja_fw_device_per_share
                        WHERE loan_to_dept_id = #{currentDeptId}
                        AND is_deleted = 0
                        )
                    </if>
                    )
                </if>
                GROUP BY
                    d.id
        ) dd on find_in_set(dd.id, ad.device_ids)
    </select>
    <select id="checkAreaBindScene" resultType="java.lang.Boolean">
        select
        count(1)
        from ja_fw_defense_scene_manage dsm
        left join ja_fw_defense_scene ds on ds.id = dsm.defense_scene_id and ds.is_deleted = 0
        where ds.is_deleted = 0
        and find_in_set(#{areaId}, ds.area_divide_ids)
        and dsm.is_deleted = 0
    </select>
    <insert id="insertWithGeom" parameterType="org.sxkj.fw.area.entity.FwAreaDivideEntity" useGeneratedKeys="true" keyProperty="id">
        insert into ja_fw_area_divide (
            id,
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwDefenseSceneManageMapper.java
@@ -24,6 +24,9 @@
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import org.sxkj.fw.common.FwBaseInfo;
import java.util.Date;
import java.util.List;
/**
@@ -76,4 +79,11 @@
     * @throws Exception 数据库查询异常
     */
    List<Long> selectDeviceId(Long id);
    /**
     *
     * @param fwBaseInfo
     * @return
     */
    List<FwDefenseSceneManageVO> selectFwDefenseSceneManageCockpitList(FwBaseInfo fwBaseInfo);
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwDefenseSceneManageMapper.xml
@@ -32,6 +32,12 @@
            <if test="param2.name != null and param2.name != ''">
                and dsm.scene_name like concat('%', #{param2.name}, '%')
            </if>
            <if test="param2.deptList != null and param2.deptList.size > 0">
                and dsm.create_dept in
                <foreach collection="param2.deptList" item="deptId" open="(" separator="," close=")">
                    #{deptId}
                </foreach>
            </if>
        </where>
    </select>
@@ -103,4 +109,39 @@
        WHERE ad.device_ids IS NOT NULL AND ad.device_ids != ''
    </select>
    <select id="selectFwDefenseSceneManageCockpitList" resultType="org.sxkj.fw.area.vo.FwDefenseSceneManageVO">
        select
        dsm.*,
        ds.scene_name as defense_scene_name
        from ja_fw_defense_scene_manage dsm
        left join ja_fw_defense_scene ds on ds.id = dsm.defense_scene_id and ds.is_deleted = 0
        left join ja_fw_area_divide ad on FIND_IN_SET(ad.id, ds.area_divide_ids) > 0 and ad.is_deleted = 0
        inner join (
                SELECT
                    d.id
                FROM
                    ja_fw_device d
                WHERE
                    d.is_deleted = 0
                    AND d.is_enabled = 1
                    AND d.final_outbound_area IS NOT NULL
                <if test="regionCode != null and regionCode != ''">
                    and ( d.final_outbound_area_code like concat(#{regionCode},'%')
                    <if test="currentDeptId != null and currentDeptId != '' ">
                        or d.id in (
                        SELECT device_id FROM ja_fw_device_per_share
                        WHERE loan_to_dept_id = #{currentDeptId}
                        AND is_deleted = 0
                        )
                    </if>
                    )
                </if>
                GROUP BY
                d.id
            ) dd on find_in_set(dd.id, ad.device_ids)
        <where>
            dsm.is_deleted = 0
        </where>
    </select>
</mapper>
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwDefenseSceneMapper.java
@@ -52,7 +52,11 @@
     * @param sceneManageId
     * @return
     */
    List<FwDefenseSceneVO> selectFwDefenseSceneList(@Param("filterSelected") Integer filterSelected, @Param("zoneId") Long zoneId, @Param("areaId") Long areaId, @Param("unbound") Integer unbound, @Param("sceneManageId") Long sceneManageId);
    List<FwDefenseSceneVO> selectFwDefenseSceneList(@Param("filterSelected") Integer filterSelected,
                                                    @Param("zoneId") Long zoneId, @Param("areaId")
                                                    Long areaId, @Param("unbound") Integer unbound,
                                                    @Param("sceneManageId") Long sceneManageId,
                                                    @Param("deptList") List<Long> deptList);
    /**
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/mapper/FwDefenseSceneMapper.xml
@@ -50,9 +50,18 @@
    </select>
    <select id="selectFwDefenseSceneList" resultMap="fwDefenseSceneResultMap">
        select ds.* from ja_fw_defense_scene ds
        select
            ds.*
        from
            ja_fw_defense_scene ds
        <where>
            ds.is_deleted = 0
                ds.is_deleted = 0
            <if test="deptList != null and deptList.size > 0">
                and ds.create_dept in
                <foreach collection="deptList" item="deptId" open="(" separator="," close=")">
                    #{deptId}
                </foreach>
            </if>
            <if test="unbound != null and unbound == 1">
                and (
                    not exists (
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/param/FwAreaDivideListParam.java
New file
@@ -0,0 +1,73 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.fw.area.param;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.sxkj.fw.common.FwBaseInfo;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
 * 区域划分列表查询参数
 *
 * @author Aix
 * @since 2026-02-04
 */
@Data
public class FwAreaDivideListParam extends FwBaseInfo implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 筛选条件
     */
    @ApiModelProperty(value = "筛选条件")
    private Integer filterSelected;
    /**
     * 场景ID
     */
    @ApiModelProperty(value = "场景ID")
    private Long sceneId;
    /**
     * 区域类型键值(逗号分隔)
     */
    @ApiModelProperty(value = "区域类型键值(逗号分隔)")
    private String areaTypeKeys;
    /**
     * 是否设置场景管理
     */
    @ApiModelProperty(value = "是否设置场景管理")
    private Integer isSetSceneManage;
    /**
     * 飞行时间
     */
    @ApiModelProperty(value = "飞行时间")
    private LocalDateTime flyTime;
    /**
     * 区域类型键值列表
     */
    private List<String> areaTypeKeyList;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/param/FwDefenseSceneManagePageParam.java
@@ -18,6 +18,7 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.sxkj.fw.common.FwBaseInfo;
import java.io.Serializable;
@@ -28,7 +29,7 @@
 * @since 2026-01-30
 */
@Data
public class FwDefenseSceneManagePageParam implements Serializable {
public class FwDefenseSceneManagePageParam extends FwBaseInfo implements Serializable {
    private static final long serialVersionUID = 1L;
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/IFwAreaDivideService.java
@@ -21,6 +21,7 @@
import org.sxkj.fw.area.dto.FwAreaDivideStatisticsDTO;
import org.sxkj.fw.area.entity.FwAreaDivideEntity;
import org.sxkj.fw.area.entity.FwAreaDivideExtEntity;
import org.sxkj.fw.area.param.FwAreaDivideListParam;
import org.sxkj.fw.area.vo.FwAreaDivideVO;
import org.sxkj.fw.area.vo.FwAreaDivideStatisticsVO;
import org.sxkj.fw.area.excel.FwAreaDivideExcel;
@@ -112,4 +113,11 @@
     */
    boolean saveOrUpdateWithExt(FwAreaDivideEntity fwAreaDivide, List<FwAreaDivideExtEntity> fwAreaDivideExtList);
    /**
     *
     * @param param
     * @return
     */
    List<FwAreaDivideVO> selectFwAreaDivideList(FwAreaDivideListParam param);
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/IFwDefenseSceneManageService.java
@@ -23,6 +23,9 @@
import org.sxkj.fw.area.excel.FwDefenseSceneManageExcel;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService;
import org.sxkj.fw.common.FwBaseInfo;
import java.util.Date;
import java.util.List;
/**
@@ -86,4 +89,11 @@
     * @return
     */
    List<Long> selectDeviceId(Long sceneManageId);
    /**
     *
     * @param fwBaseInfo
     * @return
     */
    List<FwDefenseSceneManageVO> selectFwDefenseSceneManageCockpitList(FwBaseInfo fwBaseInfo);
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/impl/FwAreaDivideServiceImpl.java
@@ -19,9 +19,11 @@
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -31,15 +33,19 @@
import org.sxkj.fw.area.entity.FwAreaDivideExtEntity;
import org.sxkj.fw.area.excel.FwAreaDivideExcel;
import org.sxkj.fw.area.mapper.FwAreaDivideMapper;
import org.sxkj.fw.area.param.FwAreaDivideListParam;
import org.sxkj.fw.area.service.IFwAreaDivideExtService;
import org.sxkj.fw.area.service.IFwAreaDivideService;
import org.sxkj.fw.area.vo.FwAreaDivideExtVO;
import org.sxkj.fw.area.vo.FwAreaDivideStatisticsVO;
import org.sxkj.fw.area.vo.FwAreaDivideVO;
import org.sxkj.fw.area.vo.FwDefenseSceneVO;
import org.sxkj.fw.device.entity.FwDeviceEntity;
import org.sxkj.fw.device.service.IFwDeviceService;
import org.sxkj.system.cache.SysCache;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 区域划分表 服务实现类
@@ -49,15 +55,16 @@
 */
@Service
@AllArgsConstructor
public class FwAreaDivideServiceImpl extends BaseServiceImpl<FwAreaDivideMapper, FwAreaDivideEntity>
    implements IFwAreaDivideService {
public class FwAreaDivideServiceImpl extends BaseServiceImpl<FwAreaDivideMapper, FwAreaDivideEntity> implements IFwAreaDivideService {
    private final IFwAreaDivideExtService fwAreaDivideExtService;
    @Override
    public IPage<FwAreaDivideVO> selectFwAreaDividePage(IPage<FwAreaDivideVO> page, FwAreaDivideDTO fwAreaDivide) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        fwAreaDivide.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwAreaDivide.setDeptList(deptList);
        }
        fwAreaDivide.setAreaTypeKeyList(parseAreaTypeKeyList(fwAreaDivide.getAreaTypeKeys()));
        List<FwAreaDivideVO> areaDivideList = baseMapper.selectFwAreaDividePage(page, fwAreaDivide);
@@ -72,8 +79,38 @@
    @Override
    public List<FwAreaDivideVO> selectFwAreaDivideList(Integer filterSelected, Long sceneId, String areaTypeKeys, Integer isSetSceneManage, java.time.LocalDateTime flyTime) {
        List<String> areaTypeKeyList = parseAreaTypeKeyList(areaTypeKeys);
        List<FwAreaDivideVO> areaDivideList = baseMapper.selectFwAreaDivideList(filterSelected, sceneId, areaTypeKeyList, isSetSceneManage, flyTime);
        // 创建参数对象
        FwAreaDivideListParam param = new FwAreaDivideListParam();
        param.setFilterSelected(filterSelected);
        param.setSceneId(sceneId);
        param.setAreaTypeKeys(areaTypeKeys);
        param.setIsSetSceneManage(isSetSceneManage);
        param.setFlyTime(flyTime);
        // 解析区域类型键值列表
        param.setAreaTypeKeyList(parseAreaTypeKeyList(areaTypeKeys));
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            param.setDeptList(deptList);
        }
        // 调用Mapper方法,传入参数对象
        List<FwAreaDivideVO> areaDivideList = baseMapper.selectFwAreaDivideList(param);
        // 获取面数据
        if (areaDivideList != null && !areaDivideList.isEmpty()) {
            enrichWithExtensionData(areaDivideList);
        }
        return areaDivideList;
    }
    /**
     * 区域划分列表查询(对象参数版本)
     *
     * @param param 区域划分列表查询参数
     * @return 区域划分列表
     */
    @Override
    public List<FwAreaDivideVO> selectFwAreaDivideList(FwAreaDivideListParam param) {
        // 调用Mapper方法,传入参数对象
        List<FwAreaDivideVO> areaDivideList = baseMapper.selectFwAreaDivideListCockpit(param);
        // 获取面数据
        if (areaDivideList != null && !areaDivideList.isEmpty()) {
            enrichWithExtensionData(areaDivideList);
@@ -202,8 +239,10 @@
    @Override
    public IPage<FwAreaDivideStatisticsVO> selectFwAreaDivideStatisticsPage(IPage<FwAreaDivideStatisticsVO> page,
                                                                            FwAreaDivideStatisticsDTO fwAreaDivideStatistics) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        fwAreaDivideStatistics.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwAreaDivideStatistics.setDeptList(deptList);
        }
        fwAreaDivideStatistics.setAreaTypeKeyList(parseAreaTypeKeyList(fwAreaDivideStatistics.getAreaTypeKeys()));
        return page.setRecords(baseMapper.selectFwAreaDivideStatisticsPage(page, fwAreaDivideStatistics));
    }
@@ -272,7 +311,12 @@
                fwAreaDivide.setAreaTypeKeys(areaTypeKeys);
            }
        }
        String deviceIds = fwAreaDivide.getDeviceIds();
        // 判断deviceIds是否和数据库里面一致,不一致需要处理
        boolean isCreate = fwAreaDivide.getId() == null;
        // 处理设备启用禁用
        handleDeviceEnablementAndDisabling(fwAreaDivide, isCreate, deviceIds);
        boolean mainResult = saveOrUpdate(fwAreaDivide);
        if (!mainResult) {
            return false;
@@ -305,6 +349,58 @@
            throw new RuntimeException("保存区域扩展面数据失败");
        }
        return true;
    }
    /**
     *
     * @param fwAreaDivide
     * @param isCreate
     * @param deviceIds
     */
    private void handleDeviceEnablementAndDisabling(FwAreaDivideEntity fwAreaDivide, boolean isCreate, String deviceIds) {
        // 查找新增和删除的设备ID
        Set<String> addedDeviceIds = new HashSet<>();
        Set<String> removedDeviceIds = new HashSet<>();
        if (!isCreate) {
            // 更新操作,需要比较数据库中的deviceIds
            FwAreaDivideEntity existingEntity = baseMapper.selectById(fwAreaDivide.getId());
            if (existingEntity != null) {
                String oldDeviceIds = existingEntity.getDeviceIds();
                // 解析新旧deviceIds为集合
                Set<String> oldDeviceIdSet = parseDeviceIds(oldDeviceIds);
                Set<String> newDeviceIdSet = parseDeviceIds(deviceIds);
                // 找出新增的设备ID
                for (String id : newDeviceIdSet) {
                    if (!oldDeviceIdSet.contains(id)) {
                        addedDeviceIds.add(id);
                    }
                }
                // 找出删除的设备ID
                for (String id : oldDeviceIdSet) {
                    if (!newDeviceIdSet.contains(id)) {
                        removedDeviceIds.add(id);
                    }
                }
            }
            // 判断区域是否绑定到场景中
            boolean isBindScene = baseMapper.checkAreaBindScene(fwAreaDivide.getId());
            if (isBindScene) {
                IFwDeviceService fwDeviceService = SpringUtil.getBean(IFwDeviceService.class);
                if (!addedDeviceIds.isEmpty()) {
                    fwDeviceService.update(Wrappers.<FwDeviceEntity>lambdaUpdate()
                        .set(FwDeviceEntity::getIsEnabled, 1)
                        .in(FwDeviceEntity::getId, addedDeviceIds));
                }
                if (!removedDeviceIds.isEmpty()) {
                    fwDeviceService.update(Wrappers.<FwDeviceEntity>lambdaUpdate()
                        .set(FwDeviceEntity::getIsEnabled, 0)
                        .in(FwDeviceEntity::getId, removedDeviceIds));
                }
            }
        }
    }
    private void fillCreateFields(FwAreaDivideEntity fwAreaDivide) {
@@ -341,6 +437,25 @@
            fwAreaDivide.setUpdateUser(userId);
        }
        fwAreaDivide.setUpdateTime(new Date());
    }
    /**
     * 解析设备ID字符串为集合
     *
     * @param deviceIds 设备ID字符串,逗号分隔
     * @return 设备ID集合
     */
    private Set<String> parseDeviceIds(String deviceIds) {
        Set<String> deviceIdSet = new HashSet<>();
        if (StringUtil.isNotBlank(deviceIds)) {
            String[] ids = deviceIds.split(",");
            for (String id : ids) {
                if (StringUtil.isNotBlank(id)) {
                    deviceIdSet.add(id.trim());
                }
            }
        }
        return deviceIdSet;
    }
    private void fillCreateFieldsExt(FwAreaDivideExtEntity fwAreaDivideExt) {
@@ -447,4 +562,60 @@
        return idList;
    }
    /**
     * 禁用设备
     * @param deviceIds 设备ID列表
     */
    private void disableDevices(List<Long> deviceIds) {
        IFwDeviceService fwDeviceService = SpringUtil.getBean(IFwDeviceService.class);
        if (deviceIds != null && !deviceIds.isEmpty()) {
            // 实现设备禁用逻辑
            // 这里假设FwDeviceEntity有enabled字段,1表示启用,0表示禁用
            for (Long deviceId : deviceIds) {
                FwDeviceEntity device = new FwDeviceEntity();
                device.setId(deviceId);
                device.setIsEnabled(false);
                fwDeviceService.updateById(device);
            }
        }
    }
    /**
     * 逻辑删除区域划分,并处理关联设备的禁用
     * @param ids 区域划分ID列表
     * @return 是否删除成功
     */
    @Override
    public boolean deleteLogic(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return false;
        }
        // 先获取要删除的区域划分
        List<FwAreaDivideEntity> areas = listByIds(ids);
        if (areas == null || areas.isEmpty()) {
            return false;
        }
            // 过滤出配置了场景的区域数据
        List<FwAreaDivideEntity> sceneBoundAreas = areas.stream()
            .filter(area -> area != null && baseMapper.checkAreaBindScene(area.getId()))
            .collect(Collectors.toList());
        // 收集所有相关的设备ID
        List<Long> deviceIds = new ArrayList<>();
        for (FwAreaDivideEntity area : sceneBoundAreas) {
            if (area != null && StringUtil.isNotBlank(area.getDeviceIds())) {
                deviceIds.addAll(parseIdList(area.getDeviceIds()));
            }
        }
        // 禁用相关设备
        if (!deviceIds.isEmpty()) {
            disableDevices(deviceIds);
        }
        // 执行逻辑删除
        return super.deleteLogic(ids);
    }
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/impl/FwDefenseSceneManageServiceImpl.java
@@ -18,6 +18,7 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.checkerframework.checker.units.qual.A;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.sxkj.fw.area.param.FwDefenseSceneManagePageParam;
import org.sxkj.fw.area.entity.FwDefenseSceneManageEntity;
@@ -29,10 +30,13 @@
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.sxkj.fw.common.FwBaseInfo;
import org.sxkj.fw.device.entity.FwDeviceEntity;
import org.sxkj.fw.device.service.IFwDeviceService;
import org.sxkj.system.cache.SysCache;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
@@ -49,6 +53,10 @@
    @Override
    public IPage<FwDefenseSceneManageVO> selectFwDefenseSceneManagePage(IPage<FwDefenseSceneManageVO> page, FwDefenseSceneManagePageParam fwDefenseSceneManagePageParam) {
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwDefenseSceneManagePageParam.setDeptList(deptList);
        }
        return page.setRecords(baseMapper.selectFwDefenseSceneManagePage(page, fwDefenseSceneManagePageParam));
    }
@@ -93,7 +101,7 @@
     */
    @Override
    public boolean deleteFwDefenseSceneManage(List<Long> longList) {
        //删除场景管理
        // 删除场景管理
        boolean b = deleteLogic(longList);
        if (b) {
            // 1.遍历所有删除的场景管理ID
@@ -124,4 +132,9 @@
    public List<Long> selectDeviceId(Long sceneManageId) {
        return baseMapper.selectDeviceId(sceneManageId);
    }
    @Override
    public List<FwDefenseSceneManageVO> selectFwDefenseSceneManageCockpitList(FwBaseInfo fwBaseInfo) {
        return baseMapper.selectFwDefenseSceneManageCockpitList(fwBaseInfo);
    }
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/area/service/impl/FwDefenseSceneServiceImpl.java
@@ -17,6 +17,7 @@
package org.sxkj.fw.area.service.impl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.sxkj.common.utils.HeaderUtils;
@@ -45,6 +46,7 @@
import java.util.Map;
import java.util.Set;
import java.util.Date;
import java.util.stream.Collectors;
/**
 * 防控场景表 服务实现类
@@ -65,8 +67,10 @@
    @Override
    public IPage<FwDefenseSceneVO> selectFwDefenseScenePage(IPage<FwDefenseSceneVO> page, FwDefenseSceneVO fwDefenseScene) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        fwDefenseScene.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwDefenseScene.setDeptList(deptList);
        }
        IPage<FwDefenseSceneVO> result = page.setRecords(baseMapper.selectFwDefenseScenePage(page, fwDefenseScene));
        List<FwDefenseSceneVO> records = result.getRecords();
        if (records == null || records.isEmpty()) {
@@ -138,7 +142,11 @@
    @Override
    public List<FwDefenseSceneVO> selectFwDefenseSceneList(Integer filterSelected, Long zoneId, Long areaId, Integer unbound, Long sceneManageId) {
        return baseMapper.selectFwDefenseSceneList(filterSelected, zoneId, areaId, unbound, sceneManageId);
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        return baseMapper.selectFwDefenseSceneList(filterSelected, zoneId, areaId, unbound, sceneManageId, deptList);
    }
    private List<Long> parseIdList(String ids) {
@@ -166,9 +174,6 @@
    @Override
    public List<FwDefenseSceneExcel> exportFwDefenseScene(Wrapper<FwDefenseSceneEntity> queryWrapper) {
        List<FwDefenseSceneExcel> fwDefenseSceneList = baseMapper.exportFwDefenseScene(queryWrapper);
        //fwDefenseSceneList.forEach(fwDefenseScene -> {
        //    fwDefenseScene.setTypeName(DictCache.getValue(DictEnum.YES_NO, FwDefenseScene.getType()));
        //});
        return fwDefenseSceneList;
    }
@@ -191,9 +196,169 @@
        } else {
            fillUpdateFields(fwDefenseScene);
        }
        String areaDivideIds = fwDefenseScene.getAreaDivideIds();
        // 处理区域划分的新增和删除
        if (fwDefenseScene.getId() != null) {
            // 更新操作,需要比较旧的areaDivideIds
            FwDefenseSceneEntity oldEntity = baseMapper.selectById(fwDefenseScene.getId());
            if (oldEntity != null) {
                String oldAreaDivideIds = oldEntity.getAreaDivideIds();
                // 解析新旧区域划分ID列表
                Set<Long> oldAreaIds = parseAreaDivideIds(oldAreaDivideIds);
                Set<Long> newAreaIds = parseAreaDivideIds(areaDivideIds);
                // 找出新增的区域划分ID
                Set<Long> addedAreaIds = new HashSet<>();
                for (Long id : newAreaIds) {
                    if (!oldAreaIds.contains(id)) {
                        addedAreaIds.add(id);
                    }
                }
                // 找出删除的区域划分ID
                Set<Long> removedAreaIds = new HashSet<>();
                for (Long id : oldAreaIds) {
                    if (!newAreaIds.contains(id)) {
                        removedAreaIds.add(id);
                    }
                }
                // 处理删除的区域划分对应的设备(禁用)
                if (!removedAreaIds.isEmpty()) {
                    List<FwAreaDivideEntity> removedAreas = fwAreaDivideService.listByIds(new ArrayList<>(removedAreaIds));
                    List<Long> removedDeviceIds = removedAreas.stream()
                        .map(item -> Func.toLongList(item.getDeviceIds()))
                        .flatMap(List::stream)
                        .collect(Collectors.toList());
                    if (!removedDeviceIds.isEmpty()) {
                        // 禁用设备
                        disableDevices(removedDeviceIds);
                    }
                }
                // 处理新增的区域划分对应的设备(启用)
                if (!addedAreaIds.isEmpty()) {
                    List<FwAreaDivideEntity> addedAreas = fwAreaDivideService.listByIds(new ArrayList<>(addedAreaIds));
                    List<Long> addedDeviceIds = addedAreas.stream()
                        .map(item -> Func.toLongList(item.getDeviceIds()))
                        .flatMap(List::stream)
                        .collect(Collectors.toList());
                    if (!addedDeviceIds.isEmpty()) {
                        // 启用设备
                        enableDevices(addedDeviceIds);
                    }
                }
            }
        } else {
            // 新增操作,所有区域划分都是新增的,启用对应设备
            List<FwAreaDivideEntity> fwAreaDivideEntities = fwAreaDivideService.listByIds(Func.toLongList(areaDivideIds));
            List<Long> addedDeviceIds = fwAreaDivideEntities.stream()
                .map(item -> Func.toLongList(item.getDeviceIds()))
                .flatMap(List::stream)
                .collect(Collectors.toList());
            if (!addedDeviceIds.isEmpty()) {
                // 启用设备
                enableDevices(addedDeviceIds);
            }
        }
        return super.saveOrUpdate(fwDefenseScene);
    }
    /**
     * 解析区域划分ID字符串为集合
     * @param areaDivideIds 区域划分ID字符串,逗号分隔
     * @return 区域划分ID集合
     */
    private Set<Long> parseAreaDivideIds(String areaDivideIds) {
        Set<Long> areaIdSet = new HashSet<>();
        if (StringUtil.isNotBlank(areaDivideIds)) {
            List<Long> ids = Func.toLongList(areaDivideIds);
            areaIdSet.addAll(ids);
        }
        return areaIdSet;
    }
    /**
     * 启用设备
     * @param deviceIds 设备ID列表
     */
    private void enableDevices(List<Long> deviceIds) {
        if (deviceIds != null && !deviceIds.isEmpty()) {
            // 实现设备启用逻辑
            // 这里假设FwDeviceEntity有enabled字段,1表示启用,0表示禁用
            for (Long deviceId : deviceIds) {
                FwDeviceEntity device = new FwDeviceEntity();
                device.setId(deviceId);
                device.setIsEnabled(true);
                fwDeviceService.updateById(device);
            }
        }
    }
    /**
     * 禁用设备
     * @param deviceIds 设备ID列表
     */
    private void disableDevices(List<Long> deviceIds) {
        if (deviceIds != null && !deviceIds.isEmpty()) {
            // 实现设备禁用逻辑
            // 这里假设FwDeviceEntity有enabled字段,1表示启用,0表示禁用
            for (Long deviceId : deviceIds) {
                FwDeviceEntity device = new FwDeviceEntity();
                device.setId(deviceId);
                device.setIsEnabled(false);
                fwDeviceService.updateById(device);
            }
        }
    }
    /**
     * 逻辑删除防控场景,并处理关联设备的禁用
     * @param ids 防控场景ID列表
     * @return 是否删除成功
     */
    @Override
    public boolean deleteLogic(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return false;
        }
        // 先获取要删除的防控场景
        List<FwDefenseSceneEntity> scenes = listByIds(ids);
        if (scenes == null || scenes.isEmpty()) {
            return false;
        }
        // 收集所有相关的区域划分ID
        Set<Long> areaDivideIds = new HashSet<>();
        for (FwDefenseSceneEntity scene : scenes) {
            if (scene != null && StringUtil.isNotBlank(scene.getAreaDivideIds())) {
                areaDivideIds.addAll(Func.toLongList(scene.getAreaDivideIds()));
            }
        }
        // 收集所有相关的设备ID
        List<Long> deviceIds = new ArrayList<>();
        if (!areaDivideIds.isEmpty()) {
            List<FwAreaDivideEntity> areas = fwAreaDivideService.listByIds(new ArrayList<>(areaDivideIds));
            deviceIds = areas.stream()
                .map(item -> Func.toLongList(item.getDeviceIds()))
                .flatMap(List::stream)
                .collect(Collectors.toList());
        }
        // 禁用相关设备
        if (!deviceIds.isEmpty()) {
            disableDevices(deviceIds);
        }
        // 执行逻辑删除
        return super.deleteLogic(ids);
    }
    private void fillCreateFields(FwDefenseSceneEntity fwDefenseScene) {
        Long userId = AuthUtil.getUserId();
        String deptIdStr = AuthUtil.getDeptId();
drone-service/drone-fw/src/main/java/org/sxkj/fw/cockpit/service/impl/CockpitServiceImpl.java
@@ -3,8 +3,10 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;
import org.sxkj.common.utils.HeaderUtils;
import org.sxkj.fw.area.param.FwAreaDivideListParam;
import org.sxkj.fw.area.service.IFwAreaDivideService;
import org.sxkj.fw.area.service.IFwDefenseSceneManageService;
import org.sxkj.fw.area.vo.FwAreaDivideVO;
@@ -12,6 +14,7 @@
import org.sxkj.fw.cockpit.service.ICockpitService;
import org.sxkj.fw.cockpit.vo.AlarmStatisticsVO;
import org.sxkj.fw.cockpit.vo.DeviceStatisticsVO;
import org.sxkj.fw.common.FwBaseInfo;
import org.sxkj.fw.detection.entity.FwEffectEvalEntity;
import org.sxkj.fw.detection.param.FwEffectEvalParam;
import org.sxkj.fw.detection.service.IFwEffectEvalService;
@@ -70,7 +73,6 @@
    @Override
    public List<DeviceStatisticsVO> statisticalDeviceType() {
        // List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        Dept dept = SysCache.getDept(Long.valueOf(AuthUtil.getDeptId()));
        Region byCode = RegionCache.getByCode(dept.getAreaCode());
        return fwDeviceService.statisticalDeviceType(HeaderUtils.formatAreaCode(byCode.getCode()), AuthUtil.getDeptId());
@@ -117,7 +119,6 @@
    @Override
    public AlarmStatisticsVO statisticsAlarmsAndDeviceRecords() {
        // List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        Dept dept = SysCache.getDept(Long.valueOf(AuthUtil.getDeptId()));
        Region byCode = RegionCache.getByCode(dept.getAreaCode());
        String regionCode = HeaderUtils.formatAreaCode(byCode.getCode());
@@ -151,7 +152,12 @@
     */
    @Override
    public List<FwDefenseSceneManageVO> selectFwDefenseSceneManageList(Date filterTime) {
        return iFwDefenseSceneManageService.selectFwDefenseSceneManageList(filterTime);
        FwBaseInfo fwBaseInfo = new FwBaseInfo();
        Dept dept = SysCache.getDept(Long.valueOf(AuthUtil.getDeptId()));
        Region byCode = RegionCache.getByCode(dept.getAreaCode());
        fwBaseInfo.setCurrentDeptId(AuthUtil.getDeptId());
        fwBaseInfo.setRegionCode(HeaderUtils.formatAreaCode(byCode.getCode()));
        return iFwDefenseSceneManageService.selectFwDefenseSceneManageCockpitList(fwBaseInfo);
    }
    /**
@@ -165,6 +171,18 @@
     */
    @Override
    public List<FwAreaDivideVO> selectFwAreaDivideList(Integer filterSelected, Long sceneId, String areaTypeKeys, Integer isSetSceneManage, LocalDateTime flyTime) {
        return iFwAreaDivideService.selectFwAreaDivideList(filterSelected, sceneId, areaTypeKeys, isSetSceneManage, flyTime);
        FwAreaDivideListParam fwAreaDivideListParam = new FwAreaDivideListParam();
        fwAreaDivideListParam.setFilterSelected(filterSelected);
        fwAreaDivideListParam.setSceneId(sceneId);
        fwAreaDivideListParam.setAreaTypeKeys(areaTypeKeys);
        fwAreaDivideListParam.setIsSetSceneManage(isSetSceneManage);
        fwAreaDivideListParam.setFlyTime(flyTime);
        // 解析区域类型键值列表
        fwAreaDivideListParam.setAreaTypeKeyList(Func.toStrList(areaTypeKeys));
        Dept dept = SysCache.getDept(Long.valueOf(AuthUtil.getDeptId()));
        Region byCode = RegionCache.getByCode(dept.getAreaCode());
        fwAreaDivideListParam.setCurrentDeptId(AuthUtil.getDeptId());
        fwAreaDivideListParam.setRegionCode(HeaderUtils.formatAreaCode(byCode.getCode()));
        return iFwAreaDivideService.selectFwAreaDivideList(fwAreaDivideListParam);
    }
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/mapper/FwTaskScheduleMapper.xml
@@ -40,7 +40,7 @@
            ts.device_id,
            ts.area_divide_id,
            ts.defense_scene_id,
            ds.scene_name as defense_scene_name,
            dsm.scene_name as defense_scene_name,
            ts.longitude,
            ts.latitude,
            ts.dispatch_user,
@@ -69,12 +69,12 @@
        left join
                ja_fw_area_divide ad on ad.id = ts.area_divide_id
        left join
                ja_fw_defense_scene ds on ds.id = ts.defense_scene_id
                ja_fw_defense_scene_manage dsm on dsm.id = ts.defense_scene_id
        left join
                ja_fw_defense_zone dz on dz.is_deleted = 0
            and dz.defense_scene_ids is not null
            and dz.defense_scene_ids != ''
            and find_in_set(ds.id, replace(dz.defense_scene_ids, ' ', ''))
            and find_in_set(dsm.id, replace(dz.defense_scene_ids, ' ', ''))
        <where>
            ts.is_deleted = 0
            <if test="param2.deviceName != null and param2.deviceName != ''">
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/service/impl/FwEffectEvalServiceImpl.java
@@ -42,8 +42,10 @@
    @Override
    public IPage<FwEffectEvalVO> selectFwEffectEvalPage(IPage<FwEffectEvalVO> page, FwEffectEvalParam fwEffectEval) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        fwEffectEval.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwEffectEval.setDeptList(deptList);
        }
        fwEffectEval.setCurrentDeptId(AuthUtil.getDeptId());
        return page.setRecords(baseMapper.selectFwEffectEvalPage(page, fwEffectEval));
    }
@@ -52,9 +54,6 @@
    @Override
    public List<FwEffectEvalExcel> exportFwEffectEval(Wrapper<FwEffectEvalEntity> queryWrapper) {
        List<FwEffectEvalExcel> fwEffectEvalList = baseMapper.exportFwEffectEval(queryWrapper);
        //fwEffectEvalList.forEach(fwEffectEval -> {
        //    fwEffectEval.setTypeName(DictCache.getValue(DictEnum.YES_NO, FwEffectEval.getType()));
        //});
        return fwEffectEvalList;
    }
drone-service/drone-fw/src/main/java/org/sxkj/fw/detection/service/impl/FwTaskScheduleServiceImpl.java
@@ -42,8 +42,10 @@
    @Override
    public IPage<FwTaskScheduleVO> selectFwTaskSchedulePage(IPage<FwTaskScheduleVO> page, FwTaskSchedulePageParam fwTaskSchedule) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        fwTaskSchedule.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwTaskSchedule.setDeptList(deptList);
        }
        return page.setRecords(baseMapper.selectFwTaskSchedulePage(page, fwTaskSchedule));
    }
@@ -51,9 +53,6 @@
    @Override
    public List<FwTaskScheduleExcel> exportFwTaskSchedule(Wrapper<FwTaskScheduleEntity> queryWrapper) {
        List<FwTaskScheduleExcel> fwTaskScheduleList = baseMapper.exportFwTaskSchedule(queryWrapper);
        //fwTaskScheduleList.forEach(fwTaskSchedule -> {
        //    fwTaskSchedule.setTypeName(DictCache.getValue(DictEnum.YES_NO, FwTaskSchedule.getType()));
        //});
        return fwTaskScheduleList;
    }
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/controller/FwDeviceController.java
@@ -40,6 +40,7 @@
import org.sxkj.fw.device.excel.FwDeviceExcel;
import org.sxkj.fw.device.param.FwDevicePageParam;
import org.sxkj.fw.device.service.IFwDeviceService;
import org.sxkj.fw.device.vo.CockpitFwDeviceVO;
import org.sxkj.fw.device.vo.DeviceTypeStatisticsVO;
import org.sxkj.fw.device.vo.FwDeviceVO;
import org.sxkj.fw.device.wrapper.FwDeviceWrapper;
@@ -239,5 +240,12 @@
        List<FwDeviceExcel> list = fwDeviceService.exportFwDevice(queryWrapper);
        ExcelUtil.export(response, "设备表数据" + DateUtil.time(), "设备表数据表", list, FwDeviceExcel.class);
    }
    // 任务调度使用
    @GetMapping("/listByTask")
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "任务调度使用")
    public R<IPage<CockpitFwDeviceVO>> listByTask(FwDeviceDTO fwDevice, Query query) {
        IPage<CockpitFwDeviceVO> pages = fwDeviceService.selectCockpitDevicePage(Condition.getPage(query), fwDevice);
         return R.data(pages);
    }
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/mapper/FwDeviceMapper.java
@@ -98,7 +98,7 @@
     * 设备生产厂商统计
     * @return 统计数据
     */
    List<DeviceStatisticsVO> getDeviceManufacturerStatistics(List<Long> deptList);
    List<DeviceStatisticsVO> getDeviceManufacturerStatistics(List<Long> deptList, String currentDeptId);
    /**
     * 告警统计
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/mapper/FwDeviceMapper.xml
@@ -44,7 +44,7 @@
        from
            ja_fw_device
        <where>
            is_deleted = 0
                is_deleted = 0
            <if test="param2.id != null and param2.id != ''">
                and id = #{param2.id}
            </if>
@@ -92,12 +92,23 @@
                and (SELECT COUNT(*) FROM ja_fw_device_track tmp WHERE ja_fw_device.id = tmp.device_id) = 0
            </if>
            <if test="param2.deptList != null and param2.deptList.size > 0">
                and create_dept in
                and ( create_dept in
                <foreach collection="param2.deptList" item="deptId" open="(" separator="," close=")">
                    #{deptId}
                </foreach>
                <!-- 或者设备是共享给当前部门的 -->
                <if test="param2.currentDeptId != null and param2.currentDeptId != '' ">
                    or id in (
                    SELECT device_id FROM ja_fw_device_per_share
                    WHERE loan_to_dept_id = #{param2.currentDeptId}
                    AND is_deleted = 0
                    )
                </if>
                )
            </if>
        </where>
        order by
            create_time desc
    </select>
    <select id="selectFwDeviceList" resultMap="fwDeviceResultMap">
@@ -333,13 +344,13 @@
            <foreach collection="deptList" item="deptId" open="(" separator="," close=")">
                #{deptId}
            </foreach>
            <!-- <if test="currentDeptId != null and currentDeptId != '' "> -->
            <!--     or a.id in ( -->
            <!--     SELECT device_id FROM ja_fw_device_per_share -->
            <!--     WHERE loan_to_dept_id = #{currentDeptId} -->
            <!--     AND is_deleted = 0 -->
            <!--     ) -->
            <!-- </if> -->
            <if test="currentDeptId != null and currentDeptId != '' ">
                or a.id in (
                SELECT device_id FROM ja_fw_device_per_share
                WHERE loan_to_dept_id = #{currentDeptId}
                AND is_deleted = 0
                )
            </if>
            )
        </if>
        group by a.device_type,b.dict_value
@@ -387,10 +398,18 @@
        WHERE
            is_deleted = 0
        <if test="deptList != null and deptList.size > 0">
            and create_dept in
            and ( create_dept in
            <foreach collection="deptList" item="deptId" open="(" separator="," close=")">
                #{deptId}
            </foreach>
            <if test="currentDeptId != null and currentDeptId != '' ">
                or id in (
                SELECT device_id FROM ja_fw_device_per_share
                WHERE loan_to_dept_id = #{currentDeptId}
                AND is_deleted = 0
                )
            </if>
            )
        </if>
        GROUP BY
            manufacturer
@@ -507,12 +526,23 @@
    <select id="selectCockpitDevicePage" resultType="org.sxkj.fw.device.vo.CockpitFwDeviceVO">
        select
            d.*
            d.*,
            min(ad.id) as area_divide_id,
            min(dsm.id) as defense_scene_manage_id
        from
            ja_fw_device d
        left join ja_fw_area_divide ad
            on find_in_set(d.id, ad.device_ids) > 0
            and ad.is_deleted = 0
        left join ja_fw_defense_scene ds
            on find_in_set(ad.id, ds.area_divide_ids) > 0
            and ds.is_deleted = 0
        left join ja_fw_defense_scene_manage dsm
            on dsm.defense_scene_id = ds.id
            and dsm.is_deleted = 0
        <where>
            d.is_deleted = 0
            and d.is_enabled = 1
                d.is_deleted = 0
                and d.is_enabled = 1
            <if test="param2.regionCode != null and param2.regionCode != ''">
                and (d.final_outbound_area_code like concat(#{param2.regionCode},'%')
                <!-- 或者设备是共享给当前部门的 -->
@@ -571,6 +601,7 @@
                </foreach>
            </if>
        </where>
            group by d.id
    </select>
    <update id="updateTrackStatusByDeviceId">
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/service/impl/FwDeviceMaintainPlanServiceImpl.java
@@ -51,8 +51,10 @@
    @Override
    public IPage<FwDeviceMaintainPlanVO> selectFwDeviceMaintainPlanPage(IPage<FwDeviceMaintainPlanVO> page, FwDeviceMaintainPlanDTO fwDeviceMaintainPlan) {
        // 按当前部门及下级部门范围过滤数据
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        fwDeviceMaintainPlan.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwDeviceMaintainPlan.setDeptList(deptList);
        }
        return page.setRecords(baseMapper.selectFwDeviceMaintainPlanPage(page, fwDeviceMaintainPlan));
    }
@@ -60,9 +62,6 @@
    @Override
    public List<FwDeviceMaintainPlanExcel> exportFwDeviceMaintainPlan(Wrapper<FwDeviceMaintainPlanEntity> queryWrapper) {
        List<FwDeviceMaintainPlanExcel> fwDeviceMaintainPlanList = baseMapper.exportFwDeviceMaintainPlan(queryWrapper);
        //fwDeviceMaintainPlanList.forEach(fwDeviceMaintainPlan -> {
        //    fwDeviceMaintainPlan.setTypeName(DictCache.getValue(DictEnum.YES_NO, FwDeviceMaintainPlan.getType()));
        //});
        return fwDeviceMaintainPlanList;
    }
@@ -75,7 +74,7 @@
        // 批量把计划调整为未维护状态
        LambdaUpdateWrapper<FwDeviceMaintainPlanEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(FwDeviceMaintainPlanEntity::getId, planIds)
                .set(FwDeviceMaintainPlanEntity::getMaintainStatus, 0); // 未维护状态
            .set(FwDeviceMaintainPlanEntity::getMaintainStatus, 0); // 未维护状态
        // 执行批量更新
        update(updateWrapper);
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/service/impl/FwDeviceScrapServiceImpl.java
@@ -72,8 +72,10 @@
    @Override
    public IPage<FwDeviceScrapVO> selectFwDeviceScrapPage(IPage<FwDeviceScrapVO> page, FwDeviceScrapDTO fwDeviceScrap) {
        // 按当前部门及下级部门范围过滤数据
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        fwDeviceScrap.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwDeviceScrap.setDeptList(deptList);
        }
        return page.setRecords(baseMapper.selectFwDeviceScrapPage(page, fwDeviceScrap));
    }
@@ -81,9 +83,6 @@
    @Override
    public List<FwDeviceScrapExcel> exportFwDeviceScrap(Wrapper<FwDeviceScrapEntity> queryWrapper) {
        List<FwDeviceScrapExcel> fwDeviceScrapList = baseMapper.exportFwDeviceScrap(queryWrapper);
        //fwDeviceScrapList.forEach(fwDeviceScrap -> {
        //    fwDeviceScrap.setTypeName(DictCache.getValue(DictEnum.YES_NO, FwDeviceScrap.getType()));
        //});
        return fwDeviceScrapList;
    }
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/service/impl/FwDeviceServiceImpl.java
@@ -16,39 +16,39 @@
 */
package org.sxkj.fw.device.service.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.stereotype.Service;
import org.sxkj.fw.area.service.IFwAreaDivideService;
import org.sxkj.fw.cockpit.vo.AlarmStatisticsVO;
import org.sxkj.fw.cockpit.vo.DeviceStatisticsVO;
import org.sxkj.fw.common.GenericConverter;
import org.sxkj.fw.device.dto.FwDeviceDTO;
import org.sxkj.fw.device.dto.FwDevicePolygonQueryDTO;
import org.sxkj.fw.device.entity.FwDeviceEntity;
import org.sxkj.fw.device.excel.FwDeviceExcel;
import org.sxkj.fw.device.mapper.FwDeviceMapper;
import org.sxkj.fw.device.param.FwDevicePageParam;
import org.sxkj.fw.device.service.IFwDeviceService;
import org.sxkj.fw.device.vo.CockpitFwDeviceVO;
import org.sxkj.fw.device.vo.DeviceTypeStatisticsVO;
import org.sxkj.fw.device.vo.FwDeviceVO;
import org.sxkj.fw.device.excel.FwDeviceExcel;
import org.sxkj.fw.device.mapper.FwDeviceMapper;
import org.sxkj.fw.device.service.IFwDeviceService;
import org.sxkj.fw.area.service.IFwAreaDivideService;
import org.sxkj.fw.device.wrapper.FwDeviceWrapper;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.utils.StringUtil;
import org.sxkj.system.cache.RegionCache;
import org.sxkj.system.cache.SysCache;
import org.sxkj.system.entity.Dept;
import org.sxkj.system.entity.Region;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
/**
 * 设备表 服务实现类
@@ -71,8 +71,12 @@
    public IPage<FwDeviceVO> selectFwDevicePageVo(FwDevicePageParam fwDevice, Query query) {
        FwDeviceDTO fwDeviceDTO = GenericConverter.convert(fwDevice, FwDeviceDTO.class);
        // 按当前部门及下级部门范围过滤数据
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        fwDeviceDTO.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            fwDeviceDTO.setDeptList(deptList);
        }
        fwDeviceDTO.setCurrentDeptId(AuthUtil.getDeptId());
        // 按区域范围过滤数据
        IPage<FwDeviceEntity> pages = selectFwDevicePage(Condition.getPage(query), fwDeviceDTO);
        IPage<FwDeviceVO> result = FwDeviceWrapper.build().pageVO(pages);
        List<FwDeviceVO> records = result.getRecords();
@@ -142,7 +146,10 @@
    @Override
    public List<DeviceTypeStatisticsVO> getDeviceTypeStatistics() {
        // 统计范围限定在当前部门及下级部门
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        List<DeviceTypeStatisticsVO> deviceTypeStatistics = baseMapper.getDeviceTypeStatistics(deptList, AuthUtil.getDeptId());
        return deviceTypeStatistics;
    }
@@ -150,15 +157,21 @@
    @Override
    public List<DeviceStatisticsVO> getDeviceOutStatistics(String effectiveRangeKmIsNotNull) {
        // 统计范围限定在当前部门及下级部门
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        return baseMapper.getDeviceOutStatistics(effectiveRangeKmIsNotNull, deptList, AuthUtil.getDeptId());
    }
    @Override
    public List<DeviceStatisticsVO> getDeviceManufacturerStatistics() {
        // 统计范围限定在当前部门及下级部门
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        return baseMapper.getDeviceManufacturerStatistics(deptList);
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        return baseMapper.getDeviceManufacturerStatistics(deptList, AuthUtil.getDeptId());
    }
    /**
@@ -206,7 +219,7 @@
     * 查询非本部门区域的设备
     *
     * @param regionCode 区域编码,用于查询不在该区域内的设备
     * @param deptId 机构ID,用于限定查询范围
     * @param deptId     机构ID,用于限定查询范围
     * @return 设备列表
     */
    @Override
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/vo/CockpitFwDeviceVO.java
@@ -41,6 +41,9 @@
    @JsonSerialize(using = ToStringSerializer.class)
    private    Long id;
    @ApiModelProperty(value = "设备序列号")
    private String deviceSn;
    /**
     * 设备名称
     */
@@ -175,4 +178,11 @@
     */
    @ApiModelProperty(value = "更新时间")
    private Date updateTime;
    @ApiModelProperty(value = "区域id")
    private Long areaDivideId;
    @ApiModelProperty(value = "场景管理id")
    private Long defenseSceneManageId;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/device/vo/FwDeviceVO.java
@@ -206,4 +206,7 @@
    @ApiModelProperty(value = "共享记录ID")
    @JsonSerialize(using = ToStringSerializer.class)
    private Long shareId;
    @ApiModelProperty(value = "最终出库区域")
    private String finalOutboundArea;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/dto/FwDroneFlightRecordDTO.java
@@ -27,6 +27,7 @@
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.sxkj.fw.common.FwBaseInfo;
/**
 * 无人机飞行记录表 数据传输对象实体类
@@ -35,7 +36,7 @@
 * @since 2026-01-08
 */
@Data
 public class FwDroneFlightRecordDTO implements Serializable {
 public class FwDroneFlightRecordDTO extends FwBaseInfo implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("主键id")
@@ -90,14 +91,5 @@
    @ApiModelProperty(value = "区域名称")
    private String areaName;
    @ApiModelProperty(value = "部门集合",hidden = true)
    private List<Long> deptList;
    @ApiModelProperty(value = "部门id",hidden = true)
    private String currentDeptId;
    // setRegionName
    @ApiModelProperty(value = "区域名称",hidden = true)
    private String regionName;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/mapper/FwDroneAlarmRecordMapper.xml
@@ -131,13 +131,6 @@
            <if test="param2.areaName != null and param2.areaName != ''">
                and dar.area_name like CONCAT('%', #{param2.areaName}, '%')
            </if>
            <!-- <if test="param2.deptList != null and param2.deptList.size > 0"> -->
            <!--     and (dar.create_dept in -->
            <!--     <foreach collection="param2.deptList" item="deptId" open="(" separator="," close=")"> -->
            <!--         #{deptId} -->
            <!--     </foreach> -->
            <!--     ) -->
            <!-- </if>  -->
        </where>
                order by favorited desc
    </select>
@@ -159,6 +152,18 @@
                    #{item}
                </foreach>
            </if>
            <if test="regionCode != null and regionCode != ''">
                and (d.final_outbound_area_code like CONCAT(#{regionCode}, '%')
                <!-- 或者设备是共享给当前部门的 -->
                <if test="currentDeptId != null and currentDeptId != '' ">
                    or dar.device_id in (
                    SELECT device_id FROM ja_fw_device_per_share
                    WHERE loan_to_dept_id = #{currentDeptId}
                    AND is_deleted = 0
                    )
                </if>
                )
            </if>
        </where>
    </select>
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/mapper/FwDroneFlightRecordMapper.xml
@@ -33,8 +33,8 @@
                dfr.is_deleted = 0
                and d.track_status = 1
                and d.is_enabled = 1
            <if test="param2.regionName != null and param2.regionName != ''">
                and (d.final_outbound_area = #{param2.regionName}
            <if test="param2.regionCode != null and param2.regionCode != ''">
                and (d.final_outbound_area_code like CONCAT(#{param2.regionCode}, '%')
                <!-- 或者设备是共享给当前部门的 -->
                <if test="param2.currentDeptId != null and param2.currentDeptId != '' ">
                    or dfr.device_id in (
@@ -75,13 +75,6 @@
            <if test="param2.areaName != null and param2.areaName != ''">
                and dfr.area_name like CONCAT('%', #{param2.areaName}, '%')
            </if>
            <!-- <if test="param2.deptList != null and param2.deptList.size > 0"> -->
            <!--     and (dfr.create_dept in -->
            <!--     <foreach collection="param2.deptList" item="deptId" open="(" separator="," close=")"> -->
            <!--         #{deptId} -->
            <!--     </foreach> -->
            <!--     ) -->
            <!-- </if> -->
        </where>
    </select>
@@ -101,6 +94,8 @@
        FROM
            ja_fw_drone_flight_record dfr
        left join
            ja_fw_device d on dfr.device_id = d.id
        left join
            ja_fw_drone_flight_record_detail dfrd on dfr.id = dfrd.flight_record_id
        <where>
            dfr.is_deleted = 0
@@ -110,6 +105,18 @@
                    #{item}
                </foreach>
            </if>
            <if test="regionCode != null and regionCode != ''">
                and (d.final_outbound_area_code like CONCAT(#{regionCode}, '%')
                <!-- 或者设备是共享给当前部门的 -->
                <if test="currentDeptId != null and currentDeptId != '' ">
                    or dfr.device_id in (
                    SELECT device_id FROM ja_fw_device_per_share
                    WHERE loan_to_dept_id = #{currentDeptId}
                    AND is_deleted = 0
                    )
                </if>
                )
            </if>
        </where>
    </select>
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/param/FwDroneAlarmRecordExportParam.java
@@ -2,11 +2,12 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.sxkj.fw.common.FwBaseInfo;
import java.util.List;
@Data
public class FwDroneAlarmRecordExportParam {
public class FwDroneAlarmRecordExportParam extends FwBaseInfo {
    @ApiModelProperty("主键id,逗号分隔")
    private List<String> ids;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/param/FwDroneFlightRecordExportParam.java
@@ -2,11 +2,12 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.sxkj.fw.common.FwBaseInfo;
import java.util.List;
@Data
public class FwDroneFlightRecordExportParam {
public class FwDroneFlightRecordExportParam extends FwBaseInfo {
    @ApiModelProperty("主键id,逗号分隔")
    private List<String> ids;
}
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/service/impl/FwDroneAlarmRecordServiceImpl.java
@@ -60,17 +60,16 @@
        fwDroneAlarmRecord.setRegionName(byCode.getName());
        fwDroneAlarmRecord.setCurrentDeptId(AuthUtil.getDeptId());
        fwDroneAlarmRecord.setRegionCode(HeaderUtils.formatAreaCode(byCode.getCode()));
        // 获取当前部门及其子部门列表
        // List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        // fwDroneAlarmRecord.setDeptList(deptList);
        // 获取共享给当前部门的设备编号列表
        // 执行查询
        return page.setRecords(baseMapper.selectFwDroneAlarmRecordPage(page, fwDroneAlarmRecord));
    }
    @Override
    public List<FwDroneAlarmRecordExcel> exportFwDroneAlarmRecord(FwDroneAlarmRecordExportParam fwDroneAlarmRecord) {
        Dept dept = SysCache.getDept(Long.valueOf(AuthUtil.getDeptId()));
        Region byCode = RegionCache.getByCode(dept.getAreaCode());
        fwDroneAlarmRecord.setRegionCode(HeaderUtils.formatAreaCode(byCode.getCode()));
        fwDroneAlarmRecord.setCurrentDeptId(AuthUtil.getDeptId());
        List<FwDroneAlarmRecordExcel> fwDroneAlarmRecordList = baseMapper.exportFwDroneAlarmRecord(fwDroneAlarmRecord);
        return fwDroneAlarmRecordList;
    }
drone-service/drone-fw/src/main/java/org/sxkj/fw/record/service/impl/FwDroneFlightRecordServiceImpl.java
@@ -17,6 +17,7 @@
package org.sxkj.fw.record.service.impl;
import org.springblade.core.secure.utils.AuthUtil;
import org.sxkj.common.utils.HeaderUtils;
import org.sxkj.fw.record.dto.FwDroneFlightRecordDTO;
import org.sxkj.fw.record.entity.FwDroneFlightRecordEntity;
import org.sxkj.fw.record.param.FwDroneFlightRecordExportParam;
@@ -48,20 +49,20 @@
    @Override
    public IPage<FwDroneFlightRecordVO> selectFwDroneFlightRecordPage(IPage<FwDroneFlightRecordVO> page, FwDroneFlightRecordDTO fwDroneFlightRecord) {
        // List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        // fwDroneFlightRecord.setDeptList(deptList);
        // fwDroneFlightRecord.setCurrentDeptId(AuthUtil.getDeptId());
        Dept dept = SysCache.getDept(Long.valueOf(AuthUtil.getDeptId()));
        // 3. 查询不在这些部门区域内的设备
        Region byCode = RegionCache.getByCode(dept.getAreaCode());
        String regionName = byCode.getName();
        fwDroneFlightRecord.setRegionName(regionName);
        fwDroneFlightRecord.setRegionCode(HeaderUtils.formatAreaCode(byCode.getCode()));
        fwDroneFlightRecord.setCurrentDeptId(AuthUtil.getDeptId());
        return page.setRecords(baseMapper.selectFwDroneFlightRecordPage(page, fwDroneFlightRecord));
    }
    @Override
    public Map<String, List<FwDroneFlightRecordExcel>> exportFwDroneFlightRecord(FwDroneFlightRecordExportParam fwDroneFlightRecord) {
        Dept dept = SysCache.getDept(Long.valueOf(AuthUtil.getDeptId()));
        Region byCode = RegionCache.getByCode(dept.getAreaCode());
        fwDroneFlightRecord.setRegionCode(HeaderUtils.formatAreaCode(byCode.getCode()));
        fwDroneFlightRecord.setCurrentDeptId(AuthUtil.getDeptId());
        List<FwDroneFlightRecordExcel> fwDroneFlightRecordList = baseMapper.exportFwDroneFlightRecord(fwDroneFlightRecord);
        // 按照 无人机名称 和 序列号 组合进行分组,键格式为 "id_serialNo"
        Map<String, List<FwDroneFlightRecordExcel>> groupedMap = fwDroneFlightRecordList.stream()
drone-service/drone-fw/src/main/resources/log/logback-prod.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-service/drone-fw/src/main/resources/log/logback-test.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-service/drone-gd/docker-compose-prod.yml
@@ -2,14 +2,14 @@
services:
  drone_gd:
    # 从 Harbor 私有仓库拉取镜像
    image: 172.21.81.239:32002/drone-manage/drone-gd:SNAPSHOT-$BUILD_NUMBER
    image: 172.21.81.239:32002/drone-manage-test/drone-gd:SNAPSHOT-$BUILD_NUMBER
    # image: drone-gd:latest
    container_name: drone-gd
    # 宿主机端口:容器启动端口
    ports:
      - "8106:8106"
      - "8102:8102"
    volumes:
      - /app/logs/gd:/data/log/gd
      - /app/logs/drone-gd:/data/logs/drone-gd
      - /software/service/liscense:/software/service/liscense
    # 设置环境变量
    environment:
drone-service/drone-gd/docker-compose-test.yml
@@ -9,7 +9,7 @@
    ports:
      - "8102:8102"
    volumes:
      - /data/log/gd:/data/log/gd
      - /data/logs/drone-gd:/data/logs/drone-gd
      - /software/service/liscense:/software/service/liscense
    # 设置环境变量
    environment:
@@ -20,6 +20,7 @@
    networks:
      - doc_drone_network
# 指定
networks:
  doc_drone_network:
drone-service/drone-gd/src/main/java/org/sxkj/gd/common/IdParam.java
@@ -20,6 +20,7 @@
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
@@ -34,7 +35,7 @@
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "主键", required = true)
    @NotEmpty
    @NotNull(message = "主键ID不能为空")
    private    Long id;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/mapper/GdFlyerMapper.xml
@@ -26,6 +26,7 @@
    <resultMap id="gdFlyerVOResultMap" type="org.sxkj.gd.flyer.vo.GdFlyerVO">
        <result column="id" property="id"/>
        <result column="flyer_id" property="flyerId"/>
        <result column="flyer_name" property="flyerName"/>
        <result column="flyer_phone" property="flyerPhone"/>
        <result column="flight_hours" property="flightHours"/>
drone-service/drone-gd/src/main/java/org/sxkj/gd/flyer/service/impl/GdFlyerServiceImpl.java
@@ -31,6 +31,7 @@
import org.sxkj.gd.utils.GdGeoAddressUtil;
import org.sxkj.system.cache.SysCache;
import java.util.ArrayList;
import java.util.List;
/**
@@ -44,16 +45,20 @@
    @Override
    public IPage<GdFlyerVO> selectGdFlyerPage(IPage<GdFlyerVO> page, GdFlyerPageParam gdFlyer) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        gdFlyer.setDeptList(deptList);
        // 通过经纬度获取行政区划
         if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            gdFlyer.setDeptList(deptList);
        }
                // 通过经纬度获取行政区划
        if (StringUtil.isNotBlank(gdFlyer.getLongitude()) && StringUtil.isNotBlank(gdFlyer.getLatitude())) {
            String areaCode = GdGeoAddressUtil.getCountyCode(Double.valueOf(gdFlyer.getLongitude()), Double.valueOf(gdFlyer.getLatitude()));
            if (areaCode != null && areaCode.length() > 6) {
                areaCode = areaCode.substring(0, 6);
            // 去掉前面三位数字
            if (areaCode != null && areaCode.length() > 3) {
                areaCode = areaCode.substring(3);
            }
            gdFlyer.setAreaCode(areaCode);
        }
        return page.setRecords(baseMapper.selectGdFlyerPage(page, gdFlyer));
    }
drone-service/drone-gd/src/main/java/org/sxkj/gd/implement/service/impl/GdImplementListServiceImpl.java
@@ -60,7 +60,10 @@
    @Override
    public IPage<GdImplementListVO> selectGdImplementListPage(IPage<GdImplementListVO> page, GdImplementListPageParam gdImplementList) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        gdImplementList.setDeptList(deptList);
        gdImplementList.setAreaCode(HeaderUtils.formatAreaCode(gdImplementList.getAreaCode()));
        return page.setRecords(baseMapper.selectGdImplementListPage(page, gdImplementList));
drone-service/drone-gd/src/main/java/org/sxkj/gd/orderdata/service/impl/GdApplicationInnovationServiceImpl.java
@@ -16,17 +16,17 @@
 */
package org.sxkj.gd.orderdata.service.impl;
import org.springblade.core.secure.utils.AuthUtil;
import org.sxkj.gd.orderdata.entity.GdApplicationInnovationEntity;
import org.sxkj.gd.orderdata.param.GdApplicationInnovationPageParam;
import org.sxkj.gd.orderdata.vo.GdApplicationInnovationVO;
import org.sxkj.gd.orderdata.excel.GdApplicationInnovationExcel;
import org.sxkj.gd.orderdata.mapper.GdApplicationInnovationMapper;
import org.sxkj.gd.orderdata.service.IGdApplicationInnovationService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.stereotype.Service;
import org.sxkj.gd.orderdata.entity.GdApplicationInnovationEntity;
import org.sxkj.gd.orderdata.excel.GdApplicationInnovationExcel;
import org.sxkj.gd.orderdata.mapper.GdApplicationInnovationMapper;
import org.sxkj.gd.orderdata.param.GdApplicationInnovationPageParam;
import org.sxkj.gd.orderdata.service.IGdApplicationInnovationService;
import org.sxkj.gd.orderdata.vo.GdApplicationInnovationVO;
import org.sxkj.system.cache.SysCache;
import java.util.List;
@@ -42,9 +42,16 @@
    @Override
    public IPage<GdApplicationInnovationVO> selectGdApplicationInnovationPage(IPage<GdApplicationInnovationVO> page, GdApplicationInnovationPageParam gdApplicationInnovation) {
        if(gdApplicationInnovation.getIsQueryAll()){
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            gdApplicationInnovation.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            if (!gdApplicationInnovation.getIsQueryAll()) {
                List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
                gdApplicationInnovation.setDeptList(deptList);
            }
        } else {
            // 管理员角色下保留原有分页信息,仅清空查询条件
            gdApplicationInnovation.setDeptList(null);
            gdApplicationInnovation.setIsQueryAll(true);
            gdApplicationInnovation.setInnovationStatus(null);
        }
        return page.setRecords(baseMapper.selectGdApplicationInnovationPage(page, gdApplicationInnovation));
    }
@@ -53,7 +60,7 @@
    @Override
    public List<GdApplicationInnovationExcel> exportGdApplicationInnovation(Wrapper<GdApplicationInnovationEntity> queryWrapper) {
        List<GdApplicationInnovationExcel> gdApplicationInnovationList = baseMapper.exportGdApplicationInnovation(queryWrapper);
        //gdApplicationInnovationList.forEach(gdApplicationInnovation -> {
        // gdApplicationInnovationList.forEach(gdApplicationInnovation -> {
        //    gdApplicationInnovation.setTypeName(DictCache.getValue(DictEnum.YES_NO, GdApplicationInnovation.getType()));
        //});
        return gdApplicationInnovationList;
drone-service/drone-gd/src/main/java/org/sxkj/gd/orderdata/service/impl/GdDataEvaluationServiceImpl.java
@@ -29,6 +29,7 @@
import org.springblade.core.mp.base.BaseServiceImpl;
import org.sxkj.system.cache.SysCache;
import java.util.ArrayList;
import java.util.List;
/**
@@ -42,9 +43,16 @@
    @Override
    public IPage<GdDataEvaluationVO> selectGdDataEvaluationPage(IPage<GdDataEvaluationVO> page, GdDataEvaluationPageParam gdDataEvaluation) {
        if(gdDataEvaluation.getIsQueryAll()){
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            gdDataEvaluation.setDeptList(deptList);
        if (!AuthUtil.isAdministrator()) {
            if (!gdDataEvaluation.getIsQueryAll()) {
                List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
                gdDataEvaluation.setDeptList(deptList);
            }
        } else {
            // 管理员角色下保留原有分页信息,仅清空查询条件
            gdDataEvaluation.setDeptList(null);
            gdDataEvaluation.setIsQueryAll(true);
            gdDataEvaluation.setIsResolved(null);
        }
        return page.setRecords(baseMapper.selectGdDataEvaluationPage(page, gdDataEvaluation));
    }
@@ -53,7 +61,7 @@
    @Override
    public List<GdDataEvaluationExcel> exportGdDataEvaluation(Wrapper<GdDataEvaluationEntity> queryWrapper) {
        List<GdDataEvaluationExcel> gdDataEvaluationList = baseMapper.exportGdDataEvaluation(queryWrapper);
        //gdDataEvaluationList.forEach(gdDataEvaluation -> {
        // gdDataEvaluationList.forEach(gdDataEvaluation -> {
        //    gdDataEvaluation.setTypeName(DictCache.getValue(DictEnum.YES_NO, GdDataEvaluation.getType()));
        //});
        return gdDataEvaluationList;
drone-service/drone-gd/src/main/java/org/sxkj/gd/orderdata/service/impl/GdDataObjectionServiceImpl.java
@@ -37,6 +37,7 @@
import org.sxkj.gd.orderdata.wrapper.GdSupplyDemandAuditAttachmentWrapper;
import org.sxkj.system.cache.SysCache;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -54,7 +55,10 @@
    @Override
    public IPage<GdDataObjectionVO> selectGdDataObjectionPage(IPage<GdDataObjectionVO> page, GdDataObjectionPageParam gdDataObjection) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        gdDataObjection.setDeptList(deptList);
        return page.setRecords(baseMapper.selectGdDataObjectionPage(page, gdDataObjection));
    }
drone-service/drone-gd/src/main/java/org/sxkj/gd/orderdata/service/impl/GdSupplyDemandServiceImpl.java
@@ -74,7 +74,11 @@
    @Override
    public IPage<GdSupplyDemandVO> selectGdSupplyDemandPage(IPage<GdSupplyDemandVO> page, GdSupplyDemandPageParam gdSupplyDemand) {
        gdSupplyDemand.setDeptList(SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId())));
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        gdSupplyDemand.setDeptList(deptList);
        return page.setRecords(baseMapper.selectGdSupplyDemandPage(page, gdSupplyDemand));
    }
@@ -88,7 +92,11 @@
        if (Func.isEmpty(gdSupplyDemand)) {
            throw new ServiceException("需求参数不能为空");
        }
        GdSupplyDemandEntity detail = baseMapper.selectGdSupplyDemandDetail(gdSupplyDemand, SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId())));
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        GdSupplyDemandEntity detail = baseMapper.selectGdSupplyDemandDetail(gdSupplyDemand, deptList);
        if (detail == null) {
            throw new ServiceException("未查询到数据");
        }
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdManageDevicePayloadController.java
New file
@@ -0,0 +1,137 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springframework.web.bind.annotation.*;
import org.sxkj.gd.workorder.vo.GdManageDevicePayloadVO;
import org.sxkj.gd.workorder.service.IGdManageDevicePayloadService;
import org.springblade.core.boot.ctrl.BladeController;
import java.util.List;
/**
 * 负载设备表 控制器
 *
 * @author lw
 * @since 2026-02-05
 */
@RestController
@AllArgsConstructor
@RequestMapping("workorder/gdManageDevicePayload")
@Api(value = "负载设备表", tags = "负载设备表接口")
public class GdManageDevicePayloadController extends BladeController {
    private final IGdManageDevicePayloadService gdManageDevicePayloadService;
    /**
     * 负载设备表 详情
     */
    // @GetMapping("/detail")
    // @ApiOperationSupport(order = 1)
    // @ApiOperation(value = "详情", notes = "传入gdManageDevicePayload")
    // public R<GdManageDevicePayloadVO> detail(GdManageDevicePayloadEntity gdManageDevicePayload) {
    //     GdManageDevicePayloadEntity detail = gdManageDevicePayloadService.getOne(Condition.getQueryWrapper(gdManageDevicePayload));
    //     return R.data(GdManageDevicePayloadWrapper.build().entityVO(detail));
    // }
    /**
     * 负载设备表 分页
     */
    // @GetMapping("/list")
    // @ApiOperationSupport(order = 2)
    // @ApiOperation(value = "分页", notes = "传入gdManageDevicePayload")
    // public R<IPage<GdManageDevicePayloadVO>> list(@ApiIgnore @RequestParam Map<String, Object> gdManageDevicePayload, Query query) {
    //     IPage<GdManageDevicePayloadEntity> pages = gdManageDevicePayloadService.page(Condition.getPage(query), Condition.getQueryWrapper(gdManageDevicePayload, GdManageDevicePayloadEntity.class));
    //     return R.data(GdManageDevicePayloadWrapper.build().pageVO(pages));
    // }
    /**
     * 负载设备表 自定义分页
     */
    @GetMapping("/list")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入gdManageDevicePayload")
    public R<List<GdManageDevicePayloadVO>> list(GdManageDevicePayloadVO gdManageDevicePayload, Query query) {
        List<GdManageDevicePayloadVO> lists = gdManageDevicePayloadService.selectGdManageDevicePayloadList();
        return R.data(lists);
    }
    /**
     * 负载设备表 新增
     */
    // @PostMapping("/save")
    // @ApiOperationSupport(order = 4)
    // @ApiOperation(value = "新增", notes = "传入gdManageDevicePayload")
    // public R save(@Valid @RequestBody GdManageDevicePayloadEntity gdManageDevicePayload) {
    //     return R.status(gdManageDevicePayloadService.save(gdManageDevicePayload));
    // }
    /**
     * 负载设备表 修改
     */
    // @PostMapping("/update")
    // @ApiOperationSupport(order = 5)
    // @ApiOperation(value = "修改", notes = "传入gdManageDevicePayload")
    // public R update(@Valid @RequestBody GdManageDevicePayloadEntity gdManageDevicePayload) {
    //     return R.status(gdManageDevicePayloadService.updateById(gdManageDevicePayload));
    // }
    /**
     * 负载设备表 新增或修改
     */
    // @PostMapping("/submit")
    // @ApiOperationSupport(order = 6)
    // @ApiOperation(value = "新增或修改", notes = "传入gdManageDevicePayload")
    // public R submit(@Valid @RequestBody GdManageDevicePayloadEntity gdManageDevicePayload) {
    //     return R.status(gdManageDevicePayloadService.saveOrUpdate(gdManageDevicePayload));
    // }
    /**
     * 负载设备表 删除
     */
    // @PostMapping("/remove")
    // @ApiOperationSupport(order = 7)
    // @ApiOperation(value = "逻辑删除", notes = "传入ids")
    // public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
    //     return R.status(gdManageDevicePayloadService.deleteLogic(Func.toLongList(ids)));
    // }
    /**
     * 导出数据
     */
    // @GetMapping("/export-gdManageDevicePayload")
    // @ApiOperationSupport(order = 9)
    // @ApiOperation(value = "导出数据", notes = "传入gdManageDevicePayload")
    // public void exportGdManageDevicePayload(@ApiIgnore @RequestParam Map<String, Object> gdManageDevicePayload, BladeUser bladeUser, HttpServletResponse response) {
    //     QueryWrapper<GdManageDevicePayloadEntity> queryWrapper = Condition.getQueryWrapper(gdManageDevicePayload, GdManageDevicePayloadEntity.class);
    //     //if (!AuthUtil.isAdministrator()) {
    //     //    queryWrapper.lambda().eq(GdManageDevicePayload::getTenantId, bladeUser.getTenantId());
    //     //}
    //     queryWrapper.lambda().eq(GdManageDevicePayloadEntity::getIsDeleted, BladeConstant.DB_NOT_DELETED);
    //     List<GdManageDevicePayloadExcel> list = gdManageDevicePayloadService.exportGdManageDevicePayload(queryWrapper);
    //     ExcelUtil.export(response, "负载设备表数据" + DateUtil.time(), "负载设备表数据表", list, GdManageDevicePayloadExcel.class);
    // }
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdPatrolTaskController.java
@@ -162,7 +162,7 @@
        GdPatrolTaskEntity auditParam = new GdPatrolTaskEntity();
        auditParam.setId(param.getId());
        auditParam.setTaskStatus(PatrolTaskStatusEnum.PENDING_ACCEPTANCE.getValue());
        return R.status(gdPatrolTaskService.updateById(auditParam));
        return R.status(gdPatrolTaskService.updatePatrolTaskById(auditParam));
    }
    /**
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdTaskResultController.java
@@ -142,7 +142,7 @@
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "批量新增", notes = "传入gdTaskResult")
    public R batchSaveExternal(@Valid @RequestBody List<GdTaskResultDTO> gdTaskResults) {
        return R.status(gdTaskResultService.saveBatch(GdTaskResultWrapper.build().listEntity(gdTaskResults)));
        return R.status(gdTaskResultService.saveBatchTaskResult(GdTaskResultWrapper.build().listEntity(gdTaskResults)));
    }
    /**
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdManageDevicePayloadDTO.java
New file
@@ -0,0 +1,34 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.dto;
import org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 负载设备表 数据传输对象实体类
 *
 * @author lw
 * @since 2026-02-05
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class GdManageDevicePayloadDTO extends GdManageDevicePayloadEntity {
    private static final long serialVersionUID = 1L;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdXingtuPayloadListDTO.java
New file
@@ -0,0 +1,23 @@
package org.sxkj.gd.workorder.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class GdXingtuPayloadListDTO {
    @ApiModelProperty("id")
    private String id;
    @ApiModelProperty("负载名称")
    private String name;
    @ApiModelProperty("负载类型")
    private String type;
    @ApiModelProperty("负载序列号")
    private String snCode;
    @ApiModelProperty("设备序列号")
    private String pilotSnCode;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/dto/GdXingtuPilotListDTO.java
@@ -20,6 +20,7 @@
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * 星图接口-设备列表(无人机)数据对象
@@ -83,6 +84,9 @@
    @ApiModelProperty("负载类型")
    private String loadType;
    @ApiModelProperty("负载设备集合")
    private List<GdXingtuPayloadListDTO> loadList;
    @ApiModelProperty("是否喷涂")
    private Integer isPainting;
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdManageDevicePayloadEntity.java
New file
@@ -0,0 +1,64 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
/**
 * 负载设备表 实体类
 *
 * @author lw
 * @since 2026-02-05
 */
@Data
@TableName(value = "ja_gd_manage_device_payload" )
@ApiModel(value = "GdManageDevicePayload对象", description = "负载设备表")
@EqualsAndHashCode(callSuper = true)
public class GdManageDevicePayloadEntity extends BaseEntity {
    /**
     * 负载名称
     */
    @ApiModelProperty(value = "负载名称")
    private String name;
    /**
     * 负载类型
     */
    @ApiModelProperty(value = "负载类型")
    private String type;
    /**
     * 负载序列号
     */
    @ApiModelProperty(value = "负载序列号")
    private String snCode;
    /**
     * 飞行员序列号
     */
    @ApiModelProperty(value = "飞行员序列号")
    private String pilotSnCode;
    /**
     * 区域编码
     */
    @ApiModelProperty(value = "区域编码")
    private String areaCode;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/enums/PatrolTaskStatusEnum.java
@@ -2,7 +2,6 @@
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/excel/GdManageDevicePayloadExcel.java
New file
@@ -0,0 +1,80 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.excel;
import lombok.Data;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import java.io.Serializable;
/**
 * 负载设备表 Excel实体类
 *
 * @author lw
 * @since 2026-02-05
 */
@Data
@ColumnWidth(25)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class GdManageDevicePayloadExcel implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 负载名称
     */
    @ColumnWidth(20)
    @ExcelProperty("负载名称")
    private String name;
    /**
     * 负载类型
     */
    @ColumnWidth(20)
    @ExcelProperty("负载类型")
    private String type;
    /**
     * 负载序列号
     */
    @ColumnWidth(20)
    @ExcelProperty("负载序列号")
    private String snCode;
    /**
     * 飞行员序列号
     */
    @ColumnWidth(20)
    @ExcelProperty("飞行员序列号")
    private String pilotSnCode;
    /**
     * 区域编码
     */
    @ColumnWidth(20)
    @ExcelProperty("区域编码")
    private String areaCode;
    /**
     * 删除标志(0存在 1删除)
     */
    @ColumnWidth(20)
    @ExcelProperty("删除标志(0存在 1删除)")
    private Byte isDeleted;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdManageDeviceMapper.xml
@@ -27,8 +27,8 @@
                blade_dept bd on md.create_dept = bd.id
        <where>
                and md.is_deleted = 0
            <if test="param2.deviceName != null and param2.deviceName != ''">
                and md.nickname like concat('%',#{param2.deviceName},'%')
            <if test="param2.nickname != null and param2.nickname != ''">
                and md.nickname like concat('%',#{param2.nickname},'%')
            </if>
            <if test="param2.deptId != null">
                and md.create_dept = #{param2.deptId}
@@ -36,6 +36,13 @@
            <if test="param2.location != null and param2.location != ''">
                and md.location like concat('%',#{param2.location},'%')
            </if>
            <if test="param2.modeCode != null and param2.modeCode != ''">
                and md.mode_code = #{param2.modeCode}
            </if>
            <if test="param2.deviceType != null and param2.deviceType != ''">
                and md.device_type = #{param2.deviceType}
            </if>
        </where>
    </select>
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdManageDevicePayloadMapper.java
New file
@@ -0,0 +1,52 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.mapper;
import org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity;
import org.sxkj.gd.workorder.vo.GdManageDevicePayloadVO;
import org.sxkj.gd.workorder.excel.GdManageDevicePayloadExcel;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * 负载设备表 Mapper 接口
 *
 * @author lw
 * @since 2026-02-05
 */
public interface GdManageDevicePayloadMapper extends BaseMapper<GdManageDevicePayloadEntity> {
    /**
     * 自定义分页
     *
     * @return
     */
    List<GdManageDevicePayloadVO> selectGdManageDevicePayloadPage();
    /**
     * 获取导出数据
     *
     * @param queryWrapper
     * @return
     */
    List<GdManageDevicePayloadExcel> exportGdManageDevicePayload(@Param("ew") Wrapper<GdManageDevicePayloadEntity> queryWrapper);
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdManageDevicePayloadMapper.xml
New file
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sxkj.gd.workorder.mapper.GdManageDevicePayloadMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="gdManageDevicePayloadResultMap" type="org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="type" property="type"/>
        <result column="sn_code" property="snCode"/>
        <result column="pilot_sn_code" property="pilotSnCode"/>
        <result column="area_code" property="areaCode"/>
        <result column="create_user" property="createUser"/>
        <result column="create_dept" property="createDept"/>
        <result column="create_time" property="createTime"/>
        <result column="update_user" property="updateUser"/>
        <result column="update_time" property="updateTime"/>
        <result column="status" property="status"/>
        <result column="is_deleted" property="isDeleted"/>
    </resultMap>
    <select id="selectGdManageDevicePayloadPage" resultMap="gdManageDevicePayloadResultMap">
        select
            *
        from
            ja_gd_manage_device_payload
        where is_deleted = 0
        group by name
    </select>
    <select id="exportGdManageDevicePayload" resultType="org.sxkj.gd.workorder.excel.GdManageDevicePayloadExcel">
        SELECT * FROM ja_gd_manage_device_payload ${ew.customSqlSegment}
    </select>
</mapper>
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.java
@@ -74,4 +74,12 @@
     * @return
     */
    GdPatrolTaskVO getPatrolTaskDetail(GdPatrolTaskEntity gdPatrolTaskEntity);
    /**
     *
     * @param id
     * @param code
     * @return
     */
    GdWorkOrderEntity getWorkOrderIdById(Long id, String code);
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.xml
@@ -34,8 +34,8 @@
            pt.*,
            md.nickname as device_name,
            wo.work_order_name,
            IFNULL(tr.result_count, 0) as result_count,
            IFNULL(tr.issue_event_count, 0) as issue_event_count
            COALESCE(tr.result_count, 0) as result_count,
            COALESCE(tr.issue_event_count, 0) as issue_event_count
        from
            ja_gd_patrol_task pt
        left join
@@ -55,6 +55,7 @@
                patrol_task_id
            ) tr on tr.patrol_task_id = pt.id
        <where>
                pt.is_deleted = 0
            <if test="param2.workOrderId != null and param2.workOrderId != ''">
                and pt.work_order_id = #{param2.workOrderId}
            </if>
@@ -114,6 +115,15 @@
        WHERE pt.id = #{id}
    </select>
    <select id="getWorkOrderIdById" resultType="org.sxkj.gd.workorder.entity.GdWorkOrderEntity">
        SELECT
            *
        FROM
            ja_gd_work_order
        WHERE id = #{id}
          AND work_order_status = #{code}
    </select>
    <!-- 自定义更新工单状态语句 -->
    <update id="updateWorkOrderById" parameterType="org.sxkj.gd.workorder.entity.GdWorkOrderEntity">
        UPDATE ja_gd_work_order
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdTaskResultMapper.xml
@@ -45,7 +45,7 @@
    <select id="selectGdTaskResultListByPatrolTaskId" resultMap="gdTaskResultResultMap">
        SELECT tr.*,
               IFNULL(bu.real_name, bu.name) as distribute_user_name,
               COALESCE(bu.real_name, bu.name) as distribute_user_name,
               bd.dept_name                  as distribute_dept_name
        FROM ja_gd_task_result tr
                 LEFT JOIN (SELECT *
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/GdManageDevicePageParam.java
@@ -58,5 +58,10 @@
    @ApiModelProperty(value = "设备类型(0机场,1无人机)")
    private String deviceType;
    /**
     * 模式编号
     */
    @ApiModelProperty(value = "状态 0 在线 1离线")
    private String modeCode;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/scheduler/GdXingtuDeviceScheduler.java
@@ -17,6 +17,7 @@
    private final IGdManageDeviceService gdManageDeviceService;
    @Scheduled(cron = "0 0 0 * * ?") // 每天凌晨0点执行
    // @Scheduled(cron = "*/10 * * * * ?")
    public void syncXingtuDevice() {
        try {
            int total = gdManageDeviceService.syncXingtuDevice();
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdManageDevicePayloadService.java
New file
@@ -0,0 +1,52 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity;
import org.sxkj.gd.workorder.vo.GdManageDevicePayloadVO;
import org.sxkj.gd.workorder.excel.GdManageDevicePayloadExcel;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService;
import java.util.List;
/**
 * 负载设备表 服务类
 *
 * @author lw
 * @since 2026-02-05
 */
public interface IGdManageDevicePayloadService extends BaseService<GdManageDevicePayloadEntity> {
    /**
     * 自定义分页
     *
     * @param page
     * @param gdManageDevicePayload
     * @return
     */
    List<GdManageDevicePayloadVO> selectGdManageDevicePayloadList();
    /**
     * 导出数据
     *
     * @param queryWrapper
     * @return
     */
    List<GdManageDevicePayloadExcel> exportGdManageDevicePayload(Wrapper<GdManageDevicePayloadEntity> queryWrapper);
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdPatrolTaskService.java
@@ -96,4 +96,11 @@
     * @return
     */
    GdPatrolTaskVO getPatrolTaskDetail(GdPatrolTaskEntity gdPatrolTaskEntity);
    /**
     *
     * @param auditParam
     * @return
     */
    boolean updatePatrolTaskById(GdPatrolTaskEntity auditParam);
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdTaskResultService.java
@@ -51,4 +51,10 @@
     */
    List<GdTaskResultExcel> exportGdTaskResult(Wrapper<GdTaskResultEntity> queryWrapper);
    /**
     *
     * @param gdTaskResultEntities
     * @return
     */
    boolean saveBatchTaskResult(List<GdTaskResultEntity> gdTaskResultEntities);
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDevicePayloadServiceImpl.java
New file
@@ -0,0 +1,54 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.service.impl;
import org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity;
import org.sxkj.gd.workorder.vo.GdManageDevicePayloadVO;
import org.sxkj.gd.workorder.excel.GdManageDevicePayloadExcel;
import org.sxkj.gd.workorder.mapper.GdManageDevicePayloadMapper;
import org.sxkj.gd.workorder.service.IGdManageDevicePayloadService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
import java.util.List;
/**
 * 负载设备表 服务实现类
 *
 * @author lw
 * @since 2026-02-05
 */
@Service
public class GdManageDevicePayloadServiceImpl extends BaseServiceImpl<GdManageDevicePayloadMapper, GdManageDevicePayloadEntity> implements IGdManageDevicePayloadService {
    @Override
    public List<GdManageDevicePayloadVO> selectGdManageDevicePayloadList() {
        return  baseMapper.selectGdManageDevicePayloadPage();
    }
    @Override
    public List<GdManageDevicePayloadExcel> exportGdManageDevicePayload(Wrapper<GdManageDevicePayloadEntity> queryWrapper) {
        List<GdManageDevicePayloadExcel> gdManageDevicePayloadList = baseMapper.exportGdManageDevicePayload(queryWrapper);
        //gdManageDevicePayloadList.forEach(gdManageDevicePayload -> {
        //    gdManageDevicePayload.setTypeName(DictCache.getValue(DictEnum.YES_NO, GdManageDevicePayload.getType()));
        //});
        return gdManageDevicePayloadList;
    }
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdManageDeviceServiceImpl.java
@@ -24,9 +24,12 @@
import org.sxkj.gd.utils.GdGeoAddressUtil;
import org.sxkj.gd.utils.GeomUtils;
import org.sxkj.gd.workorder.dto.GdXingtuAirportListDTO;
import org.sxkj.gd.workorder.dto.GdXingtuPayloadListDTO;
import org.sxkj.gd.workorder.dto.GdXingtuPilotListDTO;
import org.sxkj.gd.workorder.entity.GdManageDeviceEntity;
import org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity;
import org.sxkj.gd.workorder.param.GdManageDevicePageParam;
import org.sxkj.gd.workorder.service.IGdManageDevicePayloadService;
import org.sxkj.gd.workorder.vo.GdManageDeviceVO;
import org.sxkj.gd.workorder.excel.GdManageDeviceExcel;
import org.sxkj.gd.workorder.mapper.GdManageDeviceMapper;
@@ -41,9 +44,8 @@
import org.springblade.core.tool.utils.StringUtil;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 设备信息 服务实现类
@@ -57,6 +59,7 @@
public class GdManageDeviceServiceImpl extends BaseServiceImpl<GdManageDeviceMapper, GdManageDeviceEntity> implements IGdManageDeviceService {
    private final JianXingtuApiService jianXingtuApiService;
    private final IGdManageDevicePayloadService iGdManageDevicePayloadService;
    @Override
    public IPage<GdManageDeviceVO> selectGdManageDevicePage(IPage<GdManageDeviceVO> page, GdManageDevicePageParam gdManageDevice) {
@@ -109,7 +112,7 @@
        total += syncAirportDevices();
        // 1.同步无人机设备
        total += syncPilotDevices();
        log.info("更新或新增设备"+total);
        log.info("更新或新增设备" + total);
        return total;
    }
@@ -131,6 +134,9 @@
                continue;
            }
            if (saveOrUpdateByAirportId(entity)) {
                // 同步负载设备
                List<GdXingtuPayloadListDTO> loadList = item.getLoadList();
                syncPayloadDevices(loadList);
                count++;
            }
        }
@@ -159,6 +165,102 @@
            }
        }
        return count;
    }
    /**
     * 同步负载设备
     *
     * @param loadList 负载设备列表
     */
    private void syncPayloadDevices(List<GdXingtuPayloadListDTO> loadList) throws Exception {
        // 1. 收集所有负载设备的飞行员序列号,用于后续查询和删除操作
        Set<String> allPilotSnCodes = new HashSet<>();
        if (loadList != null && !loadList.isEmpty()) {
            for (GdXingtuPayloadListDTO load : loadList) {
                if (load.getPilotSnCode() != null) {
                    allPilotSnCodes.add(load.getPilotSnCode());
                }
            }
        }
        // 2. 获取当前数据库中这些飞行员序列号对应的所有负载设备
        List<GdManageDevicePayloadEntity> existingPayloads = new ArrayList<>();
        if (!allPilotSnCodes.isEmpty()) {
            existingPayloads = iGdManageDevicePayloadService.list(
                Wrappers.<GdManageDevicePayloadEntity>lambdaQuery().in(GdManageDevicePayloadEntity::getPilotSnCode, allPilotSnCodes)
            );
        }
        // 3. 创建现有负载设备的序列号映射,用于快速查找
        Map<String, GdManageDevicePayloadEntity> existingPayloadMap = new HashMap<>();
        for (GdManageDevicePayloadEntity payload : existingPayloads) {
            if (payload.getPilotSnCode() != null && payload.getSnCode() != null) {
                existingPayloadMap.put(payload.getPilotSnCode() + "_" + payload.getSnCode() + "_" + payload.getName(), payload);
            }
        }
        // 4. 处理负载设备列表
        if (loadList != null && !loadList.isEmpty()) {
            List<GdManageDevicePayloadEntity> toSaveOrUpdate = new ArrayList<>();
            Set<String> currentPayloadKeys = new HashSet<>();
            // 对负载设备列表进行去重处理,确保每个负载设备只被处理一次
            Map<String, GdXingtuPayloadListDTO> uniqueLoadMap = new HashMap<>();
            for (GdXingtuPayloadListDTO load : loadList) {
                if (load.getSnCode() != null && load.getPilotSnCode() != null) {
                    String payloadKey = load.getPilotSnCode() + "_" + load.getSnCode() + "_" + load.getName();
                    uniqueLoadMap.put(payloadKey, load);
                }
            }
            // 处理去重后的负载设备列表
            for (GdXingtuPayloadListDTO load : uniqueLoadMap.values()) {
                String snCode = load.getSnCode();
                String pilotSnCode1 = load.getPilotSnCode();
                String name = load.getName();
                String payloadKey = pilotSnCode1 + "_" + snCode + "_" + name;
                currentPayloadKeys.add(payloadKey);
                // 检查是否已存在
                GdManageDevicePayloadEntity existing = existingPayloadMap.remove(payloadKey);
                if (existing != null) {
                    // 更新现有负载
                    existing.setName(load.getName());
                    existing.setType(load.getType());
                    toSaveOrUpdate.add(existing);
                } else {
                    // 新增负载
                    GdManageDevicePayloadEntity newPayload = new GdManageDevicePayloadEntity();
                    newPayload.setName(load.getName());
                    newPayload.setType(load.getType());
                    newPayload.setSnCode(snCode);
                    newPayload.setPilotSnCode(pilotSnCode1);
                    // 可以根据需要设置区域编码等其他字段
                    toSaveOrUpdate.add(newPayload);
                }
            }
            // 4. 批量保存或更新负载设备
            if (!toSaveOrUpdate.isEmpty()) {
                iGdManageDevicePayloadService.saveOrUpdateBatch(toSaveOrUpdate);
            }
            // 5. 删除数据库中存在但负载列表中不存在的负载设备
            if (!existingPayloadMap.isEmpty()) {
                List<Long> toDeleteIds = existingPayloadMap.values().stream()
                    .map(GdManageDevicePayloadEntity::getId)
                    .collect(Collectors.toList());
                iGdManageDevicePayloadService.removeByIds(toDeleteIds);
            }
        } else {
            // 如果负载列表为空,删除该飞行员序列号对应的所有负载设备
            if (!existingPayloads.isEmpty()) {
                List<Long> toDeleteIds = existingPayloads.stream()
                    .map(GdManageDevicePayloadEntity::getId)
                    .collect(Collectors.toList());
                iGdManageDevicePayloadService.removeByIds(toDeleteIds);
            }
        }
    }
    /**
@@ -193,6 +295,7 @@
                entity.setLongitude(parent.getLongitude());
                entity.setLatitude(parent.getLatitude());
                entity.setHeight(parent.getHeight());
                entity.setModeCode(Long.valueOf(parent.getStatus()));
            }
        }
        return saveOrUpdateDevice(entity);
@@ -221,6 +324,17 @@
        entity.setInsureExpiredTime(parseInsuranceDate(item.getInsuranceInfo()));
        entity.setAreaCode(extractAreaCode(item.getRegionCode()));
        entity.setIsWithDock(item.getIsWithDock());
        entity.setDevicePayload(
            Optional.ofNullable(item.getLoadList())
                .orElse(Collections.emptyList())
                .stream()
                .filter(Objects::nonNull)
                .map(load -> load.getName())
                .filter(Objects::nonNull)
                .distinct()  // 添加去重逻辑
                .collect(Collectors.joining(","))
        );
        return entity;
    }
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdOperationalRevenueServiceImpl.java
@@ -14,6 +14,7 @@
import org.sxkj.system.cache.SysCache;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
@@ -78,8 +79,10 @@
            queryWrapper.like(GdOperationalRevenue::getNickName, nickName);
        }
        // 创建部门
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        queryWrapper.in(GdOperationalRevenue::getCreateDept, deptList);
         if (!AuthUtil.isAdministrator()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            queryWrapper.in(GdOperationalRevenue::getCreateDept, deptList);
        }
        // 按创建时间倒序
        queryWrapper.orderByDesc(GdOperationalRevenue::getCreateTime);
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java
@@ -19,6 +19,7 @@
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.oss.model.BladeFile;
@@ -32,6 +33,7 @@
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.sxkj.common.constant.WordOrderConstant;
import org.sxkj.common.utils.OrderNumUtils;
import org.sxkj.gd.common.GdMultipartFileUtil;
@@ -64,8 +66,8 @@
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 巡查任务表 服务实现类
@@ -73,14 +75,12 @@
 * @author lw
 * @since 2026-01-14
 */
@Slf4j
@Service
public class GdPatrolTaskServiceImpl extends BaseServiceImpl<GdPatrolTaskMapper, GdPatrolTaskEntity> implements IGdPatrolTaskService {
    @Autowired
    private IGdWorkOrderFlowService gdWorkOrderFlowService;
    // @Autowired
    // private IGdWorkOrderService gdWorkOrderService;
    @Autowired
    private ISysClient sysClient;
    @Autowired
@@ -96,7 +96,10 @@
    @Override
    public IPage<GdPatrolTaskVO> selectGdPatrolTaskPage(IPage<GdPatrolTaskVO> page, GdPatrolTaskPageParam gdPatrolTask) {
        List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        List<Long> deptList = new ArrayList<>();
        if (!AuthUtil.isAdministrator()) {
            deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
        }
        gdPatrolTask.setDeptList(deptList);
        List<GdPatrolTaskVO> gdPatrolTaskVOS = baseMapper.selectGdPatrolTaskPage(page, gdPatrolTask);
        return page.setRecords(gdPatrolTaskVOS);
@@ -228,9 +231,8 @@
                .eq(GdPatrolTaskEntity::getWorkOrderId, task.getWorkOrderId()));
            // 检查是否所有子任务都审核成功(除了被撤回和验收拒绝的)
            boolean allSubTasksAudited = checkAllSubTasksStatus(subTasks, PatrolTaskStatusEnum.AUDIT_PASSED);
            // 示例:如果所有子任务都审核成功,可以更新工单状态为已完成
            if (allSubTasksAudited) {
            boolean allSubTasksAudited = isAllSubTasksAudited(subTasks, task, PatrolTaskStatusEnum.PENDING_AUDIT);
            if (!allSubTasksAudited) {
                // 执行工单状态更新逻辑
                return updateWorkOrderStatusAndFlow(task.getWorkOrderId(),
                    WorkOrderStatusEnum.EXECUTING_TO_BE_COMPLETED);
@@ -263,9 +265,9 @@
                .eq(GdPatrolTaskEntity::getWorkOrderId, task.getWorkOrderId()));
            // 检查是否所有子任务都验收通过(除了被撤回和验收拒绝的)
            boolean allSubTasksAudited = checkAllSubTasksStatus(subTasks, PatrolTaskStatusEnum.ACCEPTANCE_PASSED);
            boolean allSubTasksAudited = isAllSubTasksAudited(subTasks, task, PatrolTaskStatusEnum.ACCEPTANCE_PASSED);
            // 这里可以根据allSubTasksAudited的结果执行后续逻辑,比如更新工单状态等
            if (allSubTasksAudited) {
            if (!allSubTasksAudited) {
                // 1.验收通过,生成报告
                asyncExportPatrolReport(task.getId());
                // 2.执行工单状态更新逻辑
@@ -276,28 +278,35 @@
        return b;
    }
    /**
     * 检查是否所有子任务都达到指定状态(除了被撤回和验收拒绝的)
     *
     * @param subTasks     子任务列表
     * @param targetStatus 目标状态枚举
     * @return 是否所有子任务都达到指定状态
     * @param subTasks
     * @param task
     * @param pendingAudit
     * @return
     */
    private boolean checkAllSubTasksStatus(List<GdPatrolTaskEntity> subTasks, PatrolTaskStatusEnum targetStatus) {
        for (GdPatrolTaskEntity subTask : subTasks) {
            String taskStatus = subTask.getTaskStatus();
            PatrolTaskStatusEnum statusEnum = PatrolTaskStatusEnum.getByValue(taskStatus);
    private static boolean isAllSubTasksAudited(List<GdPatrolTaskEntity> subTasks, GdPatrolTaskEntity task, PatrolTaskStatusEnum pendingAudit) {
        List<String> validStatusList = subTasks.stream()
            // 过滤掉当前任务本身
            .filter(subTask -> !subTask.getId().equals(task.getId()))
            .map(GdPatrolTaskEntity::getTaskStatus)
            .filter(Objects::nonNull)
            // 过滤掉撤回或验收拒绝的任务
            .filter(status -> !status.equals(PatrolTaskStatusEnum.WITHDRAWN.getValue()) &&
                !status.equals(PatrolTaskStatusEnum.REJECTED_ACCEPTANCE.getValue()))
            .collect(Collectors.toList());
            // 如果任务状态不是目标状态,且不是被撤回和验收拒绝的,则返回false
            if (statusEnum != targetStatus &&
                statusEnum != PatrolTaskStatusEnum.WITHDRAWN &&
                statusEnum != PatrolTaskStatusEnum.REJECTED_ACCEPTANCE) {
                return false;
            }
        // 如果过滤后没有有效任务,直接返回false
        if (validStatusList.isEmpty()) {
            return false;
        }
        return true;
        // 判断是否有小于待审核的任务
        boolean allSubTasksAudited = validStatusList.stream()
            .anyMatch(status -> status.compareTo(pendingAudit.getValue()) < 0);
        return allSubTasksAudited;
    }
    /**
     * 更新工单状态并保存流转记录
@@ -474,7 +483,6 @@
        }
        return true;
    }
    /**
@@ -668,20 +676,6 @@
        }
        if (StringUtil.isNotBlank(gdPatrolTaskVO.getAirportId())) {
            param.setAirportId(gdPatrolTaskVO.getAirportId());
            // GdManageDeviceEntity device = null;
            // if (StringUtils.isNumeric(taskEntity.getAirportId())) {
            //     device = gdManageDeviceService.getById(Long.valueOf(taskEntity.getDeviceId()));
            // }
            // if (device == null) {
            //     device = gdManageDeviceService.lambdaQuery()
            //         .eq(GdManageDeviceEntity::getAirportId, taskEntity.getDeviceId())
            //         .one();
            // }
            // if (device != null && StringUtil.isNotBlank(device.getAirportId())) {
            //     param.setAirportId(device.getAirportId());
            // } else {
            //     param.setAirportId(taskEntity.getAirportId());
            // }
        }
        param.setStatus("待执行");
        param.setTaskType("航线飞行");
@@ -692,4 +686,49 @@
    public GdPatrolTaskVO getPatrolTaskDetail(GdPatrolTaskEntity gdPatrolTaskEntity) {
        return baseMapper.getPatrolTaskDetail(gdPatrolTaskEntity);
    }
    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务注解,确保数据一致性
    public boolean updatePatrolTaskById(GdPatrolTaskEntity auditParam) {
        // 1. 更新当前任务状态
        boolean updateResult = updateById(auditParam);
        if (!updateResult) {
            log.warn("更新任务失败,任务ID: {}");
            return false;
        }
        // 2. 获取当前任务实体(优先使用 auditParam 中的数据,避免重复查询)
        GdPatrolTaskEntity patrolTaskEntity = Optional.ofNullable(getById(auditParam.getId()))
            .orElseThrow(() -> new RuntimeException("任务不存在,任务ID: " + auditParam.getId()));
        // 3. 保存巡查工单流转
        saveWorkOrderFlow(patrolTaskEntity.getWorkOrderId(), PatrolTaskStatusEnum.PENDING_ACCEPTANCE, null, null);
        // 4. 查询同一个工单下的所有子任务
        List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery()
            .eq(GdPatrolTaskEntity::getWorkOrderId, patrolTaskEntity.getWorkOrderId()));
        // 5. 判空处理,防止 NullPointerException
        if (CollectionUtils.isEmpty(subTasks)) {
            log.info("工单ID {} 下无子任务", patrolTaskEntity.getWorkOrderId());
            return true;
        }
        // 6. 判断是否有小于待验收的工单(统一使用枚举值比较)
        boolean hasLessThanPendingAcceptance = subTasks.stream()
            .map(GdPatrolTaskEntity::getTaskStatus)
            .filter(Objects::nonNull)
            .anyMatch(status -> status.compareTo(PatrolTaskStatusEnum.PENDING_ACCEPTANCE.getValue()) < 0);
        // 7. 根据判断结果决定是否更新工单状态
        if (!hasLessThanPendingAcceptance) {
            updateWorkOrderStatusAndFlow(patrolTaskEntity.getWorkOrderId(), WorkOrderStatusEnum.COMPLETED_TO_BE_INSPECTED);
            log.info("工单ID {} 下所有子任务均已达到待验收状态,更新工单状态为完成待验", patrolTaskEntity.getWorkOrderId());
        } else {
            log.warn("工单ID {} 下存在未达待验收状态的子任务", patrolTaskEntity.getWorkOrderId());
        }
        return updateResult;
    }
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdTaskResultServiceImpl.java
@@ -21,6 +21,7 @@
import org.sxkj.gd.workorder.excel.GdTaskResultExcel;
import org.sxkj.gd.workorder.mapper.GdTaskResultMapper;
import org.sxkj.gd.workorder.service.IGdTaskResultService;
import org.sxkj.common.utils.HeaderUtils;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -43,7 +44,11 @@
    @Override
    public List<GdTaskResultVO> listByPatrolTaskId(Long patrolTaskId) {
        return baseMapper.selectGdTaskResultListByPatrolTaskId(patrolTaskId);
        List<GdTaskResultVO> gdTaskResultVOS = baseMapper.selectGdTaskResultListByPatrolTaskId(patrolTaskId);
        for (GdTaskResultVO gdTaskResultVO : gdTaskResultVOS) {
            gdTaskResultVO.setResultUrl(unescapeUrl(gdTaskResultVO.getResultUrl()));
        }
        return gdTaskResultVOS;
    }
@@ -56,4 +61,41 @@
        return gdTaskResultList;
    }
    @Override
    public boolean saveBatchTaskResult(List<GdTaskResultEntity> gdTaskResultEntities) {
        gdTaskResultEntities.forEach(gdTaskResult -> {
            // 使用HeaderUtils处理区域代码
            String processedAreaCode = HeaderUtils.processAreaCode(gdTaskResult.getAreaCode());
            gdTaskResult.setAreaCode(processedAreaCode);
        });
        // 执行批量保存并返回结果
        return saveBatch(gdTaskResultEntities);
    }
    /**
     * 将URL中的HTML/XML转义字符还原为原始字符
     * 主要处理 &amp; 转换为 &
     *
     * @param url 包含转义字符的URL
     * @return 还原后的URL
     */
    public static String unescapeUrl(String url) {
        if (url == null || url.isEmpty()) {
            return url;
        }
        // 按照优先级顺序进行替换,避免重复替换问题
        String result = url;
        // 处理常见的HTML/XML转义字符
        result = result.replace("&amp;", "&");     // &符号
        result = result.replace("&lt;", "<");      // 小于号
        result = result.replace("&gt;", ">");      // 大于号
        result = result.replace("&quot;", "\"");   // 双引号
        result = result.replace("&#39;", "'");     // 单引号
        result = result.replace("&apos;", "'");    // 单引号
        return result;
    }
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdWorkOrderFlowServiceImpl.java
@@ -136,18 +136,6 @@
    private WorkOrderStageVO buildStage(String stageName, List<String> statusNames, List<GdWorkOrderFlowEntity> actualFlows, String flowStatus, String currentStageCode) {
        List<WorkOrderStatusDetailVO> statuses = new ArrayList<>();
        // 检查该阶段是否在当前阶段之后
        // 注意:即使流程回退,之前到达过的阶段仍然需要显示其记录
        // 而是让所有阶段都能显示其已到达的状态,只对未到达的状态进行处理
        // boolean isStageAfterCurrent = false;
        // try {
        //     int stageCode = Integer.parseInt(flowStatus);
        //     int currentCode = Integer.parseInt(currentStageCode);
        //     isStageAfterCurrent = stageCode > currentCode;
        // } catch (NumberFormatException e) {
        //     // 如果转换失败,默认不视为在当前阶段之后
        // }
        // 临时列表,用于收集所有状态详情
        List<WorkOrderStatusDetailVO> tempStatuses = new ArrayList<>();
@@ -169,7 +157,6 @@
                    }
                });
                // 为每个排序后的流程记录创建状态详情
                // 无论阶段是否在当前阶段之后,只要有匹配的流程记录,就标记为已到达
                for (GdWorkOrderFlowEntity matchingFlow : matchingFlows) {
                    tempStatuses.add(new WorkOrderStatusDetailVO(
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdWorkOrderServiceImpl.java
@@ -32,6 +32,7 @@
import org.sxkj.gd.workorder.vo.GdWorkOrderVO;
import org.sxkj.system.cache.SysCache;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -57,7 +58,10 @@
    @Override
    public IPage<GdWorkOrderVO> selectGdWorkOrderPage(IPage<GdWorkOrderVO> page, WorkOrderPageParam gdWorkOrder) {
        if (gdWorkOrder.getIsQueryAll()) {
            List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            List<Long> deptList = new ArrayList<>();
            if (!AuthUtil.isAdministrator()) {
                deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
            }
            gdWorkOrder.setDeptList(deptList);
        }
        return page.setRecords(baseMapper.selectGdWorkOrderPage(page, gdWorkOrder));
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdManageDevicePayloadVO.java
New file
@@ -0,0 +1,50 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.vo;
import io.swagger.annotations.ApiModelProperty;
import org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity;
import org.springblade.core.tool.node.INode;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 负载设备表 视图实体类
 *
 * @author lw
 * @since 2026-02-05
 */
@Data
public class GdManageDevicePayloadVO {
    private static final long serialVersionUID = 1L;
    /**
     * 负载名称
     */
    @ApiModelProperty(value = "负载名称")
    private String name;
    /**
     * 负载类型
     */
    @ApiModelProperty(value = "负载类型")
    private String type;
    /**
     * 负载序列号
     */
    @ApiModelProperty(value = "负载序列号")
    private String snCode;
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/wrapper/GdManageDevicePayloadWrapper.java
New file
@@ -0,0 +1,50 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.sxkj.gd.workorder.wrapper;
import org.springblade.core.mp.support.BaseEntityWrapper;
import org.springblade.core.tool.utils.BeanUtil;
import org.sxkj.gd.workorder.entity.GdManageDevicePayloadEntity;
import org.sxkj.gd.workorder.vo.GdManageDevicePayloadVO;
import java.util.Objects;
/**
 * 负载设备表 包装类,返回视图层所需的字段
 *
 * @author lw
 * @since 2026-02-05
 */
public class GdManageDevicePayloadWrapper extends BaseEntityWrapper<GdManageDevicePayloadEntity, GdManageDevicePayloadVO>  {
    public static GdManageDevicePayloadWrapper build() {
        return new GdManageDevicePayloadWrapper();
     }
    @Override
    public GdManageDevicePayloadVO entityVO(GdManageDevicePayloadEntity gdManageDevicePayload) {
        GdManageDevicePayloadVO gdManageDevicePayloadVO = Objects.requireNonNull(BeanUtil.copy(gdManageDevicePayload, GdManageDevicePayloadVO.class));
        //User createUser = UserCache.getUser(gdManageDevicePayload.getCreateUser());
        //User updateUser = UserCache.getUser(gdManageDevicePayload.getUpdateUser());
        //gdManageDevicePayloadVO.setCreateUserName(createUser.getName());
        //gdManageDevicePayloadVO.setUpdateUserName(updateUser.getName());
        return gdManageDevicePayloadVO;
    }
}
drone-service/drone-gd/src/main/resources/log/logback-prod.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-service/drone-gd/src/main/resources/log/logback-test.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-service/drone-system/docker-compose-prod.yml
@@ -2,14 +2,14 @@
services:
  ja_drone_system:
    # 从 Harbor 私有仓库拉取镜像
    image: 172.21.81.239:32002/drone-manage/ja-drone-system:SNAPSHOT-$BUILD_NUMBER
    image: 172.21.81.239:32002/drone-manage-test/ja-drone-system:SNAPSHOT-$BUILD_NUMBER
    # image: ja-drone-system:latest
    container_name: ja-drone-system
    # 宿主机端口:容器启动端口
    ports:
      - "8206:8206"
    volumes:
      - /app/logs/ja-system:/data/log/system
      - /app/logs/ja-system:/data/logs/drone-system
      - /software/service/liscense:/software/service/liscense
    # 设置环境变量
    environment:
drone-service/drone-system/docker-compose-test.yml
@@ -9,7 +9,7 @@
    ports:
      - "8206:8206"
    volumes:
      - /data/log/ja-system:/data/log/ja-system
      - /data/log/ja-system:/data/logs/drone-system
      - /software/service/liscense:/software/service/liscense
    # 设置环境变量
    environment:
@@ -20,6 +20,7 @@
    networks:
      - doc_drone_network
# 指定
networks:
  doc_drone_network:
drone-service/drone-system/src/main/java/org/sxkj/system/controller/DeptController.java
@@ -379,8 +379,17 @@
        String fileName = URLEncoder.encode("机构模板", StandardCharsets.UTF_8.name());
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        // 准备空数据列表
        // 准备示例数据列表
        List<DeptImportExcel> list = new ArrayList<>();
        // 创建示例数据对象
        DeptImportExcel example = new DeptImportExcel();
        // 设置示例数据
        example.setDeptName("示例机构");
        example.setAreaCode("360800000000");
        example.setRemark("这是一个示例机构");
        example.setStatus("1"); // 假设1表示启用状态
        // 将示例数据添加到列表
        list.add(example);
        // 使用EasyExcel导出,并注册RegionSheetWriteHandler
        EasyExcel.write(response.getOutputStream(), DeptImportExcel.class)
drone-service/drone-system/src/main/java/org/sxkj/system/controller/ExternalController.java
New file
@@ -0,0 +1,160 @@
package org.sxkj.system.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.log.logger.BladeLogger;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.DigestUtil;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.sxkj.common.constant.WordOrderConstant;
import org.sxkj.common.utils.HeaderUtils;
import org.sxkj.common.utils.OrderNumUtils;
import org.sxkj.system.cache.DictCache;
import org.sxkj.system.entity.Dept;
import org.sxkj.system.entity.Role;
import org.sxkj.system.entity.User;
import org.sxkj.system.entity.UserInfo;
import org.sxkj.system.enums.DictEnum;
import org.sxkj.system.param.DeptAddParam;
import org.sxkj.system.service.IDeptService;
import org.sxkj.system.service.IRoleService;
import org.sxkj.system.service.IUserService;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE;
@NonDS
@RestController
@AllArgsConstructor
@RequestMapping("/external")
@Api(value = "对外接口", tags = "对外接口")
public class ExternalController {
    private final IRoleService roleService;
    private final IDeptService deptService;
    private final IUserService userService;
    private final BladeLogger bladeLogger;
    /**
     * 新增或修改-对外
     */
    @PostMapping("/submitDeptExternal")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "机构新增或修改", notes = "传入dept")
    @ApiLog("组织机构信息新增或修改")
    public R submit(@Valid @RequestBody DeptAddParam dept) {
        // 参数校验:确保关键字段不为空
        if (dept.getId() == null) {
            return R.fail("参数缺失:id 不能为空");
        }
        // 删除操作
        if (dept.getId() != null && dept.getIsDeleted() == 1) {
            deptService.removeDept(String.valueOf(dept.getId()));
            CacheUtil.clear(SYS_CACHE); // 清理缓存
            CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
            Kv kv = Kv.create().set("id", String.valueOf(dept.getId())).set("tenantId", dept.getTenantId())
                .set("deptCategoryName", DictCache.getValue(DictEnum.ORG_CATEGORY, dept.getDeptCategory()));
            return R.data(kv);
        }
        // 新增操作
        Dept deptEntity = Objects.requireNonNull(BeanUtil.copy(dept, Dept.class));
        String times = OrderNumUtils.initOrderNum2(WordOrderConstant.ORG_CODE);
        String deptCode = WordOrderConstant.ORG_PREFIX + times;
        deptEntity.setDeptCode(deptCode);
        deptEntity.setAreaCode(HeaderUtils.processAreaCode(dept.getAreaCode()));
        deptEntity.setCreateTime(new Date());
        deptEntity.setUpdateTime(new Date());
        if (deptService.submit(deptEntity)) {
            CacheUtil.clear(SYS_CACHE);
            CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
            List<User> userList = userService.list(new LambdaQueryWrapper<User>().eq(User::getDeptId, dept.getId()));
            if (!userList.isEmpty()) {
                List<Long> userIds = userList.stream().map(User::getId).collect(Collectors.toList());
                userService.updateUserAreaCode(dept.getAreaCode(), userIds);
            }
            // 返回懒加载树更新节点所需字段
            Kv kv = Kv.create().set("id", String.valueOf(dept.getId())).set("tenantId", dept.getTenantId())
                .set("deptCategoryName", DictCache.getValue(DictEnum.ORG_CATEGORY, dept.getDeptCategory()));
            return R.data(kv);
        }
        return R.fail("操作失败");
    }
    /**
     * 新增或修改-对外
     */
    @PostMapping("/submitRoleExternal")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "角色新增或修改", notes = "传入role")
    @ApiLog("角色信息新增或修改")
    public R submit(@Valid @RequestBody Role role) {
        // 参数校验:确保关键字段不为空
        if (role.getId() == null) {
            return R.fail("参数缺失:id 不能为空");
        }
        CacheUtil.clear(SYS_CACHE);
        CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
        // 删除操作
        if (role.getIsDeleted() != null && role.getIsDeleted() == 1) {
            roleService.removeRole(String.valueOf(role.getId()));
            return R.status(true);
        }
        // 新增操作
        return R.status(roleService.submit(role));
    }
    /**
     * 用户信息新增或者修改-对外
     */
    @PostMapping("/submitUserExternal")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "新增或修改用户", notes = "传入User,新增或修改用户")
    @ApiLog("用户信息新增或者修改-对外")
    public R submitExternal(@Valid @RequestBody User user) {
        CacheUtil.clear(USER_CACHE);
        boolean isRet = false;
        UserInfo userInfo = userService.userInfo("000000", user.getAccount());
        if (userInfo != null && userInfo.getUser() != null) {
            bladeLogger.info("用户信息修改", user.toString());
            user.setId(userInfo.getUser().getId());
            user.setDeptId(userInfo.getUser().getDeptId());
            user.setRoleId(userInfo.getUser().getRoleId());
            isRet = userService.updateUser(user);
        } else {
            Dept dept = deptService.getById(user.getDeptId());
            user.setAreaCode(HeaderUtils.processAreaCode(dept.getAreaCode()));
            user.setPassword(DigestUtil.encrypt("jadk@2026"));
            user.setDeptId(user.getDeptId() == null ? String.valueOf(dept.getId()) : user.getDeptId());
            user.setRoleId(user.getRoleId() == null ? "2011678430358691842" : user.getRoleId());
            isRet = userService.save(user);
            bladeLogger.info("用户信息新增", user.toString());
        }
        return R.status(isRet);
    }
}
drone-service/drone-system/src/main/java/org/sxkj/system/controller/RoleController.java
@@ -91,9 +91,9 @@
    public R<List<RoleVO>> list(@ApiIgnore @RequestParam Map<String, Object> role, BladeUser bladeUser) {
        QueryWrapper<Role> queryWrapper = Condition.getQueryWrapper(role, Role.class);
        // 不查询超级管理员角色
        if (!AuthUtil.isAdministrator()) {
        // if (!AuthUtil.isAdministrator()) {
            queryWrapper.ne("id","1123598816738675201");
        }
        // }
        List<Role> list = roleService.list(queryWrapper);
        return R.data(RoleWrapper.build().listNodeVO(list));
    }
drone-service/drone-system/src/main/java/org/sxkj/system/controller/UserController.java
@@ -160,38 +160,6 @@
    }
    /**
     * 用户信息新增或者修改-对外
     */
    @PostMapping("/submitExternal")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "新增或修改用户", notes = "传入User,新增或修改用户")
    @ApiLog("用户信息新增或者修改-对外")
    public R submitExternal(@Valid @RequestBody User user) {
        CacheUtil.clear(USER_CACHE);
        boolean isRet = false;
        UserInfo userInfo = userService.userInfo("000000", user.getAccount());
        if (userInfo != null && userInfo.getUser() != null) {
            bladeLogger.info("用户信息修改", user.toString());
            user.setId(userInfo.getUser().getId());
            user.setDeptId(userInfo.getUser().getDeptId());
            user.setRoleId(userInfo.getUser().getRoleId());
            isRet = userService.updateUser(user);
        } else {
            Dept dept = deptMapper.selectById(1123598813738675201L);
            user.setAreaCode(dept.getAreaCode());
            user.setPassword("123456");
            user.setDeptId(String.valueOf(dept.getId()));
            user.setRoleId("2011678430358691842");
            isRet = userService.submit(user);
            bladeLogger.info("用户信息新增", user.toString());
        }
        return R.status(isRet);
    }
    /**
     * 修改
     */
    @PostMapping("/update")
drone-service/drone-system/src/main/java/org/sxkj/system/excel/DeptImportExcel.java
@@ -40,20 +40,20 @@
    private static final long serialVersionUID = 1L;
    @ExcelProperty("机构名称")
    @ExcelProperty("机构名称*")
    @ColumnWidth(20)
    private String deptName;
    @ExcelProperty(value = "所属区划编码")
    @ExcelProperty(value = "所属区划编码*")
    @ColumnWidth(20)
    private String areaCode;
    @ExcelProperty("机构描述")
    @ExcelProperty("机构描述*")
    @ColumnWidth(20)
    private String remark;
    @ColumnWidth(20)
    @ExcelProperty(value = "机构状态", converter = ExcelDictConverter.class)
    @ExcelProperty(value = "机构状态*", converter = ExcelDictConverter.class)
    @ExcelDictItemLabel(type = "institutionStatus")
    @ExcelDictItem(type = "institutionStatus")
    private String status;
drone-service/drone-system/src/main/java/org/sxkj/system/mapper/RegionMapper.xml
@@ -135,7 +135,7 @@
            code,
            parent_code,
            ancestors,
            `name`,
            "name",
            province_code,
            province_name,
            city_code,
@@ -150,7 +150,7 @@
            type,
            sort,
            remark,
            `status`,
            "status",
            CASE
            WHEN
                region_level = '5' THEN town_name
drone-service/drone-system/src/main/java/org/sxkj/system/service/IUserService.java
@@ -215,4 +215,11 @@
    public Map<Long, String> getUserIdsMap(List<Long> userIds);
    List<Long> userIdsByName(String nickName);
    /**
     * 更新区域code
     * @param areaCode
     * @param userIds
     */
    void updateUserAreaCode(String areaCode, List<Long> userIds);
}
drone-service/drone-system/src/main/java/org/sxkj/system/service/impl/DeptServiceImpl.java
@@ -324,6 +324,20 @@
    public void importDept(List<DeptImportExcel> data, Boolean isCovered) {
        List<Dept> list = new ArrayList<>();
        data.forEach(deptExcel -> {
            // 校验必填字段
            if (deptExcel.getDeptName() == null || deptExcel.getDeptName().trim().isEmpty()) {
                throw new RuntimeException("机构名称不能为空");
            }
            if (deptExcel.getAreaCode() == null || deptExcel.getAreaCode().trim().isEmpty()) {
                throw new RuntimeException("所属区划编码不能为空");
            }
            if (deptExcel.getRemark() == null || deptExcel.getRemark().trim().isEmpty()) {
                throw new RuntimeException("机构描述不能为空");
            }
            if (deptExcel.getStatus() == null || deptExcel.getStatus().trim().isEmpty()) {
                throw new RuntimeException("机构状态不能为空");
            }
            // 转换数据
            Dept dept = BeanUtil.copy(deptExcel, Dept.class);
            list.add(dept);
        });
drone-service/drone-system/src/main/java/org/sxkj/system/service/impl/UserServiceImpl.java
@@ -463,4 +463,13 @@
        return Streams.toList(list, User::getId);
    }
    /**
     *
     * @param areaCode
     * @param userIds
     */
    @Override
    public void updateUserAreaCode(String areaCode, List<Long> userIds) {
        baseMapper.updateUserAreaCode(areaCode, userIds);
    }
}
drone-service/drone-system/src/main/resources/log/logback-prod.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/system/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-service/drone-system/src/main/resources/log/logback-test.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/system/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-task/drone-odm/docker-compose-prod.yml
@@ -9,7 +9,7 @@
    ports:
      - "8310:8310"
    volumes:
      - /app/logs/odm:/data/log/odm
      - /app/logs/odm:/data/logs/drone-odm
      - /app/data/temp:/app/data/temp
      - /app/data/webodm-data:/app/data/webodm-data
      - /app/data/minio-data:/app/data/minio-data
drone-task/drone-odm/docker-compose-test.yml
@@ -9,7 +9,7 @@
    ports:
      - "8310:8310"
    volumes:
      - /data/log/odm:/data/logs/odm
      - /data/log/odm:/data/logs/drone-odm
      - /data/temp:/data/temp
      - /software/data/odm-data/docker/volumes:/software/data/odm-data/docker/volumes
      - /software/data/minio-data:/software/data/minio-data
drone-task/drone-odm/src/main/resources/log/logback-prod.xml
@@ -10,6 +10,7 @@
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 彩色日志格式 -->
    <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}}"/>
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/odm/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/odm/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/odm/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/log/odm/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
drone-task/drone-odm/src/main/resources/log/logback-test.xml
@@ -13,6 +13,7 @@
    <!-- 彩色日志格式 -->
    <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}}"/>
    <property name="LOG_PATH" value="${LOG_PATH:-/data/logs/${springAppName}}"/>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
@@ -31,7 +32,7 @@
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/odm/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到100mb的时候开始切分,最多保留7天,但最大到20GB,哪怕没到7天也要删除多余的日志 -->
@@ -54,7 +55,7 @@
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/odm/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件到30mb的时候开始切分,最多保留7天,但最大到3GB,哪怕没到7天也要删除多余的日志 -->
@@ -77,7 +78,7 @@
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/odm/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
@@ -100,7 +101,7 @@
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>/data/logs/odm/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <FileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--最多保留30天-->
            <maxHistory>30</maxHistory>
            <!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到1GB,哪怕没到30天也要删除多余的日志 -->
pom.xml
@@ -20,6 +20,8 @@
        <maven.flatten.version>1.2.2</maven.flatten.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- pgsql -->
        <pgsql.version>42.7.7</pgsql.version>
        <!-- Docker仓库服务配置 -->
        <docker.registry.url>192.168.0.188</docker.registry.url>
@@ -103,7 +105,13 @@
    <dependencies>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>${pgsql.version}</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>