From 8c131cb9a592197727b9209950c71c2095f0c3fe Mon Sep 17 00:00:00 2001 From: dfdg <2710245601@qq.com> Date: Tue, 2 Sep 2025 18:57:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=94=B6=E8=B5=84=E6=B8=85?= =?UTF-8?q?=E5=8D=95=E6=A8=A1=E6=9D=BF=E5=AF=BC=E5=87=BA=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DesCollectController.java | 22 ++++ .../design/service/IDesCollectService.java | 7 ++ .../service/impl/DesCollectServiceImpl.java | 112 ++++++++++++++++++ ...FormalitiesAreConsolidatedServiceImpl.java | 4 +- .../system/service/ISysUserService.java | 14 +++ .../service/impl/SysUserServiceImpl.java | 41 +++++++ 6 files changed, 198 insertions(+), 2 deletions(-) diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/DesCollectController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/DesCollectController.java index d479d99a..4f45ecc1 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/DesCollectController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/DesCollectController.java @@ -1,12 +1,21 @@ package org.dromara.design.controller; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import com.alibaba.excel.EasyExcel; import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.*; import cn.dev33.satoken.annotation.SaCheckPermission; +//import org.dromara.design.converter.UserConverter; +import org.dromara.design.domain.DesCollect; +import org.dromara.design.domain.DesCollectCatalogue; import org.dromara.design.domain.dto.desCollect.DesCollectBatchDto; +import org.dromara.design.domain.vo.DesCollectCatalogueVo; +//import org.dromara.design.handler.UserDropdownSheetWriteHandler; +import org.dromara.tender.domain.bo.BusBillofquantitiesLimitListBo; import org.springframework.web.bind.annotation.*; import org.springframework.validation.annotation.Validated; import org.dromara.common.idempotent.annotation.RepeatSubmit; @@ -22,6 +31,7 @@ import org.dromara.design.domain.vo.DesCollectVo; import org.dromara.design.domain.bo.DesCollectBo; import org.dromara.design.service.IDesCollectService; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.springframework.web.multipart.MultipartFile; /** * 收资清单 @@ -136,4 +146,16 @@ public class DesCollectController extends BaseController { desCollectService.exportWordById(id, response); } + + /** + * 收资清单模板导出 + */ + @SaCheckPermission("design:collect:exportExcel") + @Log(title = "收资清单", businessType = BusinessType.EXPORT) + @PostMapping("/exportExcel") + public void exportExcelByDeptId(@RequestParam("deptId") Long deptId, HttpServletResponse response){ + desCollectService.exportExcelByDeptId(deptId, response); + } + + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/IDesCollectService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/IDesCollectService.java index 225e9ab5..64abc1e3 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/IDesCollectService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/IDesCollectService.java @@ -88,4 +88,11 @@ public interface IDesCollectService extends IService{ * 导出Word */ void exportWordById(Long id, HttpServletResponse response); + + /** + * 导出模板 + * @param deptId + * @param response + */ + void exportExcelByDeptId(Long deptId, HttpServletResponse response); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/impl/DesCollectServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/impl/DesCollectServiceImpl.java index 39269ca6..a553251d 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/impl/DesCollectServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/service/impl/DesCollectServiceImpl.java @@ -13,6 +13,9 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.dromara.common.core.domain.event.ProcessDeleteEvent; import org.dromara.common.core.domain.event.ProcessEvent; import org.dromara.common.core.domain.event.ProcessTaskEvent; @@ -39,6 +42,7 @@ import org.dromara.design.mapper.DesCollectMapper; import org.dromara.design.service.IDesCollectCatalogueService; import org.dromara.design.service.IDesCollectService; import org.dromara.project.service.IBusProjectService; +import org.dromara.system.service.ISysUserService; import org.springframework.beans.BeanUtils; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; @@ -77,6 +81,8 @@ public class DesCollectServiceImpl extends ServiceImpl userNameList = sysUserService.getUserNamesByDept(deptId); + Map userIdToNameMapByDept = sysUserService.getUserIdToNameMapByDept(deptId); + + + // 2. 设置响应头 + // 设置响应头,指定Excel格式和下载文件名 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + response.setHeader("Content-Disposition", "attachment; filename=utf-8''收资清单模板.xlsx"); + + Workbook workbook = new XSSFWorkbook(); + // 创建主 Sheet 和隐藏 Sheet + Sheet mainSheet = workbook.createSheet("收资清单模板"); + Sheet dropdownSheet = workbook.createSheet("DropdownData"); + workbook.setSheetHidden(workbook.getSheetIndex(dropdownSheet), true); + + + //设置下拉列表数据 + int rowIdx = 0; + for (Map.Entry entry : userIdToNameMapByDept.entrySet()) { + Row row = dropdownSheet.createRow(rowIdx++); + row.createCell(0).setCellValue(entry.getKey()); + row.createCell(1).setCellValue(entry.getValue()); + } + + // 主 Sheet 设置表头 + Row sheetRow = mainSheet.createRow(0); + sheetRow.createCell(0).setCellValue("编码"); + sheetRow.createCell(1).setCellValue("人员"); + sheetRow.createCell(2).setCellValue("目录名"); + sheetRow.createCell(3).setCellValue("备注"); + + // 核心:锁定表头(第1行)和前1列(包含ID列) + mainSheet.createFreezePane(1, 1, 0, 0); + + // 绑定下拉列表(关联隐藏 Sheet) + DataValidationHelper helper = mainSheet.getDataValidationHelper(); //为主Sheet第二列设置下拉列表(关联隐藏Sheet的B列) + String range = "DropdownData!$B$1:$B$" + userNameList.size(); //引用隐藏Sheet的B列数据范围:DropdownData!$B$1:$B$ + DataValidationConstraint constraint = helper.createFormulaListConstraint(range); //创建下拉约束 + CellRangeAddressList addressList = new CellRangeAddressList(1, 300, 1, 1); // 支持100行数据 + //添加验证规则 + DataValidation validation = helper.createValidation(constraint, addressList); + validation.setShowErrorBox(true); + mainSheet.addValidationData(validation); + + + // 7. 创建“隐藏公式”的单元格样式 + // 样式1:第一列专用(隐藏公式 + 锁定单元格) + CellStyle hiddenFormulaAndLockedStyle = workbook.createCellStyle(); + DataFormat dataFormat = workbook.createDataFormat(); + short formatIndex = dataFormat.getFormat("0"); // 匹配“自定义→0”格式 + hiddenFormulaAndLockedStyle.setDataFormat(formatIndex); + hiddenFormulaAndLockedStyle.setHidden(true); // 隐藏公式 + hiddenFormulaAndLockedStyle.setLocked(true); // 锁定单元格 + + // 样式2:其他列专用(不锁定,允许操作) + CellStyle unlockedStyle = workbook.createCellStyle(); + unlockedStyle.setLocked(false); // 不锁定单元格 + + // 第三列自动填充ID公式 + String formulaTemplate = "IFERROR(INDEX(DropdownData!$A$1:$A$" + userIdToNameMapByDept.size() + ", MATCH(B{rowNum}, DropdownData!$B$1:$B$" + userIdToNameMapByDept.size() + ", 0)),\"\")"; + + for (int i = 1; i <= 300; i++) { // 从第2行开始(行索引1) + Row row = mainSheet.createRow(i); + int currentRowNum = i + 1; // Excel行号从1开始,第2行的行号是2 + String formula = formulaTemplate.replace("{rowNum}", String.valueOf(currentRowNum)); + // 第一列:ID列(隐藏公式 + 锁定) + Cell idCell = row.createCell(0); + idCell.setCellFormula(formula); + idCell.setCellStyle(hiddenFormulaAndLockedStyle); + + // 第二列:名称列(不锁定,可下拉选择) + Cell nameCell = row.createCell(1); + nameCell.setCellStyle(unlockedStyle); + + // 第三列:序号列(不锁定,可编辑) + Cell seqCell = row.createCell(2); + seqCell.setCellStyle(unlockedStyle); + // 第四列:备注列(不锁定,可编辑) + Cell remakerCell = row.createCell(3); + remakerCell.setCellStyle(unlockedStyle); + } + + + // 保护工作表(使“隐藏公式”生效,可自定义密码) + mainSheet.protectSheet("123456"); // 示例密码:123456 + + // 调整列宽 + mainSheet.setColumnWidth(0, 20 * 256); + mainSheet.setColumnWidth(1, 20 * 100); + mainSheet.setColumnWidth(2, 20 * 200); + mainSheet.setColumnWidth(3, 20 * 200); + + // 直接写入响应输出流 + try { + workbook.write(response.getOutputStream()); + workbook.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + /** * 根据实体获取替换数据 diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/formalities/service/impl/BusFormalitiesAreConsolidatedServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/formalities/service/impl/BusFormalitiesAreConsolidatedServiceImpl.java index 46c3ac17..cc0c859b 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/formalities/service/impl/BusFormalitiesAreConsolidatedServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/formalities/service/impl/BusFormalitiesAreConsolidatedServiceImpl.java @@ -144,8 +144,8 @@ public class BusFormalitiesAreConsolidatedServiceImpl extends ServiceImpl buildQueryWrapper(BusFormalitiesAreConsolidatedBo bo) { Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.orderByDesc(BusFormalitiesAreConsolidated::getCreatePTime); - lqw.orderByDesc(BusFormalitiesAreConsolidated::getCreateTime); + lqw.orderByAsc(BusFormalitiesAreConsolidated::getCreatePTime); + lqw.orderByAsc(BusFormalitiesAreConsolidated::getCreateTime); lqw.eq(bo.getProjectId() != null, BusFormalitiesAreConsolidated::getProjectId, bo.getProjectId()); lqw.eq(bo.getFormalitiesPid() != null, BusFormalitiesAreConsolidated::getFormalitiesPid, bo.getFormalitiesPid()); lqw.eq(bo.getFormalitiesId() != null, BusFormalitiesAreConsolidated::getFormalitiesId, bo.getFormalitiesId()); diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java index 86336dbe..176a9a97 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java @@ -9,6 +9,7 @@ import org.dromara.system.domain.vo.SysUserExportVo; import org.dromara.system.domain.vo.SysUserVo; import java.util.List; +import java.util.Map; /** * 用户 业务层 @@ -244,4 +245,17 @@ public interface ISysUserService { * @return 结果 */ List findThis(); + + + /** + * 根据部门 ID 获取用户 ID -> 名称 映射 + * @param deptId + * @return + */ + Map getUserIdToNameMapByDept(Long deptId); + + /** + * 获取指定部门的用户名称列表(用于 Excel 下拉框) + */ + List getUserNamesByDept(Long deptId); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index 7c585543..003d9be0 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -732,6 +732,47 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return baseMapper.selectList(new LambdaQueryWrapper().in(SysUser::getDeptId, longs)); } + + /** + * 根据部门 ID 获取用户 ID -> 名称 映射 + * @param deptId + * @return + */ + @Override + public Map getUserIdToNameMapByDept(Long deptId) { + List deptList = deptMapper.selectListByParentId(deptId); + List ids = StreamUtils.toList(deptList, SysDept::getDeptId); + ids.add(deptId); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.in(SysUser::getDeptId, ids); + lqw.orderByAsc(SysUser::getUserId); + List sysUsers = baseMapper.selectList(lqw); + return sysUsers.stream() + .collect(Collectors.toMap( + SysUser::getUserId, + SysUser::getNickName + )); + } + + /** + * 获取指定部门的用户名称列表(用于 Excel 下拉框) + * @param deptId + * @return + */ + @Override + public List getUserNamesByDept(Long deptId) { + List deptList = deptMapper.selectListByParentId(deptId); + List ids = StreamUtils.toList(deptList, SysDept::getDeptId); + ids.add(deptId); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.in(SysUser::getDeptId, ids); + lqw.orderByAsc(SysUser::getUserId); + List sysUsers = baseMapper.selectList(lqw); + return sysUsers.stream() + .map(SysUser::getNickName) + .collect(Collectors.toList()); + } + /** * 通过用户ID查询用户账户 *