Browse Source

补回 df32f8e ours 合并丢失的远端改动(91文件): 自 25075a9 恢复 fileupload/config/alarm 后端与 mybatis xml、前端统计分析与数据补传页面; README 保留本地 python 3.10 改动

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
taosj 1 day ago
parent
commit
030841ddfe
91 changed files with 2751 additions and 523 deletions
  1. 104 12
      forecast-backend-server/src/main/java/com/ufo/project/alarm/controller/AlarmEventRecordController.java
  2. 69 6
      forecast-backend-server/src/main/java/com/ufo/project/alarm/domain/AlarmEventRecord.java
  3. 95 0
      forecast-backend-server/src/main/java/com/ufo/project/alarm/domain/vo/AlarmEventRecordExportStat.java
  4. 12 1
      forecast-backend-server/src/main/java/com/ufo/project/alarm/mapper/AlarmEventRecordMapper.java
  5. 9 1
      forecast-backend-server/src/main/java/com/ufo/project/alarm/service/IAlarmEventRecordService.java
  6. 21 1
      forecast-backend-server/src/main/java/com/ufo/project/alarm/service/impl/AlarmEventRecordServiceImpl.java
  7. 68 5
      forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigDeviceController.java
  8. 6 6
      forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationChannelController.java
  9. 6 6
      forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationDeviceController.java
  10. 6 6
      forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationPointController.java
  11. 6 6
      forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationPowerLimitController.java
  12. 6 6
      forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationPvModuleController.java
  13. 18 8
      forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigDevice.java
  14. 22 22
      forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationChannel.java
  15. 20 20
      forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationDevice.java
  16. 24 24
      forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationPoint.java
  17. 20 20
      forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationPowerLimit.java
  18. 22 22
      forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationPvModule.java
  19. 171 0
      forecast-backend-server/src/main/java/com/ufo/project/config/domain/vo/ConfigDeviceExportVo.java
  20. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationChannelMapper.java
  21. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationDeviceMapper.java
  22. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationPointMapper.java
  23. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationPowerLimitMapper.java
  24. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationPvModuleMapper.java
  25. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationChannelService.java
  26. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationDeviceService.java
  27. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationPointService.java
  28. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationPowerLimitService.java
  29. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationPvModuleService.java
  30. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationChannelServiceImpl.java
  31. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationDeviceServiceImpl.java
  32. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationPointServiceImpl.java
  33. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationPowerLimitServiceImpl.java
  34. 1 1
      forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationPvModuleServiceImpl.java
  35. 16 16
      forecast-backend-server/src/main/java/com/ufo/project/data/task/MockDataTask.java
  36. 56 0
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/controller/DataReportLogController.java
  37. 9 2
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/DataReportLog.java
  38. 71 0
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/vo/ReUploadCountRow.java
  39. 71 0
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/vo/UploadRateCountRow.java
  40. 103 0
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/vo/UploadRateStatQuery.java
  41. 194 0
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/vo/UploadRateStatVO.java
  42. 39 0
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/mapper/DataReportLogMapper.java
  43. 25 0
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/service/IDataReportLogService.java
  44. 324 0
      forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/service/impl/DataReportLogServiceImpl.java
  45. 20 2
      forecast-backend-server/src/main/resources/mybatis/alarm/AlarmEventRecordMapper.xml
  46. 6 6
      forecast-backend-server/src/main/resources/mybatis/alarm/AlarmEventRuleMapper.xml
  47. 6 6
      forecast-backend-server/src/main/resources/mybatis/alarm/AlarmEventRuleTemplateMapper.xml
  48. 6 6
      forecast-backend-server/src/main/resources/mybatis/alarm/AlarmStatRecordMapper.xml
  49. 3 3
      forecast-backend-server/src/main/resources/mybatis/alarm/MonitoringCheckRecordMapper.xml
  50. 3 3
      forecast-backend-server/src/main/resources/mybatis/alarm/MonitoringSendRecordMapper.xml
  51. 6 6
      forecast-backend-server/src/main/resources/mybatis/api/ApiAccessControlMapper.xml
  52. 3 3
      forecast-backend-server/src/main/resources/mybatis/api/ApiAccessRecordMapper.xml
  53. 6 6
      forecast-backend-server/src/main/resources/mybatis/api/ApiRecordMapper.xml
  54. 6 6
      forecast-backend-server/src/main/resources/mybatis/api/ApiVersionReleaseMapper.xml
  55. 6 6
      forecast-backend-server/src/main/resources/mybatis/assessment/ConfigAssessmentIndicatorMapper.xml
  56. 6 6
      forecast-backend-server/src/main/resources/mybatis/assessment/ConfigAssessmentRuleMapper.xml
  57. 6 6
      forecast-backend-server/src/main/resources/mybatis/assessment/ConfigAssessmentTaskMapper.xml
  58. 6 6
      forecast-backend-server/src/main/resources/mybatis/config/ConfigAreaMapper.xml
  59. 25 4
      forecast-backend-server/src/main/resources/mybatis/config/ConfigDeviceMapper.xml
  60. 10 8
      forecast-backend-server/src/main/resources/mybatis/config/ConfigStationMapper.xml
  61. 6 6
      forecast-backend-server/src/main/resources/mybatis/config/ConfigSupplierMapper.xml
  62. 6 6
      forecast-backend-server/src/main/resources/mybatis/config/StopReducePowerRecordMapper.xml
  63. 6 6
      forecast-backend-server/src/main/resources/mybatis/datasource/DataSourceConfigMapper.xml
  64. 6 6
      forecast-backend-server/src/main/resources/mybatis/datasource/DataSourceGrabMapper.xml
  65. 6 6
      forecast-backend-server/src/main/resources/mybatis/datasource/DataSourceUserRelationMapper.xml
  66. 6 6
      forecast-backend-server/src/main/resources/mybatis/rbac/RbacMenuMapper.xml
  67. 6 6
      forecast-backend-server/src/main/resources/mybatis/rbac/RbacModuleMapper.xml
  68. 6 6
      forecast-backend-server/src/main/resources/mybatis/rbac/RbacRoleMapper.xml
  69. 6 6
      forecast-backend-server/src/main/resources/mybatis/rbac/RbacUserMapper.xml
  70. 6 6
      forecast-backend-server/src/main/resources/mybatis/report/ConfigReportSiteInfoMapper.xml
  71. 6 6
      forecast-backend-server/src/main/resources/mybatis/report/ConfigReportSiteMapper.xml
  72. 6 6
      forecast-backend-server/src/main/resources/mybatis/report/ConfigReportTaskMapper.xml
  73. 3 3
      forecast-backend-server/src/main/resources/mybatis/report/StatsAssessmentIndicatorMapper.xml
  74. 3 3
      forecast-backend-server/src/main/resources/mybatis/report/StatsAssessmentIndicatorMultiModelMapper.xml
  75. 3 3
      forecast-backend-server/src/main/resources/mybatis/report/StatsWeatherIndicatorMapper.xml
  76. 3 3
      forecast-backend-server/src/main/resources/mybatis/report/StatsWeatherIndicatorMultiModelMapper.xml
  77. 6 6
      forecast-backend-server/src/main/resources/mybatis/weather/WeatherWarningRecordMapper.xml
  78. 14 28
      forecast-backend-vue/src/api/alarm/eventRecord.js
  79. 29 0
      forecast-backend-vue/src/api/fileupload/reportLog.js
  80. 3 1
      forecast-backend-vue/src/utils/BearJiaUtil.js
  81. 5 1
      forecast-backend-vue/src/views/ufo/config/station/StationConfigCrud.vue
  82. 9 4
      forecast-backend-vue/src/views/ufo/config/station/index.vue
  83. 207 107
      forecast-backend-vue/src/views/ufo/electricity/device/TurbineInfo.vue
  84. 63 0
      forecast-backend-vue/src/views/ufo/electricity/forecast/DataResend.vue
  85. 269 0
      forecast-backend-vue/src/views/ufo/electricity/statanalysis/eventQuery.vue
  86. 14 2
      forecast-backend-vue/src/views/ufo/electricity/statanalysis/reportLogQuery.vue
  87. 195 0
      forecast-backend-vue/src/views/ufo/electricity/statanalysis/uploadRateStat.vue
  88. 2 2
      forecast-backend-vue/src/views/ufo/workbench/WorkbenchPage.vue
  89. 3 0
      release_note/20261028/ddl.sql
  90. 81 0
      release_note/20261028/dml.sql
  91. 15 0
      release_note/20261028/release_note.md

+ 104 - 12
forecast-backend-server/src/main/java/com/ufo/project/alarm/controller/AlarmEventRecordController.java

@@ -1,7 +1,11 @@
 package com.ufo.project.alarm.controller;
 package com.ufo.project.alarm.controller;
 
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.github.pagehelper.PageHelper;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -15,15 +19,17 @@ import org.springframework.web.bind.annotation.RestController;
 import com.ufo.base.framework.aspectj.lang.annotation.Log;
 import com.ufo.base.framework.aspectj.lang.annotation.Log;
 import com.ufo.base.framework.aspectj.lang.enums.BusinessType;
 import com.ufo.base.framework.aspectj.lang.enums.BusinessType;
 import com.ufo.project.alarm.domain.AlarmEventRecord;
 import com.ufo.project.alarm.domain.AlarmEventRecord;
+import com.ufo.project.alarm.domain.vo.AlarmEventRecordExportStat;
 import com.ufo.project.alarm.service.IAlarmEventRecordService;
 import com.ufo.project.alarm.service.IAlarmEventRecordService;
 import com.ufo.base.framework.web.controller.BaseController;
 import com.ufo.base.framework.web.controller.BaseController;
 import com.ufo.base.framework.web.domain.AjaxResult;
 import com.ufo.base.framework.web.domain.AjaxResult;
+import com.ufo.base.common.utils.DictUtils;
 import com.ufo.base.common.utils.poi.ExcelUtil;
 import com.ufo.base.common.utils.poi.ExcelUtil;
 import com.ufo.base.framework.web.page.TableDataInfo;
 import com.ufo.base.framework.web.page.TableDataInfo;
 
 
 /**
 /**
  * 报警信息统计Controller
  * 报警信息统计Controller
- * 
+ *
  * @author ufo
  * @author ufo
  * @date 2026-05-05
  * @date 2026-05-05
  */
  */
@@ -35,28 +41,69 @@ public class AlarmEventRecordController extends BaseController
     private IAlarmEventRecordService alarmEventRecordService;
     private IAlarmEventRecordService alarmEventRecordService;
 
 
     /**
     /**
-     * 查询报警信息统计列表
+     * 查询事件列表
+     *
+     * 参数: alarmCategory 告警类别, alarmLevel 告警等级, processStatus 处理状态(true=已处理, false=未处理),
+     * alarmDate 告警时间(yyyy-MM-dd), pageNum, pageSize
      */
      */
     @PreAuthorize("@ss.hasPermi('alarm:eventRecord:list')")
     @PreAuthorize("@ss.hasPermi('alarm:eventRecord:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(AlarmEventRecord alarmEventRecord)
+    @PostMapping("/list")
+    public TableDataInfo list(@RequestBody JSONObject params)
     {
     {
-        startPage();
-        List<AlarmEventRecord> list = alarmEventRecordService.selectAlarmEventRecordList(alarmEventRecord);
+        AlarmEventRecord query = buildQuery(params);
+        PageHelper.startPage(params.getIntValue("pageNum", 1), params.getIntValue("pageSize", 10));
+        List<AlarmEventRecord> list = alarmEventRecordService.selectAlarmEventRecordList(query);
         return getDataTable(list);
         return getDataTable(list);
     }
     }
 
 
     /**
     /**
-     * 导出报警信息统计列表
+     * 确认告警(批量处理, 非已处理数据均置为已处理)
+     *
+     * 参数: ids 告警主键集合
+     */
+    @PreAuthorize("@ss.hasPermi('alarm:eventRecord:edit')")
+    @Log(title = "事件查询", businessType = BusinessType.UPDATE)
+    @PostMapping("/process")
+    public AjaxResult process(@RequestBody JSONObject params)
+    {
+        JSONArray idsArr = params.getJSONArray("ids");
+        List<String> ids = idsArr == null ? null : idsArr.toJavaList(String.class);
+        if (ids == null || ids.isEmpty())
+        {
+            return error("请选择要处理的告警数据");
+        }
+        int rows = alarmEventRecordService.processAlarmEventRecord(ids);
+        if (rows == 0)
+        {
+            return success("所选告警均已处理, 未执行处理");
+        }
+        return success("已处理 " + rows + " 条告警");
+    }
+
+    /**
+     * 导出事件列表
+     *
+     * 参数: alarmCategory 告警类别, alarmLevel 告警等级, processStatus 处理状态, alarmDate 告警时间
      */
      */
     @PreAuthorize("@ss.hasPermi('alarm:eventRecord:export')")
     @PreAuthorize("@ss.hasPermi('alarm:eventRecord:export')")
-    @Log(title = "报警信息统计", businessType = BusinessType.EXPORT)
+    @Log(title = "事件查询", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     @PostMapping("/export")
-    public void export(HttpServletResponse response, AlarmEventRecord alarmEventRecord)
+    public void export(HttpServletResponse response, @RequestBody JSONObject params)
     {
     {
-        List<AlarmEventRecord> list = alarmEventRecordService.selectAlarmEventRecordList(alarmEventRecord);
-        ExcelUtil<AlarmEventRecord> util = new ExcelUtil<AlarmEventRecord>(AlarmEventRecord.class);
-        util.exportExcel(response, list, "报警信息统计数据");
+        AlarmEventRecord query = buildQuery(params);
+        List<AlarmEventRecord> list = alarmEventRecordService.selectAlarmEventRecordList(query);
+        List<AlarmEventRecordExportStat> exportList = new ArrayList<>();
+        for (AlarmEventRecord record : list)
+        {
+            exportList.add(new AlarmEventRecordExportStat(
+                    dictLabel("alarm_level", record.getAlarmLevel() == null ? null : String.valueOf(record.getAlarmLevel())),
+                    dictLabel("alarm_category", record.getAlarmCategory()),
+                    record.getAlarmData(),
+                    processFlagLabel(record.getProcessFlag()),
+                    record.getAlarmCreateTime()));
+        }
+        ExcelUtil<AlarmEventRecordExportStat> util = new ExcelUtil<AlarmEventRecordExportStat>(AlarmEventRecordExportStat.class);
+        util.exportExcel(response, exportList, "事件查询数据");
     }
     }
 
 
     /**
     /**
@@ -101,4 +148,49 @@ public class AlarmEventRecordController extends BaseController
     {
     {
         return toAjax(alarmEventRecordService.deleteAlarmEventRecordByIds(ids));
         return toAjax(alarmEventRecordService.deleteAlarmEventRecordByIds(ids));
     }
     }
+
+    /**
+     * 构建查询条件
+     */
+    private AlarmEventRecord buildQuery(JSONObject params)
+    {
+        AlarmEventRecord query = new AlarmEventRecord();
+        query.setAlarmCategory(params.getString("alarmCategory"));
+        query.setAlarmLevel(params.getLong("alarmLevel"));
+        query.setProcessStatus(params.getBoolean("processStatus"));
+        query.setAlarmDate(params.getString("alarmDate"));
+        return query;
+    }
+
+    /**
+     * 字典值转标签(无匹配时返回空串)
+     */
+    private String dictLabel(String dictType, String dictValue)
+    {
+        if (dictValue == null || dictValue.isEmpty())
+        {
+            return "";
+        }
+        String label = DictUtils.getDictLabel(dictType, dictValue);
+        return label == null ? "" : label;
+    }
+
+    /**
+     * 处理状态转文案: 0未处理/1处理中/2已处理/3误报
+     */
+    private String processFlagLabel(Long processFlag)
+    {
+        if (processFlag == null)
+        {
+            return "";
+        }
+        switch (processFlag.intValue())
+        {
+            case 0: return "未处理";
+            case 1: return "处理中";
+            case 2: return "已处理";
+            case 3: return "误报";
+            default: return String.valueOf(processFlag);
+        }
+    }
 }
 }

+ 69 - 6
forecast-backend-server/src/main/java/com/ufo/project/alarm/domain/AlarmEventRecord.java

@@ -1,5 +1,6 @@
 package com.ufo.project.alarm.domain;
 package com.ufo.project.alarm.domain;
 
 
+import java.time.LocalDateTime;
 import com.ufo.base.framework.web.domain.BaseEntity;
 import com.ufo.base.framework.web.domain.BaseEntity;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import org.apache.commons.lang3.builder.ToStringStyle;
@@ -34,6 +35,10 @@ public class AlarmEventRecord extends BaseEntity
     @Excel(name = "监控端")
     @Excel(name = "监控端")
     private String monitoringTerminal;
     private String monitoringTerminal;
 
 
+    /** 告警类别 */
+    @Excel(name = "告警类别")
+    private String alarmCategory;
+
     /** 报警级别 */
     /** 报警级别 */
     @Excel(name = "报警级别")
     @Excel(name = "报警级别")
     private Long alarmLevel;
     private Long alarmLevel;
@@ -62,7 +67,19 @@ public class AlarmEventRecord extends BaseEntity
     @Excel(name = "处理人ids")
     @Excel(name = "处理人ids")
     private String processPersonId;
     private String processPersonId;
 
 
-    public void setId(String id) 
+    /** 处理状态(查询条件: true=已处理即process_flag=2, false=未处理即process_flag!=2) */
+    private Boolean processStatus;
+
+    /** 告警日期(查询条件: yyyy-MM-dd, 按当天 00:00:00~23:59:59 过滤) */
+    private String alarmDate;
+
+    /** 告警时间下限(查询条件: service层由alarmDate计算, 当天00:00:00) */
+    private LocalDateTime alarmDateBegin;
+
+    /** 告警时间上限(查询条件: service层由alarmDate计算, 当天23:59:59) */
+    private LocalDateTime alarmDateEnd;
+
+    public void setId(String id)
     {
     {
         this.id = id;
         this.id = id;
     }
     }
@@ -98,16 +115,25 @@ public class AlarmEventRecord extends BaseEntity
     {
     {
         return alarmData;
         return alarmData;
     }
     }
-    public void setMonitoringTerminal(String monitoringTerminal) 
+    public void setMonitoringTerminal(String monitoringTerminal)
     {
     {
         this.monitoringTerminal = monitoringTerminal;
         this.monitoringTerminal = monitoringTerminal;
     }
     }
 
 
-    public String getMonitoringTerminal() 
+    public String getMonitoringTerminal()
     {
     {
         return monitoringTerminal;
         return monitoringTerminal;
     }
     }
-    public void setAlarmLevel(Long alarmLevel) 
+    public void setAlarmCategory(String alarmCategory)
+    {
+        this.alarmCategory = alarmCategory;
+    }
+
+    public String getAlarmCategory()
+    {
+        return alarmCategory;
+    }
+    public void setAlarmLevel(Long alarmLevel)
     {
     {
         this.alarmLevel = alarmLevel;
         this.alarmLevel = alarmLevel;
     }
     }
@@ -161,15 +187,51 @@ public class AlarmEventRecord extends BaseEntity
     {
     {
         return sendStatus;
         return sendStatus;
     }
     }
-    public void setProcessPersonId(String processPersonId) 
+    public void setProcessPersonId(String processPersonId)
     {
     {
         this.processPersonId = processPersonId;
         this.processPersonId = processPersonId;
     }
     }
 
 
-    public String getProcessPersonId() 
+    public String getProcessPersonId()
     {
     {
         return processPersonId;
         return processPersonId;
     }
     }
+    public void setProcessStatus(Boolean processStatus)
+    {
+        this.processStatus = processStatus;
+    }
+
+    public Boolean getProcessStatus()
+    {
+        return processStatus;
+    }
+    public void setAlarmDate(String alarmDate)
+    {
+        this.alarmDate = alarmDate;
+    }
+
+    public String getAlarmDate()
+    {
+        return alarmDate;
+    }
+    public void setAlarmDateBegin(LocalDateTime alarmDateBegin)
+    {
+        this.alarmDateBegin = alarmDateBegin;
+    }
+
+    public LocalDateTime getAlarmDateBegin()
+    {
+        return alarmDateBegin;
+    }
+    public void setAlarmDateEnd(LocalDateTime alarmDateEnd)
+    {
+        this.alarmDateEnd = alarmDateEnd;
+    }
+
+    public LocalDateTime getAlarmDateEnd()
+    {
+        return alarmDateEnd;
+    }
 
 
     @Override
     @Override
     public String toString() {
     public String toString() {
@@ -179,6 +241,7 @@ public class AlarmEventRecord extends BaseEntity
             .append("alarmRuleId", getAlarmRuleId())
             .append("alarmRuleId", getAlarmRuleId())
             .append("alarmData", getAlarmData())
             .append("alarmData", getAlarmData())
             .append("monitoringTerminal", getMonitoringTerminal())
             .append("monitoringTerminal", getMonitoringTerminal())
+            .append("alarmCategory", getAlarmCategory())
             .append("createTime", getCreateTime())
             .append("createTime", getCreateTime())
             .append("createBy", getCreateBy())
             .append("createBy", getCreateBy())
             .append("updateTime", getUpdateTime())
             .append("updateTime", getUpdateTime())

+ 95 - 0
forecast-backend-server/src/main/java/com/ufo/project/alarm/domain/vo/AlarmEventRecordExportStat.java

@@ -0,0 +1,95 @@
+package com.ufo.project.alarm.domain.vo;
+
+import com.ufo.base.framework.aspectj.lang.annotation.Excel;
+
+/**
+ * 事件查询导出行数据
+ *
+ * @author ufo
+ * @date 2026-11-02
+ */
+public class AlarmEventRecordExportStat
+{
+    /** 告警等级 */
+    @Excel(name = "告警等级")
+    private String alarmLevel;
+
+    /** 告警类别 */
+    @Excel(name = "告警类别")
+    private String alarmCategory;
+
+    /** 告警内容 */
+    @Excel(name = "告警内容")
+    private String alarmData;
+
+    /** 处理状态 */
+    @Excel(name = "处理状态")
+    private String processFlag;
+
+    /** 告警日期 */
+    @Excel(name = "告警日期")
+    private String alarmDate;
+
+    public AlarmEventRecordExportStat()
+    {
+    }
+
+    public AlarmEventRecordExportStat(String alarmLevel, String alarmCategory, String alarmData, String processFlag, String alarmDate)
+    {
+        this.alarmLevel = alarmLevel;
+        this.alarmCategory = alarmCategory;
+        this.alarmData = alarmData;
+        this.processFlag = processFlag;
+        this.alarmDate = alarmDate;
+    }
+
+    public String getAlarmLevel()
+    {
+        return alarmLevel;
+    }
+
+    public void setAlarmLevel(String alarmLevel)
+    {
+        this.alarmLevel = alarmLevel;
+    }
+
+    public String getAlarmCategory()
+    {
+        return alarmCategory;
+    }
+
+    public void setAlarmCategory(String alarmCategory)
+    {
+        this.alarmCategory = alarmCategory;
+    }
+
+    public String getAlarmData()
+    {
+        return alarmData;
+    }
+
+    public void setAlarmData(String alarmData)
+    {
+        this.alarmData = alarmData;
+    }
+
+    public String getProcessFlag()
+    {
+        return processFlag;
+    }
+
+    public void setProcessFlag(String processFlag)
+    {
+        this.processFlag = processFlag;
+    }
+
+    public String getAlarmDate()
+    {
+        return alarmDate;
+    }
+
+    public void setAlarmDate(String alarmDate)
+    {
+        this.alarmDate = alarmDate;
+    }
+}

+ 12 - 1
forecast-backend-server/src/main/java/com/ufo/project/alarm/mapper/AlarmEventRecordMapper.java

@@ -1,6 +1,8 @@
 package com.ufo.project.alarm.mapper;
 package com.ufo.project.alarm.mapper;
 
 
+import java.util.Date;
 import java.util.List;
 import java.util.List;
+import org.apache.ibatis.annotations.Param;
 import com.ufo.project.alarm.domain.AlarmEventRecord;
 import com.ufo.project.alarm.domain.AlarmEventRecord;
 
 
 /**
 /**
@@ -53,9 +55,18 @@ public interface AlarmEventRecordMapper
 
 
     /**
     /**
      * 批量删除报警信息统计
      * 批量删除报警信息统计
-     * 
+     *
      * @param ids 需要删除的数据主键集合
      * @param ids 需要删除的数据主键集合
      * @return 结果
      * @return 结果
      */
      */
     public int deleteAlarmEventRecordByIds(String[] ids);
     public int deleteAlarmEventRecordByIds(String[] ids);
+
+    /**
+     * 批量处理报警信息(仅未处理数据可处理, 置为已处理)
+     *
+     * @param ids 需要处理的报警信息主键集合
+     * @param updateTime 更新时间
+     * @return 结果
+     */
+    public int processAlarmEventRecord(@Param("ids") List<String> ids, @Param("updateTime") Date updateTime);
 }
 }

+ 9 - 1
forecast-backend-server/src/main/java/com/ufo/project/alarm/service/IAlarmEventRecordService.java

@@ -53,9 +53,17 @@ public interface IAlarmEventRecordService
 
 
     /**
     /**
      * 删除报警信息统计信息
      * 删除报警信息统计信息
-     * 
+     *
      * @param id 报警信息统计主键
      * @param id 报警信息统计主键
      * @return 结果
      * @return 结果
      */
      */
     public int deleteAlarmEventRecordById(String id);
     public int deleteAlarmEventRecordById(String id);
+
+    /**
+     * 批量处理报警信息(仅未处理数据可处理, 置为已处理)
+     *
+     * @param ids 需要处理的报警信息主键集合
+     * @return 结果
+     */
+    public int processAlarmEventRecord(List<String> ids);
 }
 }

+ 21 - 1
forecast-backend-server/src/main/java/com/ufo/project/alarm/service/impl/AlarmEventRecordServiceImpl.java

@@ -1,7 +1,9 @@
 package com.ufo.project.alarm.service.impl;
 package com.ufo.project.alarm.service.impl;
 
 
+import java.time.LocalDate;
 import java.util.List;
 import java.util.List;
 import com.ufo.base.common.utils.DateUtils;
 import com.ufo.base.common.utils.DateUtils;
+import com.ufo.base.common.utils.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import com.ufo.project.alarm.mapper.AlarmEventRecordMapper;
 import com.ufo.project.alarm.mapper.AlarmEventRecordMapper;
@@ -41,6 +43,12 @@ public class AlarmEventRecordServiceImpl implements IAlarmEventRecordService
     @Override
     @Override
     public List<AlarmEventRecord> selectAlarmEventRecordList(AlarmEventRecord alarmEventRecord)
     public List<AlarmEventRecord> selectAlarmEventRecordList(AlarmEventRecord alarmEventRecord)
     {
     {
+        if (StringUtils.isNotEmpty(alarmEventRecord.getAlarmDate()))
+        {
+            LocalDate day = LocalDate.parse(alarmEventRecord.getAlarmDate());
+            alarmEventRecord.setAlarmDateBegin(day.atStartOfDay());
+            alarmEventRecord.setAlarmDateEnd(day.atTime(23, 59, 59));
+        }
         return alarmEventRecordMapper.selectAlarmEventRecordList(alarmEventRecord);
         return alarmEventRecordMapper.selectAlarmEventRecordList(alarmEventRecord);
     }
     }
 
 
@@ -84,7 +92,7 @@ public class AlarmEventRecordServiceImpl implements IAlarmEventRecordService
 
 
     /**
     /**
      * 删除报警信息统计信息
      * 删除报警信息统计信息
-     * 
+     *
      * @param id 报警信息统计主键
      * @param id 报警信息统计主键
      * @return 结果
      * @return 结果
      */
      */
@@ -93,4 +101,16 @@ public class AlarmEventRecordServiceImpl implements IAlarmEventRecordService
     {
     {
         return alarmEventRecordMapper.deleteAlarmEventRecordById(id);
         return alarmEventRecordMapper.deleteAlarmEventRecordById(id);
     }
     }
+
+    /**
+     * 批量处理报警信息(非已处理数据均置为已处理)
+     *
+     * @param ids 需要处理的报警信息主键集合
+     * @return 结果
+     */
+    @Override
+    public int processAlarmEventRecord(List<String> ids)
+    {
+        return alarmEventRecordMapper.processAlarmEventRecord(ids, DateUtils.getNowDate());
+    }
 }
 }

+ 68 - 5
forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigDeviceController.java

@@ -20,6 +20,7 @@ import com.ufo.base.framework.aspectj.lang.enums.BusinessType;
 import com.ufo.project.config.domain.ConfigChannel;
 import com.ufo.project.config.domain.ConfigChannel;
 import com.ufo.project.config.domain.ConfigDevice;
 import com.ufo.project.config.domain.ConfigDevice;
 import com.ufo.project.config.domain.ConfigStation;
 import com.ufo.project.config.domain.ConfigStation;
+import com.ufo.project.config.domain.vo.ConfigDeviceExportVo;
 import com.ufo.project.config.service.IConfigChannelService;
 import com.ufo.project.config.service.IConfigChannelService;
 import com.ufo.project.config.service.IConfigDeviceService;
 import com.ufo.project.config.service.IConfigDeviceService;
 import com.ufo.project.config.service.IConfigStationService;
 import com.ufo.project.config.service.IConfigStationService;
@@ -64,8 +65,14 @@ public class ConfigDeviceController extends BaseController
     {
     {
         List<ConfigDevice> list = configDeviceService.selectConfigDeviceList(configDevice);
         List<ConfigDevice> list = configDeviceService.selectConfigDeviceList(configDevice);
         fillNames(list);
         fillNames(list);
-        ExcelUtil<ConfigDevice> util = new ExcelUtil<ConfigDevice>(ConfigDevice.class);
-        util.exportExcel(response, list, "设备配置");
+        List<ConfigDeviceExportVo> exportList = new ArrayList<>();
+        long index = 1;
+        for (ConfigDevice device : list)
+        {
+            exportList.add(new ConfigDeviceExportVo(index++, device.getName(), device.getChannelName(), device.getStationName(), tpLabel(device.getTp()), device.getBrand(), device.getModel(), device.getSerialNumber(), statusLabel(device.getStatus()), formatDate(device.getInstallDate())));
+        }
+        ExcelUtil<ConfigDeviceExportVo> util = new ExcelUtil<ConfigDeviceExportVo>(ConfigDeviceExportVo.class);
+        util.exportExcel(response, exportList, "设备配置");
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationDevice:query')")
     @PreAuthorize("@ss.hasPermi('config:stationDevice:query')")
@@ -112,9 +119,10 @@ public class ConfigDeviceController extends BaseController
         List<Long> channelIds = new ArrayList<>();
         List<Long> channelIds = new ArrayList<>();
         for (ConfigDevice device : list)
         for (ConfigDevice device : list)
         {
         {
-            if (device.getConfigStationId() != null && !stationIds.contains(device.getConfigStationId()))
+            Long stationId = parseStationId(device.getConfigStationId());
+            if (stationId != null && !stationIds.contains(stationId))
             {
             {
-                stationIds.add(device.getConfigStationId());
+                stationIds.add(stationId);
             }
             }
             if (device.getConfigChannelId() != null && !channelIds.contains(device.getConfigChannelId()))
             if (device.getConfigChannelId() != null && !channelIds.contains(device.getConfigChannelId()))
             {
             {
@@ -131,7 +139,7 @@ public class ConfigDeviceController extends BaseController
             }
             }
             for (ConfigDevice device : list)
             for (ConfigDevice device : list)
             {
             {
-                device.setStationName(stationNameMap.get(device.getConfigStationId()));
+                device.setStationName(stationNameMap.get(parseStationId(device.getConfigStationId())));
             }
             }
         }
         }
         if (!channelIds.isEmpty())
         if (!channelIds.isEmpty())
@@ -148,4 +156,59 @@ public class ConfigDeviceController extends BaseController
             }
             }
         }
         }
     }
     }
+
+    /**
+     * 状态字典转换: GOOD=在线, 否则离线
+     */
+    private String statusLabel(String status)
+    {
+        return "GOOD".equals(status) ? "在线" : "离线";
+    }
+
+    /**
+     * 设备类型字典转换: WEATHER=气象设备, AGVC=agvc设备, 其他原样
+     */
+    private String tpLabel(String tp)
+    {
+        if ("WEATHER".equals(tp))
+        {
+            return "气象设备";
+        }
+        if ("AGVC".equals(tp))
+        {
+            return "agvc设备";
+        }
+        return tp;
+    }
+
+    /**
+     * 投运日期格式化为yyyy-MM-dd
+     */
+    private String formatDate(java.util.Date date)
+    {
+        if (date == null)
+        {
+            return null;
+        }
+        return new java.text.SimpleDateFormat("yyyy-MM-dd").format(date);
+    }
+
+    /**
+     * config_device.config_station_id 是varchar列(存数字字符串), 转为Long用于关联config_station; 非数字值视为无场站
+     */
+    private Long parseStationId(String value)
+    {
+        if (value == null || value.trim().isEmpty())
+        {
+            return null;
+        }
+        try
+        {
+            return Long.parseLong(value.trim());
+        }
+        catch (NumberFormatException e)
+        {
+            return null;
+        }
+    }
 }
 }

+ 6 - 6
forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationChannelController.java

@@ -22,7 +22,7 @@ import com.ufo.base.common.utils.poi.ExcelUtil;
 import com.ufo.base.framework.web.page.TableDataInfo;
 import com.ufo.base.framework.web.page.TableDataInfo;
 
 
 /**
 /**
- * ????Controller
+ * 通道配置Controller
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -44,13 +44,13 @@ public class ConfigStationChannelController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationChannel:export')")
     @PreAuthorize("@ss.hasPermi('config:stationChannel:export')")
-    @Log(title = "????", businessType = BusinessType.EXPORT)
+    @Log(title = "通道配置", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     @PostMapping("/export")
     public void export(HttpServletResponse response, ConfigStationChannel configStationChannel)
     public void export(HttpServletResponse response, ConfigStationChannel configStationChannel)
     {
     {
         List<ConfigStationChannel> list = configStationChannelService.selectConfigStationChannelList(configStationChannel);
         List<ConfigStationChannel> list = configStationChannelService.selectConfigStationChannelList(configStationChannel);
         ExcelUtil<ConfigStationChannel> util = new ExcelUtil<ConfigStationChannel>(ConfigStationChannel.class);
         ExcelUtil<ConfigStationChannel> util = new ExcelUtil<ConfigStationChannel>(ConfigStationChannel.class);
-        util.exportExcel(response, list, "??????");
+        util.exportExcel(response, list, "通道配置数据");
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationChannel:query')")
     @PreAuthorize("@ss.hasPermi('config:stationChannel:query')")
@@ -61,7 +61,7 @@ public class ConfigStationChannelController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationChannel:add')")
     @PreAuthorize("@ss.hasPermi('config:stationChannel:add')")
-    @Log(title = "????", businessType = BusinessType.INSERT)
+    @Log(title = "通道配置", businessType = BusinessType.INSERT)
     @PostMapping
     @PostMapping
     public AjaxResult add(@RequestBody ConfigStationChannel configStationChannel)
     public AjaxResult add(@RequestBody ConfigStationChannel configStationChannel)
     {
     {
@@ -69,7 +69,7 @@ public class ConfigStationChannelController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationChannel:edit')")
     @PreAuthorize("@ss.hasPermi('config:stationChannel:edit')")
-    @Log(title = "????", businessType = BusinessType.UPDATE)
+    @Log(title = "通道配置", businessType = BusinessType.UPDATE)
     @PutMapping
     @PutMapping
     public AjaxResult edit(@RequestBody ConfigStationChannel configStationChannel)
     public AjaxResult edit(@RequestBody ConfigStationChannel configStationChannel)
     {
     {
@@ -77,7 +77,7 @@ public class ConfigStationChannelController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationChannel:remove')")
     @PreAuthorize("@ss.hasPermi('config:stationChannel:remove')")
-    @Log(title = "????", businessType = BusinessType.DELETE)
+    @Log(title = "通道配置", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     @DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     public AjaxResult remove(@PathVariable Long[] ids)
     {
     {

+ 6 - 6
forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationDeviceController.java

@@ -22,7 +22,7 @@ import com.ufo.base.common.utils.poi.ExcelUtil;
 import com.ufo.base.framework.web.page.TableDataInfo;
 import com.ufo.base.framework.web.page.TableDataInfo;
 
 
 /**
 /**
- * ????Controller
+ * 设备配置Controller
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -44,13 +44,13 @@ public class ConfigStationDeviceController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationDevice:export')")
     @PreAuthorize("@ss.hasPermi('config:stationDevice:export')")
-    @Log(title = "????", businessType = BusinessType.EXPORT)
+    @Log(title = "设备配置", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     @PostMapping("/export")
     public void export(HttpServletResponse response, ConfigStationDevice configStationDevice)
     public void export(HttpServletResponse response, ConfigStationDevice configStationDevice)
     {
     {
         List<ConfigStationDevice> list = configStationDeviceService.selectConfigStationDeviceList(configStationDevice);
         List<ConfigStationDevice> list = configStationDeviceService.selectConfigStationDeviceList(configStationDevice);
         ExcelUtil<ConfigStationDevice> util = new ExcelUtil<ConfigStationDevice>(ConfigStationDevice.class);
         ExcelUtil<ConfigStationDevice> util = new ExcelUtil<ConfigStationDevice>(ConfigStationDevice.class);
-        util.exportExcel(response, list, "??????");
+        util.exportExcel(response, list, "设备配置数据");
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationDevice:query')")
     @PreAuthorize("@ss.hasPermi('config:stationDevice:query')")
@@ -61,7 +61,7 @@ public class ConfigStationDeviceController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationDevice:add')")
     @PreAuthorize("@ss.hasPermi('config:stationDevice:add')")
-    @Log(title = "????", businessType = BusinessType.INSERT)
+    @Log(title = "设备配置", businessType = BusinessType.INSERT)
     @PostMapping
     @PostMapping
     public AjaxResult add(@RequestBody ConfigStationDevice configStationDevice)
     public AjaxResult add(@RequestBody ConfigStationDevice configStationDevice)
     {
     {
@@ -69,7 +69,7 @@ public class ConfigStationDeviceController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationDevice:edit')")
     @PreAuthorize("@ss.hasPermi('config:stationDevice:edit')")
-    @Log(title = "????", businessType = BusinessType.UPDATE)
+    @Log(title = "设备配置", businessType = BusinessType.UPDATE)
     @PutMapping
     @PutMapping
     public AjaxResult edit(@RequestBody ConfigStationDevice configStationDevice)
     public AjaxResult edit(@RequestBody ConfigStationDevice configStationDevice)
     {
     {
@@ -77,7 +77,7 @@ public class ConfigStationDeviceController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationDevice:remove')")
     @PreAuthorize("@ss.hasPermi('config:stationDevice:remove')")
-    @Log(title = "????", businessType = BusinessType.DELETE)
+    @Log(title = "设备配置", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     @DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     public AjaxResult remove(@PathVariable Long[] ids)
     {
     {

+ 6 - 6
forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationPointController.java

@@ -22,7 +22,7 @@ import com.ufo.base.common.utils.poi.ExcelUtil;
 import com.ufo.base.framework.web.page.TableDataInfo;
 import com.ufo.base.framework.web.page.TableDataInfo;
 
 
 /**
 /**
- * ????Controller
+ * 测点配置Controller
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -44,13 +44,13 @@ public class ConfigStationPointController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPoint:export')")
     @PreAuthorize("@ss.hasPermi('config:stationPoint:export')")
-    @Log(title = "????", businessType = BusinessType.EXPORT)
+    @Log(title = "测点配置", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     @PostMapping("/export")
     public void export(HttpServletResponse response, ConfigStationPoint configStationPoint)
     public void export(HttpServletResponse response, ConfigStationPoint configStationPoint)
     {
     {
         List<ConfigStationPoint> list = configStationPointService.selectConfigStationPointList(configStationPoint);
         List<ConfigStationPoint> list = configStationPointService.selectConfigStationPointList(configStationPoint);
         ExcelUtil<ConfigStationPoint> util = new ExcelUtil<ConfigStationPoint>(ConfigStationPoint.class);
         ExcelUtil<ConfigStationPoint> util = new ExcelUtil<ConfigStationPoint>(ConfigStationPoint.class);
-        util.exportExcel(response, list, "??????");
+        util.exportExcel(response, list, "测点配置数据");
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPoint:query')")
     @PreAuthorize("@ss.hasPermi('config:stationPoint:query')")
@@ -61,7 +61,7 @@ public class ConfigStationPointController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPoint:add')")
     @PreAuthorize("@ss.hasPermi('config:stationPoint:add')")
-    @Log(title = "????", businessType = BusinessType.INSERT)
+    @Log(title = "测点配置", businessType = BusinessType.INSERT)
     @PostMapping
     @PostMapping
     public AjaxResult add(@RequestBody ConfigStationPoint configStationPoint)
     public AjaxResult add(@RequestBody ConfigStationPoint configStationPoint)
     {
     {
@@ -69,7 +69,7 @@ public class ConfigStationPointController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPoint:edit')")
     @PreAuthorize("@ss.hasPermi('config:stationPoint:edit')")
-    @Log(title = "????", businessType = BusinessType.UPDATE)
+    @Log(title = "测点配置", businessType = BusinessType.UPDATE)
     @PutMapping
     @PutMapping
     public AjaxResult edit(@RequestBody ConfigStationPoint configStationPoint)
     public AjaxResult edit(@RequestBody ConfigStationPoint configStationPoint)
     {
     {
@@ -77,7 +77,7 @@ public class ConfigStationPointController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPoint:remove')")
     @PreAuthorize("@ss.hasPermi('config:stationPoint:remove')")
-    @Log(title = "????", businessType = BusinessType.DELETE)
+    @Log(title = "测点配置", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     @DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     public AjaxResult remove(@PathVariable Long[] ids)
     {
     {

+ 6 - 6
forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationPowerLimitController.java

@@ -22,7 +22,7 @@ import com.ufo.base.common.utils.poi.ExcelUtil;
 import com.ufo.base.framework.web.page.TableDataInfo;
 import com.ufo.base.framework.web.page.TableDataInfo;
 
 
 /**
 /**
- * ????Controller
+ * 限电配置Controller
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -44,13 +44,13 @@ public class ConfigStationPowerLimitController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:export')")
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:export')")
-    @Log(title = "????", businessType = BusinessType.EXPORT)
+    @Log(title = "限电配置", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     @PostMapping("/export")
     public void export(HttpServletResponse response, ConfigStationPowerLimit configStationPowerLimit)
     public void export(HttpServletResponse response, ConfigStationPowerLimit configStationPowerLimit)
     {
     {
         List<ConfigStationPowerLimit> list = configStationPowerLimitService.selectConfigStationPowerLimitList(configStationPowerLimit);
         List<ConfigStationPowerLimit> list = configStationPowerLimitService.selectConfigStationPowerLimitList(configStationPowerLimit);
         ExcelUtil<ConfigStationPowerLimit> util = new ExcelUtil<ConfigStationPowerLimit>(ConfigStationPowerLimit.class);
         ExcelUtil<ConfigStationPowerLimit> util = new ExcelUtil<ConfigStationPowerLimit>(ConfigStationPowerLimit.class);
-        util.exportExcel(response, list, "??????");
+        util.exportExcel(response, list, "限电配置数据");
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:query')")
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:query')")
@@ -61,7 +61,7 @@ public class ConfigStationPowerLimitController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:add')")
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:add')")
-    @Log(title = "????", businessType = BusinessType.INSERT)
+    @Log(title = "限电配置", businessType = BusinessType.INSERT)
     @PostMapping
     @PostMapping
     public AjaxResult add(@RequestBody ConfigStationPowerLimit configStationPowerLimit)
     public AjaxResult add(@RequestBody ConfigStationPowerLimit configStationPowerLimit)
     {
     {
@@ -69,7 +69,7 @@ public class ConfigStationPowerLimitController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:edit')")
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:edit')")
-    @Log(title = "????", businessType = BusinessType.UPDATE)
+    @Log(title = "限电配置", businessType = BusinessType.UPDATE)
     @PutMapping
     @PutMapping
     public AjaxResult edit(@RequestBody ConfigStationPowerLimit configStationPowerLimit)
     public AjaxResult edit(@RequestBody ConfigStationPowerLimit configStationPowerLimit)
     {
     {
@@ -77,7 +77,7 @@ public class ConfigStationPowerLimitController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:remove')")
     @PreAuthorize("@ss.hasPermi('config:stationPowerLimit:remove')")
-    @Log(title = "????", businessType = BusinessType.DELETE)
+    @Log(title = "限电配置", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     @DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     public AjaxResult remove(@PathVariable Long[] ids)
     {
     {

+ 6 - 6
forecast-backend-server/src/main/java/com/ufo/project/config/controller/ConfigStationPvModuleController.java

@@ -22,7 +22,7 @@ import com.ufo.base.common.utils.poi.ExcelUtil;
 import com.ufo.base.framework.web.page.TableDataInfo;
 import com.ufo.base.framework.web.page.TableDataInfo;
 
 
 /**
 /**
- * ????Controller
+ * 光伏组件Controller
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -44,13 +44,13 @@ public class ConfigStationPvModuleController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationModule:export')")
     @PreAuthorize("@ss.hasPermi('config:stationModule:export')")
-    @Log(title = "????", businessType = BusinessType.EXPORT)
+    @Log(title = "光伏组件", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     @PostMapping("/export")
     public void export(HttpServletResponse response, ConfigStationPvModule configStationPvModule)
     public void export(HttpServletResponse response, ConfigStationPvModule configStationPvModule)
     {
     {
         List<ConfigStationPvModule> list = configStationPvModuleService.selectConfigStationPvModuleList(configStationPvModule);
         List<ConfigStationPvModule> list = configStationPvModuleService.selectConfigStationPvModuleList(configStationPvModule);
         ExcelUtil<ConfigStationPvModule> util = new ExcelUtil<ConfigStationPvModule>(ConfigStationPvModule.class);
         ExcelUtil<ConfigStationPvModule> util = new ExcelUtil<ConfigStationPvModule>(ConfigStationPvModule.class);
-        util.exportExcel(response, list, "??????");
+        util.exportExcel(response, list, "光伏组件数据");
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationModule:query')")
     @PreAuthorize("@ss.hasPermi('config:stationModule:query')")
@@ -61,7 +61,7 @@ public class ConfigStationPvModuleController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationModule:add')")
     @PreAuthorize("@ss.hasPermi('config:stationModule:add')")
-    @Log(title = "????", businessType = BusinessType.INSERT)
+    @Log(title = "光伏组件", businessType = BusinessType.INSERT)
     @PostMapping
     @PostMapping
     public AjaxResult add(@RequestBody ConfigStationPvModule configStationPvModule)
     public AjaxResult add(@RequestBody ConfigStationPvModule configStationPvModule)
     {
     {
@@ -69,7 +69,7 @@ public class ConfigStationPvModuleController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationModule:edit')")
     @PreAuthorize("@ss.hasPermi('config:stationModule:edit')")
-    @Log(title = "????", businessType = BusinessType.UPDATE)
+    @Log(title = "光伏组件", businessType = BusinessType.UPDATE)
     @PutMapping
     @PutMapping
     public AjaxResult edit(@RequestBody ConfigStationPvModule configStationPvModule)
     public AjaxResult edit(@RequestBody ConfigStationPvModule configStationPvModule)
     {
     {
@@ -77,7 +77,7 @@ public class ConfigStationPvModuleController extends BaseController
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('config:stationModule:remove')")
     @PreAuthorize("@ss.hasPermi('config:stationModule:remove')")
-    @Log(title = "????", businessType = BusinessType.DELETE)
+    @Log(title = "光伏组件", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     @DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     public AjaxResult remove(@PathVariable Long[] ids)
     {
     {

+ 18 - 8
forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigDevice.java

@@ -1,6 +1,7 @@
 package com.ufo.project.config.domain;
 package com.ufo.project.config.domain;
-import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 
 
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.Data;
 
 
 /**
 /**
@@ -9,7 +10,7 @@ import lombok.Data;
  * @author ufo
  * @author ufo
  * @date 2026-08-06
  * @date 2026-08-06
  */
  */
-@Data 
+@Data
 public class ConfigDevice
 public class ConfigDevice
 {
 {
 
 
@@ -17,23 +18,32 @@ public class ConfigDevice
     private Long id;
     private Long id;
 
 
     /** 名称 */
     /** 名称 */
-    @Excel(name = "名称")
     private String name;
     private String name;
+    /** 设备类型 */
+    private String tp;
+    /** 品牌 */
+    private String brand;
+    /** 型号 */
+    private String model;
+    /** 序列号 */
+    private String serialNumber;
+    /** 状态 */
+    private String status;
+    /** 投运日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date installDate;
     /**
     /**
      * 配置通道ID
      * 配置通道ID
      */
      */
-    @Excel(name = "通道")
     private Long configChannelId;
     private Long configChannelId;
     /**
     /**
-     * 配置站点ID
+     * 配置站点ID(数据库列为varchar, 存数字字符串)
      */
      */
-    @Excel(name = "场站")
-    private Long configStationId;
+    private String configStationId;
 
 
     /**
     /**
      * Parent配置设备ID
      * Parent配置设备ID
      */
      */
-    @Excel(name = "父级设备")
     private Long configDeviceId;
     private Long configDeviceId;
 
 
     /**
     /**

+ 22 - 22
forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationChannel.java

@@ -6,7 +6,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 
 
 /**
 /**
- * ?????? config_station_channel
+ * 通道配置对象 config_station_channel
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -15,47 +15,47 @@ public class ConfigStationChannel extends BaseEntity
 {
 {
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
-    /** ???? */
+    /** 唯一标识 */
     private Long id;
     private Long id;
 
 
-    /** ??ID */
-    @Excel(name = "??ID")
+    /** 场站ID */
+    @Excel(name = "场站ID")
     private Long stationId;
     private Long stationId;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 所属场站 */
+    @Excel(name = "所属场站")
     private String stationName;
     private String stationName;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 通道名称 */
+    @Excel(name = "通道名称")
     private String channelName;
     private String channelName;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 协议 */
+    @Excel(name = "协议")
     private String protocol;
     private String protocol;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 主机地址 */
+    @Excel(name = "主机地址")
     private String host;
     private String host;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 端口 */
+    @Excel(name = "端口")
     private Long port;
     private Long port;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 采集间隔 */
+    @Excel(name = "采集间隔")
     private String collectInterval;
     private String collectInterval;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 数据类型 */
+    @Excel(name = "数据类型")
     private String dataType;
     private String dataType;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 状态 */
+    @Excel(name = "状态")
     private String status;
     private String status;
 
 
-    /** ?????? */
-    @Excel(name = "??????")
+    /** 最后同步时间 */
+    @Excel(name = "最后同步时间")
     private String lastSyncTime;
     private String lastSyncTime;
 
 
     public void setId(Long id) 
     public void setId(Long id) 

+ 20 - 20
forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationDevice.java

@@ -6,7 +6,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 
 
 /**
 /**
- * ?????? config_station_device
+ * 设备配置对象 config_station_device
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -15,43 +15,43 @@ public class ConfigStationDevice extends BaseEntity
 {
 {
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
-    /** ???? */
+    /** 唯一标识 */
     private Long id;
     private Long id;
 
 
-    /** ??ID */
-    @Excel(name = "??ID")
+    /** 场站ID */
+    @Excel(name = "场站ID")
     private Long stationId;
     private Long stationId;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 所属场站 */
+    @Excel(name = "所属场站")
     private String stationName;
     private String stationName;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 设备名称 */
+    @Excel(name = "设备名称")
     private String deviceName;
     private String deviceName;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 设备类型 */
+    @Excel(name = "设备类型")
     private String deviceType;
     private String deviceType;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 品牌 */
+    @Excel(name = "品牌")
     private String brand;
     private String brand;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 型号 */
+    @Excel(name = "型号")
     private String model;
     private String model;
 
 
-    /** ??? */
-    @Excel(name = "???")
+    /** 序列号 */
+    @Excel(name = "序列号")
     private String serialNumber;
     private String serialNumber;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 状态 */
+    @Excel(name = "状态")
     private String status;
     private String status;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 安装日期 */
+    @Excel(name = "安装日期")
     private String installDate;
     private String installDate;
 
 
     public void setId(Long id) 
     public void setId(Long id) 

+ 24 - 24
forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationPoint.java

@@ -6,7 +6,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 
 
 /**
 /**
- * ?????? config_station_point
+ * 测点配置对象 config_station_point
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -15,51 +15,51 @@ public class ConfigStationPoint extends BaseEntity
 {
 {
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
-    /** ???? */
+    /** 唯一标识 */
     private Long id;
     private Long id;
 
 
-    /** ??ID */
-    @Excel(name = "??ID")
+    /** 场站ID */
+    @Excel(name = "场站ID")
     private Long stationId;
     private Long stationId;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 所属场站 */
+    @Excel(name = "所属场站")
     private String stationName;
     private String stationName;
 
 
-    /** ??ID */
-    @Excel(name = "??ID")
+    /** 设备ID */
+    @Excel(name = "设备ID")
     private Long deviceId;
     private Long deviceId;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 设备名称 */
+    @Excel(name = "设备名称")
     private String deviceName;
     private String deviceName;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 测点名称 */
+    @Excel(name = "测点名称")
     private String pointName;
     private String pointName;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 单位 */
+    @Excel(name = "单位")
     private String unit;
     private String unit;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 精度 */
+    @Excel(name = "精度")
     private Long precisionValue;
     private Long precisionValue;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 量程 */
+    @Excel(name = "量程")
     private String measureRange;
     private String measureRange;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 协议 */
+    @Excel(name = "协议")
     private String protocol;
     private String protocol;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 地址 */
+    @Excel(name = "地址")
     private String address;
     private String address;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 采集间隔 */
+    @Excel(name = "采集间隔")
     private String collectInterval;
     private String collectInterval;
 
 
     public void setId(Long id) 
     public void setId(Long id) 

+ 20 - 20
forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationPowerLimit.java

@@ -6,7 +6,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 
 
 /**
 /**
- * ?????? config_station_power_limit
+ * 限电配置对象 config_station_power_limit
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -15,43 +15,43 @@ public class ConfigStationPowerLimit extends BaseEntity
 {
 {
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
-    /** ???? */
+    /** 唯一标识 */
     private Long id;
     private Long id;
 
 
-    /** ??ID */
-    @Excel(name = "??ID")
+    /** 场站ID */
+    @Excel(name = "场站ID")
     private Long stationId;
     private Long stationId;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 所属场站 */
+    @Excel(name = "所属场站")
     private String stationName;
     private String stationName;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 限电类型 */
+    @Excel(name = "限电类型")
     private String limitType;
     private String limitType;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 开始日期 */
+    @Excel(name = "开始日期")
     private String startDate;
     private String startDate;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 结束日期 */
+    @Excel(name = "结束日期")
     private String endDate;
     private String endDate;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 限电比例 */
+    @Excel(name = "限电比例")
     private String limitPercent;
     private String limitPercent;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 原因 */
+    @Excel(name = "原因")
     private String reason;
     private String reason;
 
 
-    /** ??? */
-    @Excel(name = "???")
+    /** 审批方 */
+    @Excel(name = "审批方")
     private String approver;
     private String approver;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 状态 */
+    @Excel(name = "状态")
     private String status;
     private String status;
 
 
     public void setId(Long id) 
     public void setId(Long id) 

+ 22 - 22
forecast-backend-server/src/main/java/com/ufo/project/config/domain/ConfigStationPvModule.java

@@ -7,7 +7,7 @@ import com.ufo.base.framework.aspectj.lang.annotation.Excel;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 
 
 /**
 /**
- * ?????? config_station_pv_module
+ * 光伏组件对象 config_station_pv_module
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21
@@ -16,47 +16,47 @@ public class ConfigStationPvModule extends BaseEntity
 {
 {
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
-    /** ???? */
+    /** 唯一标识 */
     private Long id;
     private Long id;
 
 
-    /** ??ID */
-    @Excel(name = "??ID")
+    /** 场站ID */
+    @Excel(name = "场站ID")
     private Long stationId;
     private Long stationId;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 所属场站 */
+    @Excel(name = "所属场站")
     private String stationName;
     private String stationName;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 组件型号 */
+    @Excel(name = "组件型号")
     private String model;
     private String model;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 品牌 */
+    @Excel(name = "品牌")
     private String brand;
     private String brand;
 
 
-    /** ????(W) */
-    @Excel(name = "????(W)")
+    /** 额定功率(W) */
+    @Excel(name = "额定功率(W)")
     private BigDecimal ratedPower;
     private BigDecimal ratedPower;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 组件类型 */
+    @Excel(name = "组件类型")
     private String moduleType;
     private String moduleType;
 
 
-    /** ?? */
-    @Excel(name = "??")
+    /** 数量 */
+    @Excel(name = "数量")
     private Long moduleCount;
     private Long moduleCount;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 转换效率 */
+    @Excel(name = "转换效率")
     private String conversionEfficiency;
     private String conversionEfficiency;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 温度系数 */
+    @Excel(name = "温度系数")
     private String temperatureCoefficient;
     private String temperatureCoefficient;
 
 
-    /** ???? */
-    @Excel(name = "????")
+    /** 安装日期 */
+    @Excel(name = "安装日期")
     private String installDate;
     private String installDate;
 
 
     public void setId(Long id) 
     public void setId(Long id) 

+ 171 - 0
forecast-backend-server/src/main/java/com/ufo/project/config/domain/vo/ConfigDeviceExportVo.java

@@ -0,0 +1,171 @@
+package com.ufo.project.config.domain.vo;
+
+import com.ufo.base.framework.aspectj.lang.annotation.Excel;
+import com.ufo.base.framework.aspectj.lang.annotation.Excel.ColumnType;
+
+/**
+ * 设备配置导出行数据(列名/值/顺序与设备管理页表格一致)
+ *
+ * @author ufo
+ * @date 2026-11-06
+ */
+public class ConfigDeviceExportVo
+{
+    /** 序号 */
+    @Excel(name = "序号", cellType = ColumnType.NUMERIC)
+    private Long serial;
+
+    /** 设备名称 */
+    @Excel(name = "设备名称")
+    private String name;
+
+    /** 通道 */
+    @Excel(name = "通道")
+    private String channelName;
+
+    /** 所属场站 */
+    @Excel(name = "所属场站")
+    private String stationName;
+
+    /** 设备类型 */
+    @Excel(name = "设备类型")
+    private String tp;
+
+    /** 品牌 */
+    @Excel(name = "品牌")
+    private String brand;
+
+    /** 型号 */
+    @Excel(name = "型号")
+    private String model;
+
+    /** 序列号 */
+    @Excel(name = "序列号")
+    private String serialNumber;
+
+    /** 状态 */
+    @Excel(name = "状态")
+    private String status;
+
+    /** 投运日期 */
+    @Excel(name = "投运日期")
+    private String installDate;
+
+    public ConfigDeviceExportVo()
+    {
+    }
+
+    public ConfigDeviceExportVo(Long serial, String name, String channelName, String stationName, String tp, String brand, String model, String serialNumber, String status, String installDate)
+    {
+        this.serial = serial;
+        this.name = name;
+        this.channelName = channelName;
+        this.stationName = stationName;
+        this.tp = tp;
+        this.brand = brand;
+        this.model = model;
+        this.serialNumber = serialNumber;
+        this.status = status;
+        this.installDate = installDate;
+    }
+
+    public Long getSerial()
+    {
+        return serial;
+    }
+
+    public void setSerial(Long serial)
+    {
+        this.serial = serial;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getChannelName()
+    {
+        return channelName;
+    }
+
+    public void setChannelName(String channelName)
+    {
+        this.channelName = channelName;
+    }
+
+    public String getStationName()
+    {
+        return stationName;
+    }
+
+    public void setStationName(String stationName)
+    {
+        this.stationName = stationName;
+    }
+
+    public String getTp()
+    {
+        return tp;
+    }
+
+    public void setTp(String tp)
+    {
+        this.tp = tp;
+    }
+
+    public String getBrand()
+    {
+        return brand;
+    }
+
+    public void setBrand(String brand)
+    {
+        this.brand = brand;
+    }
+
+    public String getModel()
+    {
+        return model;
+    }
+
+    public void setModel(String model)
+    {
+        this.model = model;
+    }
+
+    public String getSerialNumber()
+    {
+        return serialNumber;
+    }
+
+    public void setSerialNumber(String serialNumber)
+    {
+        this.serialNumber = serialNumber;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getInstallDate()
+    {
+        return installDate;
+    }
+
+    public void setInstallDate(String installDate)
+    {
+        this.installDate = installDate;
+    }
+}

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationChannelMapper.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationChannel;
 import com.ufo.project.config.domain.ConfigStationChannel;
 
 
 /**
 /**
- * ????Mapper??
+ * 通道配置Mapper接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationDeviceMapper.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationDevice;
 import com.ufo.project.config.domain.ConfigStationDevice;
 
 
 /**
 /**
- * ????Mapper??
+ * 设备配置Mapper接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationPointMapper.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationPoint;
 import com.ufo.project.config.domain.ConfigStationPoint;
 
 
 /**
 /**
- * ????Mapper??
+ * 测点配置Mapper接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationPowerLimitMapper.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationPowerLimit;
 import com.ufo.project.config.domain.ConfigStationPowerLimit;
 
 
 /**
 /**
- * ????Mapper??
+ * 限电配置Mapper接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/mapper/ConfigStationPvModuleMapper.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationPvModule;
 import com.ufo.project.config.domain.ConfigStationPvModule;
 
 
 /**
 /**
- * ????Mapper??
+ * 光伏组件Mapper接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationChannelService.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationChannel;
 import com.ufo.project.config.domain.ConfigStationChannel;
 
 
 /**
 /**
- * ????Service??
+ * 通道配置Service接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationDeviceService.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationDevice;
 import com.ufo.project.config.domain.ConfigStationDevice;
 
 
 /**
 /**
- * ????Service??
+ * 设备配置Service接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationPointService.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationPoint;
 import com.ufo.project.config.domain.ConfigStationPoint;
 
 
 /**
 /**
- * ????Service??
+ * 测点配置Service接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationPowerLimitService.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationPowerLimit;
 import com.ufo.project.config.domain.ConfigStationPowerLimit;
 
 
 /**
 /**
- * ????Service??
+ * 限电配置Service接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/IConfigStationPvModuleService.java

@@ -4,7 +4,7 @@ import java.util.List;
 import com.ufo.project.config.domain.ConfigStationPvModule;
 import com.ufo.project.config.domain.ConfigStationPvModule;
 
 
 /**
 /**
- * ????Service??
+ * 光伏组件Service接口
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationChannelServiceImpl.java

@@ -9,7 +9,7 @@ import com.ufo.project.config.domain.ConfigStationChannel;
 import com.ufo.project.config.service.IConfigStationChannelService;
 import com.ufo.project.config.service.IConfigStationChannelService;
 
 
 /**
 /**
- * ????Service?????
+ * 通道配置Service业务层处理
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationDeviceServiceImpl.java

@@ -9,7 +9,7 @@ import com.ufo.project.config.domain.ConfigStationDevice;
 import com.ufo.project.config.service.IConfigStationDeviceService;
 import com.ufo.project.config.service.IConfigStationDeviceService;
 
 
 /**
 /**
- * ????Service?????
+ * 设备配置Service业务层处理
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationPointServiceImpl.java

@@ -9,7 +9,7 @@ import com.ufo.project.config.domain.ConfigStationPoint;
 import com.ufo.project.config.service.IConfigStationPointService;
 import com.ufo.project.config.service.IConfigStationPointService;
 
 
 /**
 /**
- * ????Service?????
+ * 测点配置Service业务层处理
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationPowerLimitServiceImpl.java

@@ -9,7 +9,7 @@ import com.ufo.project.config.domain.ConfigStationPowerLimit;
 import com.ufo.project.config.service.IConfigStationPowerLimitService;
 import com.ufo.project.config.service.IConfigStationPowerLimitService;
 
 
 /**
 /**
- * ????Service?????
+ * 限电配置Service业务层处理
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 1 - 1
forecast-backend-server/src/main/java/com/ufo/project/config/service/impl/ConfigStationPvModuleServiceImpl.java

@@ -9,7 +9,7 @@ import com.ufo.project.config.domain.ConfigStationPvModule;
 import com.ufo.project.config.service.IConfigStationPvModuleService;
 import com.ufo.project.config.service.IConfigStationPvModuleService;
 
 
 /**
 /**
- * ????Service?????
+ * 光伏组件Service业务层处理
  *
  *
  * @author ufo
  * @author ufo
  * @date 2026-07-21
  * @date 2026-07-21

+ 16 - 16
forecast-backend-server/src/main/java/com/ufo/project/data/task/MockDataTask.java

@@ -29,8 +29,8 @@ import com.ufo.project.weather.mapper.DataWeatherLocalMapper;
 /**
 /**
  * 功率与气象mock数据生成任务
  * 功率与气象mock数据生成任务
  *
  *
- * 在 project.profile 目录下生成 超短期/短期/中期 功率预测mock文件(生产环境即 /home/power/upload/power/MOCK/BHWP01 下)
- * 及短期气象mock文件(生产环境即 /home/power/upload/weather/MOCK/BHWP01 下),
+ * 在 project.profile 目录下生成 超短期/短期/中期 功率预测mock文件(生产环境即 /home/power/upload/power/MOCK/YMPV03 下)
+ * 及短期气象mock文件(生产环境即 /home/power/upload/weather/MOCK/YMPV03 下),
  * 供数据文件同步任务(data_file_sync_config)消费.
  * 供数据文件同步任务(data_file_sync_config)消费.
  * 文件命名与init_time均使用UTC时间; time列为UTC, time_shanghai列为UTC+8.
  * 文件命名与init_time均使用UTC时间; time列为UTC, time_shanghai列为UTC+8.
  * 文件格式:
  * 文件格式:
@@ -44,10 +44,10 @@ import com.ufo.project.weather.mapper.DataWeatherLocalMapper;
  *
  *
  * 短期气象mock为SYSU格式38列CSV, 自起报时间(含)起961点(10天), 间隔15分钟,
  * 短期气象mock为SYSU格式38列CSV, 自起报时间(含)起961点(10天), 间隔15分钟,
  * 文件名时间为UTC, date_time列为GMT+8(即文件名时间+8h);
  * 文件名时间为UTC, date_time列为GMT+8(即文件名时间+8h);
- * t2m/rh2/sp/云量/风/ghi/dni/dhi尽量符合物理规律, 按北纬38.9度定标, 同样按起报时间可复现.
+ * t2m/rh2/sp/云量/风/ghi/dni/dhi尽量符合物理规律, 按北纬35.1度定标, 同样按起报时间可复现.
  *
  *
  * 另含采集数据mock任务(generateCollectedData): 每5分钟向 data_weather_local 与
  * 另含采集数据mock任务(generateCollectedData): 每5分钟向 data_weather_local 与
- * data_electricity_local 各插1行, tm取当前最近5分钟整北京时间, config_station_id固定为2,
+ * data_electricity_local 各插1行, tm取当前最近5分钟整北京时间, config_station_id固定为4,
  * 两行共享同一时刻物理状态(云量/钟形/季节), 数据尽量接近真实, 按北京日期可复现.
  * 两行共享同一时刻物理状态(云量/钟形/季节), 数据尽量接近真实, 按北京日期可复现.
  *
  *
  * @author ufo
  * @author ufo
@@ -97,14 +97,14 @@ public class MockDataTask
     /** 中期数据点数(自起报时间(含)起960点) */
     /** 中期数据点数(自起报时间(含)起960点) */
     private static final int MEDIUM_POINTS = 960;
     private static final int MEDIUM_POINTS = 960;
 
 
-    /** 出力上限(kW, 与采集数据mock一致, 按150000kW装机容量定标) */
-    private static final double POWER_CAP = 150000.0;
+    /** 出力上限(kW, 与采集数据mock一致, 按80000kW装机容量定标) */
+    private static final double POWER_CAP = 80000.0;
 
 
     /** 采集数据mock固定场站ID(config_station_id) */
     /** 采集数据mock固定场站ID(config_station_id) */
-    private static final long COLLECT_STATION_ID = 2L;
+    private static final long COLLECT_STATION_ID = 4L;
 
 
     /** 采集数据mock装机容量(kW) */
     /** 采集数据mock装机容量(kW) */
-    private static final double COLLECT_CAPACITY_KW = 150000.0;
+    private static final double COLLECT_CAPACITY_KW = 80000.0;
 
 
     /** 采集数据mock理论出力定标的晴空峰值辐照度(W/m², 夏季正午晴空) */
     /** 采集数据mock理论出力定标的晴空峰值辐照度(W/m², 夏季正午晴空) */
     private static final double CLEAR_PEAK_REF = 850.0;
     private static final double CLEAR_PEAK_REF = 850.0;
@@ -113,13 +113,13 @@ public class MockDataTask
     private static final int WEATHER_POINTS = 961;
     private static final int WEATHER_POINTS = 961;
 
 
     /** 气象mock场站编号(farm_id, 同时是文件名的场站段) */
     /** 气象mock场站编号(farm_id, 同时是文件名的场站段) */
-    private static final String WEATHER_FARM_ID = "BHWP01";
+    private static final String WEATHER_FARM_ID = "YMPV03";
 
 
     /** 气象mock固定经度(文件名按经度-纬度顺序) */
     /** 气象mock固定经度(文件名按经度-纬度顺序) */
-    private static final double WEATHER_LON = 121.4737;
+    private static final double WEATHER_LON = 118.3262;
 
 
     /** 气象mock固定纬度 */
     /** 气象mock固定纬度 */
-    private static final double WEATHER_LAT = 38.9087;
+    private static final double WEATHER_LAT = 35.0654;
 
 
     /** 气象文件名日期格式(yyyyMMdd, UTC即北京日期) */
     /** 气象文件名日期格式(yyyyMMdd, UTC即北京日期) */
     private static final DateTimeFormatter WEATHER_FILE_DATE_FMT = DateTimeFormatter.ofPattern("yyyyMMdd");
     private static final DateTimeFormatter WEATHER_FILE_DATE_FMT = DateTimeFormatter.ofPattern("yyyyMMdd");
@@ -217,7 +217,7 @@ public class MockDataTask
 
 
     /**
     /**
      * 短期气象: 每天凌晨2点执行一次, 生成当日(北京日期)12:00 UTC起报的一个预报文件,
      * 短期气象: 每天凌晨2点执行一次, 生成当日(北京日期)12:00 UTC起报的一个预报文件,
-     * 自起报时间(含)起961点, 间隔15分钟, 输出到 weather/MOCK/BHWP01/;
+     * 自起报时间(含)起961点, 间隔15分钟, 输出到 weather/MOCK/YMPV03/;
      * 文件名时间为UTC, date_time列为GMT+8(即文件名时间+8h)
      * 文件名时间为UTC, date_time列为GMT+8(即文件名时间+8h)
      */
      */
     @Scheduled(cron = "0 0 2 * * ?")
     @Scheduled(cron = "0 0 2 * * ?")
@@ -238,8 +238,8 @@ public class MockDataTask
     /**
     /**
      * 采集数据: 每5分钟执行一次, 向 data_weather_local 与 data_electricity_local 各插1行,
      * 采集数据: 每5分钟执行一次, 向 data_weather_local 与 data_electricity_local 各插1行,
      * tm为当前时间就近取整到最近5分钟整北京时间(如00:05:34→00:05:00, 00:09:12→00:10:00),
      * tm为当前时间就近取整到最近5分钟整北京时间(如00:05:34→00:05:00, 00:09:12→00:10:00),
-     * config_station_id固定为2; 两行共享同一时刻的物理状态(云量/钟形/季节), 功率与气象描述同一天气;
-     * 理论出力为按150000kW装机容量定标的晴空钟形(夏峰~150000/冬峰~112500, 夜间0),
+     * config_station_id固定为4; 两行共享同一时刻的物理状态(云量/钟形/季节), 功率与气象描述同一天气;
+     * 理论出力为按80000kW装机容量定标的晴空钟形(夏峰~80000/冬峰~61800, 夜间0),
      * 实发功率=理论×慢快云量衰减×可用率(恒≤理论), 随机参数按北京日期派生, 当日数据稳定可复现
      * 实发功率=理论×慢快云量衰减×可用率(恒≤理论), 随机参数按北京日期派生, 当日数据稳定可复现
      */
      */
     @Scheduled(cron = "0 0/5 * * * ?")
     @Scheduled(cron = "0 0/5 * * * ?")
@@ -476,7 +476,7 @@ public class MockDataTask
     private Path generateFile(String type, ZonedDateTime init, DateTimeFormatter fileFmt,
     private Path generateFile(String type, ZonedDateTime init, DateTimeFormatter fileFmt,
             DateTimeFormatter initFmt, int firstOffsetMin, int points) throws IOException
             DateTimeFormatter initFmt, int firstOffsetMin, int points) throws IOException
     {
     {
-        Path dir = Paths.get(ProjectConfig.getProfile(), "power", "MOCK", "BHWP01", type,
+        Path dir = Paths.get(ProjectConfig.getProfile(), "power", "MOCK", "YMPV03", type,
                 String.format(Locale.ROOT, "%04d", init.getYear()),
                 String.format(Locale.ROOT, "%04d", init.getYear()),
                 String.format(Locale.ROOT, "%02d", init.getMonthValue()),
                 String.format(Locale.ROOT, "%02d", init.getMonthValue()),
                 String.format(Locale.ROOT, "%02d", init.getDayOfMonth()));
                 String.format(Locale.ROOT, "%02d", init.getDayOfMonth()));
@@ -512,7 +512,7 @@ public class MockDataTask
 
 
     /**
     /**
      * 计算mock光伏出力: 夜间为0, 白天钟形曲线, 峰值与日照时长随季节变化, 叠加缓慢云量波动;
      * 计算mock光伏出力: 夜间为0, 白天钟形曲线, 峰值与日照时长随季节变化, 叠加缓慢云量波动;
-     * 峰值按150000kW装机容量对晴空辐照定标(与采集数据mock同量纲, 夏峰~150000/冬峰~112500),
+     * 峰值按80000kW装机容量对晴空辐照定标(与采集数据mock同量纲, 夏峰~80000/冬峰~61800),
      * 与采集数据在相近时刻的数值接近
      * 与采集数据在相近时刻的数值接近
      *
      *
      * @param tUtc 数据时刻(UTC)
      * @param tUtc 数据时刻(UTC)

+ 56 - 0
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/controller/DataReportLogController.java

@@ -2,21 +2,31 @@ package com.ufo.project.forecast.fileupload.controller;
 
 
 import java.io.File;
 import java.io.File;
 import java.io.IOException;
 import java.io.IOException;
+import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Files;
 import java.util.List;
 import java.util.List;
+import javax.servlet.http.HttpServletResponse;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PathVariable;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
+import com.alibaba.excel.EasyExcel;
 import com.ufo.base.common.utils.StringUtils;
 import com.ufo.base.common.utils.StringUtils;
+import com.ufo.base.framework.aspectj.lang.annotation.Log;
+import com.ufo.base.framework.aspectj.lang.enums.BusinessType;
 import com.ufo.base.framework.web.controller.BaseController;
 import com.ufo.base.framework.web.controller.BaseController;
 import com.ufo.base.framework.web.domain.AjaxResult;
 import com.ufo.base.framework.web.domain.AjaxResult;
 import com.ufo.base.framework.web.page.TableDataInfo;
 import com.ufo.base.framework.web.page.TableDataInfo;
 import com.ufo.project.forecast.fileupload.domain.DataReportLog;
 import com.ufo.project.forecast.fileupload.domain.DataReportLog;
+import com.ufo.project.forecast.fileupload.domain.vo.UploadRateStatQuery;
+import com.ufo.project.forecast.fileupload.domain.vo.UploadRateStatVO;
 import com.ufo.project.forecast.fileupload.service.IDataReportLogService;
 import com.ufo.project.forecast.fileupload.service.IDataReportLogService;
 
 
 /**
 /**
@@ -79,4 +89,50 @@ public class DataReportLogController extends BaseController
             return AjaxResult.error("读取上报文件失败: " + path);
             return AjaxResult.error("读取上报文件失败: " + path);
         }
         }
     }
     }
+
+    /**
+     * 光伏上传率统计查询(手动分页: total=范围内天数)
+     */
+    @PreAuthorize("@ss.hasPermi('fileupload:reportLog:uploadRate')")
+    @Log(title = "光伏上传率统计", businessType = BusinessType.OTHER)
+    @PostMapping("/uploadRate/list")
+    public TableDataInfo uploadRateList(@RequestBody UploadRateStatQuery query)
+    {
+        long total = dataReportLogService.uploadRateTotalDays(query);
+        List<UploadRateStatVO> rows = dataReportLogService.uploadRatePageList(query);
+        return new TableDataInfo(rows, (int) total);
+    }
+
+    /**
+     * 光伏上传率统计导出(全量日期范围)
+     */
+    @PreAuthorize("@ss.hasPermi('fileupload:reportLog:uploadRateExport')")
+    @Log(title = "光伏上传率统计", businessType = BusinessType.EXPORT)
+    @PostMapping("/uploadRate/export")
+    public void uploadRateExport(@RequestBody UploadRateStatQuery query, HttpServletResponse response) throws IOException
+    {
+        List<UploadRateStatVO> data = dataReportLogService.uploadRateExportList(query);
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        String dateRange = StringUtils.equals(query.getStartTime(), query.getEndTime())
+                ? query.getStartTime()
+                : query.getStartTime() + "_" + query.getEndTime();
+        String fileName = URLEncoder.encode("光伏上传率统计_" + dateRange.replace("-", "") + ".xlsx",
+                "UTF-8").replaceAll("\\+", "%20");
+        response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName);
+        EasyExcel.write(response.getOutputStream(), UploadRateStatVO.class)
+                .sheet("光伏上传率统计")
+                .doWrite(data);
+    }
+
+    /**
+     * 数据补传: 对比当日上报成功条数与每日文件上传配置, 缺失类型插入对应条数上传成功记录
+     */
+    @PreAuthorize("@ss.hasPermi('fileupload:reportLog:reUpload')")
+    @Log(title = "数据补传", businessType = BusinessType.INSERT)
+    @GetMapping("/reUpload")
+    public AjaxResult reUpload(@RequestParam("stationCode") String stationCode)
+    {
+        return AjaxResult.success(dataReportLogService.reUpload(stationCode));
+    }
 }
 }

+ 9 - 2
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/DataReportLog.java

@@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
 
@@ -18,8 +20,13 @@ import org.apache.commons.lang3.builder.ToStringStyle;
 @TableName("data_report_log")
 @TableName("data_report_log")
 public class DataReportLog
 public class DataReportLog
 {
 {
-    /** 日志主键ID */
-    @TableId(value = "id", type = IdType.AUTO)
+    /**
+     * 日志主键ID
+     * 雪花ID客户端生成(ASSIGN_ID): 该表由外部服务写入显式ID, DB自增序列与max(id)失步, 依赖AUTO会主键冲突
+     * 序列化为字符串: 雪花ID超过JS Number安全整数(2^53), 前端回传file/content/{id}需保持精度
+     */
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @JsonSerialize(using = ToStringSerializer.class)
     private Long id;
     private Long id;
 
 
     /** 文件类型:supershort|short|medium */
     /** 文件类型:supershort|short|medium */

+ 71 - 0
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/vo/ReUploadCountRow.java

@@ -0,0 +1,71 @@
+package com.ufo.project.forecast.fileupload.domain.vo;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 数据补传聚合行(仅 Mapper 聚合结果映射用)
+ *
+ * @author ufo
+ * @date 2026-11-05
+ */
+public class ReUploadCountRow implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 文件类型 */
+    private String type;
+
+    /** 上报状态:0待发送,1上报成功 */
+    private Integer status;
+
+    /** 记录条数 */
+    private Long cnt;
+
+    /** 获取文件类型 */
+    public String getType()
+    {
+        return type;
+    }
+
+    /** 设置文件类型 */
+    public void setType(String type)
+    {
+        this.type = type;
+    }
+
+    /** 获取上报状态 */
+    public Integer getStatus()
+    {
+        return status;
+    }
+
+    /** 设置上报状态 */
+    public void setStatus(Integer status)
+    {
+        this.status = status;
+    }
+
+    /** 获取记录条数 */
+    public Long getCnt()
+    {
+        return cnt;
+    }
+
+    /** 设置记录条数 */
+    public void setCnt(Long cnt)
+    {
+        this.cnt = cnt;
+    }
+
+    @Override
+    public String toString()
+    {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("type", getType())
+            .append("status", getStatus())
+            .append("cnt", getCnt())
+            .toString();
+    }
+}

+ 71 - 0
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/vo/UploadRateCountRow.java

@@ -0,0 +1,71 @@
+package com.ufo.project.forecast.fileupload.domain.vo;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 光伏上传率统计聚合行(仅 Mapper 聚合结果映射用)
+ *
+ * @author ufo
+ * @date 2026-11-04
+ */
+public class UploadRateCountRow implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 上海时区日期 yyyy-MM-dd */
+    private String statDate;
+
+    /** 文件类型 */
+    private String type;
+
+    /** 成功条数 */
+    private Long cnt;
+
+    /** 获取上海时区日期 */
+    public String getStatDate()
+    {
+        return statDate;
+    }
+
+    /** 设置上海时区日期 */
+    public void setStatDate(String statDate)
+    {
+        this.statDate = statDate;
+    }
+
+    /** 获取文件类型 */
+    public String getType()
+    {
+        return type;
+    }
+
+    /** 设置文件类型 */
+    public void setType(String type)
+    {
+        this.type = type;
+    }
+
+    /** 获取成功条数 */
+    public Long getCnt()
+    {
+        return cnt;
+    }
+
+    /** 设置成功条数 */
+    public void setCnt(Long cnt)
+    {
+        this.cnt = cnt;
+    }
+
+    @Override
+    public String toString()
+    {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("statDate", getStatDate())
+            .append("type", getType())
+            .append("cnt", getCnt())
+            .toString();
+    }
+}

+ 103 - 0
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/vo/UploadRateStatQuery.java

@@ -0,0 +1,103 @@
+package com.ufo.project.forecast.fileupload.domain.vo;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 光伏上传率统计查询对象
+ *
+ * @author ufo
+ * @date 2026-11-04
+ */
+public class UploadRateStatQuery implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 场站编码(必填) */
+    private String stationCode;
+
+    /** 起始时间 yyyy-MM-dd(必填) */
+    private String startTime;
+
+    /** 截止时间 yyyy-MM-dd(必填) */
+    private String endTime;
+
+    /** 页码,缺省按 1 */
+    private Integer pageNum;
+
+    /** 每页行数,缺省按 10 */
+    private Integer pageSize;
+
+    /** 获取场站编码 */
+    public String getStationCode()
+    {
+        return stationCode;
+    }
+
+    /** 设置场站编码 */
+    public void setStationCode(String stationCode)
+    {
+        this.stationCode = stationCode;
+    }
+
+    /** 获取起始时间 */
+    public String getStartTime()
+    {
+        return startTime;
+    }
+
+    /** 设置起始时间 */
+    public void setStartTime(String startTime)
+    {
+        this.startTime = startTime;
+    }
+
+    /** 获取截止时间 */
+    public String getEndTime()
+    {
+        return endTime;
+    }
+
+    /** 设置截止时间 */
+    public void setEndTime(String endTime)
+    {
+        this.endTime = endTime;
+    }
+
+    /** 获取页码 */
+    public Integer getPageNum()
+    {
+        return pageNum;
+    }
+
+    /** 设置页码 */
+    public void setPageNum(Integer pageNum)
+    {
+        this.pageNum = pageNum;
+    }
+
+    /** 获取每页行数 */
+    public Integer getPageSize()
+    {
+        return pageSize;
+    }
+
+    /** 设置每页行数 */
+    public void setPageSize(Integer pageSize)
+    {
+        this.pageSize = pageSize;
+    }
+
+    @Override
+    public String toString()
+    {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("stationCode", getStationCode())
+            .append("startTime", getStartTime())
+            .append("endTime", getEndTime())
+            .append("pageNum", getPageNum())
+            .append("pageSize", getPageSize())
+            .toString();
+    }
+}

+ 194 - 0
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/domain/vo/UploadRateStatVO.java

@@ -0,0 +1,194 @@
+package com.ufo.project.forecast.fileupload.domain.vo;
+
+import java.io.Serializable;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 光伏上传率统计结果行(一行一天)
+ *
+ * @author ufo
+ * @date 2026-11-04
+ */
+public class UploadRateStatVO implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 日期时间 yyyy-MM-dd */
+    @ExcelProperty(index = 0, value = "日期时间")
+    private String date;
+
+    /** 超短期文件上传率(%) */
+    @ExcelProperty(index = 1, value = "超短期文件上传率(%)")
+    private Double supershortRate;
+
+    /** 短期文件上传率(%) */
+    @ExcelProperty(index = 2, value = "短期文件上传率(%)")
+    private Double shortRate;
+
+    /** 中期文件上传率(%) */
+    @ExcelProperty(index = 3, value = "中期文件上传率(%)")
+    private Double mediumRate;
+
+    /** 环境检测仪数据上传率(%) */
+    @ExcelProperty(index = 4, value = "环境检测仪数据上传率(%)")
+    private Double envlDetectorRate;
+
+    /** 逆变器运行信息文件上传率(%) */
+    @ExcelProperty(index = 5, value = "逆变器运行信息文件上传率(%)")
+    private Double inverterOperationRate;
+
+    /** 升压变数据上传率(%) */
+    @ExcelProperty(index = 6, value = "升压变数据上传率(%)")
+    private Double boosterTransformerRate;
+
+    /** 理论功率文件上传率(%) */
+    @ExcelProperty(index = 7, value = "理论功率文件上传率(%)")
+    private Double theoreticalPowerRate;
+
+    /** 数值天气预报文件上传率(%) */
+    @ExcelProperty(index = 8, value = "数值天气预报文件上传率(%)")
+    private Double numericalWeatherRate;
+
+    /** 发电计划文件上传率(%) */
+    @ExcelProperty(index = 9, value = "发电计划文件上传率(%)")
+    private Double powerGenerationPlanRate;
+
+    /** 获取日期时间 */
+    public String getDate()
+    {
+        return date;
+    }
+
+    /** 设置日期时间 */
+    public void setDate(String date)
+    {
+        this.date = date;
+    }
+
+    /** 获取超短期文件上传率 */
+    public Double getSupershortRate()
+    {
+        return supershortRate;
+    }
+
+    /** 设置超短期文件上传率 */
+    public void setSupershortRate(Double supershortRate)
+    {
+        this.supershortRate = supershortRate;
+    }
+
+    /** 获取短期文件上传率 */
+    public Double getShortRate()
+    {
+        return shortRate;
+    }
+
+    /** 设置短期文件上传率 */
+    public void setShortRate(Double shortRate)
+    {
+        this.shortRate = shortRate;
+    }
+
+    /** 获取中期文件上传率 */
+    public Double getMediumRate()
+    {
+        return mediumRate;
+    }
+
+    /** 设置中期文件上传率 */
+    public void setMediumRate(Double mediumRate)
+    {
+        this.mediumRate = mediumRate;
+    }
+
+    /** 获取环境检测仪数据上传率 */
+    public Double getEnvlDetectorRate()
+    {
+        return envlDetectorRate;
+    }
+
+    /** 设置环境检测仪数据上传率 */
+    public void setEnvlDetectorRate(Double envlDetectorRate)
+    {
+        this.envlDetectorRate = envlDetectorRate;
+    }
+
+    /** 获取逆变器运行信息文件上传率 */
+    public Double getInverterOperationRate()
+    {
+        return inverterOperationRate;
+    }
+
+    /** 设置逆变器运行信息文件上传率 */
+    public void setInverterOperationRate(Double inverterOperationRate)
+    {
+        this.inverterOperationRate = inverterOperationRate;
+    }
+
+    /** 获取升压变数据上传率 */
+    public Double getBoosterTransformerRate()
+    {
+        return boosterTransformerRate;
+    }
+
+    /** 设置升压变数据上传率 */
+    public void setBoosterTransformerRate(Double boosterTransformerRate)
+    {
+        this.boosterTransformerRate = boosterTransformerRate;
+    }
+
+    /** 获取理论功率文件上传率 */
+    public Double getTheoreticalPowerRate()
+    {
+        return theoreticalPowerRate;
+    }
+
+    /** 设置理论功率文件上传率 */
+    public void setTheoreticalPowerRate(Double theoreticalPowerRate)
+    {
+        this.theoreticalPowerRate = theoreticalPowerRate;
+    }
+
+    /** 获取数值天气预报文件上传率 */
+    public Double getNumericalWeatherRate()
+    {
+        return numericalWeatherRate;
+    }
+
+    /** 设置数值天气预报文件上传率 */
+    public void setNumericalWeatherRate(Double numericalWeatherRate)
+    {
+        this.numericalWeatherRate = numericalWeatherRate;
+    }
+
+    /** 获取发电计划文件上传率 */
+    public Double getPowerGenerationPlanRate()
+    {
+        return powerGenerationPlanRate;
+    }
+
+    /** 设置发电计划文件上传率 */
+    public void setPowerGenerationPlanRate(Double powerGenerationPlanRate)
+    {
+        this.powerGenerationPlanRate = powerGenerationPlanRate;
+    }
+
+    @Override
+    public String toString()
+    {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("date", getDate())
+            .append("supershortRate", getSupershortRate())
+            .append("shortRate", getShortRate())
+            .append("mediumRate", getMediumRate())
+            .append("envlDetectorRate", getEnvlDetectorRate())
+            .append("inverterOperationRate", getInverterOperationRate())
+            .append("boosterTransformerRate", getBoosterTransformerRate())
+            .append("theoreticalPowerRate", getTheoreticalPowerRate())
+            .append("numericalWeatherRate", getNumericalWeatherRate())
+            .append("powerGenerationPlanRate", getPowerGenerationPlanRate())
+            .toString();
+    }
+}

+ 39 - 0
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/mapper/DataReportLogMapper.java

@@ -1,7 +1,12 @@
 package com.ufo.project.forecast.fileupload.mapper;
 package com.ufo.project.forecast.fileupload.mapper;
 
 
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ufo.project.forecast.fileupload.domain.DataReportLog;
 import com.ufo.project.forecast.fileupload.domain.DataReportLog;
+import com.ufo.project.forecast.fileupload.domain.vo.ReUploadCountRow;
+import com.ufo.project.forecast.fileupload.domain.vo.UploadRateCountRow;
 
 
 /**
 /**
  * 功率预测上报日志Mapper接口(MyBatis-Plus, 无需Mapper XML)
  * 功率预测上报日志Mapper接口(MyBatis-Plus, 无需Mapper XML)
@@ -11,4 +16,38 @@ import com.ufo.project.forecast.fileupload.domain.DataReportLog;
  */
  */
 public interface DataReportLogMapper extends BaseMapper<DataReportLog>
 public interface DataReportLogMapper extends BaseMapper<DataReportLog>
 {
 {
+    /**
+     * 按"天×type"统计上报成功条数(只统计status=1, 上海时区分天, 时间范围左闭右开含截止日全天)
+     *
+     * @param stationCode 场站编码
+     * @param windowStart 窗口起始日 yyyy-MM-dd
+     * @param windowEnd 窗口截止日 yyyy-MM-dd
+     * @return statDate/type/cnt 聚合行
+     */
+    @Select("SELECT DATE(est_report_time AT TIME ZONE 'Asia/Shanghai') AS stat_date, "
+            + "type, COUNT(*) AS cnt "
+            + "FROM data_report_log "
+            + "WHERE station_code = #{stationCode} "
+            + "AND status = 1 "
+            + "AND est_report_time >= (#{windowStart}::timestamp AT TIME ZONE 'Asia/Shanghai') "
+            + "AND est_report_time < (#{windowEnd}::timestamp AT TIME ZONE 'Asia/Shanghai') + INTERVAL '1 day' "
+            + "GROUP BY 1, 2")
+    List<UploadRateCountRow> selectUploadRateCounts(@Param("stationCode") String stationCode,
+            @Param("windowStart") String windowStart, @Param("windowEnd") String windowEnd);
+
+    /**
+     * 按"type×status"统计当日上报表条数(上海时区分天, status只取0待发送/1上报成功)
+     *
+     * @param stationCode 场站编码
+     * @param day 当日日期(上海时区) yyyy-MM-dd
+     * @return type/status/cnt 聚合行
+     */
+    @Select("SELECT type, status, COUNT(*) AS cnt "
+            + "FROM data_report_log "
+            + "WHERE station_code = #{stationCode} "
+            + "AND status IN (0, 1) "
+            + "AND DATE(est_report_time AT TIME ZONE 'Asia/Shanghai') = #{day}::date "
+            + "GROUP BY 1, 2")
+    List<ReUploadCountRow> selectTodayCounts(@Param("stationCode") String stationCode,
+            @Param("day") String day);
 }
 }

+ 25 - 0
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/service/IDataReportLogService.java

@@ -2,6 +2,8 @@ package com.ufo.project.forecast.fileupload.service;
 
 
 import java.util.List;
 import java.util.List;
 import com.ufo.project.forecast.fileupload.domain.DataReportLog;
 import com.ufo.project.forecast.fileupload.domain.DataReportLog;
+import com.ufo.project.forecast.fileupload.domain.vo.UploadRateStatQuery;
+import com.ufo.project.forecast.fileupload.domain.vo.UploadRateStatVO;
 
 
 /**
 /**
  * 功率预测上报日志Service接口
  * 功率预测上报日志Service接口
@@ -26,4 +28,27 @@ public interface IDataReportLogService
      * @return 功率预测上报日志集合
      * @return 功率预测上报日志集合
      */
      */
     public List<DataReportLog> selectDataReportLogList(DataReportLog dataReportLog);
     public List<DataReportLog> selectDataReportLogList(DataReportLog dataReportLog);
+
+    /**
+     * 光伏上传率统计: 日期范围天数(手动分页的total)
+     */
+    public long uploadRateTotalDays(UploadRateStatQuery query);
+
+    /**
+     * 光伏上传率统计: 查询当前页(每页每天一行, 无记录天为0.00)
+     */
+    public List<UploadRateStatVO> uploadRatePageList(UploadRateStatQuery query);
+
+    /**
+     * 光伏上传率统计: 查询全量日期(导出用)
+     */
+    public List<UploadRateStatVO> uploadRateExportList(UploadRateStatQuery query);
+
+    /**
+     * 数据补传: 按类型对比当日上报成功条数与每日文件上传配置, 缺失类型插入对应条数上传成功记录
+     *
+     * @param stationCode 场站编码
+     * @return 补传结果提示消息
+     */
+    public String reUpload(String stationCode);
 }
 }

+ 324 - 0
forecast-backend-server/src/main/java/com/ufo/project/forecast/fileupload/service/impl/DataReportLogServiceImpl.java

@@ -1,20 +1,36 @@
 package com.ufo.project.forecast.fileupload.service.impl;
 package com.ufo.project.forecast.fileupload.service.impl;
 
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDate;
 import java.time.ZoneId;
 import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
 import java.util.Set;
 import java.util.Set;
+import java.util.UUID;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ufo.base.common.exception.ServiceException;
+import com.ufo.base.common.utils.SecurityUtils;
 import com.ufo.base.common.utils.StringUtils;
 import com.ufo.base.common.utils.StringUtils;
+import com.ufo.module.system.domain.SysDictData;
+import com.ufo.module.system.service.ISysDictTypeService;
 import com.ufo.project.config.domain.ConfigStation;
 import com.ufo.project.config.domain.ConfigStation;
 import com.ufo.project.config.service.IConfigStationService;
 import com.ufo.project.config.service.IConfigStationService;
 import com.ufo.project.forecast.fileupload.domain.DataReportLog;
 import com.ufo.project.forecast.fileupload.domain.DataReportLog;
+import com.ufo.project.forecast.fileupload.domain.vo.ReUploadCountRow;
+import com.ufo.project.forecast.fileupload.domain.vo.UploadRateCountRow;
+import com.ufo.project.forecast.fileupload.domain.vo.UploadRateStatQuery;
+import com.ufo.project.forecast.fileupload.domain.vo.UploadRateStatVO;
 import com.ufo.project.forecast.fileupload.mapper.DataReportLogMapper;
 import com.ufo.project.forecast.fileupload.mapper.DataReportLogMapper;
 import com.ufo.project.forecast.fileupload.service.IDataReportLogService;
 import com.ufo.project.forecast.fileupload.service.IDataReportLogService;
 
 
@@ -33,6 +49,17 @@ public class DataReportLogServiceImpl implements IDataReportLogService
     @Autowired
     @Autowired
     private IConfigStationService configStationService;
     private IConfigStationService configStationService;
 
 
+    /** 字典类型: 每日文件上传配置 */
+    private static final String DICT_TYPE = "daily_file_upload_config";
+
+    /** 9 类上报文件 type(与字典及VO字段顺序一致) */
+    private static final List<String> ALL_TYPES = Arrays.asList("supershort", "short", "medium",
+            "envlDetec", "ivtOpr", "bstTrn",
+            "thrPower", "nmrWeather", "pwrGen");
+
+    @Autowired
+    private ISysDictTypeService dictTypeService;
+
     /**
     /**
      * 查询功率预测上报日志
      * 查询功率预测上报日志
      *
      *
@@ -72,6 +99,172 @@ public class DataReportLogServiceImpl implements IDataReportLogService
         return list;
         return list;
     }
     }
 
 
+    @Override
+    public long uploadRateTotalDays(UploadRateStatQuery query)
+    {
+        LocalDate[] range = parseRange(query);
+        return ChronoUnit.DAYS.between(range[0], range[1]) + 1;
+    }
+
+    @Override
+    public List<UploadRateStatVO> uploadRatePageList(UploadRateStatQuery query)
+    {
+        LocalDate[] range = parseRange(query);
+        LocalDate start = range[0];
+        LocalDate end = range[1];
+        int pageNum = query.getPageNum() == null || query.getPageNum() < 1 ? 1 : query.getPageNum();
+        int pageSize = query.getPageSize() == null || query.getPageSize() < 1 ? 10 : query.getPageSize();
+        LocalDate windowStart = start.plusDays((long) (pageNum - 1) * pageSize);
+        if (windowStart.isAfter(end))
+        {
+            // 超出末页: 返回空
+            return new ArrayList<>();
+        }
+        LocalDate windowEnd = windowStart.plusDays(pageSize - 1L);
+        if (windowEnd.isAfter(end))
+        {
+            windowEnd = end;
+        }
+        return buildDayVos(windowStart, windowEnd, query.getStationCode());
+    }
+
+    @Override
+    public List<UploadRateStatVO> uploadRateExportList(UploadRateStatQuery query)
+    {
+        LocalDate[] range = parseRange(query);
+        return buildDayVos(range[0], range[1], query.getStationCode());
+    }
+
+    @Override
+    public String reUpload(String stationCode)
+    {
+        if (StringUtils.isEmpty(stationCode))
+        {
+            throw new ServiceException("stationCode不能为空");
+        }
+        Map<String, Integer> nums = loadNums();
+        Map<String, String> labels = loadLabels();
+        LocalDate today = LocalDate.now(ZoneId.of("Asia/Shanghai"));
+        List<ReUploadCountRow> rows = dataReportLogMapper.selectTodayCounts(stationCode, today.toString());
+        Map<String, Long> successCnt = new HashMap<>();
+        Map<String, Long> pendingCnt = new HashMap<>();
+        for (ReUploadCountRow row : rows)
+        {
+            if (row.getStatus() == null)
+            {
+                continue;
+            }
+            if (row.getStatus() == 1)
+            {
+                successCnt.merge(row.getType(), row.getCnt() == null ? 0L : row.getCnt(), Long::sum);
+            }
+            else
+            {
+                pendingCnt.merge(row.getType(), row.getCnt() == null ? 0L : row.getCnt(), Long::sum);
+            }
+        }
+
+        // 按ALL_TYPES固定顺序逐类决策: 成功数>=num视为已完成; 存在待发送(上传中/处理中)则跳过; 否则补插缺失条数
+        List<String> pendingLabels = new ArrayList<>();
+        int insertCount = 0;
+        Date now = new Date();
+        String username = SecurityUtils.getUsername();
+        for (String type : ALL_TYPES)
+        {
+            int num = nums.get(type);
+            long ok = successCnt.getOrDefault(type, 0L);
+            long pending = pendingCnt.getOrDefault(type, 0L);
+            if (ok >= num)
+            {
+                continue;
+            }
+            if (pending > 0)
+            {
+                pendingLabels.add(labels.getOrDefault(type, type));
+                continue;
+            }
+            for (int i = 0; i < num - ok; i++)
+            {
+                dataReportLogMapper.insert(buildReUploadLog(type, stationCode, now, username));
+                insertCount++;
+            }
+        }
+
+        if (insertCount == 0 && pendingLabels.isEmpty())
+        {
+            return "当日文件已全部上传,无需补传";
+        }
+        StringBuilder sb = new StringBuilder();
+        if (insertCount > 0)
+        {
+            sb.append("补传成功 ").append(insertCount).append(" 条");
+        }
+        if (!pendingLabels.isEmpty())
+        {
+            if (sb.length() > 0)
+            {
+                sb.append(",");
+            }
+            sb.append("以下类型正在上传/处理中,未补传: ").append(String.join("、", pendingLabels));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 构造补传记录: 固定模拟字段值(curve_id=9999/省调/通道1/ACK:OK/模拟生成), message_no随机保证唯一
+     */
+    private DataReportLog buildReUploadLog(String type, String stationCode, Date now, String username)
+    {
+        DataReportLog log = new DataReportLog();
+        log.setType(type);
+        log.setStationCode(stationCode);
+        log.setCurveId(9999L);
+        log.setEstReportTime(now);
+        log.setReportTime(now);
+        log.setTargetDispatch("省调");
+        log.setChannel(1);
+        log.setMessageNo("SUP" + now.getTime() + type
+                + UUID.randomUUID().toString().replace("-", "").substring(0, 8).toUpperCase());
+        log.setStatus(1);
+        log.setResponseMsg("ACK:OK");
+        log.setRemark("模拟生成");
+        log.setCreateTime(now);
+        log.setUpdateTime(now);
+        log.setCreateBy(username);
+        log.setUpdateBy(username);
+        return log;
+    }
+
+    /**
+     * 读字典 daily_file_upload_config → type→中文label(用于提示消息), 解析失败回退type编码
+     */
+    private Map<String, String> loadLabels()
+    {
+        Map<String, String> labels = new HashMap<>();
+        List<SysDictData> dictDatas = dictTypeService.selectDictDataByType(DICT_TYPE);
+        if (dictDatas == null || dictDatas.isEmpty())
+        {
+            return labels;
+        }
+        for (SysDictData dict : dictDatas)
+        {
+            try
+            {
+                JSONObject obj = JSON.parseObject(dict.getDictValue());
+                String type = obj == null ? null : obj.getString("type");
+                if (StringUtils.isNotEmpty(type) && StringUtils.isNotEmpty(dict.getDictLabel()))
+                {
+                    labels.put(type, dict.getDictLabel());
+                }
+            }
+            catch (Exception e)
+            {
+                // label解析失败时该type回退为type编码
+            }
+        }
+        return labels;
+    }
+
     /**
     /**
      * 按计划上报时间过滤单日(queryDate, yyyy-MM-dd)
      * 按计划上报时间过滤单日(queryDate, yyyy-MM-dd)
      */
      */
@@ -135,4 +328,135 @@ public class DataReportLogServiceImpl implements IDataReportLogService
             }
             }
         }
         }
     }
     }
+
+    /**
+     * 查窗口内聚合并按天生成VO(无记录天全0.00)
+     */
+    private List<UploadRateStatVO> buildDayVos(LocalDate windowStart, LocalDate windowEnd, String stationCode)
+    {
+        Map<String, Integer> nums = loadNums();
+        List<UploadRateCountRow> rows = dataReportLogMapper.selectUploadRateCounts(
+                stationCode, windowStart.toString(), windowEnd.toString());
+        Map<String, Map<String, Long>> byDay = new HashMap<>();
+        for (UploadRateCountRow row : rows)
+        {
+            byDay.computeIfAbsent(row.getStatDate(), k -> new HashMap<>()).put(row.getType(), row.getCnt());
+        }
+        List<UploadRateStatVO> result = new ArrayList<>();
+        for (LocalDate day = windowStart; !day.isAfter(windowEnd); day = day.plusDays(1))
+        {
+            Map<String, Long> typeCnt = byDay.get(day.toString());
+            UploadRateStatVO vo = new UploadRateStatVO();
+            vo.setDate(day.toString());
+            vo.setSupershortRate(calcRate("supershort", typeCnt, nums));
+            vo.setShortRate(calcRate("short", typeCnt, nums));
+            vo.setMediumRate(calcRate("medium", typeCnt, nums));
+            vo.setEnvlDetectorRate(calcRate("envlDetec", typeCnt, nums));
+            vo.setInverterOperationRate(calcRate("ivtOpr", typeCnt, nums));
+            vo.setBoosterTransformerRate(calcRate("bstTrn", typeCnt, nums));
+            vo.setTheoreticalPowerRate(calcRate("thrPower", typeCnt, nums));
+            vo.setNumericalWeatherRate(calcRate("nmrWeather", typeCnt, nums));
+            vo.setPowerGenerationPlanRate(calcRate("pwrGen", typeCnt, nums));
+            result.add(vo);
+        }
+        return result;
+    }
+
+    /**
+     * 比率 = 成功条数/num×100, 保留2位小数(HALF_UP), 超过100按100计; 无记录为0.0
+     */
+    private Double calcRate(String type, Map<String, Long> typeCnt, Map<String, Integer> nums)
+    {
+        long cnt = typeCnt == null ? 0L : typeCnt.getOrDefault(type, 0L);
+        if (cnt == 0)
+        {
+            return 0.0;
+        }
+        BigDecimal rate = new BigDecimal(cnt * 100).divide(new BigDecimal(nums.get(type)), 2, RoundingMode.HALF_UP);
+        if (rate.compareTo(new BigDecimal("100")) > 0)
+        {
+            rate = new BigDecimal("100");
+        }
+        return rate.doubleValue();
+    }
+
+    /**
+     * 参数校验: stationCode/startTime/endTime非空、格式yyyy-MM-dd、start<=end
+     */
+    private LocalDate[] parseRange(UploadRateStatQuery query)
+    {
+        if (StringUtils.isEmpty(query.getStationCode()))
+        {
+            throw new ServiceException("stationCode不能为空");
+        }
+        LocalDate start = parseDay(query.getStartTime(), "起始时间");
+        LocalDate end = parseDay(query.getEndTime(), "截止时间");
+        if (start.isAfter(end))
+        {
+            throw new ServiceException("起始时间不能晚于截止时间");
+        }
+        return new LocalDate[]{start, end};
+    }
+
+    private LocalDate parseDay(String value, String label)
+    {
+        if (StringUtils.isEmpty(value))
+        {
+            throw new ServiceException(label + "不能为空");
+        }
+        try
+        {
+            return LocalDate.parse(value);
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException(label + "格式不正确, 应为yyyy-MM-dd: " + value);
+        }
+    }
+
+    /**
+     * 读字典 daily_file_upload_config → type→num; 未配置/JSON非法/缺项/num非法时fail fast
+     */
+    private Map<String, Integer> loadNums()
+    {
+        List<SysDictData> dictDatas = dictTypeService.selectDictDataByType(DICT_TYPE);
+        if (dictDatas == null || dictDatas.isEmpty())
+        {
+            throw new ServiceException("字典" + DICT_TYPE + "未配置, 请先在字典管理中添加每日文件上传配置");
+        }
+        Map<String, Integer> nums = new HashMap<>();
+        for (SysDictData dict : dictDatas)
+        {
+            String dictValue = dict.getDictValue();
+            try
+            {
+                JSONObject obj = JSON.parseObject(dictValue);
+                String type = obj == null ? null : obj.getString("type");
+                Integer num = obj == null ? null : obj.getInteger("num");
+                if (StringUtils.isEmpty(type) || num == null || num <= 0)
+                {
+                    throw new ServiceException("字典" + DICT_TYPE + "数据[" + dict.getDictLabel()
+                            + "]缺少type或num不合法: " + dictValue);
+                }
+                nums.put(type, num);
+            }
+            catch (ServiceException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new ServiceException("字典" + DICT_TYPE + "数据[" + dict.getDictLabel()
+                        + "]不是合法JSON: " + dictValue);
+            }
+        }
+        for (String type : ALL_TYPES)
+        {
+            if (!nums.containsKey(type))
+            {
+                throw new ServiceException("字典" + DICT_TYPE + "缺少" + type + "的配置");
+            }
+        }
+        return nums;
+    }
 }
 }

+ 20 - 2
forecast-backend-server/src/main/resources/mybatis/alarm/AlarmEventRecordMapper.xml

@@ -10,6 +10,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="alarmRuleId"    column="alarm_rule_id"    />
         <result property="alarmRuleId"    column="alarm_rule_id"    />
         <result property="alarmData"    column="alarm_data"    />
         <result property="alarmData"    column="alarm_data"    />
         <result property="monitoringTerminal"    column="monitoring_terminal"    />
         <result property="monitoringTerminal"    column="monitoring_terminal"    />
+        <result property="alarmCategory"    column="alarm_category"    />
         <result property="createTime"    column="create_time"    />
         <result property="createTime"    column="create_time"    />
         <result property="createBy"    column="create_by"    />
         <result property="createBy"    column="create_by"    />
         <result property="updateTime"    column="update_time"    />
         <result property="updateTime"    column="update_time"    />
@@ -24,7 +25,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
     </resultMap>
 
 
     <sql id="selectAlarmEventRecordVo">
     <sql id="selectAlarmEventRecordVo">
-        select id, station_id, alarm_rule_id, alarm_data, monitoring_terminal, create_time, create_by, update_time, update_by, alarm_level, alarm_create_time, process_flag, process_person, process_result, send_status, process_person_id from alarm_event_record
+        select id, station_id, alarm_rule_id, alarm_data, monitoring_terminal, alarm_category, create_time, create_by, update_time, update_by, alarm_level, alarm_create_time, process_flag, process_person, process_result, send_status, process_person_id from alarm_event_record
     </sql>
     </sql>
 
 
     <select id="selectAlarmEventRecordList" parameterType="AlarmEventRecord" resultMap="AlarmEventRecordResult">
     <select id="selectAlarmEventRecordList" parameterType="AlarmEventRecord" resultMap="AlarmEventRecordResult">
@@ -34,14 +35,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmRuleId != null  and alarmRuleId != ''"> and alarm_rule_id = #{alarmRuleId}</if>
             <if test="alarmRuleId != null  and alarmRuleId != ''"> and alarm_rule_id = #{alarmRuleId}</if>
             <if test="alarmData != null  and alarmData != ''"> and alarm_data = #{alarmData}</if>
             <if test="alarmData != null  and alarmData != ''"> and alarm_data = #{alarmData}</if>
             <if test="monitoringTerminal != null  and monitoringTerminal != ''"> and monitoring_terminal = #{monitoringTerminal}</if>
             <if test="monitoringTerminal != null  and monitoringTerminal != ''"> and monitoring_terminal = #{monitoringTerminal}</if>
+            <if test="alarmCategory != null  and alarmCategory != ''"> and alarm_category = #{alarmCategory}</if>
             <if test="alarmLevel != null "> and alarm_level = #{alarmLevel}</if>
             <if test="alarmLevel != null "> and alarm_level = #{alarmLevel}</if>
             <if test="alarmCreateTime != null  and alarmCreateTime != ''"> and alarm_create_time = #{alarmCreateTime}</if>
             <if test="alarmCreateTime != null  and alarmCreateTime != ''"> and alarm_create_time = #{alarmCreateTime}</if>
+            <if test="processStatus != null and processStatus"> and process_flag = 2</if>
+            <if test="processStatus != null and !processStatus"> and process_flag != 2</if>
+            <if test="alarmDateBegin != null and alarmDateEnd != null"> and alarm_create_time &gt;= #{alarmDateBegin} and alarm_create_time &lt;= #{alarmDateEnd}</if>
             <if test="processFlag != null "> and process_flag = #{processFlag}</if>
             <if test="processFlag != null "> and process_flag = #{processFlag}</if>
             <if test="processPerson != null  and processPerson != ''"> and process_person = #{processPerson}</if>
             <if test="processPerson != null  and processPerson != ''"> and process_person = #{processPerson}</if>
             <if test="processResult != null  and processResult != ''"> and process_result = #{processResult}</if>
             <if test="processResult != null  and processResult != ''"> and process_result = #{processResult}</if>
             <if test="sendStatus != null "> and send_status = #{sendStatus}</if>
             <if test="sendStatus != null "> and send_status = #{sendStatus}</if>
             <if test="processPersonId != null  and processPersonId != ''"> and process_person_id = #{processPersonId}</if>
             <if test="processPersonId != null  and processPersonId != ''"> and process_person_id = #{processPersonId}</if>
         </where>
         </where>
+        order by alarm_create_time desc
     </select>
     </select>
     
     
     <select id="selectAlarmEventRecordById" parameterType="String" resultMap="AlarmEventRecordResult">
     <select id="selectAlarmEventRecordById" parameterType="String" resultMap="AlarmEventRecordResult">
@@ -57,6 +63,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmRuleId != null and alarmRuleId != ''">alarm_rule_id,</if>
             <if test="alarmRuleId != null and alarmRuleId != ''">alarm_rule_id,</if>
             <if test="alarmData != null">alarm_data,</if>
             <if test="alarmData != null">alarm_data,</if>
             <if test="monitoringTerminal != null">monitoring_terminal,</if>
             <if test="monitoringTerminal != null">monitoring_terminal,</if>
+            <if test="alarmCategory != null and alarmCategory != ''">alarm_category,</if>
             <if test="createTime != null">create_time,</if>
             <if test="createTime != null">create_time,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="updateTime != null">update_time,</if>
@@ -75,6 +82,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmRuleId != null and alarmRuleId != ''">#{alarmRuleId},</if>
             <if test="alarmRuleId != null and alarmRuleId != ''">#{alarmRuleId},</if>
             <if test="alarmData != null">#{alarmData},</if>
             <if test="alarmData != null">#{alarmData},</if>
             <if test="monitoringTerminal != null">#{monitoringTerminal},</if>
             <if test="monitoringTerminal != null">#{monitoringTerminal},</if>
+            <if test="alarmCategory != null and alarmCategory != ''">#{alarmCategory},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
@@ -96,6 +104,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmRuleId != null and alarmRuleId != ''">alarm_rule_id = #{alarmRuleId},</if>
             <if test="alarmRuleId != null and alarmRuleId != ''">alarm_rule_id = #{alarmRuleId},</if>
             <if test="alarmData != null">alarm_data = #{alarmData},</if>
             <if test="alarmData != null">alarm_data = #{alarmData},</if>
             <if test="monitoringTerminal != null">monitoring_terminal = #{monitoringTerminal},</if>
             <if test="monitoringTerminal != null">monitoring_terminal = #{monitoringTerminal},</if>
+            <if test="alarmCategory != null and alarmCategory != ''">alarm_category = #{alarmCategory},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
@@ -116,9 +125,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </delete>
     </delete>
 
 
     <delete id="deleteAlarmEventRecordByIds" parameterType="String">
     <delete id="deleteAlarmEventRecordByIds" parameterType="String">
-        delete from alarm_event_record where id in 
+        delete from alarm_event_record where id in
         <foreach item="id" collection="array" open="(" separator="," close=")">
         <foreach item="id" collection="array" open="(" separator="," close=")">
             #{id}
             #{id}
         </foreach>
         </foreach>
     </delete>
     </delete>
+
+    <update id="processAlarmEventRecord">
+        update alarm_event_record
+        set process_flag = 2, update_time = #{updateTime}
+        where process_flag != 2 and id in
+        <foreach item="id" collection="ids" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
 </mapper>
 </mapper>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/alarm/AlarmEventRuleMapper.xml

@@ -54,9 +54,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmTemplateId != null and alarmTemplateId != ''">alarm_template_id,</if>
             <if test="alarmTemplateId != null and alarmTemplateId != ''">alarm_template_id,</if>
             <if test="enableFlag != null">enable_flag,</if>
             <if test="enableFlag != null">enable_flag,</if>
             <if test="delFlag != null">del_flag,</if>
             <if test="delFlag != null">del_flag,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="alarmWarnLevel != null">alarm_warn_level,</if>
             <if test="alarmWarnLevel != null">alarm_warn_level,</if>
             <if test="sendSet != null">send_set,</if>
             <if test="sendSet != null">send_set,</if>
@@ -71,9 +71,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmTemplateId != null and alarmTemplateId != ''">#{alarmTemplateId},</if>
             <if test="alarmTemplateId != null and alarmTemplateId != ''">#{alarmTemplateId},</if>
             <if test="enableFlag != null">#{enableFlag},</if>
             <if test="enableFlag != null">#{enableFlag},</if>
             <if test="delFlag != null">#{delFlag},</if>
             <if test="delFlag != null">#{delFlag},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="alarmWarnLevel != null">#{alarmWarnLevel},</if>
             <if test="alarmWarnLevel != null">#{alarmWarnLevel},</if>
             <if test="sendSet != null">#{sendSet},</if>
             <if test="sendSet != null">#{sendSet},</if>
@@ -91,9 +91,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmTemplateId != null and alarmTemplateId != ''">alarm_template_id = #{alarmTemplateId},</if>
             <if test="alarmTemplateId != null and alarmTemplateId != ''">alarm_template_id = #{alarmTemplateId},</if>
             <if test="enableFlag != null">enable_flag = #{enableFlag},</if>
             <if test="enableFlag != null">enable_flag = #{enableFlag},</if>
             <if test="delFlag != null">del_flag = #{delFlag},</if>
             <if test="delFlag != null">del_flag = #{delFlag},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="alarmWarnLevel != null">alarm_warn_level = #{alarmWarnLevel},</if>
             <if test="alarmWarnLevel != null">alarm_warn_level = #{alarmWarnLevel},</if>
             <if test="sendSet != null">send_set = #{sendSet},</if>
             <if test="sendSet != null">send_set = #{sendSet},</if>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/alarm/AlarmEventRuleTemplateMapper.xml

@@ -45,9 +45,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmLevelUp != null and alarmLevelUp != ''">alarm_level_up,</if>
             <if test="alarmLevelUp != null and alarmLevelUp != ''">alarm_level_up,</if>
             <if test="alarmLevel != null">alarm_level,</if>
             <if test="alarmLevel != null">alarm_level,</if>
             <if test="alarmName != null">alarm_name,</if>
             <if test="alarmName != null">alarm_name,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="delFlag != null">del_flag,</if>
             <if test="delFlag != null">del_flag,</if>
             <if test="alarmKey != null">alarm_key,</if>
             <if test="alarmKey != null">alarm_key,</if>
@@ -58,9 +58,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmLevelUp != null and alarmLevelUp != ''">#{alarmLevelUp},</if>
             <if test="alarmLevelUp != null and alarmLevelUp != ''">#{alarmLevelUp},</if>
             <if test="alarmLevel != null">#{alarmLevel},</if>
             <if test="alarmLevel != null">#{alarmLevel},</if>
             <if test="alarmName != null">#{alarmName},</if>
             <if test="alarmName != null">#{alarmName},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="delFlag != null">#{delFlag},</if>
             <if test="delFlag != null">#{delFlag},</if>
             <if test="alarmKey != null">#{alarmKey},</if>
             <if test="alarmKey != null">#{alarmKey},</if>
@@ -74,9 +74,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="alarmLevelUp != null and alarmLevelUp != ''">alarm_level_up = #{alarmLevelUp},</if>
             <if test="alarmLevelUp != null and alarmLevelUp != ''">alarm_level_up = #{alarmLevelUp},</if>
             <if test="alarmLevel != null">alarm_level = #{alarmLevel},</if>
             <if test="alarmLevel != null">alarm_level = #{alarmLevel},</if>
             <if test="alarmName != null">alarm_name = #{alarmName},</if>
             <if test="alarmName != null">alarm_name = #{alarmName},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="delFlag != null">del_flag = #{delFlag},</if>
             <if test="delFlag != null">del_flag = #{delFlag},</if>
             <if test="alarmKey != null">alarm_key = #{alarmKey},</if>
             <if test="alarmKey != null">alarm_key = #{alarmKey},</if>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/alarm/AlarmStatRecordMapper.xml

@@ -37,18 +37,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="id != null">id,</if>
             <if test="id != null">id,</if>
             <if test="scheduleTime != null">schedule_time,</if>
             <if test="scheduleTime != null">schedule_time,</if>
             <if test="alarmData != null">alarm_data,</if>
             <if test="alarmData != null">alarm_data,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="id != null">#{id},</if>
             <if test="scheduleTime != null">#{scheduleTime},</if>
             <if test="scheduleTime != null">#{scheduleTime},</if>
             <if test="alarmData != null">#{alarmData},</if>
             <if test="alarmData != null">#{alarmData},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
          </trim>
          </trim>
     </insert>
     </insert>
@@ -58,9 +58,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <trim prefix="SET" suffixOverrides=",">
         <trim prefix="SET" suffixOverrides=",">
             <if test="scheduleTime != null">schedule_time = #{scheduleTime},</if>
             <if test="scheduleTime != null">schedule_time = #{scheduleTime},</if>
             <if test="alarmData != null">alarm_data = #{alarmData},</if>
             <if test="alarmData != null">alarm_data = #{alarmData},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}

+ 3 - 3
forecast-backend-server/src/main/resources/mybatis/alarm/MonitoringCheckRecordMapper.xml

@@ -53,7 +53,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="div != null">div,</if>
             <if test="div != null">div,</if>
             <if test="thresholdCount != null">threshold_count,</if>
             <if test="thresholdCount != null">threshold_count,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="dataSourcegrabId != null">#{dataSourcegrabId},</if>
             <if test="dataSourcegrabId != null">#{dataSourcegrabId},</if>
@@ -65,7 +65,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="div != null">#{div},</if>
             <if test="div != null">#{div},</if>
             <if test="thresholdCount != null">#{thresholdCount},</if>
             <if test="thresholdCount != null">#{thresholdCount},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -81,7 +81,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="div != null">div = #{div},</if>
             <if test="div != null">div = #{div},</if>
             <if test="thresholdCount != null">threshold_count = #{thresholdCount},</if>
             <if test="thresholdCount != null">threshold_count = #{thresholdCount},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 3 - 3
forecast-backend-server/src/main/resources/mybatis/alarm/MonitoringSendRecordMapper.xml

@@ -41,7 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="recipientEmail != null">recipient_email,</if>
             <if test="recipientEmail != null">recipient_email,</if>
             <if test="emailInfo != null">email_info,</if>
             <if test="emailInfo != null">email_info,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="checkRecordId != null">#{checkRecordId},</if>
             <if test="checkRecordId != null">#{checkRecordId},</if>
@@ -49,7 +49,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="recipientEmail != null">#{recipientEmail},</if>
             <if test="recipientEmail != null">#{recipientEmail},</if>
             <if test="emailInfo != null">#{emailInfo},</if>
             <if test="emailInfo != null">#{emailInfo},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -61,7 +61,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="recipientEmail != null">recipient_email = #{recipientEmail},</if>
             <if test="recipientEmail != null">recipient_email = #{recipientEmail},</if>
             <if test="emailInfo != null">email_info = #{emailInfo},</if>
             <if test="emailInfo != null">email_info = #{emailInfo},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/api/ApiAccessControlMapper.xml

@@ -49,9 +49,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="callNumber != null">call_number,</if>
             <if test="callNumber != null">call_number,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="accessKey != null and accessKey != ''">#{accessKey},</if>
             <if test="accessKey != null and accessKey != ''">#{accessKey},</if>
@@ -61,9 +61,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="callNumber != null">#{callNumber},</if>
             <if test="callNumber != null">#{callNumber},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -77,9 +77,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="callNumber != null">call_number = #{callNumber},</if>
             <if test="callNumber != null">call_number = #{callNumber},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 3 - 3
forecast-backend-server/src/main/resources/mybatis/api/ApiAccessRecordMapper.xml

@@ -52,7 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="time != null">time,</if>
             <if test="time != null">time,</if>
             <if test="accessKey != null and accessKey != ''">access_key,</if>
             <if test="accessKey != null and accessKey != ''">access_key,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="apiRecordId != null">api_record_id,</if>
             <if test="apiRecordId != null">api_record_id,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
@@ -64,7 +64,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="time != null">#{time},</if>
             <if test="time != null">#{time},</if>
             <if test="accessKey != null and accessKey != ''">#{accessKey},</if>
             <if test="accessKey != null and accessKey != ''">#{accessKey},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="apiRecordId != null">#{apiRecordId},</if>
             <if test="apiRecordId != null">#{apiRecordId},</if>
          </trim>
          </trim>
     </insert>
     </insert>
@@ -80,7 +80,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="time != null">time = #{time},</if>
             <if test="time != null">time = #{time},</if>
             <if test="accessKey != null and accessKey != ''">access_key = #{accessKey},</if>
             <if test="accessKey != null and accessKey != ''">access_key = #{accessKey},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="apiRecordId != null">api_record_id = #{apiRecordId},</if>
             <if test="apiRecordId != null">api_record_id = #{apiRecordId},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/api/ApiRecordMapper.xml

@@ -43,9 +43,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="apiDescription != null">api_description,</if>
             <if test="apiDescription != null">api_description,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="apiPath != null and apiPath != ''">#{apiPath},</if>
             <if test="apiPath != null and apiPath != ''">#{apiPath},</if>
@@ -53,9 +53,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="apiDescription != null">#{apiDescription},</if>
             <if test="apiDescription != null">#{apiDescription},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -67,9 +67,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="apiDescription != null">api_description = #{apiDescription},</if>
             <if test="apiDescription != null">api_description = #{apiDescription},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/api/ApiVersionReleaseMapper.xml

@@ -42,9 +42,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="version != null and version != ''">version,</if>
             <if test="version != null and version != ''">version,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="apis != null and apis != ''">apis,</if>
             <if test="apis != null and apis != ''">apis,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
@@ -52,9 +52,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="version != null and version != ''">#{version},</if>
             <if test="version != null and version != ''">#{version},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="apis != null and apis != ''">#{apis},</if>
             <if test="apis != null and apis != ''">#{apis},</if>
          </trim>
          </trim>
     </insert>
     </insert>
@@ -66,9 +66,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="version != null and version != ''">version = #{version},</if>
             <if test="version != null and version != ''">version = #{version},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="apis != null and apis != ''">apis = #{apis},</if>
             <if test="apis != null and apis != ''">apis = #{apis},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/assessment/ConfigAssessmentIndicatorMapper.xml

@@ -54,9 +54,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">enable_flag,</if>
             <if test="enableFlag != null and enableFlag != ''">enable_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="id != null">#{id},</if>
@@ -69,9 +69,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">#{enableFlag},</if>
             <if test="enableFlag != null and enableFlag != ''">#{enableFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -87,9 +87,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">enable_flag = #{enableFlag},</if>
             <if test="enableFlag != null and enableFlag != ''">enable_flag = #{enableFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/assessment/ConfigAssessmentRuleMapper.xml

@@ -40,9 +40,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="provinceNumber != null">province_number,</if>
             <if test="provinceNumber != null">province_number,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="id != null">#{id},</if>
@@ -50,9 +50,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="provinceNumber != null">#{provinceNumber},</if>
             <if test="provinceNumber != null">#{provinceNumber},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -63,9 +63,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="provinceNumber != null">province_number = #{provinceNumber},</if>
             <if test="provinceNumber != null">province_number = #{provinceNumber},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/assessment/ConfigAssessmentTaskMapper.xml

@@ -43,9 +43,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">enable_flag,</if>
             <if test="enableFlag != null and enableFlag != ''">enable_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="id != null">#{id},</if>
@@ -54,9 +54,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">#{enableFlag},</if>
             <if test="enableFlag != null and enableFlag != ''">#{enableFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -68,9 +68,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">enable_flag = #{enableFlag},</if>
             <if test="enableFlag != null and enableFlag != ''">enable_flag = #{enableFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/config/ConfigAreaMapper.xml

@@ -44,9 +44,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="superiorAreaId != null">superior_area_id,</if>
             <if test="superiorAreaId != null">superior_area_id,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null and id != ''">#{id},</if>
             <if test="id != null and id != ''">#{id},</if>
@@ -55,9 +55,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="superiorAreaId != null">#{superiorAreaId},</if>
             <if test="superiorAreaId != null">#{superiorAreaId},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -69,9 +69,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="superiorAreaId != null">superior_area_id = #{superiorAreaId},</if>
             <if test="superiorAreaId != null">superior_area_id = #{superiorAreaId},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 25 - 4
forecast-backend-server/src/main/resources/mybatis/config/ConfigDeviceMapper.xml

@@ -7,6 +7,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <resultMap type="ConfigDevice" id="ConfigDeviceResult">
     <resultMap type="ConfigDevice" id="ConfigDeviceResult">
         <result property="id"    column="id"    />
         <result property="id"    column="id"    />
         <result property="name"    column="name"    />
         <result property="name"    column="name"    />
+        <result property="tp"    column="tp"    />
+        <result property="brand"    column="brand"    />
+        <result property="model"    column="model"    />
+        <result property="serialNumber"    column="serial_number"    />
+        <result property="status"    column="status"    />
+        <result property="installDate"    column="install_date"    />
         <result property="configChannelId"    column="config_channel_id"    />
         <result property="configChannelId"    column="config_channel_id"    />
         <result property="configStationId"    column="config_station_id"    />
         <result property="configStationId"    column="config_station_id"    />
         <result property="configDeviceId"    column="config_device_id"    />
         <result property="configDeviceId"    column="config_device_id"    />
@@ -14,7 +20,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
     </resultMap>
 
 
     <sql id="selectConfigDeviceVo">
     <sql id="selectConfigDeviceVo">
-        select id, name, config_channel_id, config_station_id, config_device_id, remark from config_device
+        select id, name, tp, brand, model, serial_number, status, install_date, config_channel_id, config_station_id, config_device_id, remark from config_device
     </sql>
     </sql>
 
 
     <select id="selectConfigDeviceList" parameterType="ConfigDevice" resultMap="ConfigDeviceResult">
     <select id="selectConfigDeviceList" parameterType="ConfigDevice" resultMap="ConfigDeviceResult">
@@ -54,17 +60,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         insert into config_device
         insert into config_device
         <trim prefix="(" suffix=")" suffixOverrides=",">
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="name != null and name != ''">name,</if>
             <if test="name != null and name != ''">name,</if>
+            <if test="tp != null and tp != ''">tp,</if>
+            <if test="brand != null and brand != ''">brand,</if>
+            <if test="model != null and model != ''">model,</if>
+            <if test="serialNumber != null and serialNumber != ''">serial_number,</if>
+            <if test="status != null and status != ''">status,</if>
+            <if test="installDate != null">install_date,</if>
             <if test="configChannelId != null">config_channel_id,</if>
             <if test="configChannelId != null">config_channel_id,</if>
             <if test="configStationId != null">config_station_id,</if>
             <if test="configStationId != null">config_station_id,</if>
-            <if test="configDeviceId != null and configDeviceId != ''">config_device_id,</if>
             <if test="configDeviceId != null">config_device_id,</if>
             <if test="configDeviceId != null">config_device_id,</if>
             <if test="remark != null and remark != ''">remark,</if>
             <if test="remark != null and remark != ''">remark,</if>
         </trim>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="name != null and name != ''">#{name},</if>
             <if test="name != null and name != ''">#{name},</if>
+            <if test="tp != null and tp != ''">#{tp},</if>
+            <if test="brand != null and brand != ''">#{brand},</if>
+            <if test="model != null and model != ''">#{model},</if>
+            <if test="serialNumber != null and serialNumber != ''">#{serialNumber},</if>
+            <if test="status != null and status != ''">#{status},</if>
+            <if test="installDate != null">#{installDate},</if>
             <if test="configChannelId != null">#{configChannelId},</if>
             <if test="configChannelId != null">#{configChannelId},</if>
             <if test="configStationId != null">#{configStationId},</if>
             <if test="configStationId != null">#{configStationId},</if>
-            <if test="configDeviceId != null and configDeviceId != ''">#{configDeviceId},</if>
             <if test="configDeviceId != null">#{configDeviceId},</if>
             <if test="configDeviceId != null">#{configDeviceId},</if>
             <if test="remark != null and remark != ''">#{remark},</if>
             <if test="remark != null and remark != ''">#{remark},</if>
         </trim>
         </trim>
@@ -74,9 +90,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         update config_device
         update config_device
         <trim prefix="SET" suffixOverrides=",">
         <trim prefix="SET" suffixOverrides=",">
             <if test="name != null and name != ''">name = #{name},</if>
             <if test="name != null and name != ''">name = #{name},</if>
+            <if test="tp != null and tp != ''">tp = #{tp},</if>
+            <if test="brand != null and brand != ''">brand = #{brand},</if>
+            <if test="model != null and model != ''">model = #{model},</if>
+            <if test="serialNumber != null and serialNumber != ''">serial_number = #{serialNumber},</if>
+            <if test="status != null and status != ''">status = #{status},</if>
+            <if test="installDate != null">install_date = #{installDate},</if>
             <if test="configChannelId != null">config_channel_id = #{configChannelId},</if>
             <if test="configChannelId != null">config_channel_id = #{configChannelId},</if>
             <if test="configStationId != null">config_station_id = #{configStationId},</if>
             <if test="configStationId != null">config_station_id = #{configStationId},</if>
-            <if test="configDeviceId != null and configDeviceId != ''">config_device_id = #{configDeviceId},</if>
             <if test="configDeviceId != null">config_device_id = #{configDeviceId},</if>
             <if test="configDeviceId != null">config_device_id = #{configDeviceId},</if>
             <if test="remark != null and remark != ''">remark = #{remark},</if>
             <if test="remark != null and remark != ''">remark = #{remark},</if>
             update_time = CURRENT_TIMESTAMP,
             update_time = CURRENT_TIMESTAMP,

+ 10 - 8
forecast-backend-server/src/main/resources/mybatis/config/ConfigStationMapper.xml

@@ -45,7 +45,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
 
     <select id="selectConfigStationList" parameterType="ConfigStation" resultMap="ConfigStationResult">
     <select id="selectConfigStationList" parameterType="ConfigStation" resultMap="ConfigStationResult">
         <include refid="selectConfigStationVo"/>
         <include refid="selectConfigStationVo"/>
-        <where>  
+        <where>
+            and station_type = 1
             <if test="stationName != null  and stationName != ''"> and station_name like concat('%', #{stationName}, '%')</if>
             <if test="stationName != null  and stationName != ''"> and station_name like concat('%', #{stationName}, '%')</if>
             <if test="stationCode != null  and stationCode != ''"> and station_code = #{stationCode}</if>
             <if test="stationCode != null  and stationCode != ''"> and station_code = #{stationCode}</if>
             <if test="superiorAreaId != null  and superiorAreaId != ''"> and superior_area_id = #{superiorAreaId}</if>
             <if test="superiorAreaId != null  and superiorAreaId != ''"> and superior_area_id = #{superiorAreaId}</if>
@@ -78,7 +79,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     
     
     <select id="selectConfigStationById" parameterType="Long" resultMap="ConfigStationResult">
     <select id="selectConfigStationById" parameterType="Long" resultMap="ConfigStationResult">
         <include refid="selectConfigStationVo"/>
         <include refid="selectConfigStationVo"/>
-        where id = #{id}
+        where id = #{id} and station_type = 1
     </select>
     </select>
 
 
     <select id="selectConfigStationByIds" parameterType="Long" resultMap="ConfigStationResult">
     <select id="selectConfigStationByIds" parameterType="Long" resultMap="ConfigStationResult">
@@ -86,6 +87,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <foreach item="id" collection="array" open="(" separator="," close=")">
         <foreach item="id" collection="array" open="(" separator="," close=")">
             #{id}
             #{id}
         </foreach>
         </foreach>
+        and station_type = 1
     </select>
     </select>
         
         
     <insert id="insertConfigStation" parameterType="ConfigStation">
     <insert id="insertConfigStation" parameterType="ConfigStation">
@@ -117,9 +119,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isFullPower != null and isFullPower != ''">is_full_power,</if>
             <if test="isFullPower != null and isFullPower != ''">is_full_power,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="stationType != null">station_type,</if>
             <if test="stationType != null">station_type,</if>
             <if test="systemPowerUuid != null">system_power_uuid,</if>
             <if test="systemPowerUuid != null">system_power_uuid,</if>
             <if test="areaId != null">area_id,</if>
             <if test="areaId != null">area_id,</if>
@@ -151,9 +153,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isFullPower != null and isFullPower != ''">#{isFullPower},</if>
             <if test="isFullPower != null and isFullPower != ''">#{isFullPower},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="stationType != null">#{stationType},</if>
             <if test="stationType != null">#{stationType},</if>
             <if test="systemPowerUuid != null">#{systemPowerUuid},</if>
             <if test="systemPowerUuid != null">#{systemPowerUuid},</if>
             <if test="areaId != null">#{areaId},</if>
             <if test="areaId != null">#{areaId},</if>
@@ -188,9 +190,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isFullPower != null and isFullPower != ''">is_full_power = #{isFullPower},</if>
             <if test="isFullPower != null and isFullPower != ''">is_full_power = #{isFullPower},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="stationType != null">station_type = #{stationType},</if>
             <if test="stationType != null">station_type = #{stationType},</if>
             <if test="systemPowerUuid != null">system_power_uuid = #{systemPowerUuid},</if>
             <if test="systemPowerUuid != null">system_power_uuid = #{systemPowerUuid},</if>
             <if test="areaId != null">area_id = #{areaId},</if>
             <if test="areaId != null">area_id = #{areaId},</if>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/config/ConfigSupplierMapper.xml

@@ -40,18 +40,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="supplierName != null and supplierName != ''">supplier_name,</if>
             <if test="supplierName != null and supplierName != ''">supplier_name,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="supplierCode != null and supplierCode != ''">#{supplierCode},</if>
             <if test="supplierCode != null and supplierCode != ''">#{supplierCode},</if>
             <if test="supplierName != null and supplierName != ''">#{supplierName},</if>
             <if test="supplierName != null and supplierName != ''">#{supplierName},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -62,9 +62,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="supplierName != null and supplierName != ''">supplier_name = #{supplierName},</if>
             <if test="supplierName != null and supplierName != ''">supplier_name = #{supplierName},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/config/StopReducePowerRecordMapper.xml

@@ -51,9 +51,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="stationId != null">station_id,</if>
             <if test="stationId != null">station_id,</if>
             <if test="startTime != null">start_time,</if>
             <if test="startTime != null">start_time,</if>
             <if test="endTime != null">end_time,</if>
             <if test="endTime != null">end_time,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="note != null">note,</if>
             <if test="note != null">note,</if>
@@ -67,9 +67,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="stationId != null">#{stationId},</if>
             <if test="stationId != null">#{stationId},</if>
             <if test="startTime != null">#{startTime},</if>
             <if test="startTime != null">#{startTime},</if>
             <if test="endTime != null">#{endTime},</if>
             <if test="endTime != null">#{endTime},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="note != null">#{note},</if>
             <if test="note != null">#{note},</if>
@@ -86,9 +86,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="stationId != null">station_id = #{stationId},</if>
             <if test="stationId != null">station_id = #{stationId},</if>
             <if test="startTime != null">start_time = #{startTime},</if>
             <if test="startTime != null">start_time = #{startTime},</if>
             <if test="endTime != null">end_time = #{endTime},</if>
             <if test="endTime != null">end_time = #{endTime},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="note != null">note = #{note},</if>
             <if test="note != null">note = #{note},</if>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/datasource/DataSourceConfigMapper.xml

@@ -77,9 +77,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataInactivityPollInterval != null">data_inactivity_poll_interval,</if>
             <if test="dataInactivityPollInterval != null">data_inactivity_poll_interval,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="grabDays != null">grab_days,</if>
             <if test="grabDays != null">grab_days,</if>
             <if test="topicName != null">topic_name,</if>
             <if test="topicName != null">topic_name,</if>
          </trim>
          </trim>
@@ -99,9 +99,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataInactivityPollInterval != null">#{dataInactivityPollInterval},</if>
             <if test="dataInactivityPollInterval != null">#{dataInactivityPollInterval},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="grabDays != null">#{grabDays},</if>
             <if test="grabDays != null">#{grabDays},</if>
             <if test="topicName != null">#{topicName},</if>
             <if test="topicName != null">#{topicName},</if>
          </trim>
          </trim>
@@ -125,9 +125,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataInactivityPollInterval != null">data_inactivity_poll_interval = #{dataInactivityPollInterval},</if>
             <if test="dataInactivityPollInterval != null">data_inactivity_poll_interval = #{dataInactivityPollInterval},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="grabDays != null">grab_days = #{grabDays},</if>
             <if test="grabDays != null">grab_days = #{grabDays},</if>
             <if test="topicName != null">topic_name = #{topicName},</if>
             <if test="topicName != null">topic_name = #{topicName},</if>
         </trim>
         </trim>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/datasource/DataSourceGrabMapper.xml

@@ -86,9 +86,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dateMatchPattern != null">date_match_pattern,</if>
             <if test="dateMatchPattern != null">date_match_pattern,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="patternName != null">pattern_name,</if>
             <if test="patternName != null">pattern_name,</if>
             <if test="batchOfDay != null">batch_of_day,</if>
             <if test="batchOfDay != null">batch_of_day,</if>
             <if test="threshold != null">threshold,</if>
             <if test="threshold != null">threshold,</if>
@@ -113,9 +113,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dateMatchPattern != null">#{dateMatchPattern},</if>
             <if test="dateMatchPattern != null">#{dateMatchPattern},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="patternName != null">#{patternName},</if>
             <if test="patternName != null">#{patternName},</if>
             <if test="batchOfDay != null">#{batchOfDay},</if>
             <if test="batchOfDay != null">#{batchOfDay},</if>
             <if test="threshold != null">#{threshold},</if>
             <if test="threshold != null">#{threshold},</if>
@@ -144,9 +144,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dateMatchPattern != null">date_match_pattern = #{dateMatchPattern},</if>
             <if test="dateMatchPattern != null">date_match_pattern = #{dateMatchPattern},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="patternName != null">pattern_name = #{patternName},</if>
             <if test="patternName != null">pattern_name = #{patternName},</if>
             <if test="batchOfDay != null">batch_of_day = #{batchOfDay},</if>
             <if test="batchOfDay != null">batch_of_day = #{batchOfDay},</if>
             <if test="threshold != null">threshold = #{threshold},</if>
             <if test="threshold != null">threshold = #{threshold},</if>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/datasource/DataSourceUserRelationMapper.xml

@@ -64,9 +64,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isBusinessDownload != null and isBusinessDownload != ''">is_business_download,</if>
             <if test="isBusinessDownload != null and isBusinessDownload != ''">is_business_download,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="dataSourceGrabId != null">#{dataSourceGrabId},</if>
             <if test="dataSourceGrabId != null">#{dataSourceGrabId},</if>
@@ -81,9 +81,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isBusinessDownload != null and isBusinessDownload != ''">#{isBusinessDownload},</if>
             <if test="isBusinessDownload != null and isBusinessDownload != ''">#{isBusinessDownload},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -102,9 +102,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isBusinessDownload != null and isBusinessDownload != ''">is_business_download = #{isBusinessDownload},</if>
             <if test="isBusinessDownload != null and isBusinessDownload != ''">is_business_download = #{isBusinessDownload},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/rbac/RbacMenuMapper.xml

@@ -63,9 +63,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isSystem != null and isSystem != ''">is_system,</if>
             <if test="isSystem != null and isSystem != ''">is_system,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="icon != null">icon,</if>
             <if test="icon != null">icon,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
@@ -80,9 +80,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isSystem != null and isSystem != ''">#{isSystem},</if>
             <if test="isSystem != null and isSystem != ''">#{isSystem},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="icon != null">#{icon},</if>
             <if test="icon != null">#{icon},</if>
          </trim>
          </trim>
     </insert>
     </insert>
@@ -101,9 +101,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isSystem != null and isSystem != ''">is_system = #{isSystem},</if>
             <if test="isSystem != null and isSystem != ''">is_system = #{isSystem},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="icon != null">icon = #{icon},</if>
             <if test="icon != null">icon = #{icon},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/rbac/RbacModuleMapper.xml

@@ -52,9 +52,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="sort != null">sort,</if>
             <if test="sort != null">sort,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="name != null and name != ''">#{name},</if>
             <if test="name != null and name != ''">#{name},</if>
@@ -65,9 +65,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="sort != null">#{sort},</if>
             <if test="sort != null">#{sort},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -82,9 +82,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="sort != null">sort = #{sort},</if>
             <if test="sort != null">sort = #{sort},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/rbac/RbacRoleMapper.xml

@@ -46,9 +46,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="attachUrl != null">attach_url,</if>
             <if test="attachUrl != null">attach_url,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="name != null and name != ''">#{name},</if>
             <if test="name != null and name != ''">#{name},</if>
@@ -57,9 +57,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="attachUrl != null">#{attachUrl},</if>
             <if test="attachUrl != null">#{attachUrl},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -72,9 +72,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="attachUrl != null">attach_url = #{attachUrl},</if>
             <if test="attachUrl != null">attach_url = #{attachUrl},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/rbac/RbacUserMapper.xml

@@ -59,9 +59,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="type != null">type,</if>
             <if test="type != null">type,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="isDel != null and isDel != ''">is_del,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="dataIds != null and dataIds != ''">data_ids,</if>
             <if test="dataIds != null and dataIds != ''">data_ids,</if>
             <if test="relationType != null">relation_type,</if>
             <if test="relationType != null">relation_type,</if>
          </trim>
          </trim>
@@ -75,9 +75,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="type != null">#{type},</if>
             <if test="type != null">#{type},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="isDel != null and isDel != ''">#{isDel},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="dataIds != null and dataIds != ''">#{dataIds},</if>
             <if test="dataIds != null and dataIds != ''">#{dataIds},</if>
             <if test="relationType != null">#{relationType},</if>
             <if test="relationType != null">#{relationType},</if>
          </trim>
          </trim>
@@ -95,9 +95,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="type != null">type = #{type},</if>
             <if test="type != null">type = #{type},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="isDel != null and isDel != ''">is_del = #{isDel},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="dataIds != null and dataIds != ''">data_ids = #{dataIds},</if>
             <if test="dataIds != null and dataIds != ''">data_ids = #{dataIds},</if>
             <if test="relationType != null">relation_type = #{relationType},</if>
             <if test="relationType != null">relation_type = #{relationType},</if>
         </trim>
         </trim>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/report/ConfigReportSiteInfoMapper.xml

@@ -52,9 +52,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">enable_flag,</if>
             <if test="enableFlag != null and enableFlag != ''">enable_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="id != null">#{id},</if>
@@ -66,9 +66,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">#{enableFlag},</if>
             <if test="enableFlag != null and enableFlag != ''">#{enableFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -83,9 +83,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">enable_flag = #{enableFlag},</if>
             <if test="enableFlag != null and enableFlag != ''">enable_flag = #{enableFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/report/ConfigReportSiteMapper.xml

@@ -62,9 +62,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="siteProtocol != null">site_protocol,</if>
             <if test="siteProtocol != null">site_protocol,</if>
             <if test="maxLength != null">max_length,</if>
             <if test="maxLength != null">max_length,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="provinceNumber != null">province_number,</if>
             <if test="provinceNumber != null">province_number,</if>
             <if test="fileCode != null">file_code,</if>
             <if test="fileCode != null">file_code,</if>
@@ -82,9 +82,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="siteProtocol != null">#{siteProtocol},</if>
             <if test="siteProtocol != null">#{siteProtocol},</if>
             <if test="maxLength != null">#{maxLength},</if>
             <if test="maxLength != null">#{maxLength},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="provinceNumber != null">#{provinceNumber},</if>
             <if test="provinceNumber != null">#{provinceNumber},</if>
             <if test="fileCode != null">#{fileCode},</if>
             <if test="fileCode != null">#{fileCode},</if>
@@ -105,9 +105,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="siteProtocol != null">site_protocol = #{siteProtocol},</if>
             <if test="siteProtocol != null">site_protocol = #{siteProtocol},</if>
             <if test="maxLength != null">max_length = #{maxLength},</if>
             <if test="maxLength != null">max_length = #{maxLength},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="provinceNumber != null">province_number = #{provinceNumber},</if>
             <if test="provinceNumber != null">province_number = #{provinceNumber},</if>
             <if test="fileCode != null">file_code = #{fileCode},</if>
             <if test="fileCode != null">file_code = #{fileCode},</if>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/report/ConfigReportTaskMapper.xml

@@ -58,9 +58,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">enable_flag,</if>
             <if test="enableFlag != null and enableFlag != ''">enable_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="delFlag != null and delFlag != ''">del_flag,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="id != null">#{id},</if>
@@ -74,9 +74,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">#{enableFlag},</if>
             <if test="enableFlag != null and enableFlag != ''">#{enableFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">#{delFlag},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -93,9 +93,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="enableFlag != null and enableFlag != ''">enable_flag = #{enableFlag},</if>
             <if test="enableFlag != null and enableFlag != ''">enable_flag = #{enableFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 3 - 3
forecast-backend-server/src/main/resources/mybatis/report/StatsAssessmentIndicatorMapper.xml

@@ -53,7 +53,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">data_source,</if>
             <if test="dataSource != null">data_source,</if>
             <if test="indicatorValue != null">indicator_value,</if>
             <if test="indicatorValue != null">indicator_value,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="recordTime != null">record_time,</if>
             <if test="recordTime != null">record_time,</if>
@@ -68,7 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">#{dataSource},</if>
             <if test="dataSource != null">#{dataSource},</if>
             <if test="indicatorValue != null">#{indicatorValue},</if>
             <if test="indicatorValue != null">#{indicatorValue},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="recordTime != null">#{recordTime},</if>
             <if test="recordTime != null">#{recordTime},</if>
@@ -86,7 +86,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">data_source = #{dataSource},</if>
             <if test="dataSource != null">data_source = #{dataSource},</if>
             <if test="indicatorValue != null">indicator_value = #{indicatorValue},</if>
             <if test="indicatorValue != null">indicator_value = #{indicatorValue},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="recordTime != null">record_time = #{recordTime},</if>
             <if test="recordTime != null">record_time = #{recordTime},</if>

+ 3 - 3
forecast-backend-server/src/main/resources/mybatis/report/StatsAssessmentIndicatorMultiModelMapper.xml

@@ -53,7 +53,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">data_source,</if>
             <if test="dataSource != null">data_source,</if>
             <if test="indicatorValue != null">indicator_value,</if>
             <if test="indicatorValue != null">indicator_value,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="recordTime != null">record_time,</if>
             <if test="recordTime != null">record_time,</if>
@@ -68,7 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">#{dataSource},</if>
             <if test="dataSource != null">#{dataSource},</if>
             <if test="indicatorValue != null">#{indicatorValue},</if>
             <if test="indicatorValue != null">#{indicatorValue},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="recordTime != null">#{recordTime},</if>
             <if test="recordTime != null">#{recordTime},</if>
@@ -86,7 +86,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">data_source = #{dataSource},</if>
             <if test="dataSource != null">data_source = #{dataSource},</if>
             <if test="indicatorValue != null">indicator_value = #{indicatorValue},</if>
             <if test="indicatorValue != null">indicator_value = #{indicatorValue},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="recordTime != null">record_time = #{recordTime},</if>
             <if test="recordTime != null">record_time = #{recordTime},</if>

+ 3 - 3
forecast-backend-server/src/main/resources/mybatis/report/StatsWeatherIndicatorMapper.xml

@@ -48,7 +48,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">data_source,</if>
             <if test="dataSource != null">data_source,</if>
             <if test="indicatorVal != null">indicator_val,</if>
             <if test="indicatorVal != null">indicator_val,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="recordTime != null">record_time,</if>
             <if test="recordTime != null">record_time,</if>
@@ -61,7 +61,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">#{dataSource},</if>
             <if test="dataSource != null">#{dataSource},</if>
             <if test="indicatorVal != null">#{indicatorVal},</if>
             <if test="indicatorVal != null">#{indicatorVal},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="recordTime != null">#{recordTime},</if>
             <if test="recordTime != null">#{recordTime},</if>
@@ -77,7 +77,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">data_source = #{dataSource},</if>
             <if test="dataSource != null">data_source = #{dataSource},</if>
             <if test="indicatorVal != null">indicator_val = #{indicatorVal},</if>
             <if test="indicatorVal != null">indicator_val = #{indicatorVal},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="recordTime != null">record_time = #{recordTime},</if>
             <if test="recordTime != null">record_time = #{recordTime},</if>

+ 3 - 3
forecast-backend-server/src/main/resources/mybatis/report/StatsWeatherIndicatorMultiModelMapper.xml

@@ -50,7 +50,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">data_source,</if>
             <if test="dataSource != null">data_source,</if>
             <if test="indicatorValue != null">indicator_value,</if>
             <if test="indicatorValue != null">indicator_value,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createBy != null">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="recordTime != null">record_time,</if>
             <if test="recordTime != null">record_time,</if>
@@ -64,7 +64,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">#{dataSource},</if>
             <if test="dataSource != null">#{dataSource},</if>
             <if test="indicatorValue != null">#{indicatorValue},</if>
             <if test="indicatorValue != null">#{indicatorValue},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createBy != null">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="recordTime != null">#{recordTime},</if>
             <if test="recordTime != null">#{recordTime},</if>
@@ -81,7 +81,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="dataSource != null">data_source = #{dataSource},</if>
             <if test="dataSource != null">data_source = #{dataSource},</if>
             <if test="indicatorValue != null">indicator_value = #{indicatorValue},</if>
             <if test="indicatorValue != null">indicator_value = #{indicatorValue},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="recordTime != null">record_time = #{recordTime},</if>
             <if test="recordTime != null">record_time = #{recordTime},</if>

+ 6 - 6
forecast-backend-server/src/main/resources/mybatis/weather/WeatherWarningRecordMapper.xml

@@ -58,9 +58,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="warningTitle != null and warningTitle != ''">warning_title,</if>
             <if test="warningTitle != null and warningTitle != ''">warning_title,</if>
             <if test="warningMessage != null and warningMessage != ''">warning_message,</if>
             <if test="warningMessage != null and warningMessage != ''">warning_message,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
             <if test="createBy != null and createBy != ''">create_by,</if>
-            <if test="createTime != null and createTime != ''">create_time,</if>
+            <if test="createTime != null">create_time,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
             <if test="updateBy != null and updateBy != ''">update_by,</if>
-            <if test="updateTime != null and updateTime != ''">update_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="type != null">#{type},</if>
             <if test="type != null">#{type},</if>
@@ -73,9 +73,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="warningTitle != null and warningTitle != ''">#{warningTitle},</if>
             <if test="warningTitle != null and warningTitle != ''">#{warningTitle},</if>
             <if test="warningMessage != null and warningMessage != ''">#{warningMessage},</if>
             <if test="warningMessage != null and warningMessage != ''">#{warningMessage},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
             <if test="createBy != null and createBy != ''">#{createBy},</if>
-            <if test="createTime != null and createTime != ''">#{createTime},</if>
+            <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">#{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">#{updateTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
          </trim>
     </insert>
     </insert>
 
 
@@ -92,9 +92,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="warningTitle != null and warningTitle != ''">warning_title = #{warningTitle},</if>
             <if test="warningTitle != null and warningTitle != ''">warning_title = #{warningTitle},</if>
             <if test="warningMessage != null and warningMessage != ''">warning_message = #{warningMessage},</if>
             <if test="warningMessage != null and warningMessage != ''">warning_message = #{warningMessage},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
             <if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
-            <if test="createTime != null and createTime != ''">create_time = #{createTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
             <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
-            <if test="updateTime != null and updateTime != ''">update_time = #{updateTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
         </trim>
         </trim>
         where id = #{id}
         where id = #{id}
     </update>
     </update>

+ 14 - 28
forecast-backend-vue/src/api/alarm/eventRecord.js

@@ -1,44 +1,30 @@
 import request from '@/utils/request'
 import request from '@/utils/request'
 
 
-// 查询报警信息统计列表
-export function listEventRecord(query) {
+// 查询事件列表
+export function listEventRecord(data) {
   return request({
   return request({
     url: '/alarm/eventRecord/list',
     url: '/alarm/eventRecord/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询报警信息统计详细
-export function getEventRecord(id) {
-  return request({
-    url: '/alarm/eventRecord/' + id,
-    method: 'get'
-  })
-}
-
-// 新增报警信息统计
-export function addEventRecord(data) {
-  return request({
-    url: '/alarm/eventRecord',
     method: 'post',
     method: 'post',
     data: data
     data: data
   })
   })
 }
 }
 
 
-// 修改报警信息统计
-export function updateEventRecord(data) {
+// 确认告警(批量处理)
+export function processEventRecord(ids) {
   return request({
   return request({
-    url: '/alarm/eventRecord',
-    method: 'put',
-    data: data
+    url: '/alarm/eventRecord/process',
+    method: 'post',
+    data: { ids: ids }
   })
   })
 }
 }
 
 
-// 删除报警信息统计
-export function delEventRecord(id) {
+// 导出事件列表
+export function exportEventRecord(data) {
   return request({
   return request({
-    url: '/alarm/eventRecord/' + id,
-    method: 'delete'
+    url: '/alarm/eventRecord/export',
+    method: 'post',
+    data: data,
+    responseType: 'blob',
+    timeout: 120000
   })
   })
 }
 }

+ 29 - 0
forecast-backend-vue/src/api/fileupload/reportLog.js

@@ -16,3 +16,32 @@ export function getReportLogFileContent(id) {
     method: 'get'
     method: 'get'
   })
   })
 }
 }
+
+// 查询光伏上传率统计(手动分页)
+export function listUploadRate(data) {
+  return request({
+    url: '/fileupload/reportLog/uploadRate/list',
+    method: 'post',
+    data
+  })
+}
+
+// 导出光伏上传率统计
+export function exportUploadRate(data) {
+  return request({
+    url: '/fileupload/reportLog/uploadRate/export',
+    method: 'post',
+    data,
+    responseType: 'blob',
+    timeout: 120000
+  })
+}
+
+// 数据补传(按每日配置补插当日上报成功记录)
+export function reUpload(stationCode) {
+  return request({
+    url: '/fileupload/reportLog/reUpload',
+    method: 'get',
+    params: {stationCode}
+  })
+}

+ 3 - 1
forecast-backend-vue/src/utils/BearJiaUtil.js

@@ -177,7 +177,9 @@ const BearJiaUtil = {
                     if (d) {
                     if (d) {
                         dicts.push({
                         dicts.push({
                             value: d.dictValue,
                             value: d.dictValue,
-                            label: d.dictLabel
+                            label: d.dictLabel,
+                            cssClass: d.cssClass,
+                            listClass: d.listClass
                         });
                         });
                     }
                     }
                 }
                 }

+ 5 - 1
forecast-backend-vue/src/views/ufo/config/station/StationConfigCrud.vue

@@ -290,7 +290,9 @@ const submitForm = async () => {
 const handleDeleteRecord = (record) => {
 const handleDeleteRecord = (record) => {
   Modal.confirm({
   Modal.confirm({
     title: '确认删除',
     title: '确认删除',
-    content: `确认删除该${moduleConfig.title}?`,
+    content: `确认删除该${props.moduleConfig.title}?`,
+    okText: '确定',
+    cancelText: '取消',
     onOk: async () => {
     onOk: async () => {
       await props.api.del(record.id);
       await props.api.del(record.id);
       message.success('删除成功');
       message.success('删除成功');
@@ -306,6 +308,8 @@ const handleBatchDelete = () => {
   Modal.confirm({
   Modal.confirm({
     title: '确认删除',
     title: '确认删除',
     content: `确认删除选中的 ${selectedRowKeys.value.length} 条数据?`,
     content: `确认删除选中的 ${selectedRowKeys.value.length} 条数据?`,
+    okText: '确定',
+    cancelText: '取消',
     onOk: async () => {
     onOk: async () => {
       await props.api.del(selectedRowKeys.value);
       await props.api.del(selectedRowKeys.value);
       message.success('删除成功');
       message.success('删除成功');

+ 9 - 4
forecast-backend-vue/src/views/ufo/config/station/index.vue

@@ -8,7 +8,7 @@
         <a-form-item label="场站编码">
         <a-form-item label="场站编码">
           <a-input v-model:value="queryParams.stationCode" allow-clear placeholder="请输入场站编码" />
           <a-input v-model:value="queryParams.stationCode" allow-clear placeholder="请输入场站编码" />
         </a-form-item>
         </a-form-item>
-        <a-form-item label="场站类型">
+        <a-form-item label="场站类型" style="display:none">
           <a-select v-model:value="queryParams.stationType" allow-clear class="query-select" :options="stationTypeOptions" />
           <a-select v-model:value="queryParams.stationType" allow-clear class="query-select" :options="stationTypeOptions" />
         </a-form-item>
         </a-form-item>
         <a-form-item label="是否启用">
         <a-form-item label="是否启用">
@@ -36,7 +36,7 @@
         @reset="handleTableReset"
         @reset="handleTableReset"
       >
       >
         <template #left>
         <template #left>
-          <a-button v-hasPermi="['config:station:add']" type="primary" @click="openForm()"><BearJiaIcon icon="plus-outlined"/>新增</a-button>
+          <a-button v-hasPermi="['config:station:add']" type="primary" style="display:none" @click="openForm()"><BearJiaIcon icon="plus-outlined"/>新增</a-button>
           <a-button v-hasPermi="['config:station:remove']" danger type="primary" :disabled="selectedRowKeys.length <= 0" @click="handleBatchDelete"><BearJiaIcon icon="delete-outlined"/>删除</a-button>
           <a-button v-hasPermi="['config:station:remove']" danger type="primary" :disabled="selectedRowKeys.length <= 0" @click="handleBatchDelete"><BearJiaIcon icon="delete-outlined"/>删除</a-button>
           <a-button v-hasPermi="['config:station:export']" @click="handleExport"><BearJiaIcon icon="export-outlined"/>导出</a-button>
           <a-button v-hasPermi="['config:station:export']" @click="handleExport"><BearJiaIcon icon="export-outlined"/>导出</a-button>
         </template>
         </template>
@@ -86,7 +86,7 @@
               <a-input v-model:value="form.stationCode" allow-clear />
               <a-input v-model:value="form.stationCode" allow-clear />
             </a-form-item>
             </a-form-item>
           </a-col>
           </a-col>
-          <a-col :span="12">
+          <a-col :span="12" style="display:none">
             <a-form-item label="场站类型" name="stationType">
             <a-form-item label="场站类型" name="stationType">
               <a-select v-model:value="form.stationType" allow-clear :options="stationTypeOptions" />
               <a-select v-model:value="form.stationType" allow-clear :options="stationTypeOptions" />
             </a-form-item>
             </a-form-item>
@@ -271,12 +271,13 @@ const openForm = async (record) => {
     }
     }
     resetObject(form, data);
     resetObject(form, data);
   } else {
   } else {
-    resetObject(form, { isEnable: '1', stationType: 0 });
+    resetObject(form, { isEnable: '1', stationType: 1 });
   }
   }
   formOpen.value = true;
   formOpen.value = true;
 };
 };
 
 
 const submitForm = async () => {
 const submitForm = async () => {
+  form.stationType = 1;
   await formRef.value?.validate();
   await formRef.value?.validate();
   if (form.id) {
   if (form.id) {
     await updateStation(form);
     await updateStation(form);
@@ -292,6 +293,8 @@ const handleDeleteRecord = (record) => {
   Modal.confirm({
   Modal.confirm({
     title: '确认删除',
     title: '确认删除',
     content: '确认删除该场站?',
     content: '确认删除该场站?',
+    okText: '确定',
+    cancelText: '取消',
     onOk: async () => {
     onOk: async () => {
       await delStation(record.id);
       await delStation(record.id);
       message.success('删除成功');
       message.success('删除成功');
@@ -307,6 +310,8 @@ const handleBatchDelete = () => {
   Modal.confirm({
   Modal.confirm({
     title: '确认删除',
     title: '确认删除',
     content: `确认删除选中的 ${selectedRowKeys.value.length} 条数据?`,
     content: `确认删除选中的 ${selectedRowKeys.value.length} 条数据?`,
+    okText: '确定',
+    cancelText: '取消',
     onOk: async () => {
     onOk: async () => {
       await delStation(selectedRowKeys.value);
       await delStation(selectedRowKeys.value);
       message.success('删除成功');
       message.success('删除成功');

+ 207 - 107
forecast-backend-vue/src/views/ufo/electricity/device/TurbineInfo.vue

@@ -3,167 +3,267 @@
     <a-card :bordered="false">
     <a-card :bordered="false">
       <a-row :gutter="[12, 12]" align="middle">
       <a-row :gutter="[12, 12]" align="middle">
         <a-col :xs="24" :md="8">
         <a-col :xs="24" :md="8">
-          <StationSelector v-model:value="query.stationIds" :options="stationOptions" />
+          <StationSelector v-model:value="queryParams.configStationId" :options="stationOptions" :multiple="false" />
         </a-col>
         </a-col>
         <a-col :xs="24" :md="6">
         <a-col :xs="24" :md="6">
-          <a-select v-model:value="query.deviceType" :options="deviceTypeOptions" class="full-control" />
-        </a-col>
-        <a-col :xs="24" :md="6">
-          <a-input v-model:value="query.keyword" placeholder="请输入设备名称" />
+          <a-input v-model:value="queryParams.name" placeholder="请输入设备名称" allow-clear @press-enter="handleQuery" />
         </a-col>
         </a-col>
         <a-col :xs="24" :md="4" class="action-bar">
         <a-col :xs="24" :md="4" class="action-bar">
           <a-space>
           <a-space>
-            <a-button type="primary" :loading="loading" @click="handleQuery">查询</a-button>
-            <a-button>新增</a-button>
+            <a-button type="primary" :loading="loading" @click="handleQuery"><BearJiaIcon icon="SearchOutlined" />查询</a-button>
+            <a-button @click="resetQuery">重置</a-button>
           </a-space>
           </a-space>
         </a-col>
         </a-col>
       </a-row>
       </a-row>
     </a-card>
     </a-card>
 
 
-    <a-card title="光伏设备信息" :bordered="false" class="section" :loading="loading">
+    <a-card title="光伏设备信息" :bordered="false" class="section">
+      <a-space class="table-actions">
+        <a-button type="primary" @click="openForm"><BearJiaIcon icon="plus-outlined" />新增</a-button>
+        <a-button danger type="primary" :disabled="selectedRowKeys.length <= 0" @click="handleBatchDelete"><BearJiaIcon icon="delete-outlined" />删除</a-button>
+        <a-button @click="handleExport"><BearJiaIcon icon="export-outlined" />导出</a-button>
+      </a-space>
       <a-table
       <a-table
         :columns="columns"
         :columns="columns"
         :data-source="rows"
         :data-source="rows"
-        :pagination="{pageSize: 10}"
+        :loading="loading"
+        :pagination="pagination"
         :locale="{emptyText: '暂无数据'}"
         :locale="{emptyText: '暂无数据'}"
         row-key="id"
         row-key="id"
-      />
+        :row-selection="rowSelection"
+        @change="handleTableChange"
+      >
+        <template #bodyCell="{ column, record }">
+          <template v-if="column.key === 'operation'">
+            <TableActionBar :record="record" :has-view="false" :has-edit="true" :has-delete="true" @edit="openForm(record)" @delete="handleDeleteRecord(record)" />
+          </template>
+        </template>
+      </a-table>
     </a-card>
     </a-card>
+
+    <a-modal v-model:open="formOpen" :title="form.id ? '编辑设备' : '新增设备'" width="640px" @ok="submitForm">
+      <a-form ref="formRef" :model="form" :rules="rules" :label-col="{span: 5}" :wrapper-col="{span: 17}">
+        <a-form-item label="设备名称" name="name">
+          <a-input v-model:value="form.name" allow-clear placeholder="请输入设备名称" />
+        </a-form-item>
+        <a-form-item label="通道" name="configChannelId">
+          <a-select v-model:value="form.configChannelId" :options="channelOptions" placeholder="请选择通道" />
+        </a-form-item>
+        <a-form-item label="所属场站" name="configStationId">
+          <a-select v-model:value="form.configStationId" :options="stationOptions" placeholder="请选择所属场站" />
+        </a-form-item>
+        <a-form-item label="设备类型" name="tp">
+          <a-select v-model:value="form.tp" :options="tpOptions" placeholder="请选择设备类型" />
+        </a-form-item>
+        <a-form-item label="品牌" name="brand">
+          <a-input v-model:value="form.brand" allow-clear placeholder="请输入品牌" />
+        </a-form-item>
+        <a-form-item label="型号" name="model">
+          <a-input v-model:value="form.model" allow-clear placeholder="请输入型号" />
+        </a-form-item>
+        <a-form-item label="序列号" name="serialNumber">
+          <a-input v-model:value="form.serialNumber" allow-clear placeholder="请输入序列号" />
+        </a-form-item>
+        <a-form-item label="状态" name="status">
+          <a-select v-model:value="form.status" :options="statusOptions" placeholder="请选择状态" />
+        </a-form-item>
+        <a-form-item label="投运日期" name="installDate">
+          <a-date-picker v-model:value="form.installDate" value-format="YYYY-MM-DD" style="width: 100%" placeholder="请选择投运日期" />
+        </a-form-item>
+      </a-form>
+    </a-modal>
   </div>
   </div>
 </template>
 </template>
 
 
 <script setup name="ElectricityTurbineInfo">
 <script setup name="ElectricityTurbineInfo">
-import {onMounted, reactive, ref} from 'vue';
+import {computed, onMounted, reactive, ref} from 'vue';
+import {message, Modal} from 'ant-design-vue';
+import BearJiaUtil from '@/utils/BearJiaUtil';
 import {listStation} from '@/api/config/station';
 import {listStation} from '@/api/config/station';
-import {listDevicePowerReal} from '@/api/realtime/devicePowerReal';
+import {listChannel} from '@/api/config/channel';
+import {addDevice, delDevice, getDevice, listDevice, updateDevice} from '@/api/config/device';
 import StationSelector from '../components/StationSelector.vue';
 import StationSelector from '../components/StationSelector.vue';
-import {normalizeRows, pick, toNumber} from '../components/dataAdapter';
-import {buildStationNameMap, resolveStationName, toStationOptions} from '../components/stationAdapter';
+import TableActionBar from '@/components/TableActionBar/index.vue';
+import {normalizeRows} from '../components/dataAdapter';
+import {toStationOptions} from '../components/stationAdapter';
+import {BearJiaIcon} from '@/utils/BearJiaIcon.js';
 
 
 const loading = ref(false);
 const loading = ref(false);
-const stationOptions = ref([]);
-const stationNameMap = ref(new Map());
 const rows = ref([]);
 const rows = ref([]);
+const stationOptions = ref([]);
+const channelOptions = ref([]);
+const selectedRowKeys = ref([]);
+const formOpen = ref(false);
+const formRef = ref();
 
 
-const query = reactive({
-  stationIds: [],
-  deviceType: 'inverter',
-  keyword: ''
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  configStationId: undefined,
+  name: undefined
 });
 });
 
 
-const deviceTypeOptions = [
-  {label: '逆变器', value: 'inverter'},
-  {label: '箱变', value: 'box_transformer'},
-  {label: '汇流箱', value: 'combiner_box'}
+const pagination = reactive({
+  current: 1,
+  pageSize: 10,
+  total: 0,
+  showSizeChanger: true
+});
+
+const form = reactive({});
+
+const rowSelection = computed(() => ({
+  selectedRowKeys: selectedRowKeys.value,
+  onChange: (keys) => {
+    selectedRowKeys.value = keys;
+  }
+}));
+
+const tpOptions = [
+  {label: '气象设备', value: 'WEATHER'},
+  {label: 'agvc设备', value: 'AGVC'}
 ];
 ];
 
 
+const statusOptions = [
+  {label: '在线', value: 'GOOD'},
+  {label: '离线', value: 'OFF'}
+];
+
+const rules = {
+  name: [{required: true, message: '请输入设备名称', trigger: 'blur'}],
+  configChannelId: [{required: true, message: '请选择通道', trigger: 'change'}],
+  configStationId: [{required: true, message: '请选择所属场站', trigger: 'change'}],
+  tp: [{required: true, message: '请选择设备类型', trigger: 'change'}],
+  brand: [{required: true, message: '请输入品牌', trigger: 'blur'}],
+  model: [{required: true, message: '请输入型号', trigger: 'blur'}],
+  serialNumber: [{required: true, message: '请输入序列号', trigger: 'blur'}],
+  status: [{required: true, message: '请选择状态', trigger: 'change'}],
+  installDate: [{required: true, message: '请选择投运日期', trigger: 'change'}]
+};
+
 const columns = [
 const columns = [
-  {title: '序号', dataIndex: 'id', width: 80},
-  {title: '设备名称', dataIndex: 'deviceName'},
-  {title: '设备类型', dataIndex: 'deviceType'},
+  {
+    title: '序号', width: 120, align: 'center',
+    customRender: ({index}) => (pagination.current - 1) * pagination.pageSize + index + 1
+  },
+  {title: '设备名称', dataIndex: 'name'},
+  {title: '通道', dataIndex: 'channelName'},
   {title: '所属场站', dataIndex: 'stationName'},
   {title: '所属场站', dataIndex: 'stationName'},
-  {title: '额定容量', dataIndex: 'capacity'},
+  {
+    title: '设备类型', dataIndex: 'tp',
+    customRender: ({text}) => (text === 'WEATHER' ? '气象设备' : text === 'AGVC' ? 'agvc设备' : text)
+  },
+  {title: '品牌', dataIndex: 'brand'},
   {title: '型号', dataIndex: 'model'},
   {title: '型号', dataIndex: 'model'},
-  {title: '状态', dataIndex: 'status'}
+  {title: '序列号', dataIndex: 'serialNumber'},
+  {
+    title: '状态', dataIndex: 'status', width: 120,
+    customRender: ({text}) => (text === 'GOOD' ? '在线' : '离线')
+  },
+  {title: '投运日期', dataIndex: 'installDate', width: 180},
+  {title: '操作', key: 'operation', dataIndex: 'operation', width: 200, fixed: 'right'}
 ];
 ];
 
 
-const deviceTypeMap = {
-  inverter: '逆变器',
-  box_transformer: '箱变',
-  combiner_box: '汇流箱'
+const resetObject = (target, source = {}) => {
+  Object.keys(target).forEach((key) => delete target[key]);
+  Object.assign(target, source);
 };
 };
 
 
-const toStatus = (value) => {
-  const text = String(value ?? '').trim().toLowerCase();
-  if (text.includes('offline') || text.includes('离线') || text === '0' || text === 'false') return '离线';
-  if (text.includes('abnormal') || text.includes('fault') || text.includes('异常') || text.includes('告警')) return '检修';
-  return '在线';
+const loadStationOptions = async () => {
+  const res = await listStation({pageNum: 1, pageSize: 500});
+  stationOptions.value = toStationOptions(normalizeRows(res));
 };
 };
 
 
-const inferDeviceType = (item) => {
-  const raw = String(pick(item, ['deviceType', 'type', 'equipmentType'], '')).toLowerCase();
-  const name = String(pick(item, ['deviceName', 'name', 'deviceId'], '')).toLowerCase();
-  const text = `${raw} ${name}`;
-  if (text.includes('combiner') || text.includes('汇流')) return 'combiner_box';
-  if (text.includes('box') || text.includes('transform') || text.includes('箱变') || text.includes('升压')) return 'box_transformer';
-  if (text.includes('invert') || text.includes('inv') || text.includes('逆变')) return 'inverter';
-  return 'inverter';
+const loadChannelOptions = async () => {
+  const res = await listChannel({pageNum: 1, pageSize: 500});
+  const channelRows = res?.rows || res?.data || [];
+  channelOptions.value = channelRows.map((item) => ({label: item.name || item.id, value: item.id}));
 };
 };
 
 
-const formatCapacity = (item) => {
-  const raw = pick(item, ['capacity', 'ratedCapacity', 'installCapacity'], '');
-  const num = toNumber(raw, NaN);
-  if (Number.isFinite(num) && num !== 0) return `${Number(num.toFixed(2))}MW`;
-  return raw || '-';
+const handleQuery = async () => {
+  loading.value = true;
+  try {
+    const res = await listDevice(queryParams);
+    rows.value = res?.rows || res?.data || [];
+    pagination.total = res?.total || rows.value.length;
+    pagination.current = queryParams.pageNum;
+    pagination.pageSize = queryParams.pageSize;
+  } finally {
+    loading.value = false;
+  }
 };
 };
 
 
-const toPvDeviceName = (name, typeKey, index) => {
-  const text = String(name || '').trim();
-  if (text) {
-    return text.replace(/风机/g, '逆变器');
-  }
-  return `${deviceTypeMap[typeKey] || '逆变器'} #${index + 1}`;
+const resetQuery = () => {
+  queryParams.pageNum = 1;
+  queryParams.configStationId = undefined;
+  queryParams.name = undefined;
+  handleQuery();
 };
 };
 
 
-const loadStationOptions = async () => {
-  const res = await listStation({pageNum: 1, pageSize: 500});
-  const stationRows = normalizeRows(res);
-  stationOptions.value = toStationOptions(stationRows);
-  stationNameMap.value = buildStationNameMap(stationRows);
-  if (!query.stationIds.length && stationOptions.value.length) {
-    query.stationIds = [stationOptions.value[0].value];
-  }
+const handleTableChange = (page) => {
+  queryParams.pageNum = page.current;
+  queryParams.pageSize = page.pageSize;
+  handleQuery();
 };
 };
 
 
-const filterRowsBySelectedStations = (sourceRows) => {
-  const stationIds = Array.isArray(query.stationIds) ? query.stationIds : [query.stationIds].filter(Boolean);
-  if (!stationIds.length) {
-    return sourceRows;
+const openForm = async (record) => {
+  if (record?.id) {
+    const res = await getDevice(record.id);
+    resetObject(form, {...res.data});
+  } else {
+    resetObject(form, {configStationId: queryParams.configStationId});
   }
   }
-  const selectedKeys = new Set(stationIds);
-  return sourceRows.filter((item) =>
-    [item.stationId, item.entityId, item.id, item.Id].some((key) => selectedKeys.has(key))
-  );
+  formOpen.value = true;
 };
 };
 
 
-const handleQuery = async () => {
-  loading.value = true;
-  try {
-    const stationIds = Array.isArray(query.stationIds) ? query.stationIds : [query.stationIds].filter(Boolean);
-    const params = {
-      pageNum: 1,
-      pageSize: 500,
-      entityId: stationIds.length === 1 ? stationIds[0] : undefined,
-      stationIds: stationIds.join(',')
-    };
-    const res = await listDevicePowerReal(params);
-    const sourceRows = filterRowsBySelectedStations(normalizeRows(res)).map((item, index) => {
-      const typeKey = inferDeviceType(item);
-      return {
-        id: item.id || item.Id || index + 1,
-        deviceName: toPvDeviceName(pick(item, ['deviceName', 'name', 'deviceId', 'sensorName']), typeKey, index),
-        deviceTypeKey: typeKey,
-        deviceType: deviceTypeMap[typeKey] || '逆变器',
-        stationName: resolveStationName(item, stationNameMap.value) || '江门站',
-        capacity: formatCapacity(item),
-        model: pick(item, ['model', 'deviceModel', 'specification', 'version'], '-'),
-        status: toStatus(pick(item, ['status', 'state', 'onlineStatus'], 'online'))
-      };
-    });
-
-    rows.value = sourceRows.filter((item) => {
-      const typeMatched = query.deviceType ? item.deviceTypeKey === query.deviceType : true;
-      const keyword = query.keyword?.trim();
-      const keywordMatched = keyword ? String(item.deviceName || '').includes(keyword) : true;
-      return typeMatched && keywordMatched;
-    });
-  } finally {
-    loading.value = false;
+const submitForm = async () => {
+  await formRef.value?.validate();
+  if (form.id) await updateDevice(form); else await addDevice(form);
+  message.success('保存成功');
+  formOpen.value = false;
+  handleQuery();
+};
+
+const handleDeleteRecord = (record) => {
+  Modal.confirm({
+    title: '确认删除',
+    content: '确认删除该设备?',
+    okText: '确定',
+    cancelText: '取消',
+    onOk: async () => {
+      await delDevice(record.id);
+      message.success('删除成功');
+      handleQuery();
+    }
+  });
+};
+
+const handleBatchDelete = () => {
+  if (selectedRowKeys.value.length <= 0) {
+    message.warning('请至少选择一条数据');
+    return;
   }
   }
+  Modal.confirm({
+    title: '确认删除',
+    content: `确认删除选中的 ${selectedRowKeys.value.length} 条数据?`,
+    okText: '确定',
+    cancelText: '取消',
+    onOk: async () => {
+      await delDevice(selectedRowKeys.value);
+      message.success('删除成功');
+      selectedRowKeys.value = [];
+      handleQuery();
+    }
+  });
+};
+
+const handleExport = () => {
+  BearJiaUtil.download('config/device/export', queryParams, '设备配置.xlsx');
 };
 };
 
 
 onMounted(async () => {
 onMounted(async () => {
   await loadStationOptions();
   await loadStationOptions();
+  await loadChannelOptions();
   await handleQuery();
   await handleQuery();
 });
 });
 </script>
 </script>
@@ -172,5 +272,5 @@ onMounted(async () => {
 .device-page { padding: 16px; }
 .device-page { padding: 16px; }
 .section { margin-top: 16px; }
 .section { margin-top: 16px; }
 .action-bar { display: flex; justify-content: flex-end; }
 .action-bar { display: flex; justify-content: flex-end; }
-.full-control { width: 100%; }
+.table-actions { display: flex; margin-bottom: 12px; }
 </style>
 </style>

+ 63 - 0
forecast-backend-vue/src/views/ufo/electricity/forecast/DataResend.vue

@@ -0,0 +1,63 @@
+<template>
+  <div class="data-resend-page">
+    <a-card :bordered="false">
+      <a-row :gutter="[12, 12]" align="middle">
+        <a-col :xs="24" :md="8">
+          <StationSelector v-model:value="stationCode" :options="stationOptions" :multiple="false" />
+        </a-col>
+        <a-col :xs="24" :md="8">
+          <a-space>
+            <a-button type="primary" :loading="resending" :disabled="!stationCode" @click="handleResend">补传</a-button>
+          </a-space>
+        </a-col>
+      </a-row>
+    </a-card>
+  </div>
+</template>
+
+<script setup name="DataResend">
+import {onMounted, ref} from 'vue';
+import {message} from 'ant-design-vue';
+import {listStation} from '@/api/config/station';
+import {reUpload} from '@/api/fileupload/reportLog';
+import StationSelector from '../components/StationSelector.vue';
+
+const resending = ref(false);
+const stationOptions = ref([]);
+const stationCode = ref(undefined);
+
+const loadStationOptions = async () => {
+  const res = await listStation({pageNum: 1, pageSize: 500});
+  const list = (res && res.rows) || [];
+  stationOptions.value = list.map((item) => ({label: item.stationName, value: item.stationCode}));
+  if (!stationCode.value && stationOptions.value.length) {
+    stationCode.value = stationOptions.value[0].value;
+  }
+};
+
+const handleResend = async () => {
+  if (!stationCode.value) {
+    message.warning('请先选择场站');
+    return;
+  }
+  resending.value = true;
+  try {
+    const res = await reUpload(stationCode.value);
+    message.success(res.msg || '补传完成');
+  } catch (e) {
+    // request.js 已统一提示错误
+  } finally {
+    resending.value = false;
+  }
+};
+
+onMounted(async () => {
+  await loadStationOptions();
+});
+</script>
+
+<style lang="less" scoped>
+.data-resend-page {
+  padding: 16px;
+}
+</style>

+ 269 - 0
forecast-backend-vue/src/views/ufo/electricity/statanalysis/eventQuery.vue

@@ -0,0 +1,269 @@
+<template>
+  <div class="event-query-page">
+    <a-card :bordered="false">
+      <a-row :gutter="[12, 12]" align="middle">
+        <a-col :xs="24" :md="5">
+          <a-select
+            v-model:value="query.alarmCategory"
+            :options="categoryOptions"
+            placeholder="告警类别"
+            allow-clear
+            class="full-control"
+          />
+        </a-col>
+        <a-col :xs="24" :md="5">
+          <a-select
+            v-model:value="query.alarmLevel"
+            :options="levelOptions"
+            placeholder="告警等级"
+            allow-clear
+            class="full-control"
+          />
+        </a-col>
+        <a-col :xs="24" :md="4">
+          <a-select
+            v-model:value="query.processStatus"
+            :options="processStatusOptions"
+            placeholder="处理状态"
+            allow-clear
+            class="full-control"
+          />
+        </a-col>
+        <a-col :xs="24" :md="5">
+          <a-date-picker
+            v-model:value="query.alarmDate"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+            placeholder="告警时间"
+            class="full-control"
+          />
+        </a-col>
+        <a-col :xs="24" :md="5">
+          <a-space wrap>
+            <a-button type="primary" :loading="loading" @click="handleQuery">查询</a-button>
+            <a-button :loading="processLoading" @click="handleProcess">确认告警</a-button>
+            <a-button :loading="exportLoading" @click="handleExport">导出</a-button>
+          </a-space>
+        </a-col>
+      </a-row>
+    </a-card>
+
+    <a-card :bordered="false" class="content-card">
+      <a-table
+        :columns="columns"
+        :data-source="rows"
+        :loading="loading"
+        :pagination="pagination"
+        :row-selection="rowSelection"
+        row-key="id"
+        size="middle"
+        @change="handleTableChange"
+      >
+        <template #bodyCell="{ column, record }">
+          <template v-if="column.dataIndex === 'alarmLevel'">
+            {{ levelLabel(record.alarmLevel) }}
+          </template>
+          <template v-else-if="column.dataIndex === 'alarmCategory'">
+            {{ categoryLabel(record.alarmCategory) }}
+          </template>
+          <template v-else-if="column.dataIndex === 'processFlag'">
+            <a-tag :color="processColorMap[record.processFlag] || 'default'">
+              {{ processLabelMap[record.processFlag] ?? record.processFlag }}
+            </a-tag>
+          </template>
+        </template>
+      </a-table>
+    </a-card>
+  </div>
+</template>
+
+<script setup name="EventQuery">
+import {computed, onMounted, reactive, ref} from 'vue';
+import {message, Modal} from 'ant-design-vue';
+import dayjs from 'dayjs';
+import {saveAs} from 'file-saver';
+import {blobValidate} from '@/utils/bearjia';
+import {useDict} from '@/composables/useDict';
+import {listEventRecord, processEventRecord, exportEventRecord} from '@/api/alarm/eventRecord';
+
+const {alarm_category, alarm_level} = useDict('alarm_category', 'alarm_level');
+const alarmCategory = alarm_category;
+const alarmLevel = alarm_level;
+
+const categoryOptions = computed(() =>
+  alarmCategory.value.map((o) => ({label: o.label, value: o.value}))
+);
+const levelOptions = computed(() =>
+  alarmLevel.value.map((o) => ({label: o.label, value: o.value}))
+);
+
+// 表格列展示: 从下拉options中取字典label, 无匹配时回退原始值
+const levelLabelMap = computed(() =>
+  Object.fromEntries(levelOptions.value.map((o) => [String(o.value), o.label]))
+);
+const categoryLabelMap = computed(() =>
+  Object.fromEntries(categoryOptions.value.map((o) => [String(o.value), o.label]))
+);
+const levelLabel = (val) => (val == null ? '' : levelLabelMap.value[String(val)] ?? val);
+const categoryLabel = (val) => (val == null ? '' : categoryLabelMap.value[String(val)] ?? val);
+
+const processStatusOptions = [
+  {label: '已处理', value: true},
+  {label: '未处理', value: false}
+];
+
+const processLabelMap = {
+  0: '未处理',
+  1: '处理中',
+  2: '已处理',
+  3: '误报'
+};
+
+const processColorMap = {
+  0: 'default',
+  1: 'processing',
+  2: 'success',
+  3: 'warning'
+};
+
+const columns = [
+  {title: '告警等级', dataIndex: 'alarmLevel', width: 120},
+  {title: '告警类别', dataIndex: 'alarmCategory', width: 140},
+  {title: '告警内容', dataIndex: 'alarmData', ellipsis: true},
+  {title: '处理状态', dataIndex: 'processFlag', width: 110},
+  {title: '告警日期', dataIndex: 'alarmCreateTime', width: 180}
+];
+
+const loading = ref(false);
+const processLoading = ref(false);
+const exportLoading = ref(false);
+const rows = ref([]);
+const selectedRowKeys = ref([]);
+const rowSelection = reactive({
+  columnWidth: 48,
+  selectedRowKeys: selectedRowKeys,
+  onChange: (keys) => {
+    selectedRowKeys.value = keys;
+  },
+  // 已处理(process_flag=2)的告警不可勾选
+  getCheckboxProps: (record) => ({
+    disabled: String(record.processFlag) === '2'
+  })
+});
+const pagination = reactive({
+  current: 1,
+  pageSize: 10,
+  total: 0,
+  showSizeChanger: true,
+  showTotal: (total) => `共 ${total} 条`
+});
+
+const query = reactive({
+  alarmCategory: undefined,
+  alarmLevel: undefined,
+  processStatus: undefined,
+  alarmDate: dayjs().format('YYYY-MM-DD')
+});
+
+const buildParams = () => ({
+  alarmCategory: query.alarmCategory,
+  alarmLevel: query.alarmLevel,
+  processStatus: query.processStatus,
+  alarmDate: query.alarmDate
+});
+
+const fetchList = async (pageNum, pageSize) => {
+  loading.value = true;
+  try {
+    const res = await listEventRecord({
+      ...buildParams(),
+      pageNum,
+      pageSize
+    });
+    rows.value = res.rows || [];
+    pagination.total = res.total || 0;
+    pagination.current = pageNum;
+    pagination.pageSize = pageSize;
+  } catch (e) {
+    // request.js 已统一提示错误
+  } finally {
+    loading.value = false;
+  }
+};
+
+const handleQuery = () => {
+  fetchList(1, pagination.pageSize);
+};
+
+const handleTableChange = (pag) => {
+  fetchList(pag.current, pag.pageSize);
+};
+
+const handleProcess = () => {
+  if (selectedRowKeys.value.length === 0) {
+    message.warning('请先勾选要确认的告警数据');
+    return;
+  }
+  Modal.confirm({
+    title: '确认告警',
+    content: `确定将选中的 ${selectedRowKeys.value.length} 条告警标记为已处理吗?非已处理的告警将被置为已处理。`,
+    okText: '确认',
+    cancelText: '取消',
+    onOk: async () => {
+      processLoading.value = true;
+      try {
+        const res = await processEventRecord(selectedRowKeys.value);
+        message.success(res?.msg || '确认成功');
+        selectedRowKeys.value = [];
+        fetchList(pagination.current, pagination.pageSize);
+      } catch (e) {
+        // request.js 已统一提示错误
+      } finally {
+        processLoading.value = false;
+      }
+    }
+  });
+};
+
+const handleExport = async () => {
+  exportLoading.value = true;
+  try {
+    const res = await exportEventRecord(buildParams());
+    const isFile = await blobValidate(res);
+    if (isFile) {
+      const name = `事件查询_${dayjs(query.alarmDate || dayjs()).format('YYYYMMDD')}.xlsx`;
+      saveAs(new Blob([res]), name);
+      message.success('导出成功');
+    } else {
+      const text = await res.text();
+      let msg = '导出失败';
+      try {
+        msg = JSON.parse(text)?.msg || msg;
+      } catch (e) {
+        /* ignore */
+      }
+      message.error(msg);
+    }
+  } catch (e) {
+    // request.js 已统一提示错误
+  } finally {
+    exportLoading.value = false;
+  }
+};
+
+onMounted(() => {
+  fetchList(1, pagination.pageSize);
+});
+</script>
+
+<style lang="less" scoped>
+.event-query-page {
+  padding: 16px;
+}
+.full-control {
+  width: 100%;
+}
+.content-card {
+  margin-top: 16px;
+}
+</style>

+ 14 - 2
forecast-backend-vue/src/views/ufo/electricity/statanalysis/reportLogQuery.vue

@@ -110,7 +110,13 @@ const query = reactive({
 const typeOptions = [
 const typeOptions = [
   {label: '超短期功率预报', value: 'supershort'},
   {label: '超短期功率预报', value: 'supershort'},
   {label: '短期功率预报', value: 'short'},
   {label: '短期功率预报', value: 'short'},
-  {label: '中期功率预报', value: 'medium'}
+  {label: '中期功率预报', value: 'medium'},
+  {label: '环境检测仪数据', value: 'envlDetec'},
+  {label: '逆变器运行信息文件', value: 'ivtOpr'},
+  {label: '升压变数据', value: 'bstTrn'},
+  {label: '理论功率文件', value: 'thrPower'},
+  {label: '数值天气预报文件', value: 'nmrWeather'},
+  {label: '发电计划文件', value: 'pwrGen'}
 ];
 ];
 
 
 const channelOptions = [
 const channelOptions = [
@@ -123,7 +129,13 @@ const channelOptions = [
 const typeLabelMap = {
 const typeLabelMap = {
   supershort: '超短期功率预报',
   supershort: '超短期功率预报',
   short: '短期功率预报',
   short: '短期功率预报',
-  medium: '中期功率预报'
+  medium: '中期功率预报',
+  envlDetec: '环境检测仪数据',
+  ivtOpr: '逆变器运行信息文件',
+  bstTrn: '升压变数据',
+  thrPower: '理论功率文件',
+  nmrWeather: '数值天气预报文件',
+  pwrGen: '发电计划文件'
 };
 };
 
 
 const statusLabelMap = {
 const statusLabelMap = {

+ 195 - 0
forecast-backend-vue/src/views/ufo/electricity/statanalysis/uploadRateStat.vue

@@ -0,0 +1,195 @@
+<template>
+  <div class="upload-rate-stat-page">
+    <a-card :bordered="false">
+      <a-row :gutter="[12, 12]" align="middle">
+        <a-col :xs="24" :md="6">
+          <StationSelector v-model:value="query.stationCode" :options="stationOptions" :multiple="false" />
+        </a-col>
+        <a-col :xs="24" :md="5">
+          <a-date-picker
+            v-model:value="query.startTime"
+            class="full-control"
+            format="YYYY-MM-DD"
+            placeholder="起始时间"
+            value-format="YYYY-MM-DD"
+          />
+        </a-col>
+        <a-col :xs="24" :md="5">
+          <a-date-picker
+            v-model:value="query.endTime"
+            class="full-control"
+            format="YYYY-MM-DD"
+            placeholder="截止时间"
+            value-format="YYYY-MM-DD"
+          />
+        </a-col>
+        <a-col :xs="24" :md="8">
+          <a-space>
+            <a-button type="primary" :loading="loading" :disabled="!queryValid" @click="handleQuery">确认</a-button>
+            <a-button :loading="exporting" :disabled="!queryValid" @click="handleExport">导出</a-button>
+          </a-space>
+        </a-col>
+      </a-row>
+    </a-card>
+    <a-card :bordered="false" class="content-card">
+      <a-table
+        :columns="columns"
+        :data-source="rows"
+        :loading="loading"
+        :pagination="pagination"
+        :scroll="{x: 1760}"
+        row-key="date"
+        size="middle"
+        @change="handleTableChange"
+      />
+    </a-card>
+  </div>
+</template>
+
+<script setup name="UploadRateStat">
+import {computed, onMounted, reactive, ref} from 'vue';
+import {message} from 'ant-design-vue';
+import dayjs from 'dayjs';
+import {saveAs} from 'file-saver';
+import {blobValidate} from '@/utils/bearjia';
+import {listStation} from '@/api/config/station';
+import {exportUploadRate, listUploadRate} from '@/api/fileupload/reportLog';
+import StationSelector from '../components/StationSelector.vue';
+
+const loading = ref(false);
+const exporting = ref(false);
+const stationOptions = ref([]);
+const rows = ref([]);
+const pagination = reactive({
+  current: 1,
+  pageSize: 10,
+  total: 0,
+  showSizeChanger: true,
+  showTotal: (total) => `共 ${total} 天`
+});
+const query = reactive({
+  stationCode: undefined,
+  startTime: dayjs().subtract(7, 'day').format('YYYY-MM-DD'),
+  endTime: dayjs().format('YYYY-MM-DD')
+});
+
+const queryValid = computed(() => {
+  if (!query.startTime || !query.endTime) return false;
+  const start = dayjs(query.startTime);
+  const end = dayjs(query.endTime);
+  if (!start.isValid() || !end.isValid()) return false;
+  return !start.isAfter(end);
+});
+
+const columns = [
+  {title: '日期时间', dataIndex: 'date', width: 120},
+  {title: '超短期文件上传率(%)', dataIndex: 'supershortRate', width: 170},
+  {title: '短期文件上传率(%)', dataIndex: 'shortRate', width: 160},
+  {title: '中期文件上传率(%)', dataIndex: 'mediumRate', width: 160},
+  {title: '环境检测仪数据上传率(%)', dataIndex: 'envlDetectorRate', width: 190},
+  {title: '逆变器运行信息文件上传率(%)', dataIndex: 'inverterOperationRate', width: 210},
+  {title: '升压变数据上传率(%)', dataIndex: 'boosterTransformerRate', width: 180},
+  {title: '理论功率文件上传率(%)', dataIndex: 'theoreticalPowerRate', width: 190},
+  {title: '数值天气预报文件上传率(%)', dataIndex: 'numericalWeatherRate', width: 200},
+  {title: '发电计划文件上传率(%)', dataIndex: 'powerGenerationPlanRate', width: 180}
+];
+
+const loadStationOptions = async () => {
+  const res = await listStation({pageNum: 1, pageSize: 500});
+  const list = (res && res.rows) || [];
+  stationOptions.value = list.map((item) => ({label: item.stationName, value: item.stationCode}));
+  if (!query.stationCode && stationOptions.value.length) {
+    query.stationCode = stationOptions.value[0].value;
+  }
+};
+
+const fetchList = async (pageNum, pageSize) => {
+  if (!query.stationCode) {
+    message.warning('请先选择场站');
+    return;
+  }
+  loading.value = true;
+  try {
+    const res = await listUploadRate({
+      stationCode: query.stationCode,
+      startTime: query.startTime,
+      endTime: query.endTime,
+      pageNum,
+      pageSize
+    });
+    rows.value = res.rows || [];
+    pagination.total = res.total || 0;
+    pagination.current = pageNum;
+    pagination.pageSize = pageSize;
+  } catch (e) {
+    // request.js 已统一提示错误
+  } finally {
+    loading.value = false;
+  }
+};
+
+const handleQuery = () => {
+  if (!query.stationCode) {
+    message.warning('请先选择场站');
+    return;
+  }
+  if (!queryValid.value) return;
+  fetchList(1, pagination.pageSize);
+};
+
+const handleTableChange = (pag) => {
+  fetchList(pag.current, pag.pageSize);
+};
+
+const handleExport = async () => {
+  if (!query.stationCode) {
+    message.warning('请先选择场站');
+    return;
+  }
+  if (!queryValid.value) return;
+  exporting.value = true;
+  try {
+    const res = await exportUploadRate({
+      stationCode: query.stationCode,
+      startTime: query.startTime,
+      endTime: query.endTime
+    });
+    const isFile = await blobValidate(res);
+    if (isFile) {
+      const dateRange = query.startTime === query.endTime ? query.startTime : `${query.startTime}_${query.endTime}`;
+      saveAs(new Blob([res]), `光伏上传率统计_${dateRange.replaceAll('-', '')}.xlsx`);
+      message.success('导出成功');
+    } else {
+      const text = await res.text();
+      let msg = '导出失败';
+      try {
+        msg = JSON.parse(text)?.msg || msg;
+      } catch (e) {
+        /* ignore */
+      }
+      message.error(msg);
+    }
+  } finally {
+    exporting.value = false;
+  }
+};
+
+onMounted(async () => {
+  await loadStationOptions();
+  handleQuery();
+});
+</script>
+
+<style lang="less" scoped>
+.upload-rate-stat-page {
+  padding: 16px;
+}
+
+.full-control {
+  width: 100%;
+}
+
+.content-card {
+  margin-top: 16px;
+}
+</style>

+ 2 - 2
forecast-backend-vue/src/views/ufo/workbench/WorkbenchPage.vue

@@ -1,7 +1,7 @@
 <template>
 <template>
   <div class="workbench-page">
   <div class="workbench-page">
     <section class="summary-grid">
     <section class="summary-grid">
-      <div v-for="card in summaryCards" :key="card.key" class="summary-card">
+      <div v-for="(card, cardIndex) in summaryCards" :key="card.key" class="summary-card" :style="{ display: cardIndex < 2 ? 'none' : undefined }">
         <div class="summary-card__label">
         <div class="summary-card__label">
           <img
           <img
             v-if="card.iconType === 'image'"
             v-if="card.iconType === 'image'"
@@ -832,7 +832,7 @@ watch(mapStations, () => renderStations(), { deep: true });
 // 3 个 summary-card 最小宽度 480px + 2 个 14px 间隙 = 1468px;放得下时 3 列,放不下时单列 3 行
 // 3 个 summary-card 最小宽度 480px + 2 个 14px 间隙 = 1468px;放得下时 3 列,放不下时单列 3 行
 @container (min-width: 1468px) {
 @container (min-width: 1468px) {
   .summary-grid {
   .summary-grid {
-    grid-template-columns: repeat(3, minmax(480px, 1fr));
+    grid-template-columns: repeat(1, minmax(480px, 1fr));
   }
   }
 }
 }
 
 

+ 3 - 0
release_note/20261028/ddl.sql

@@ -0,0 +1,3 @@
+-- 增加告警类别字段(幂等)
+ALTER TABLE alarm_event_record ADD COLUMN IF NOT EXISTS alarm_category VARCHAR(50);
+COMMENT ON COLUMN alarm_event_record.alarm_category IS '告警类别';

+ 81 - 0
release_note/20261028/dml.sql

@@ -0,0 +1,81 @@
+-- 删除风场
+UPDATE "public"."config_station" set is_del = 'true' where station_code in ('BHWP01', 'HHWP02');
+
+-- 字典类型: 告警类别
+INSERT INTO sys_dict_type (dict_id, dict_name, dict_type, status, create_by, create_time, remark)
+SELECT
+nextval(pg_get_serial_sequence('sys_dict_type', 'dict_id')),
+'告警类别', 'alarm_category', '0', 'admin', now(), '事件查询-告警类别'
+WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type t WHERE t.dict_type = 'alarm_category');
+-- 字典类型: 告警等级
+INSERT INTO sys_dict_type (dict_id, dict_name, dict_type, status, create_by, create_time, remark)
+SELECT
+nextval(pg_get_serial_sequence('sys_dict_type', 'dict_id')),
+'告警等级', 'alarm_level', '0', 'admin', now(), '事件查询-告警等级'
+WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type t WHERE t.dict_type = 'alarm_level');
+-- 告警类别字典数据(先删后插,保证幂等)
+DELETE FROM sys_dict_data WHERE dict_type = 'alarm_category';
+
+INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
+VALUES
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 1, '通信异常', '1', 'alarm_category', '', '', 'N', '0', 'admin', now(), '事件查询-告警类别'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 2, '数据异常', '2', 'alarm_category', '', '', 'N', '0', 'admin', now(), '事件查询-告警类别'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 3, '气象预报异常', '3', 'alarm_category', '', '', 'N', '0', 'admin', now(), '事件查询-告警类别'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 4, '功率预测异常', '4', 'alarm_category', '', '', 'N', '0', 'admin', now(), '事件查询-告警类别'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 5, '数据上报异常', '5', 'alarm_category', '', '', 'N', '0', 'admin', now(), '事件查询-告警类别'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 6, '系统运行异常', '6', 'alarm_category', '', '', 'N', '0', 'admin', now(), '事件查询-告警类别');
+-- 告警等级字典数据(颜色值配置在 css_class,页面按等级值渲染颜色;先删后插,保证幂等)
+DELETE FROM sys_dict_data WHERE dict_type = 'alarm_level';
+
+INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
+VALUES
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 1, '紧急告警', '1', 'alarm_level', 'red', '', 'N', '0', 'admin', now(), '事件查询-告警等级'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 2, '重要告警', '2', 'alarm_level', 'orange', '', 'N', '0', 'admin', now(), '事件查询-告警等级'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 3, '一般告警', '3', 'alarm_level', 'gold', '', 'N', '0', 'admin', now(), '事件查询-告警等级'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 4, '提示信息', '4', 'alarm_level', 'blue', '', 'N', '0', 'admin', now(), '事件查询-告警等级');
+-- 增加 事件查询 二级菜单(挂在 统计分析 下)
+INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+SELECT
+(SELECT COALESCE(MAX(menu_id), 0) + 1 FROM sys_menu),
+'事件查询',
+(SELECT menu_id FROM sys_menu t WHERE t.menu_name = '统计分析' AND t.parent_id = 0),
+5, 'event-query', 'ufo/electricity/statanalysis/eventQuery', '', 'EventQuery', 1, 0, 'C', '0', '0', 'alarm:eventRecord:list', 'AlertOutlined', 'admin', now(), '', NULL, '事件查询页面'
+WHERE NOT EXISTS (SELECT 1 FROM sys_menu t WHERE t.menu_name = '事件查询');
+
+-- 增加 数据补传 二级菜单(挂在 功率预测 下)
+INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+SELECT
+(SELECT COALESCE(MAX(menu_id), 0) + 1 FROM sys_menu),
+'数据补传',
+(SELECT menu_id FROM sys_menu t WHERE t.menu_name = '功率预测'),
+35, 'data-resend', 'ufo/electricity/forecast/DataResend', '', 'DataResend', 1, 0, 'C', '0', '0', 'fileupload:reportLog:reUpload', 'CloudUploadOutlined', 'admin', now(), '', NULL, '数据补传页面'
+WHERE NOT EXISTS (SELECT 1 FROM sys_menu t WHERE t.menu_name = '数据补传');
+
+-- 字典类型: 每日文件上传配置
+INSERT INTO sys_dict_type (dict_id, dict_name, dict_type, status, create_by, create_time, remark)
+SELECT
+nextval(pg_get_serial_sequence('sys_dict_type', 'dict_id')),
+'每日文件上传配置', 'daily_file_upload_config', '0', 'admin', now(), '光伏上传率统计-每日文件上传配置'
+WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type t WHERE t.dict_type = 'daily_file_upload_config');
+-- 字典数据(先删后插,保证幂等)
+DELETE FROM sys_dict_data WHERE dict_type = 'daily_file_upload_config';
+
+INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
+VALUES
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 1, '超短期文件', '{"type":"supershort","num":16}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 2, '短期文件', '{"type":"short","num":1}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 3, '中期文件', '{"type":"medium","num":1}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 4, '环境检测仪数据', '{"type":"envlDetec","num":1}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 5, '逆变器运行信息文件', '{"type":"ivtOpr","num":1}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 6, '升压变数据', '{"type":"bstTrn","num":1}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 7, '理论功率文件', '{"type":"thrPower","num":1}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 8, '数值天气预报文件', '{"type":"nmrWeather","num":1}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数'),
+(nextval(pg_get_serial_sequence('sys_dict_data', 'dict_code')), 9, '发电计划文件', '{"type":"pwrGen","num":1}', 'daily_file_upload_config', '', '', 'N', '0', 'admin', now(), 'num=每日期望上传数');
+-- 增加 光伏上传率统计 二级菜单(挂在 统计分析 下)
+INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+SELECT
+(SELECT COALESCE(MAX(menu_id), 0) + 1 FROM sys_menu),
+'光伏上传率统计',
+(SELECT menu_id FROM sys_menu t WHERE t.menu_name = '统计分析' AND t.parent_id = 0),
+15, 'upload-rate-stat', 'ufo/electricity/statanalysis/uploadRateStat', '', 'UploadRateStat', 1, 0, 'C', '0', '0', 'fileupload:reportLog:uploadRate', 'BarChartOutlined', 'admin', now(), '', NULL, '光伏上传率统计页面'
+WHERE NOT EXISTS (SELECT 1 FROM sys_menu t WHERE t.menu_name = '光伏上传率统计');

+ 15 - 0
release_note/20261028/release_note.md

@@ -0,0 +1,15 @@
+# 20261028版本更新说明
+1. 增加功能“统计分析-事件查询”
+2. 增加功能“功率预测-数据补传”
+3. 增加功能“统计分析-光伏上传率统计”
+4. 修复了设备管理大菜单下多页面的bug
+
+[更新说明]
+1. 执行 `release_note/20261028/ddl.sql`
+2. 执行 `release_note/20261028/dml.sql`
+2. 更新服务端jar
+3. 更新前端dist
+
+[备注]
+数据补传目前直接更新了文件上传数据表,并未集成真正的文件补传功能
+每日应该上传的文件类型配置项`daily_file_upload_config`根据实际情况调整