Merge remote-tracking branch 'origin/main'

This commit is contained in:
@jyuhsin
2025-12-17 08:56:47 +08:00
12 changed files with 422 additions and 167 deletions
@@ -106,6 +106,14 @@ public class WelfareSelectionSituationController {
situationService.exportXlsx(pageForm, response);
}
@At
@SaCheckPermission("welfare.selection.situation")
@Ok("void")
@ApiOperation("导出Excel")
public void receiveXlsx(@Valid @Param("pageForm") WelfareSelectionSituationPageForm pageForm, HttpServletResponse response) {
situationService.receiveXlsx(pageForm, response);
}
@At
@SaCheckLogin
public Result getMobileByUserId(String userId) {
@@ -12,5 +12,6 @@ public interface WelfareSelectionSituationService extends BaseService<WelfareLis
Pagination pageData(WelfareSelectionSituationPageForm pageForm);
void exportXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response);
void receiveXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response);
}
@@ -16,13 +16,12 @@ import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -42,7 +41,7 @@ public class WelfareProjectServiceImpl extends BaseServiceImpl<WelfareProject> i
@Override
public WelfareProject projectInfo(String projectId) {
WelfareProject project = fetch(projectId);
fetchLinks(project, "options",Cnd.NEW().asc("optionSort"));
fetchLinks(project, "options", Cnd.NEW().asc("optionSort"));
return project;
}
@@ -63,9 +62,27 @@ public class WelfareProjectServiceImpl extends BaseServiceImpl<WelfareProject> i
public void updateProject(WelfareProject project) {
// 更新项目
update(project);
dao().clear(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", project.getId()));
List<WelfareProjectSubjectOption> optionList = dao().query(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", project.getId()));
List<String> dbOptionIds = optionList.stream()
.map(WelfareProjectSubjectOption::getId)
.toList();
// 2. 获取 project 中的所有选项 ID(注意 null 安全)
List<String> projectOptionIds = project.getOptions() == null ?
Collections.emptyList() :
project.getOptions().stream()
.map(WelfareProjectSubjectOption::getId)
.filter(Objects::nonNull) // 避免 null id
.toList();
// 3. 找出需要删除的 ID:在 db 中但不在 project 中
List<String> toDeleteIds = dbOptionIds.stream()
.filter(id -> !projectOptionIds.contains(id))
.collect(Collectors.toList());
// 4. 批量删除
if (!toDeleteIds.isEmpty()) {
dao().clear(WelfareProjectSubjectOption.class,
Cnd.where(WelfareProjectSubjectOption::getId, "in", toDeleteIds));
}
// 新增或更新选项
for (WelfareProjectSubjectOption option : project.getOptions()) {
option.setWelfareId(project.getId());
dao().insertOrUpdate(option);
@@ -1,33 +1,45 @@
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;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.excel.export.ExcelExportService;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.sys.models.Sys_file;
import com.budwk.app.sys.services.SysFileService;
import com.budwk.app.sys.utils.SysFileMinIoUtil;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.welfare.model.WelfareList;
import com.budwk.app.zhgh.welfare.model.WelfareProject;
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.Workbook;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.stream.Collectors;
@IocBean(args = {"refer:dao"})
@Slf4j
@@ -36,6 +48,9 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
super(dao);
}
@Inject
private SysFileService sysFileService;
@Override
public Pagination pageData(WelfareSelectionSituationPageForm pageForm) {
Sql sql = Sqls.create("""
@@ -46,7 +61,7 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
t1.welfareUnionName,
t1.welfareUnitName,
t1.welfareUnitId,
GROUP_CONCAT(DISTINCT t3.optionName) AS selectedOptions,
GROUP_CONCAT(DISTINCT t3.optionName ,'',t2.selectNum,'份)') AS selectedOptions,
GROUP_CONCAT(DISTINCT t2.mobile) AS mobile,
GROUP_CONCAT(DISTINCT t2.receiveAddress) AS receiveAddress,
t4.username AS userName,
@@ -105,7 +120,7 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
t1.id,
t1.welfareUnionName,
t1.welfareUnitName,
GROUP_CONCAT(DISTINCT t3.optionName) AS selectedOptions,
GROUP_CONCAT(DISTINCT t3.optionName,'',t2.selectNum,'份)') AS selectedOptions,
GROUP_CONCAT(DISTINCT t2.mobile) AS mobile,
GROUP_CONCAT(DISTINCT t2.receiveAddress) AS receiveAddress,
t4.username AS userName,
@@ -183,4 +198,84 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
log.error("导出Excel失败", e);
}
}
@Override
public void receiveXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response) {
Sql sql = Sqls.create("""
SELECT
t1.*,
t2.userSign,
t3.username userName,
t3.loginname loginName,
GROUP_CONCAT(DISTINCT t2.selectOptionId) AS selectOptionIds
FROM
welfare_list t1
LEFT JOIN welfare_project_user_selection t2 ON t2.welfareId = t1.projectId
AND t2.selectUserId = t1.userId
LEFT JOIN sys_user t3 ON t3.id = t1.userId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t1.projectId", "=", pageForm.getProjectId());
cnd.groupBy("t1.id");
cnd.asc("t1.welfareUnitId");
sql.setCondition(cnd);
List<NutMap> list = listMap(sql);
List<WelfareProjectSubjectOption> optionList = dao().query(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", pageForm.getProjectId()).asc("optionSort"));
for (NutMap map : list) {
if (map.get("selectOptionIds") != null){
String[] selectOptionIds = map.getString("selectOptionIds").split(",");
for (WelfareProjectSubjectOption option : optionList) {
if(Arrays.asList(selectOptionIds).contains(option.getId())){
map.put(option.getOptionName(), "");
}
}
}
if (map.get("userSign") != null){
try {
Sys_file file = dao().fetch(Sys_file.class, Cnd.where(Sys_file::getDownloadPath, "=", map.getString("userSign")));
byte[] userSignBytes = SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath());
map.put("userSign", userSignBytes);
}catch (Exception e){
e.printStackTrace();
log.error("下载图片失败", e);
}
}
}
List<Map<String, Object>> safeList = list.stream().map(nutMap -> {
Map<String, Object> map = new HashMap<>(nutMap);
return map;
}).toList();
// 分组
Map<String, List<Map<String, Object>>> listMap = safeList.stream()
.collect(Collectors.groupingBy(n -> (String) n.get("welfareUnionName")));
// 构建 Excel 列
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("工号", "loginName", 20));
entities.add(new ExcelExportEntity("姓名", "userName", 20));
optionList.forEach(option -> {
entities.add(new ExcelExportEntity(option.getOptionName(), option.getOptionName(), 20));
});
ExcelExportEntity userSignEntity = new ExcelExportEntity("签字", "userSign", 20);
userSignEntity.setType(2);
userSignEntity.setExportImageType(2);
entities.add(userSignEntity);
// 导出
Workbook workbook = new HSSFWorkbook();
listMap.forEach((k, v) -> {
ExcelExportService service = new ExcelExportService();
ExportParams exportParams = new ExportParams();
exportParams.setSheetName(k);
exportParams.setType(ExcelType.HSSF);
service.createSheetForMap(workbook, exportParams, entities, v);
});
CommonDownloadUtil.download("领取表.xls", workbook, response);
}
}
@@ -97,11 +97,12 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
for (NutMap union : mapUnions) {
// 福利人数
long teacherSum = welfareSelectionList.stream().filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId", "").equals(union.getString("id"))).count();
long teacherSum = welfareSelectionList.stream().filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId", "").equals(union.getString("id"))).count();
union.put("teacherSum", teacherSum);
// 已选人数
long selectedNum = welfareSelectionList.stream().filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId", "").equals(union.getString("id")) && v.getBoolean("has_selected")).count();
long selectedNum = welfareSelectionList.stream().filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId", "").equals(union.getString("id")) && v.getBoolean("has_selected")).count();
union.put("selectedNum", selectedNum);
// 未选人数
@@ -109,8 +110,25 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
// 各选项的选择人数
for (WelfareProjectSubjectOption option : welfareOptions) {
long count = userSelections.stream().filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId").equals(union.getString("id")) && StrUtil.isNotBlank(v.getString("selectOptionId")) && v.getString("selectOptionId").equals(option.getId())).map(v -> v.getString("selectUserId")).distinct().count();
union.put(option.getId(), count);
int total = userSelections.stream()
.filter(v ->
StrUtil.isNotBlank(v.getString("welfareUnionId"))
&& v.getString("welfareUnionId").equals(union.getString("id"))
&& StrUtil.isNotBlank(v.getString("selectOptionId"))
&& v.getString("selectOptionId").equals(option.getId())
&& StrUtil.isNotBlank(v.getString("selectUserId")) // 确保 userId 有效
)
.collect(Collectors.toMap(
v -> v.getString("selectUserId"),
v -> v,
(existing, replacement) -> existing // 保留第一个
// 不传第四个参数,默认用 HashMap
))
.values()
.stream()
.mapToInt(v -> v.getInt("selectNum"))
.sum();
union.put(option.getId(), total);
}
}
@@ -360,7 +378,7 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
exportEntities.add(new ExcelExportEntity("电话号码", "mobile", 20));
exportEntities.add(new ExcelExportEntity("所在分工会", "welfareUnionName", 20));
exportEntities.add(new ExcelExportEntity("所在单位", "welfareUnitName", 20));
exportEntities.add(new ExcelExportEntity("所在福利", "optionName", 50));
exportEntities.add(new ExcelExportEntity("所在福利", "selectOptionName", 50));
Sql sql = Sqls.create("""
SELECT
@@ -419,14 +437,22 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("分工会", "name", 20));
entities.add(new ExcelExportEntity("本次福利会员人数", "teacherSum", 20));
entities.add(new ExcelExportEntity("已选人数", "selectedNum", 20));
entities.add(new ExcelExportEntity("未选人数", "unSelectedNum", 20));
ExcelExportEntity teacherSumEntity = new ExcelExportEntity("本次福利会员人数", "teacherSum", 20);
teacherSumEntity.setType(10);
entities.add(teacherSumEntity);
ExcelExportEntity selectedNumEntity = new ExcelExportEntity("已选人数", "selectedNum", 20);
selectedNumEntity.setType(10);
entities.add(selectedNumEntity);
ExcelExportEntity unSelectedNumEntity = new ExcelExportEntity("未选人数", "unSelectedNum", 20);
unSelectedNumEntity.setType(10);
entities.add(unSelectedNumEntity);
// 选项数据
List<WelfareProjectSubjectOption> welfareOptions = dao().query(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", projectId));
for (WelfareProjectSubjectOption welfareOption : welfareOptions) {
entities.add(new ExcelExportEntity(welfareOption.getOptionName(), welfareOption.getId(), 20));
ExcelExportEntity entity = new ExcelExportEntity(welfareOption.getOptionName(), welfareOption.getId(), 20);
entity.setType(10);
entities.add(entity);
}
// 查询福利名单以及查询出选项数据
@@ -474,8 +500,25 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
// 各选项的选择人数
for (WelfareProjectSubjectOption option : welfareOptions) {
long count = userSelections.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id")) && v.getString("selectOptionId").equals(option.getId())).map(v -> v.getString("selectUserId")).distinct().count();
union.put(option.getId(), count);
int total = userSelections.stream()
.filter(v ->
StrUtil.isNotBlank(v.getString("welfareUnionId"))
&& v.getString("welfareUnionId").equals(union.getString("id"))
&& StrUtil.isNotBlank(v.getString("selectOptionId"))
&& v.getString("selectOptionId").equals(option.getId())
&& StrUtil.isNotBlank(v.getString("selectUserId")) // 确保 userId 有效
)
.collect(Collectors.toMap(
v -> v.getString("selectUserId"),
v -> v,
(existing, replacement) -> existing // 保留第一个
// 不传第四个参数,默认用 HashMap
))
.values()
.stream()
.mapToInt(v -> v.getInt("selectNum"))
.sum();
union.put(option.getId(), total);
}
}