Merge remote-tracking branch 'origin/feature_民主管理、人员管理' into release_20261030问题整改
# Conflicts: # src/main/resources/views/platform/zhgh/activity/culture/common/applyActivity.js
This commit is contained in:
@@ -57,6 +57,8 @@ public class SysV4ServController {
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
// 先取每个流程的最新定义,再判断是否启用,避免最新版本停用后回退展示旧版本。
|
||||
cnd.and("t.state", "=", 1);
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
cnd.where().andLike("t.disPlayName", keyword);
|
||||
}
|
||||
|
||||
+21
@@ -620,6 +620,27 @@ public class ActivitySportsApplyUserServiceImpl extends BaseServiceImpl<Activity
|
||||
continue;
|
||||
}
|
||||
|
||||
// 以系统人员档案为准校验男女分组,不能用 Excel 性别绕过限制;校验失败时保留已有报名。
|
||||
Integer isMenWomen = activityEvent.getIsMenWomen();
|
||||
if (Integer.valueOf(1).equals(isMenWomen) || Integer.valueOf(2).equals(isMenWomen)) {
|
||||
String sex = normalizeText(sysUser.getSex());
|
||||
boolean male = "男".equals(sex) || "男性".equals(sex);
|
||||
boolean female = "女".equals(sex) || "女性".equals(sex);
|
||||
String errorMessage = null;
|
||||
if (!male && !female) {
|
||||
errorMessage = "系统人员档案性别为空或无法识别,请维护后重新导入";
|
||||
} else if (Integer.valueOf(1).equals(isMenWomen) && !male) {
|
||||
errorMessage = "该项目为男子组,系统人员档案性别为女,不能报名";
|
||||
} else if (Integer.valueOf(2).equals(isMenWomen) && !female) {
|
||||
errorMessage = "该项目为女子组,系统人员档案性别为男,不能报名";
|
||||
}
|
||||
if (errorMessage != null) {
|
||||
importTemp.setNotes(errorMessage);
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
activitySchoolApply.setEventId(schoolEvent.getEventId());
|
||||
activitySchoolApply.setAwardsMode(activityEvent.getProjectType());
|
||||
if ("2".equals(activityEvent.getProjectType())) {
|
||||
|
||||
+57
-8
@@ -1,6 +1,5 @@
|
||||
package com.budwk.app.zhgh.welfare.service.impl;
|
||||
|
||||
import cn.afterturn.easypoi.entity.ImageEntity;
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
@@ -23,8 +22,12 @@ import com.budwk.app.zhgh.welfare.model.WelfareProjectSubjectOption;
|
||||
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
|
||||
import com.budwk.app.zhgh.welfare.service.WelfareSelectionSituationService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
@@ -246,7 +249,8 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
||||
byte[] userSignBytes = SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath());
|
||||
map.put("userSign", userSignBytes);
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
// 下载失败时不把原文件地址写入签字单元格。
|
||||
map.put("userSign", null);
|
||||
log.error("下载图片失败", e);
|
||||
}
|
||||
}
|
||||
@@ -268,21 +272,66 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
||||
optionList.forEach(option -> {
|
||||
entities.add(new ExcelExportEntity(option.getOptionName(), option.getOptionName(), 20));
|
||||
});
|
||||
// 签字列先按空白文本导出,图片另行写入,避开 EasyPOI 对 Map 图片字段的反射。
|
||||
ExcelExportEntity userSignEntity = new ExcelExportEntity("签字", "userSign", 20);
|
||||
userSignEntity.setType(2);
|
||||
userSignEntity.setExportImageType(2);
|
||||
entities.add(userSignEntity);
|
||||
|
||||
// 导出
|
||||
Workbook workbook = new HSSFWorkbook();
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
listMap.forEach((k, v) -> {
|
||||
List<byte[]> signatures = new ArrayList<>();
|
||||
v.forEach(row -> {
|
||||
Object signature = row.remove("userSign");
|
||||
signatures.add(signature instanceof byte[] ? (byte[]) signature : null);
|
||||
});
|
||||
ExcelExportService service = new ExcelExportService();
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setSheetName(k);
|
||||
exportParams.setType(ExcelType.HSSF);
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
int firstSheet = workbook.getNumberOfSheets();
|
||||
service.createSheetForMap(workbook, exportParams, entities, v);
|
||||
// 无标题、单层列头的数据从第二行开始;按新增 Sheet 顺序兼容 EasyPOI 自动拆表。
|
||||
int signatureIndex = 0;
|
||||
for (int sheetIndex = firstSheet; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
Drawing<?> drawing = sheet.createDrawingPatriarch();
|
||||
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum() && signatureIndex < signatures.size(); rowIndex++) {
|
||||
byte[] signature = signatures.get(signatureIndex++);
|
||||
if (signature != null && signature.length > 0) {
|
||||
insertReceiveSignature(workbook, sheet, drawing, rowIndex, entities.size() - 1, signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CommonDownloadUtil.download("领取表.xls", workbook, response);
|
||||
CommonDownloadUtil.download("领取表.xlsx", workbook, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将签字字节数组写入领取表指定单元格。行列索引从 0 开始,图片统一转为 PNG;
|
||||
* 无法解码的图片仅记录日志并保留空白签字格,不中断其他人员的导出。
|
||||
*/
|
||||
private void insertReceiveSignature(Workbook workbook, Sheet sheet, Drawing<?> drawing,
|
||||
int rowIndex, int columnIndex, byte[] signature) {
|
||||
try (ByteArrayInputStream input = new ByteArrayInputStream(signature);
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||
BufferedImage image = ImageIO.read(input);
|
||||
if (image == null) {
|
||||
log.warn("领取表签字图片无法识别,Sheet={},行={}", sheet.getSheetName(), rowIndex + 1);
|
||||
return;
|
||||
}
|
||||
ImageIO.write(image, "png", output);
|
||||
Row row = sheet.getRow(rowIndex);
|
||||
row.setHeightInPoints(Math.max(row.getHeightInPoints(), 50));
|
||||
ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
|
||||
anchor.setCol1(columnIndex);
|
||||
anchor.setCol2(columnIndex + 1);
|
||||
anchor.setRow1(rowIndex);
|
||||
anchor.setRow2(rowIndex + 1);
|
||||
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
|
||||
drawing.createPicture(anchor, workbook.addPicture(output.toByteArray(), Workbook.PICTURE_TYPE_PNG));
|
||||
} catch (Exception e) {
|
||||
log.error("领取表签字图片写入失败,Sheet={},行={}", sheet.getSheetName(), rowIndex + 1, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,10 @@
|
||||
#v4-home-app .todo-center .el-tabs__nav { display: flex; width: 100%; border-color: #e9eff6; border-radius: 6px 6px 0 0; }
|
||||
#v4-home-app .todo-center .el-tabs__item { flex: 1; min-width: 0; padding: 0 7px; font-size: 12px; height: 36px; line-height: 36px; text-align: center; }
|
||||
#v4-home-app .todo-center .el-tabs__item.is-active { border-bottom: 2px solid #1687f5; color: #1687f5; }
|
||||
#v4-home-app .portal-task-list { display: flex; flex-direction: column; justify-content: space-evenly; flex: 1; min-height: 180px; }
|
||||
/* 任务从标签栏下方依次排列,避免单条记录被剩余高度推到中间。 */
|
||||
#v4-home-app .portal-task-list { display: flex; flex-direction: column; justify-content: flex-start; flex: 1; min-height: 180px; }
|
||||
/* 空数据提示独立占满列表区域,保留居中展示。 */
|
||||
#v4-home-app .portal-task-list > .portal-empty { flex: 1; }
|
||||
#v4-home-app .portal-task-row { display: flex; gap: 10px; align-items: center; padding: 8px 6px; border-bottom: 1px solid #eef3f8; }
|
||||
#v4-home-app .portal-task-row:last-child { border-bottom: 0; }
|
||||
#v4-home-app .portal-task-row:hover { background: #f7fbff; }
|
||||
|
||||
@@ -181,7 +181,7 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/css/home-portal.css?v=20261030-1" />
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/css/home-portal.css?v=20261102-1" />
|
||||
|
||||
<!-- 登录资料仅在 HTML 属性中输出并转义;放在 Vue 挂载区域外,避免名称被当作模板表达式解析。 -->
|
||||
<div id="v4-home-profile-data" hidden
|
||||
|
||||
+14
-3
@@ -82,6 +82,7 @@ layout("/layouts/platform.html"){
|
||||
</el-popover>
|
||||
</table-tool>
|
||||
<el-table
|
||||
ref="memberTableRef"
|
||||
:data="tableData"
|
||||
style="width: 100%"
|
||||
stripe
|
||||
@@ -102,12 +103,12 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column
|
||||
align="center"
|
||||
header-align="center"
|
||||
v-for="column in tableColumns"
|
||||
v-for="column in showColumns"
|
||||
:key="column.prop"
|
||||
show-overflow-tooltip
|
||||
v-if="checkedFields.includes(column.prop)"
|
||||
:label="column.label"
|
||||
:prop="column.prop"
|
||||
:width="column.width"
|
||||
:min-width="column.width || 120"
|
||||
:fixed="column.fixed"
|
||||
:sortable="column.sortable"
|
||||
>
|
||||
@@ -268,6 +269,16 @@ layout("/layouts/platform.html"){
|
||||
this.checkedFields = all.filter(p => !this.checkedFields.includes(p));
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
checkedFields() {
|
||||
// 可见列更新后重新计算列宽,保证右侧固定操作列与表头、数据行对齐。
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.memberTableRef) {
|
||||
this.$refs.memberTableRef.doLayout()
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showColumns() {
|
||||
return this.tableColumns.filter(c => this.checkedFields.includes(c.prop));
|
||||
|
||||
Reference in New Issue
Block a user