فهرست منبع

新增防火值班表与接口代码

fuyuchuan 2 ماه پیش
والد
کامیت
e0849dbf3e
14فایلهای تغییر یافته به همراه920 افزوده شده و 2 حذف شده
  1. 1 1
      service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/MybatisGeneratorUtils.java
  2. 21 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/web/MhFireDutyBusinessController.java
  3. 95 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/web/MhFireDutyController.java
  4. 123 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/domain/MhFireDuty.java
  5. 79 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/domain/MhFireDutyBusiness.java
  6. 18 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/mapper/MhFireDutyBusinessMapper.java
  7. 18 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/mapper/MhFireDutyMapper.java
  8. 16 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/MhFireDutyBusinessService.java
  9. 68 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/MhFireDutyService.java
  10. 20 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/MhFireDutyBusinessServiceImpl.java
  11. 421 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/MhFireDutyServiceImpl.java
  12. 1 1
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/ReportIndexResultServiceImpl.java
  13. 18 0
      service-fire/service-fire-biz/src/main/resources/mapper/fire/MhFireDutyBusinessMapper.xml
  14. 21 0
      service-fire/service-fire-biz/src/main/resources/mapper/fire/MhFireDutyMapper.xml

+ 1 - 1
service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/MybatisGeneratorUtils.java

@@ -71,7 +71,7 @@ public class MybatisGeneratorUtils {
         // strategy.setTablePrefix("t_"); // 表名前缀
         strategy.setEntityLombokModel(true); //使用lombok
         //修改自己想要生成的表
-        strategy.setInclude(new String[]{"mh_build"});  // 逆向工程使用的表   如果要生成多个,这里可以传入String[]
+        strategy.setInclude(new String[]{"mh_fire_duty", "mh_fire_duty_business"});  // 逆向工程使用的表   如果要生成多个,这里可以传入String[]
         mpg.setStrategy(strategy);
 
         // 关闭默认 xml 生成,调整生成 至 根目录

+ 21 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/web/MhFireDutyBusinessController.java

@@ -0,0 +1,21 @@
+package com.usky.fire.controller.web;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 防火值班业务子表 前端控制器
+ * </p>
+ *
+ * @author han
+ * @since 2025-10-10
+ */
+@Controller
+@RequestMapping("/fireDutyBusiness")
+public class MhFireDutyBusinessController {
+
+}
+

+ 95 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/web/MhFireDutyController.java

@@ -0,0 +1,95 @@
+package com.usky.fire.controller.web;
+
+
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.log.annotation.Log;
+import com.usky.common.log.enums.BusinessType;
+import com.usky.fire.domain.MhFireDuty;
+import com.usky.fire.service.MhFireDutyService;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.web.bind.annotation.*;
+
+import org.springframework.stereotype.Controller;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 防火值班主表 前端控制器
+ * </p>
+ *
+ * @author han
+ * @since 2025-10-10
+ */
+@RestController
+@RequestMapping("/fireDuty")
+public class MhFireDutyController {
+    @Autowired
+    private MhFireDutyService fireDutyService;
+
+    @PostMapping("/page")
+    @ApiOperation("新增值班记录")
+    @Log(title = "新增值班记录", businessType = BusinessType.INSERT)
+    public ApiResult<?> save(@RequestBody MhFireDuty fireDuty) {
+        boolean success = fireDutyService.saveWithSubTables(fireDuty);
+        return success ? ApiResult.success() : ApiResult.error("防火值班记录新增失败!");
+    }
+
+    @DeleteMapping("/page/{id}")
+    @ApiOperation("删除值班记录(含子表)")
+    @Log(title = "删除值班记录", businessType = BusinessType.DELETE)
+    public ApiResult<?> delete(@PathVariable Long id) {
+        boolean success = fireDutyService.removeById(id);
+        return success ? ApiResult.success() : ApiResult.error("防火值班记录删除失败!");
+    }
+
+    @PutMapping("/page")
+    @ApiOperation("修改值班记录(含子表)")
+    @Log(title = "修改值班记录", businessType = BusinessType.UPDATE)
+    public ApiResult<?> update(@RequestBody MhFireDuty fireDuty) {
+        boolean success = fireDutyService.updateWithSubTables(fireDuty);
+        return success ? ApiResult.success() : ApiResult.error("防火值班记录修改失败!");
+    }
+
+    /**
+     * 分页查询值班记录
+     *
+     * @param pageNum       页码
+     * @param pageSize      每页条数
+     * @param startTime     开始时间
+     * @param endTime       结束时间
+     * @param memberName    值班人员姓名
+     * @param id            防火值班记录表主键id
+     * @param type          防火值班记录类型
+     * @return 分页查询结果
+     */
+    @GetMapping("/page")
+    @ApiOperation("分页查询值班记录")
+    public ApiResult<CommonPage<MhFireDuty>> page(
+            @RequestParam Integer pageNum,
+            @RequestParam Integer pageSize,
+            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startTime,
+            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endTime,
+            @RequestParam(required = false) String memberName,
+            @RequestParam(required = false) Long id,
+            @RequestParam(required = false) Integer type
+    ) {
+        return ApiResult.success(fireDutyService.getPage(pageNum, pageSize, startTime, endTime, memberName, id, type));
+    }
+
+    @GetMapping("/export")
+    @ApiOperation("批量导出值班记录到Excel")
+    @Log(title = "导出防火值班记录", businessType = BusinessType.EXPORT)
+    public void export(@RequestParam List<Long> ids, HttpServletResponse response) throws IOException {
+        fireDutyService.exportExcel(ids, response);
+    }
+
+}
+

+ 123 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/domain/MhFireDuty.java

@@ -0,0 +1,123 @@
+package com.usky.fire.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+
+import java.time.LocalDate;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import java.util.List;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.usky.common.core.annotation.Excel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 防火值班主表
+ * </p>
+ *
+ * @author fu
+ * @since 2025-10-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("mh_fire_duty")
+public class MhFireDuty implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 值班人员姓名(多个用逗号分隔)
+     */
+    private String member;
+
+    /**
+     * 值班人员ID(多个用逗号分隔)
+     */
+    private String memberId;
+
+    /**
+     * 值班日期
+     */
+    // @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private LocalDate dutyDate;
+
+    /**
+     * 舆情跟踪应对处置内容
+     */
+    private String disposalContent;
+
+    /**
+     * 素材收集情况
+     */
+    private String materialCollection;
+
+    /**
+     * 训练区域动态监测情况
+     */
+    private String dynamicMonitoring;
+
+    /**
+     * 记录创建时间
+     */
+    // @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    /**
+     * 创建人
+     */
+    private String creator;
+
+    /**
+     * 更新时间
+     */
+    // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime updateTime;
+
+    /**
+     * 更新人
+     */
+    private String updateBy;
+
+    /**
+     * 逻辑删除标识(0-未删除,1-已删除)
+     */
+    private Integer isDeleted;
+
+    /**
+     * 数据对接平台
+     */
+    @TableField(exist = false)
+    private List<MhFireDutyBusiness> dataDocking;
+
+    /**
+     * 可视对讲抽查
+     */
+    @TableField(exist = false)
+    private List<MhFireDutyBusiness> intercomSpotCheck;
+
+    /**
+     * 安全监管平台
+     */
+    @TableField(exist = false)
+    private List<MhFireDutyBusiness> safetySupervision;
+
+    /**
+     * 技术服务系统
+     */
+    @TableField(exist = false)
+    private List<MhFireDutyBusiness> technicalService;
+
+}

+ 79 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/domain/MhFireDutyBusiness.java

@@ -0,0 +1,79 @@
+package com.usky.fire.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 防火值班业务子表
+ * </p>
+ *
+ * @author fu
+ * @since 2025-10-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("mh_fire_duty_business")
+public class MhFireDutyBusiness implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 关联主表fire_duty的id
+     */
+    private Long dutyId;
+
+    /**
+     * 业务类型:1(数据对接平台)、2(可视对讲抽查)、3(安全监管平台)、4(技术服务系统)
+     */
+    private Integer businessType;
+
+    /**
+     * 单位ID
+     */
+    private String companyId;
+
+    /**
+     * 单位名称
+     */
+    @TableField("company_name")
+    private String unit;
+
+    /**
+     * 检查情况
+     */
+    @TableField("content")
+    private String status;
+
+    /**
+     * 创建时间
+     */
+    // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime updateTime;
+
+    /**
+     * 逻辑删除标识(0-未删除,1-已删除)
+     */
+    private Integer isDeleted;
+
+}

+ 18 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/mapper/MhFireDutyBusinessMapper.java

@@ -0,0 +1,18 @@
+package com.usky.fire.mapper;
+
+import com.usky.fire.domain.MhFireDutyBusiness;
+import com.usky.common.mybatis.core.CrudMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * <p>
+ * 防火值班业务子表 Mapper 接口
+ * </p>
+ *
+ * @author han
+ * @since 2025-10-10
+ */
+@Repository
+public interface MhFireDutyBusinessMapper extends CrudMapper<MhFireDutyBusiness> {
+
+}

+ 18 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/mapper/MhFireDutyMapper.java

@@ -0,0 +1,18 @@
+package com.usky.fire.mapper;
+
+import com.usky.fire.domain.MhFireDuty;
+import com.usky.common.mybatis.core.CrudMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * <p>
+ * 防火值班主表 Mapper 接口
+ * </p>
+ *
+ * @author han
+ * @since 2025-10-10
+ */
+@Repository
+public interface MhFireDutyMapper extends CrudMapper<MhFireDuty> {
+
+}

+ 16 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/MhFireDutyBusinessService.java

@@ -0,0 +1,16 @@
+package com.usky.fire.service;
+
+import com.usky.fire.domain.MhFireDutyBusiness;
+import com.usky.common.mybatis.core.CrudService;
+
+/**
+ * <p>
+ * 防火值班业务子表 服务类
+ * </p>
+ *
+ * @author han
+ * @since 2025-10-10
+ */
+public interface MhFireDutyBusinessService extends CrudService<MhFireDutyBusiness> {
+
+}

+ 68 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/MhFireDutyService.java

@@ -0,0 +1,68 @@
+package com.usky.fire.service;
+
+import com.usky.common.core.bean.CommonPage;
+import com.usky.fire.domain.MhFireDuty;
+import com.usky.common.mybatis.core.CrudService;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 防火值班主表 服务类
+ * </p>
+ *
+ * @author han
+ * @since 2025-10-10
+ */
+public interface MhFireDutyService extends CrudService<MhFireDuty> {
+
+    /**
+     * 新增防火值班记录(含子表)
+     *
+     * @param fireDuty 防火值班记录
+     * @return 是否保存成功
+     */
+    boolean saveWithSubTables(MhFireDuty fireDuty);
+
+    /**
+     * 删除防火值班记录(含子表)
+     *
+     * @param id 防火值班记录表主键id
+     * @return 是否删除成功
+     */
+    boolean removeById(Long id);
+
+    /**
+     * 修改防火值班记录(含子表)
+     *
+     * @param fireDuty 防火值班记录
+     * @return 是否修改成功
+     */
+    boolean updateWithSubTables(MhFireDuty fireDuty);
+
+    /**
+     * 分页查询防火值班记录
+     *
+     * @param pageNum      页码
+     * @param pageSize     页大小
+     * @param startTime    开始时间
+     * @param endTime      结束时间
+     * @param memberName   值班人员名称
+     *  @param id           防火值班记录表主键id
+     * @param type         防火值班记录类型
+     * @return 分页数据
+     */
+    CommonPage<MhFireDuty> getPage(Integer pageNum, Integer pageSize, LocalDate startTime, LocalDate endTime, String memberName, Long id, Integer type);
+
+    /**
+     * 批量导出防火值班记录到Excel
+     *
+     * @param ids        防火值班记录表主键id
+     * @param response   HttpServletResponse
+     */
+    void exportExcel(List<Long> ids, HttpServletResponse response) throws IOException;
+}

+ 20 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/MhFireDutyBusinessServiceImpl.java

@@ -0,0 +1,20 @@
+package com.usky.fire.service.impl;
+
+import com.usky.fire.domain.MhFireDutyBusiness;
+import com.usky.fire.mapper.MhFireDutyBusinessMapper;
+import com.usky.fire.service.MhFireDutyBusinessService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 防火值班业务子表 服务实现类
+ * </p>
+ *
+ * @author han
+ * @since 2025-10-10
+ */
+@Service
+public class MhFireDutyBusinessServiceImpl extends AbstractCrudService<MhFireDutyBusinessMapper, MhFireDutyBusiness> implements MhFireDutyBusinessService {
+
+}

+ 421 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/MhFireDutyServiceImpl.java

@@ -0,0 +1,421 @@
+package com.usky.fire.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.fire.domain.MhCompany;
+import com.usky.fire.domain.MhFireDuty;
+import com.usky.fire.domain.MhFireDutyBusiness;
+import com.usky.fire.mapper.MhFireDutyBusinessMapper;
+import com.usky.fire.mapper.MhFireDutyMapper;
+import com.usky.fire.service.MhFireDutyBusinessService;
+import com.usky.fire.service.MhFireDutyService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 防火值班主表 服务实现类
+ * </p>
+ *
+ * @author han
+ * @since 2025-10-10
+ */
+@Service
+@Slf4j
+public class MhFireDutyServiceImpl extends AbstractCrudService<MhFireDutyMapper, MhFireDuty> implements MhFireDutyService {
+
+    @Autowired
+    private MhFireDutyBusinessService businessService;
+    @Autowired
+    private MhFireDutyBusinessMapper businessMapper;
+
+    // private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean saveWithSubTables(MhFireDuty fireDuty) {
+        checkEmpty(fireDuty);
+        boolean isSaved = this.save(fireDuty);
+        if (!isSaved) {
+            return false;
+        }
+
+        LocalDateTime createTime = fireDuty.getCreateTime();
+        handleSubTableData(fireDuty.getId(), createTime, null,
+                fireDuty.getDataDocking(), 1);
+        handleSubTableData(fireDuty.getId(), createTime, null,
+                fireDuty.getIntercomSpotCheck(), 2);
+        handleSubTableData(fireDuty.getId(), createTime, null,
+                fireDuty.getSafetySupervision(), 3);
+        handleSubTableData(fireDuty.getId(), createTime, null,
+                fireDuty.getTechnicalService(), 4);
+
+        return true;
+    }
+
+    private void handleSubTableData(Long dutyId, LocalDateTime createTime, LocalDateTime updateTime,
+                                    List<MhFireDutyBusiness> businessList, Integer businessType) {
+        if (CollectionUtils.isEmpty(businessList)) {
+            return;
+        }
+        // 批量设置公共字段
+        businessList.forEach(business -> {
+            business.setDutyId(dutyId);
+            business.setBusinessType(businessType);
+            business.setCreateTime(createTime);
+            business.setIsDeleted(0);
+
+            if (Objects.nonNull(updateTime)) {
+                business.setUpdateTime(updateTime);
+            }
+        });
+        // 批量保存
+        businessService.saveBatch(businessList);
+    }
+
+    /**
+     * 空数据校验
+     */
+    private void checkEmpty(MhFireDuty fireDuty) {
+        if (StringUtils.isBlank(fireDuty.getMember())) {
+            throw new BusinessException("请填写值班人员!");
+        }
+        if (fireDuty.getDutyDate() == null) {
+            throw new BusinessException("请填写值班日期!");
+        }
+        if (StringUtils.isBlank(fireDuty.getCreator())) {
+            throw new BusinessException("创建人不能为空!");
+        }
+        if (fireDuty.getCreateTime() == null) {
+            throw new BusinessException("创建时间不能为空!");
+        }
+    }
+
+    /**
+     * 逻辑删除
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean removeById(Long id) {
+        try {
+            MhFireDuty fireDuty = new MhFireDuty();
+            fireDuty.setId(id);
+            fireDuty.setIsDeleted(1);
+            baseMapper.updateById(fireDuty);
+
+            MhFireDutyBusiness business = new MhFireDutyBusiness();
+            business.setIsDeleted(1);
+            LambdaQueryWrapper<MhFireDutyBusiness> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(MhFireDutyBusiness::getDutyId, id);
+            businessMapper.update(business, wrapper);
+
+            return true;
+        } catch (Exception e) {
+            log.error("删除防火值班记录[{}]失败", id, e);
+            return false;
+        }
+    }
+
+    /**
+     * 更新主表及子表
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean updateWithSubTables(MhFireDuty fireDuty) {
+        checkEmpty(fireDuty);
+        fireDuty.setUpdateTime(LocalDateTime.now());
+        boolean isUpdated = this.updateById(fireDuty);
+        if (!isUpdated) {
+            return false;
+        }
+
+        Long dutyId = fireDuty.getId();
+        LambdaQueryWrapper<MhFireDutyBusiness> delWrapper = new LambdaQueryWrapper<>();
+        delWrapper.eq(MhFireDutyBusiness::getDutyId, dutyId);
+        businessMapper.delete(delWrapper);
+
+        LocalDateTime updateTime = fireDuty.getUpdateTime();
+        handleSubTableData(dutyId, fireDuty.getCreateTime(), updateTime,
+                fireDuty.getDataDocking(), 1);
+        handleSubTableData(dutyId, fireDuty.getCreateTime(), updateTime,
+                fireDuty.getIntercomSpotCheck(), 2);
+        handleSubTableData(dutyId, fireDuty.getCreateTime(), updateTime,
+                fireDuty.getSafetySupervision(), 3);
+        handleSubTableData(dutyId, fireDuty.getCreateTime(), updateTime,
+                fireDuty.getTechnicalService(), 4);
+
+        return true;
+    }
+
+    /**
+     * 分页查询(优化子表数据关联逻辑,使用Map分组提升性能)
+     */
+    @Override
+    public CommonPage<MhFireDuty> getPage(Integer pageNum, Integer pageSize,
+                                          LocalDate startTime, LocalDate endTime,
+                                          String memberName, Long id, Integer type) {
+
+        IPage<MhFireDuty> page = new Page<>(pageNum, pageSize);
+        LambdaQueryWrapper<MhFireDuty> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(Objects.nonNull(id), MhFireDuty::getId, id)
+                .like(StringUtils.isNotBlank(memberName), MhFireDuty::getMember, memberName)
+                .between(Objects.nonNull(startTime) && Objects.nonNull(endTime),
+                        MhFireDuty::getDutyDate, startTime, endTime)
+                .eq(MhFireDuty::getIsDeleted, 0)
+                .orderByDesc(MhFireDuty::getDutyDate);
+
+        page = this.page(page, queryWrapper);
+        List<MhFireDuty> dutyList = page.getRecords();
+        if (CollectionUtils.isEmpty(dutyList)) {
+            return new CommonPage<>();
+        }
+
+        List<Long> dutyIds = dutyList.stream().map(MhFireDuty::getId).collect(Collectors.toList());
+        LambdaQueryWrapper<MhFireDutyBusiness> businessWrapper = new LambdaQueryWrapper<>();
+        businessWrapper.eq(Objects.nonNull(type), MhFireDutyBusiness::getBusinessType, type)
+                .in(MhFireDutyBusiness::getDutyId, dutyIds);
+        List<MhFireDutyBusiness> businessList = businessMapper.selectList(businessWrapper);
+
+        Map<String, List<MhFireDutyBusiness>> businessMap = businessList.stream()
+                .collect(Collectors.groupingBy(biz -> biz.getDutyId() + "_" + biz.getBusinessType()));
+
+        dutyList.forEach(duty -> {
+            Long dutyId = duty.getId();
+            duty.setDataDocking(getBusinessByType(businessMap, dutyId, 1));
+            duty.setIntercomSpotCheck(getBusinessByType(businessMap, dutyId, 2));
+            duty.setSafetySupervision(getBusinessByType(businessMap, dutyId, 3));
+            duty.setTechnicalService(getBusinessByType(businessMap, dutyId, 4));
+        });
+
+        page.setRecords(dutyList);
+        return new CommonPage<>(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent());
+    }
+
+    /**
+     * 从分组Map中获取指定dutyId和业务类型的子表数据
+     */
+    private List<MhFireDutyBusiness> getBusinessByType(Map<String, List<MhFireDutyBusiness>> businessMap,
+                                                       Long dutyId, Integer businessType) {
+        return businessMap.getOrDefault(dutyId + "_" + businessType, Collections.emptyList());
+    }
+
+    /**
+     * 生成Excel
+     */
+    @Override
+    public void exportExcel(List<Long> ids, HttpServletResponse response) throws IOException {
+        if (ids.isEmpty()) {
+            throw new BusinessException("请选择需要导出的记录!");
+        }
+
+        // 1. 查询所有主表数据
+        List<MhFireDuty> dutyList = new ArrayList<>();
+        for (Long id : ids) {
+            MhFireDuty duty = this.getById(id);
+            if (duty != null) {
+                dutyList.add(duty);
+            }
+        }
+        if (dutyList.isEmpty()) {
+            throw new BusinessException("所选记录不存在!");
+        }
+
+        List<Long> dutyIds = dutyList.stream().map(MhFireDuty::getId).collect(Collectors.toList());
+        List<MhFireDutyBusiness> allBusiness = businessMapper.selectList(
+                new LambdaQueryWrapper<MhFireDutyBusiness>()
+                        .in(MhFireDutyBusiness::getDutyId, dutyIds)
+                        .eq(MhFireDutyBusiness::getIsDeleted, 0)
+        );
+        Map<Long, Map<Integer, List<MhFireDutyBusiness>>> dutyBusinessMap = allBusiness.stream()
+                .collect(Collectors.groupingBy(
+                        MhFireDutyBusiness::getDutyId,
+                        Collectors.groupingBy(MhFireDutyBusiness::getBusinessType)
+                ));
+
+        Workbook workbook = new XSSFWorkbook();
+        Sheet sheet = workbook.createSheet("批量坐班值守任务表");
+
+        CellStyle titleStyle = createTitleStyle(workbook);
+        CellStyle headerStyle = createHeaderStyle(workbook);
+        CellStyle contentStyle = createContentStyle(workbook);
+
+        List<TaskDef> taskDefs = Arrays.asList(
+                new TaskDef(1, "通过指挥中心可视化和对讲机,抽查不少于3家消防安全重点单位消控室值班值守、消防控制柜、疏散通道及消防车道情况。"),
+                new TaskDef(2, "通过上海消防数据对接平台,抽查不少于3家消防安全重点单位物联网系统近72小时在线情况。"),
+                new TaskDef(3, "通过社会单位消防安全监管平台,抽查不少于3家消防安全重点单位近7天消防控制室人员持证上岗情况。"),
+                new TaskDef(4, "通过上海市消防技术服务管理系统V2.0,抽查不少于3家消防安全重点单位消防设施长期处于报修状态情况。"),
+                new TaskDef(5, "做好舆情跟踪和应对处置工作。"),
+                new TaskDef(6, "提示出警队站做好灭火救援现场素材搜集工作。"),
+                new TaskDef(7, "高温气温35℃以上时,每日10:00-16:00期间,调取营区监控等方式,对各训练区域进行动态监测。重点排查是否存在违规训练行为,做好监控画面截图留存,发现问题立即汇报。")
+        );
+
+        int currentRow = 0; // 当前行指针,逐行填充
+        for (MhFireDuty duty : dutyList) {
+            // 获取当前记录的子表分组数据(默认空Map)
+            Map<Integer, List<MhFireDutyBusiness>> businessMap = dutyBusinessMap.getOrDefault(
+                    duty.getId(), new HashMap<>()
+            );
+
+            // 6.1 填充标题行(合并4列)
+            Row titleRow = sheet.createRow(currentRow);
+            Cell titleCell = titleRow.createCell(0);
+            titleCell.setCellValue("坐班值守岗位工作量化任务(防火值班员/行政值班员)");
+            titleCell.setCellStyle(titleStyle);
+            sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow, 0, 3));
+            currentRow++;
+
+            // 6.2 填充表头行
+            Row headerRow = sheet.createRow(currentRow);
+            String[] headers = {"时间", "值班人员", "工作任务", "完成情况"};
+            for (int i = 0; i < headers.length; i++) {
+                Cell cell = headerRow.createCell(i);
+                cell.setCellValue(headers[i]);
+                cell.setCellStyle(headerStyle);
+                // 仅在第一组数据时设置列宽(避免重复设置)
+                if (dutyList.indexOf(duty) == 0) {
+                    sheet.setColumnWidth(i, i == 2 ? 256 * 60 : 256 * 20);
+                }
+            }
+            currentRow++;
+
+            // 6.3 填充7行任务数据
+            int taskStartRow = currentRow; // 任务起始行(用于合并单元格)
+            for (TaskDef task : taskDefs) {
+                Row dataRow = sheet.createRow(currentRow);
+
+                // 时间列(首行填充,后续合并)
+                Cell dateCell = dataRow.createCell(0);
+                if (currentRow == taskStartRow) {
+                    dateCell.setCellValue(duty.getDutyDate().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
+                }
+                dateCell.setCellStyle(contentStyle);
+
+                // 值班人员列(首行填充,后续合并)
+                Cell memberCell = dataRow.createCell(1);
+                if (currentRow == taskStartRow) {
+                    memberCell.setCellValue(duty.getMember());
+                }
+                memberCell.setCellStyle(contentStyle);
+
+                // 工作任务列
+                Cell taskCell = dataRow.createCell(2);
+                taskCell.setCellValue(task.getTaskContent());
+                taskCell.setCellStyle(contentStyle);
+
+                // 完成情况列
+                Cell statusCell = dataRow.createCell(3);
+                statusCell.setCellValue(getCompletionStatus(task.getTaskType(), businessMap, duty));
+                statusCell.setCellStyle(contentStyle);
+
+                currentRow++;
+            }
+
+            sheet.addMergedRegion(new CellRangeAddress(taskStartRow, currentRow - 1, 0, 0));
+            sheet.addMergedRegion(new CellRangeAddress(taskStartRow, currentRow - 1, 1, 1));
+
+            currentRow++;
+        }
+
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        String fileName = URLEncoder.encode("批量坐班值守任务表.xlsx", "UTF-8");
+        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
+        workbook.write(response.getOutputStream());
+        workbook.close();
+    }
+
+    /**
+     * 获取任务完成情况(复用单条导出逻辑)
+     */
+    private String getCompletionStatus(int taskType, Map<Integer, List<MhFireDutyBusiness>> businessMap, MhFireDuty fireDuty) {
+        if (taskType >= 1 && taskType <= 4) {
+            List<MhFireDutyBusiness> businessList = businessMap.getOrDefault(taskType, Collections.emptyList());
+            return businessList.stream()
+                    .map(biz -> biz.getUnit() + "-" + biz.getStatus())
+                    .collect(Collectors.joining(";"));
+        } else if (taskType == 5) {
+            return Optional.ofNullable(fireDuty.getDisposalContent()).orElse("");
+        } else if (taskType == 6) {
+            return Optional.ofNullable(fireDuty.getMaterialCollection()).orElse("");
+        } else if (taskType == 7) {
+            return Optional.ofNullable(fireDuty.getDynamicMonitoring()).orElse("");
+        }
+        return "";
+    }
+
+    // 样式创建方法(与之前一致)
+    private CellStyle createTitleStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        Font font = workbook.createFont();
+        font.setBold(true);
+        font.setFontHeightInPoints((short) 14);
+        style.setFont(font);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        return style;
+    }
+
+    private CellStyle createHeaderStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        Font font = workbook.createFont();
+        font.setBold(true);
+        style.setFont(font);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+        return style;
+    }
+
+    private CellStyle createContentStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        style.setAlignment(HorizontalAlignment.LEFT);
+        style.setVerticalAlignment(VerticalAlignment.TOP);
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setWrapText(true);
+        return style;
+    }
+
+    // 任务定义内部类
+    private static class TaskDef {
+        private final int taskType;
+        private final String taskContent;
+
+        public TaskDef(int taskType, String taskContent) {
+            this.taskType = taskType;
+            this.taskContent = taskContent;
+        }
+
+        public int getTaskType() {
+            return taskType;
+        }
+
+        public String getTaskContent() {
+            return taskContent;
+        }
+    }
+
+}

+ 1 - 1
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/ReportIndexResultServiceImpl.java

@@ -128,7 +128,7 @@ public class ReportIndexResultServiceImpl extends AbstractCrudService<ReportInde
                     int month = now.get(Calendar.MONTH) + 1; // Calendar.MONTH从0开始,所以要+1
                     String monthStr = String.format("%02d", month); // 月份补零成两位数
                     String dirName = year + monthStr; // 生成 "202509" 格式
-                    File file = new File("/home/service/usky-file/" + dirName + "/" + dirName + baseCompanies.get(i).getCompanyId() + ".pdf");
+                    File file = new File("/home/service/usky-file/" + dirName + "/" + year + "_" + baseCompanies.get(i).getCompanyId() + ".pdf");
 
                     File monthDir = file.getParentFile();
                     if (!monthDir.exists()) {

+ 18 - 0
service-fire/service-fire-biz/src/main/resources/mapper/fire/MhFireDutyBusinessMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.fire.mapper.MhFireDutyBusinessMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.fire.domain.MhFireDutyBusiness">
+        <id column="id" property="id" />
+        <result column="duty_id" property="dutyId" />
+        <result column="business_type" property="businessType" />
+        <result column="company_id" property="companyId" />
+        <result column="company_name" property="companyName" />
+        <result column="content" property="content" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="is_deleted" property="isDeleted" />
+    </resultMap>
+
+</mapper>

+ 21 - 0
service-fire/service-fire-biz/src/main/resources/mapper/fire/MhFireDutyMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.fire.mapper.MhFireDutyMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.fire.domain.MhFireDuty">
+        <id column="id" property="id" />
+        <result column="member_name" property="memberName" />
+        <result column="member_id" property="memberId" />
+        <result column="duty_date" property="dutyDate" />
+        <result column="disposal_content" property="disposalContent" />
+        <result column="material_collection" property="materialCollection" />
+        <result column="dynamic_monitoring" property="dynamicMonitoring" />
+        <result column="create_time" property="createTime" />
+        <result column="create_by" property="createBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="is_deleted" property="isDeleted" />
+    </resultMap>
+
+</mapper>