From 4bc9d9f073544f72a76780cbd9581b71e16ecf14 Mon Sep 17 00:00:00 2001 From: zhangrui Date: Fri, 3 Jul 2026 15:48:04 +0800 Subject: [PATCH] change --- dependency-reduced-pom.xml | 2 +- pom.xml | 2 +- .../MemberPersonalInfoMaintainController.java | 14 ++ .../member/service/MemberInfoService.java | 8 + .../service/impl/MemberInfoServiceImpl.java | 207 ++++++++++++++++++ .../member/info/maintain/index.html | 16 ++ 6 files changed, 247 insertions(+), 2 deletions(-) diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 81cb4a3..0984c76 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.budwk - zhgh_jshvc + mini 5.6.0-plus diff --git a/pom.xml b/pom.xml index 6e1fd03..18f4bae 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 jar com.budwk - zhgh_jshvc + mini 5.6.0-plus 2.6.0-SNAPSHOT diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberPersonalInfoMaintainController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberPersonalInfoMaintainController.java index 88f1ecc..05736c7 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberPersonalInfoMaintainController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberPersonalInfoMaintainController.java @@ -18,6 +18,7 @@ import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; +import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; @@ -68,6 +69,19 @@ public class MemberPersonalInfoMaintainController { return Result.success(pagination); } + /** + * 导出个人信息维护列表数据,导出条件与页面查询保持一致,具体 Excel 生成逻辑放在 service 层。 + * + * @param pageForm 页面查询和显示列参数 + * @param response 文件下载响应 + */ + @At + @Ok("void") + @SaCheckPermission(value = {"member.info.maintain", "member.info.group"}, mode = SaMode.OR) + public void doExport(MemberInfoPageForm pageForm, HttpServletResponse response) { + memberInfoService.exportPersonalMaintain(pageForm, response); + } + /** * 查询个人信息维护详情,返回只读会员信息和可编辑子女信息。 * diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberInfoService.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberInfoService.java index a929b27..5f83f6e 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberInfoService.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberInfoService.java @@ -51,6 +51,14 @@ public interface MemberInfoService extends BaseService { */ void savePersonalMaintainMarriage(String userId, String marriage); + /** + * 导出个人信息维护列表数据,查询条件与页面列表保持一致,并汇总导出家庭主要成员信息。 + * + * @param pageForm 页面查询和显示列参数 + * @param response 文件下载响应 + */ + void exportPersonalMaintain(MemberInfoPageForm pageForm, HttpServletResponse response); + /** * 获取会员历史 * @param pageForm diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberInfoServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberInfoServiceImpl.java index fd1e750..208bcab 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberInfoServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberInfoServiceImpl.java @@ -20,11 +20,24 @@ import com.budwk.app.web.commons.auth.utils.AuthUtil; import com.budwk.app.sys.models.Sys_user; import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.zhgh.staffmanage.member.models.MemberHistory; +import com.budwk.app.zhgh.staffmanage.member.models.MemberChild; import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberInfoPageForm; import com.budwk.app.zhgh.staffmanage.member.service.MemberInfoService; import com.budwk.app.zhgh.staffmanage.member.vo.MemberImportVo; +import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.formula.functions.T; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; @@ -41,9 +54,12 @@ import org.nutz.lang.util.NutMap; import org.nutz.mvc.upload.TempFile; import javax.servlet.http.HttpServletResponse; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -208,6 +224,197 @@ public class MemberInfoServiceImpl extends BaseServiceImpl implements dao().update(Sys_user.class, Chain.make("marriage", marriage), Cnd.where("id", "=", userId)); } + /** + * 导出个人信息维护列表,人员数据复用页面查询 SQL,家庭主要成员按同一人员汇总到一行。 + * + * @param pageForm 页面查询和显示列参数 + * @param response 文件下载响应 + */ + @Override + public void exportPersonalMaintain(MemberInfoPageForm pageForm, HttpServletResponse response) { + Sql sql = getPersonalMaintainSql(pageForm); + List list = listMap(sql); + fillChildExportData(list); + List> personColumns = Lang.isNotEmpty(pageForm.getColumns()) + ? pageForm.getColumns() + : buildDefaultPersonalMaintainColumns(); + Workbook workbook = buildPersonalMaintainWorkbook(personColumns, list); + CommonDownloadUtil.download("人员信息维护.xlsx", workbook, response); + } + + /** + * 为查询结果追加子女信息汇总字段,多个子女之间使用“ | ”分隔。 + * + * @param list 页面查询出的人员数据 + */ + private void fillChildExportData(List list) { + if (Lang.isEmpty(list)) { + return; + } + List userIds = list.stream().map(item -> item.getString("id")).filter(StrUtil::isNotBlank).toList(); + if (Lang.isEmpty(userIds)) { + return; + } + // Query child records in batch so exported child data follows the same people returned by the page query. + Map> childMap = dao().query(MemberChild.class, Cnd.where("userId", "in", userIds).asc("createdAt")) + .stream().collect(Collectors.groupingBy(MemberChild::getUserId)); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + for (NutMap item : list) { + List children = childMap.get(item.getString("id")); + item.put("childRelation", joinChildField(children, MemberChild::getRelation)); + item.put("childName", joinChildField(children, MemberChild::getName)); + item.put("childSex", joinChildField(children, MemberChild::getSex)); + item.put("childBirthday", joinChildField(children, child -> child.getBirthday() == null ? "" : dateFormat.format(child.getBirthday()))); + } + } + + /** + * 聚合子女信息单个字段,保持每个子女字段在同一导出行内的顺序一致。 + * + * @param children 子女信息列表 + * @param getter 字段取值函数 + * @return 使用“ | ”分隔的字段内容 + */ + private String joinChildField(List children, Function getter) { + if (Lang.isEmpty(children)) { + return ""; + } + // Keep child field order consistent across all exported child columns. + return children.stream() + .map(child -> StrUtil.nullToEmpty(getter.apply(child))) + .collect(Collectors.joining(" | ")); + } + + /** + * 页面未传显示列时,使用个人信息维护列表当前默认显示列作为导出字段。 + * + * @return 默认人员信息导出列 + */ + private List> buildDefaultPersonalMaintainColumns() { + List> columns = new ArrayList<>(); + addExportColumn(columns, "工号", "loginname"); + addExportColumn(columns, "姓名", "username"); + addExportColumn(columns, "性别", "sex"); + addExportColumn(columns, "出生年月", "birthday"); + addExportColumn(columns, "民族", "nation"); + addExportColumn(columns, "联系电话", "mobile"); + addExportColumn(columns, "政治面貌", "political"); + addExportColumn(columns, "在职状态", "userState"); + addExportColumn(columns, "教职工类别", "personType"); + addExportColumn(columns, "编制类别", "preparedBy"); + addExportColumn(columns, "所属工会", "unionName"); + addExportColumn(columns, "所属单位", "unitName"); + return columns; + } + + /** + * 添加导出列配置,使用有序 Map 保持 Excel 列顺序。 + */ + private void addExportColumn(List> columns, String label, String prop) { + Map column = new LinkedHashMap<>(); + column.put("label", label); + column.put("prop", prop); + columns.add(column); + } + + /** + * 构建带“人员信息 / 子女信息”分组表头的 Excel。 + * + * @param personColumns 人员信息列 + * @param list 导出数据 + * @return Excel 工作簿 + */ + private Workbook buildPersonalMaintainWorkbook(List> personColumns, List list) { + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet("人员信息维护"); + CellStyle groupStyle = createExportCellStyle(workbook, true, IndexedColors.PALE_BLUE.getIndex()); + CellStyle childGroupStyle = createExportCellStyle(workbook, true, IndexedColors.LIGHT_GREEN.getIndex()); + CellStyle headerStyle = createExportCellStyle(workbook, true, IndexedColors.GREY_25_PERCENT.getIndex()); + CellStyle dataStyle = createExportCellStyle(workbook, false, IndexedColors.WHITE.getIndex()); + + List> childColumns = new ArrayList<>(); + addExportColumn(childColumns, "关系", "childRelation"); + addExportColumn(childColumns, "姓名", "childName"); + addExportColumn(childColumns, "性别", "childSex"); + addExportColumn(childColumns, "出生日期", "childBirthday"); + + Row groupRow = sheet.createRow(0); + Row headerRow = sheet.createRow(1); + int colIndex = 0; + createMergedCell(sheet, groupRow, 0, Math.max(personColumns.size() - 1, 0), "人员信息", groupStyle); + for (Map column : personColumns) { + createCell(headerRow, colIndex++, column.get("label"), headerStyle); + } + int childStartIndex = colIndex; + createMergedCell(sheet, groupRow, childStartIndex, childStartIndex + childColumns.size() - 1, "子女信息", childGroupStyle); + for (Map column : childColumns) { + createCell(headerRow, colIndex++, column.get("label"), headerStyle); + } + for (int i = 0; i < list.size(); i++) { + Row dataRow = sheet.createRow(i + 2); + int dataCol = 0; + NutMap data = list.get(i); + for (Map column : personColumns) { + createCell(dataRow, dataCol++, data.getString(column.get("prop"), ""), dataStyle); + } + for (Map column : childColumns) { + createCell(dataRow, dataCol++, data.getString(column.get("prop"), ""), dataStyle); + } + } + for (int i = 0; i < colIndex; i++) { + sheet.setColumnWidth(i, 20 * 256); + } + return workbook; + } + + /** + * 创建导出单元格样式,统一表头和数据区的边框、对齐、换行。 + */ + private CellStyle createExportCellStyle(Workbook workbook, boolean bold, short fillColor) { + CellStyle style = workbook.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setWrapText(true); + style.setFillForegroundColor(fillColor); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + style.setBorderTop(BorderStyle.THIN); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.BLACK.getIndex()); + style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); + style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); + style.setRightBorderColor(IndexedColors.BLACK.getIndex()); + Font font = workbook.createFont(); + font.setBold(bold); + style.setFont(font); + return style; + } + + /** + * 创建普通单元格并写入文本值。 + */ + private void createCell(Row row, int colIndex, String value, CellStyle style) { + Cell cell = row.createCell(colIndex); + cell.setCellValue(value == null ? "" : value); + cell.setCellStyle(style); + } + + /** + * 创建横向合并单元格,作为 Excel 分组表头。 + */ + private void createMergedCell(Sheet sheet, Row row, int firstCol, int lastCol, String value, CellStyle style) { + createCell(row, firstCol, value, style); + if (lastCol > firstCol) { + sheet.addMergedRegion(new CellRangeAddress(row.getRowNum(), row.getRowNum(), firstCol, lastCol)); + for (int i = firstCol + 1; i <= lastCol; i++) { + createCell(row, i, "", style); + } + } + } + @Override public Sql getMemberHistorySql(MemberInfoPageForm pageForm) { diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/info/maintain/index.html b/src/main/resources/views/platform/zhgh/staffmanage/member/info/maintain/index.html index 0680c70..f08ea37 100644 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/info/maintain/index.html +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/info/maintain/index.html @@ -35,6 +35,7 @@ layout("/layouts/platform.html"){ 列设置 + 导出 @@ -157,6 +158,21 @@ layout("/layouts/platform.html"){ this.tableLoading = false }) }, + doExport() { + const pageForm = clone(this.pageForm) + pageForm.userStates = Array.isArray(this.pageForm.userStates) ? JSON.stringify(this.pageForm.userStates) : this.pageForm.userStates + pageForm.personTypes = Array.isArray(this.pageForm.personTypes) ? JSON.stringify(this.pageForm.personTypes) : this.pageForm.personTypes + pageForm.preparedBys = Array.isArray(this.pageForm.preparedBys) ? JSON.stringify(this.pageForm.preparedBys) : this.pageForm.preparedBys + pageForm.columns = JSON.stringify(this.tableColumns.filter((column) => { + return this.checkedFields.includes(column.prop) + }).map((column) => { + return { + label: column.label, + prop: column.prop + } + })) + this.$downLoad(loc() + "/doExport", pageForm) + }, checkAll() { this.checkedFields = this.tableColumns.map(c => c.prop) },