This commit is contained in:
2026-07-03 15:48:04 +08:00
parent 0083cfeed4
commit 4bc9d9f073
6 changed files with 247 additions and 2 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.budwk</groupId>
<artifactId>zhgh_jshvc</artifactId>
<artifactId>mini</artifactId>
<version>5.6.0-plus</version>
<build>
<resources>
+1 -1
View File
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<groupId>com.budwk</groupId>
<artifactId>zhgh_jshvc</artifactId>
<artifactId>mini</artifactId>
<version>5.6.0-plus</version>
<properties>
<nutzboot.version>2.6.0-SNAPSHOT</nutzboot.version>
@@ -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);
}
/**
* 查询个人信息维护详情,返回只读会员信息和可编辑子女信息。
*
@@ -51,6 +51,14 @@ public interface MemberInfoService extends BaseService<Sys_user> {
*/
void savePersonalMaintainMarriage(String userId, String marriage);
/**
* 导出个人信息维护列表数据,查询条件与页面列表保持一致,并汇总导出家庭主要成员信息。
*
* @param pageForm 页面查询和显示列参数
* @param response 文件下载响应
*/
void exportPersonalMaintain(MemberInfoPageForm pageForm, HttpServletResponse response);
/**
* 获取会员历史
* @param pageForm
@@ -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<Sys_user> 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<NutMap> list = listMap(sql);
fillChildExportData(list);
List<Map<String, String>> personColumns = Lang.isNotEmpty(pageForm.getColumns())
? pageForm.getColumns()
: buildDefaultPersonalMaintainColumns();
Workbook workbook = buildPersonalMaintainWorkbook(personColumns, list);
CommonDownloadUtil.download("人员信息维护.xlsx", workbook, response);
}
/**
* 为查询结果追加子女信息汇总字段,多个子女之间使用“ | ”分隔。
*
* @param list 页面查询出的人员数据
*/
private void fillChildExportData(List<NutMap> list) {
if (Lang.isEmpty(list)) {
return;
}
List<String> 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<String, List<MemberChild>> 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<MemberChild> 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<MemberChild> children, Function<MemberChild, String> 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<Map<String, String>> buildDefaultPersonalMaintainColumns() {
List<Map<String, String>> 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<Map<String, String>> columns, String label, String prop) {
Map<String, String> 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<Map<String, String>> personColumns, List<NutMap> 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<Map<String, String>> 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<String, String> column : personColumns) {
createCell(headerRow, colIndex++, column.get("label"), headerStyle);
}
int childStartIndex = colIndex;
createMergedCell(sheet, groupRow, childStartIndex, childStartIndex + childColumns.size() - 1, "子女信息", childGroupStyle);
for (Map<String, String> 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<String, String> column : personColumns) {
createCell(dataRow, dataCol++, data.getString(column.get("prop"), ""), dataStyle);
}
for (Map<String, String> 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) {
@@ -35,6 +35,7 @@ layout("/layouts/platform.html"){
列设置
</el-button>
</el-popover>
<el-button type="primary" size="small" icon="el-icon-download" @click="doExport">导出</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id" @sort-change="pageOrder" :size="tableSize" class="vi-table">
@@ -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)
},