bug
This commit is contained in:
@ -0,0 +1,60 @@
|
|||||||
|
package org.dromara.contractor.controller.app;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.common.excel.utils.ExcelUtil;
|
||||||
|
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||||
|
import org.dromara.common.log.annotation.Log;
|
||||||
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.contractor.domain.SubUserSalaryDetail;
|
||||||
|
import org.dromara.contractor.domain.dto.usersalarydetail.SubUserSalaryDetailQueryReq;
|
||||||
|
import org.dromara.contractor.domain.dto.usersalaryperiod.SubConstructionUserSalaryDto;
|
||||||
|
import org.dromara.contractor.domain.vo.usersalarydetail.SubUserSalaryDetailVo;
|
||||||
|
import org.dromara.contractor.domain.vo.usersalaryperiod.SubConstructionUserSalaryVo;
|
||||||
|
import org.dromara.contractor.service.ISubUserSalaryDetailService;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app工资
|
||||||
|
*
|
||||||
|
* @author lilemy
|
||||||
|
* @date 2025-09-04
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/app/contractor/userSalaryDetail")
|
||||||
|
public class SubUserSalaryDetailAppController extends BaseController {
|
||||||
|
|
||||||
|
private final ISubUserSalaryDetailService subUserSalaryDetailService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工资分页
|
||||||
|
*/
|
||||||
|
@GetMapping("/salaryPageList")
|
||||||
|
public TableDataInfo<SubConstructionUserSalaryVo> salaryPageList( SubConstructionUserSalaryDto dto, PageQuery pageQuery) {
|
||||||
|
return subUserSalaryDetailService.salaryPageList(dto, pageQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工资详情
|
||||||
|
*/
|
||||||
|
@GetMapping("/detailList")
|
||||||
|
public R<List<SubUserSalaryDetail>> detailList( SubConstructionUserSalaryDto dto) {
|
||||||
|
return R.ok(subUserSalaryDetailService.detailList(dto));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -100,4 +100,29 @@ public class SubConstructionUserSalaryVo implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String createTime;
|
private String createTime;
|
||||||
|
|
||||||
|
private Long createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人
|
||||||
|
*/
|
||||||
|
@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")
|
||||||
|
private String createByName;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发放时间
|
||||||
|
*/
|
||||||
|
private Long tim;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 班组id
|
||||||
|
*/
|
||||||
|
private Long teamId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 班组名
|
||||||
|
*/
|
||||||
|
private String teamName;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,6 +56,7 @@ import org.dromara.project.service.IBusAttendanceService;
|
|||||||
import org.dromara.project.service.IBusProjectService;
|
import org.dromara.project.service.IBusProjectService;
|
||||||
import org.dromara.project.service.IBusProjectTeamService;
|
import org.dromara.project.service.IBusProjectTeamService;
|
||||||
import org.dromara.project.service.IBusWorkWageService;
|
import org.dromara.project.service.IBusWorkWageService;
|
||||||
|
import org.dromara.project.service.impl.BusProjectTeamServiceImpl;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
@ -64,10 +65,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import software.amazon.awssdk.utils.CollectionUtils;
|
import software.amazon.awssdk.utils.CollectionUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
@ -277,14 +275,13 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl<SubUserSalaryDet
|
|||||||
@Override
|
@Override
|
||||||
public TableDataInfo<SubConstructionUserSalaryVo> salaryPageList(SubConstructionUserSalaryDto dto, PageQuery pageQuery) {
|
public TableDataInfo<SubConstructionUserSalaryVo> salaryPageList(SubConstructionUserSalaryDto dto, PageQuery pageQuery) {
|
||||||
|
|
||||||
|
|
||||||
String time = dto.getTime();
|
String time = dto.getTime();
|
||||||
YearMonth parse = YearMonth.parse(time, DateTimeFormatter.ofPattern("yyyy-MM"));
|
YearMonth parse = YearMonth.parse(time, DateTimeFormatter.ofPattern("yyyy-MM"));
|
||||||
LocalDate start = parse.atDay(1);
|
LocalDate start = parse.atDay(1);
|
||||||
LocalDate end = parse.atEndOfMonth();
|
LocalDate end = parse.atEndOfMonth();
|
||||||
|
|
||||||
QueryWrapper<SubUserSalaryDetail> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<SubUserSalaryDetail> queryWrapper = new QueryWrapper<>();
|
||||||
queryWrapper.select("user_id", "SUM(work_hour) as workHour", "SUM(total_salary) as totalSalary","max(create_time) as createTime")
|
queryWrapper.select("user_id","max(team_id) as teamId","max(create_by) as createBy", "SUM(work_hour) as workHour", "SUM(total_salary) as totalSalary","max(create_time) as createTime")
|
||||||
.eq("project_id", dto.getProjectId())
|
.eq("project_id", dto.getProjectId())
|
||||||
.between("report_date", start, end)
|
.between("report_date", start, end)
|
||||||
.eq(dto.getTeamId()!=null,"team_id", dto.getTeamId())
|
.eq(dto.getTeamId()!=null,"team_id", dto.getTeamId())
|
||||||
@ -295,15 +292,24 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl<SubUserSalaryDet
|
|||||||
Page<SubUserSalaryDetail> result = this.page(pageQuery.build(), queryWrapper);
|
Page<SubUserSalaryDetail> result = this.page(pageQuery.build(), queryWrapper);
|
||||||
List<SubUserSalaryDetail> records = result.getRecords();
|
List<SubUserSalaryDetail> records = result.getRecords();
|
||||||
List<Long> userIds = records.stream().map(SubUserSalaryDetail::getUserId).toList();
|
List<Long> userIds = records.stream().map(SubUserSalaryDetail::getUserId).toList();
|
||||||
|
|
||||||
Map<Long, SubConstructionUser> collect = new HashMap<>();
|
Map<Long, SubConstructionUser> collect = new HashMap<>();
|
||||||
if(CollectionUtil.isNotEmpty(userIds)){
|
if(CollectionUtil.isNotEmpty(userIds)){
|
||||||
List<SubConstructionUser> subConstructionUsers = constructionUserService.list(Wrappers.lambdaQuery(SubConstructionUser.class)
|
List<SubConstructionUser> subConstructionUsers = constructionUserService.list(Wrappers.lambdaQuery(SubConstructionUser.class)
|
||||||
.in(SubConstructionUser::getSysUserId, userIds));
|
.in(SubConstructionUser::getSysUserId, userIds));
|
||||||
collect = subConstructionUsers.stream().collect(Collectors.toMap(SubConstructionUser::getSysUserId, vo -> vo));
|
collect = subConstructionUsers.stream().collect(Collectors.toMap(SubConstructionUser::getSysUserId, vo -> vo));
|
||||||
}
|
}
|
||||||
|
Set<Long> teamIds = records.stream().map(SubUserSalaryDetail::getTeamId).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
Map<Long, BusProjectTeam> teamMap = new HashMap<>();
|
||||||
|
if(CollectionUtil.isNotEmpty(teamIds)){
|
||||||
|
List<BusProjectTeam> busProjectTeams = projectTeamService.listByIds(teamIds);
|
||||||
|
teamMap = busProjectTeams.stream().collect(Collectors.toMap(BusProjectTeam::getId, vo -> vo));
|
||||||
|
}
|
||||||
ArrayList<SubConstructionUserSalaryVo> vos = new ArrayList<>();
|
ArrayList<SubConstructionUserSalaryVo> vos = new ArrayList<>();
|
||||||
for (SubUserSalaryDetail detail : records) {
|
for (SubUserSalaryDetail detail : records) {
|
||||||
SubConstructionUserSalaryVo vo = new SubConstructionUserSalaryVo();
|
SubConstructionUserSalaryVo vo = new SubConstructionUserSalaryVo();
|
||||||
|
vo.setCreateBy(detail.getCreateBy());
|
||||||
vo.setId(detail.getId());
|
vo.setId(detail.getId());
|
||||||
vo.setTime(dto.getTime());
|
vo.setTime(dto.getTime());
|
||||||
vo.setTotalSalary(detail.getTotalSalary());
|
vo.setTotalSalary(detail.getTotalSalary());
|
||||||
@ -311,6 +317,7 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl<SubUserSalaryDet
|
|||||||
vo.setWorkDay(detail.getWorkHour());
|
vo.setWorkDay(detail.getWorkHour());
|
||||||
vo.setProjectId(dto.getProjectId());
|
vo.setProjectId(dto.getProjectId());
|
||||||
vo.setUserId(detail.getUserId());
|
vo.setUserId(detail.getUserId());
|
||||||
|
vo.setTeamId(detail.getTeamId());
|
||||||
SubConstructionUser constructionUser = collect.get(detail.getUserId());
|
SubConstructionUser constructionUser = collect.get(detail.getUserId());
|
||||||
if(constructionUser != null){
|
if(constructionUser != null){
|
||||||
if(constructionUser.getSfzNumber() != null){
|
if(constructionUser.getSfzNumber() != null){
|
||||||
@ -319,6 +326,11 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl<SubUserSalaryDet
|
|||||||
vo.setUserName(constructionUser.getUserName());
|
vo.setUserName(constructionUser.getUserName());
|
||||||
vo.setYhkNumber(constructionUser.getYhkNumber());
|
vo.setYhkNumber(constructionUser.getYhkNumber());
|
||||||
vo.setYhkOpeningBank(constructionUser.getYhkOpeningBank());
|
vo.setYhkOpeningBank(constructionUser.getYhkOpeningBank());
|
||||||
|
|
||||||
|
}
|
||||||
|
BusProjectTeam projectTeam = teamMap.get(detail.getTeamId());
|
||||||
|
if(projectTeam != null){
|
||||||
|
vo.setTeamName(projectTeam.getTeamName());
|
||||||
}
|
}
|
||||||
vos.add(vo);
|
vos.add(vo);
|
||||||
}
|
}
|
||||||
@ -328,157 +340,162 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl<SubUserSalaryDet
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void export(HttpServletResponse response, SubConstructionUserSalaryDto dto) throws IOException {
|
public void export(HttpServletResponse response, SubConstructionUserSalaryDto dto) throws IOException {
|
||||||
// 1. 查询项目和人员数据
|
// 1. 查询项目信息并校验
|
||||||
BusProject project = projectService.getById(dto.getProjectId());
|
BusProject project = projectService.getById(dto.getProjectId());
|
||||||
if (project == null) {
|
if (project == null) {
|
||||||
throw new ServiceException("项目不存在");
|
throw new ServiceException("项目不存在");
|
||||||
}
|
}
|
||||||
// 2. 解析年月和查询薪资明细
|
|
||||||
|
// 2. 解析时间参数
|
||||||
YearMonth yearMonth = YearMonth.parse(dto.getTime(), DateTimeFormatter.ofPattern("yyyy-MM"));
|
YearMonth yearMonth = YearMonth.parse(dto.getTime(), DateTimeFormatter.ofPattern("yyyy-MM"));
|
||||||
LocalDate start = yearMonth.atDay(1);
|
LocalDate start = yearMonth.atDay(1);
|
||||||
LocalDate end = yearMonth.atEndOfMonth();
|
LocalDate end = yearMonth.atEndOfMonth();
|
||||||
|
|
||||||
|
// 3. 查询薪资明细数据
|
||||||
QueryWrapper<SubUserSalaryDetail> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<SubUserSalaryDetail> queryWrapper = new QueryWrapper<>();
|
||||||
queryWrapper.select("user_id", "SUM(work_hour) as workHour", "SUM(total_salary) as totalSalary","max(create_time) as createTime")
|
queryWrapper.select("user_id", "SUM(work_hour) as workHour", "SUM(total_salary) as totalSalary")
|
||||||
.eq("project_id", dto.getProjectId())
|
.eq("project_id", dto.getProjectId())
|
||||||
.between("report_date", start, end)
|
.between("report_date", start, end)
|
||||||
.eq(dto.getUserId()!=null,"user_id", dto.getUserId())
|
.eq(dto.getUserId() != null, "user_id", dto.getUserId())
|
||||||
.eq(dto.getTeamId()!=null,"team_id", dto.getTeamId())
|
.eq(dto.getTeamId() != null, "team_id", dto.getTeamId())
|
||||||
.like(StringUtils.isNotBlank(dto.getUserName()),"user_name", dto.getUserName())
|
.like(StringUtils.isNotBlank(dto.getUserName()), "user_name", dto.getUserName())
|
||||||
.groupBy("user_id");
|
.groupBy("user_id");
|
||||||
|
|
||||||
List<SubUserSalaryDetail> salaryDetailsList= baseMapper.selectList(queryWrapper);
|
List<SubUserSalaryDetail> salaryDetailsList = baseMapper.selectList(queryWrapper);
|
||||||
|
|
||||||
if (salaryDetailsList.isEmpty()) {
|
if (salaryDetailsList.isEmpty()) {
|
||||||
throw new ServiceException("暂无数据");
|
throw new ServiceException("暂无数据");
|
||||||
}
|
}
|
||||||
Map<Long, SubUserSalaryDetail> map = salaryDetailsList.stream().collect(Collectors.toMap(SubUserSalaryDetail::getUserId, vo -> vo));
|
|
||||||
|
|
||||||
|
|
||||||
List<Long> userIds = salaryDetailsList.stream().map(SubUserSalaryDetail::getUserId).toList();
|
|
||||||
|
|
||||||
|
|
||||||
|
// 4. 构建薪资数据映射
|
||||||
|
Map<Long, SubUserSalaryDetail> salaryMap = salaryDetailsList.stream()
|
||||||
|
.collect(Collectors.toMap(SubUserSalaryDetail::getUserId, vo -> vo));
|
||||||
|
|
||||||
|
// 5. 批量查询用户信息(只查必要字段)
|
||||||
|
Set<Long> userIds = salaryMap.keySet();
|
||||||
List<SubConstructionUser> userList = constructionUserService.lambdaQuery()
|
List<SubConstructionUser> userList = constructionUserService.lambdaQuery()
|
||||||
|
.select(SubConstructionUser::getSysUserId, SubConstructionUser::getTeamId, SubConstructionUser::getUserName
|
||||||
|
, SubConstructionUser::getYhkNumber, SubConstructionUser::getYhkOpeningBank)
|
||||||
.in(SubConstructionUser::getSysUserId, userIds)
|
.in(SubConstructionUser::getSysUserId, userIds)
|
||||||
.list();
|
.list();
|
||||||
|
|
||||||
// 3. 设置响应头(下载文件配置)
|
// 6. 预处理班组信息(解决null键问题)
|
||||||
|
// 使用-1L作为临时键替代null,避免groupingBy出现null键错误
|
||||||
|
Map<Long, List<SubConstructionUser>> teamUsersMap = userList.stream()
|
||||||
|
.collect(Collectors.groupingBy(user -> {
|
||||||
|
Long teamId = user.getTeamId();
|
||||||
|
return teamId != null ? teamId : -1L; // 关键修复:null键映射为-1
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 提取实际班组ID(排除-1)并计算数量
|
||||||
|
List<Long> teamIds = teamUsersMap.keySet().stream()
|
||||||
|
.filter(id -> !id.equals(-1L))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
int actualTeamCount = teamIds.size();
|
||||||
|
|
||||||
|
// 动态计算初始容量,避免HashMap扩容
|
||||||
|
Map<Long, String> teamNameMap = new HashMap<>((int) Math.ceil(actualTeamCount * 1.5));
|
||||||
|
|
||||||
|
// 批量查询班组名称
|
||||||
|
if (!teamIds.isEmpty()) {
|
||||||
|
List<BusProjectTeam> teams = projectTeamService.lambdaQuery()
|
||||||
|
.select(BusProjectTeam::getId, BusProjectTeam::getTeamName)
|
||||||
|
.in(BusProjectTeam::getId, teamIds)
|
||||||
|
.list();
|
||||||
|
teams.forEach(team -> teamNameMap.put(team.getId(), team.getTeamName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 检查班组数量阈值
|
||||||
|
int maxSheetThreshold = 100; // 根据实际情况调整
|
||||||
|
if (actualTeamCount > maxSheetThreshold) {
|
||||||
|
log.warn("班组数量过多({}个),可能导致Excel文件过大或导出缓慢", actualTeamCount);
|
||||||
|
// 若需严格限制,可在此处抛出异常
|
||||||
|
// throw new ServiceException("班组数量超过限制,最多支持" + maxSheetThreshold + "个");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 设置响应头
|
||||||
setResponseHeader(response, yearMonth.getYear(), yearMonth.getMonthValue());
|
setResponseHeader(response, yearMonth.getYear(), yearMonth.getMonthValue());
|
||||||
|
|
||||||
// 5. 读取模板文件到字节数组(复用模板)
|
// 9. 读取模板文件(缓冲流优化)
|
||||||
byte[] templateBytes;
|
byte[] templateBytes;
|
||||||
try (InputStream templateStream = Thread.currentThread().getContextClassLoader()
|
try (InputStream templateStream = Thread.currentThread().getContextClassLoader()
|
||||||
.getResourceAsStream("excelTemplate/salary_template.xlsx")) {
|
.getResourceAsStream("excelTemplate/salary_template.xlsx");
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(templateStream);
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||||
|
|
||||||
if (templateStream == null) {
|
if (templateStream == null) {
|
||||||
throw new ServiceException("模板文件不存在(路径:excelTemplate/salary_template.xlsx)");
|
throw new ServiceException("模板文件不存在(路径:excelTemplate/salary_template.xlsx)");
|
||||||
}
|
}
|
||||||
templateBytes = IOUtils.toByteArray(templateStream);
|
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = bis.read(buffer)) != -1) {
|
||||||
|
baos.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
templateBytes = baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. POI 处理多 sheet(核心:克隆模板 + 命名)
|
// 10. POI处理多Sheet(核心逻辑)
|
||||||
// 存储 <sheet名称, sheet对象> 映射,方便后续 EasyExcel 匹配
|
|
||||||
Map<String, Sheet> sheetMap = new LinkedHashMap<>();
|
|
||||||
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(templateBytes));
|
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(templateBytes));
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||||
|
|
||||||
// 校验模板是否有有效 sheet
|
|
||||||
if (workbook.getNumberOfSheets() == 0) {
|
if (workbook.getNumberOfSheets() == 0) {
|
||||||
throw new ServiceException("模板文件中无任何 sheet 页,请检查模板");
|
throw new ServiceException("模板文件中无任何sheet页,请检查模板");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.1 预处理班组信息(获取班组ID + 班组名称映射)
|
int originalSheetIndex = 0;
|
||||||
List<Long> teamIds = userList.stream()
|
|
||||||
.map(SubConstructionUser::getTeamId)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.distinct()
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
Map<Long, String> teamNameMap = new HashMap<>();
|
|
||||||
if (!teamIds.isEmpty()) {
|
|
||||||
List<BusProjectTeam> teams = projectTeamService.lambdaQuery()
|
|
||||||
.in(BusProjectTeam::getId, teamIds)
|
|
||||||
.list();
|
|
||||||
teamNameMap = teams.stream()
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
BusProjectTeam::getId,
|
|
||||||
BusProjectTeam::getTeamName,
|
|
||||||
(oldVal, newVal) -> newVal // 避免重复ID冲突
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6.2 克隆模板:为每个班组生成 sheet(关键修正)
|
// 10.1 为每个班组创建sheet
|
||||||
for (Long teamId : teamIds) {
|
for (Long teamId : teamIds) {
|
||||||
// ① 克隆原始模板 sheet(返回克隆后的 Sheet 对象)
|
Sheet newSheet = workbook.cloneSheet(originalSheetIndex);
|
||||||
Sheet newSheet = workbook.cloneSheet(0);
|
|
||||||
// ② 生成班组名称(避免空名称)
|
|
||||||
String teamName = teamNameMap.getOrDefault(teamId, "未知班组_" + teamId);
|
String teamName = teamNameMap.getOrDefault(teamId, "未知班组_" + teamId);
|
||||||
// ③ 给新 sheet 命名(通过 sheet 对象获取索引)
|
|
||||||
int newSheetIndex = workbook.getSheetIndex(newSheet);
|
int newSheetIndex = workbook.getSheetIndex(newSheet);
|
||||||
workbook.setSheetName(newSheetIndex, teamName);
|
workbook.setSheetName(newSheetIndex, teamName);
|
||||||
// ④ 存入映射,方便后续填充
|
|
||||||
sheetMap.put(teamName, newSheet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.3 克隆模板:处理“无班组”数据(如果需要)
|
// 10.2 处理无班组数据(使用-1对应的用户列表)
|
||||||
boolean needNoTeamSheet = dto.getTeamId() == null;
|
boolean needNoTeamSheet = dto.getTeamId() == null && teamUsersMap.containsKey(-1L);
|
||||||
if (needNoTeamSheet) {
|
if (needNoTeamSheet) {
|
||||||
Sheet noTeamSheet = workbook.cloneSheet(0);
|
Sheet noTeamSheet = workbook.cloneSheet(originalSheetIndex);
|
||||||
String noTeamName = "无班组";
|
|
||||||
int noTeamSheetIndex = workbook.getSheetIndex(noTeamSheet);
|
int noTeamSheetIndex = workbook.getSheetIndex(noTeamSheet);
|
||||||
workbook.setSheetName(noTeamSheetIndex, noTeamName);
|
workbook.setSheetName(noTeamSheetIndex, "无班组");
|
||||||
sheetMap.put(noTeamName, noTeamSheet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.4 删除原始模板 sheet(避免最终文件保留空模板)
|
// 10.3 移除原始模板sheet
|
||||||
workbook.removeSheetAt(0);
|
workbook.removeSheetAt(originalSheetIndex);
|
||||||
|
|
||||||
// 6.5 将 POI 处理后的 workbook 写入字节数组,供 EasyExcel 使用
|
// 10.4 写入并关闭workbook
|
||||||
workbook.write(bos);
|
workbook.write(bos);
|
||||||
|
workbook.close();
|
||||||
byte[] workbookBytes = bos.toByteArray();
|
byte[] workbookBytes = bos.toByteArray();
|
||||||
|
|
||||||
// 7. EasyExcel 填充数据(按 sheet 映射顺序填充)
|
// 11. EasyExcel填充数据
|
||||||
try (InputStream workbookStream = new ByteArrayInputStream(workbookBytes);
|
try (InputStream workbookStream = new ByteArrayInputStream(workbookBytes);
|
||||||
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
|
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
|
||||||
.withTemplate(workbookStream)
|
.withTemplate(workbookStream)
|
||||||
.build()) {
|
.build()) {
|
||||||
|
|
||||||
// 7.1 填充“班组”sheet 数据
|
FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();
|
||||||
for (Map.Entry<String, Sheet> entry : sheetMap.entrySet()) {
|
|
||||||
String sheetName = entry.getKey();
|
|
||||||
// 跳过“无班组”sheet,后续单独处理
|
|
||||||
if ("无班组".equals(sheetName)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 根据 sheet 名称反查班组ID(用于过滤数据)
|
|
||||||
Long teamId = teamNameMap.entrySet().stream()
|
|
||||||
.filter(e -> sheetName.equals(e.getValue()))
|
|
||||||
.map(Map.Entry::getKey)
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
|
|
||||||
// 创建 EasyExcel 的 WriteSheet(通过名称匹配 sheet)
|
// 11.1 填充各班组数据
|
||||||
WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
|
for (Long teamId : teamIds) {
|
||||||
FillConfig fillConfig = FillConfig.builder()
|
String teamName = teamNameMap.getOrDefault(teamId, "未知班组_" + teamId);
|
||||||
.forceNewRow(true) // 强制新增行,不覆盖模板内容
|
WriteSheet writeSheet = EasyExcel.writerSheet(teamName).build();
|
||||||
.build();
|
// 使用提前分组好的数据
|
||||||
|
excelWriter.fill(getTeamData(teamUsersMap.get(teamId), salaryMap, teamId), fillConfig, writeSheet);
|
||||||
// 填充列表数据和汇总数据
|
excelWriter.fill(getTeamSummary(project, teamName, yearMonth), writeSheet);
|
||||||
excelWriter.fill(getTeamData(userList, map, teamId), fillConfig, writeSheet);
|
|
||||||
excelWriter.fill(getTeamSummary(project, teamNameMap.get(teamId), yearMonth), writeSheet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.2 填充“无班组”sheet 数据
|
// 11.2 填充无班组数据
|
||||||
if (needNoTeamSheet) {
|
if (needNoTeamSheet) {
|
||||||
WriteSheet noTeamSheet = EasyExcel.writerSheet("无班组").build();
|
WriteSheet noTeamSheet = EasyExcel.writerSheet("无班组").build();
|
||||||
FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();
|
excelWriter.fill(getTeamData(teamUsersMap.get(-1L), salaryMap, null), fillConfig, noTeamSheet);
|
||||||
|
|
||||||
excelWriter.fill(getTeamData(userList, map, null), fillConfig, noTeamSheet);
|
|
||||||
excelWriter.fill(getTeamSummary(project, null, yearMonth), noTeamSheet);
|
excelWriter.fill(getTeamSummary(project, null, yearMonth), noTeamSheet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置响应头信息
|
* 设置响应头信息
|
||||||
*/
|
*/
|
||||||
@ -497,15 +514,15 @@ public class SubUserSalaryDetailServiceImpl extends ServiceImpl<SubUserSalaryDet
|
|||||||
|
|
||||||
private List<SubConstructionUserSalaryVo> getTeamData(List<SubConstructionUser> rows,
|
private List<SubConstructionUserSalaryVo> getTeamData(List<SubConstructionUser> rows,
|
||||||
Map<Long, SubUserSalaryDetail> map,Long teamId){
|
Map<Long, SubUserSalaryDetail> map,Long teamId){
|
||||||
List<SubConstructionUser> list1 ;
|
// List<SubConstructionUser> list1 ;
|
||||||
if(teamId == null){
|
// if(teamId == null){
|
||||||
list1 = rows.stream().filter(row -> row.getTeamId() == null && Arrays.asList("1","2").contains(row.getExitStatus())).toList();
|
// list1 = rows.stream().filter(row -> row.getTeamId() == null && Arrays.asList("1","2").contains(row.getExitStatus())).toList();
|
||||||
}else {
|
// }else {
|
||||||
list1 = rows.stream().filter(row -> teamId.equals(row.getTeamId())).toList();
|
// list1 = rows.stream().filter(row -> teamId.equals(row.getTeamId())).toList();
|
||||||
}
|
// }
|
||||||
ArrayList<SubConstructionUserSalaryVo> vos = new ArrayList<>();
|
ArrayList<SubConstructionUserSalaryVo> vos = new ArrayList<>();
|
||||||
int i =1;
|
int i =1;
|
||||||
for (SubConstructionUser row : list1) {
|
for (SubConstructionUser row : rows) {
|
||||||
SubConstructionUserSalaryVo vo = new SubConstructionUserSalaryVo();
|
SubConstructionUserSalaryVo vo = new SubConstructionUserSalaryVo();
|
||||||
BeanUtil.copyProperties(row,vo);
|
BeanUtil.copyProperties(row,vo);
|
||||||
vo.setOrder(i);
|
vo.setOrder(i);
|
||||||
|
|||||||
@ -0,0 +1,70 @@
|
|||||||
|
package org.dromara.cory.controller.app;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.common.core.validate.AddGroup;
|
||||||
|
import org.dromara.common.core.validate.EditGroup;
|
||||||
|
import org.dromara.common.excel.utils.ExcelUtil;
|
||||||
|
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||||
|
import org.dromara.common.log.annotation.Log;
|
||||||
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.cory.domain.bo.BusContactnoticeBo;
|
||||||
|
import org.dromara.cory.domain.dto.BusContactnoticeAppDto;
|
||||||
|
import org.dromara.cory.domain.vo.BusContactnoticeVo;
|
||||||
|
import org.dromara.cory.service.IBusContactnoticeService;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APP联系单
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
* @date 2025-07-03
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/app/cory/contactnotice")
|
||||||
|
public class BusContactnoticeAppController extends BaseController {
|
||||||
|
|
||||||
|
private final IBusContactnoticeService busContactnoticeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询联系单列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<BusContactnoticeVo> list(BusContactnoticeAppDto dto, PageQuery pageQuery) {
|
||||||
|
return busContactnoticeService.queryAppPageList(dto, pageQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取联系单详细信息
|
||||||
|
*
|
||||||
|
* @param id 主键
|
||||||
|
*/
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public R<BusContactnoticeVo> getInfo(@NotNull(message = "主键不能为空")
|
||||||
|
@PathVariable Long id) {
|
||||||
|
return R.ok(busContactnoticeService.queryById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增联系单
|
||||||
|
*/
|
||||||
|
@Log(title = "联系单", businessType = BusinessType.INSERT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PostMapping()
|
||||||
|
public R<BusContactnoticeVo> add(@Validated(AddGroup.class) @RequestBody BusContactnoticeBo bo) {
|
||||||
|
return R.ok(busContactnoticeService.insertByBo(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package org.dromara.cory.domain.dto;
|
||||||
|
|
||||||
|
import io.github.linpeilie.annotations.AutoMapper;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.dromara.common.core.validate.AddGroup;
|
||||||
|
import org.dromara.common.core.validate.EditGroup;
|
||||||
|
import org.dromara.common.core.validate.QueryGroup;
|
||||||
|
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||||
|
import org.dromara.cory.domain.BusContactnotice;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系单业务对象 bus_contactnotice
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
* @date 2025-07-03
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BusContactnoticeAppDto extends BaseEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目ID
|
||||||
|
*/
|
||||||
|
private Long projectId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板类型
|
||||||
|
*/
|
||||||
|
private Long type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询参数
|
||||||
|
*/
|
||||||
|
private String queryParam;
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package org.dromara.cory.service;
|
|||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
import org.dromara.cory.domain.bo.BusContactnoticeBo;
|
import org.dromara.cory.domain.bo.BusContactnoticeBo;
|
||||||
|
import org.dromara.cory.domain.dto.BusContactnoticeAppDto;
|
||||||
import org.dromara.cory.domain.vo.BusContactnoticeVo;
|
import org.dromara.cory.domain.vo.BusContactnoticeVo;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -65,4 +66,9 @@ public interface IBusContactnoticeService {
|
|||||||
* @return 是否删除成功
|
* @return 是否删除成功
|
||||||
*/
|
*/
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app列表
|
||||||
|
*/
|
||||||
|
TableDataInfo<BusContactnoticeVo> queryAppPageList(BusContactnoticeAppDto dto, PageQuery pageQuery);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
package org.dromara.cory.service.impl;
|
package org.dromara.cory.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
|
import cn.hutool.core.stream.StreamUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
@ -19,12 +21,14 @@ import org.dromara.common.mybatis.core.page.PageQuery;
|
|||||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
import org.dromara.cory.domain.BusContactnotice;
|
import org.dromara.cory.domain.BusContactnotice;
|
||||||
import org.dromara.cory.domain.bo.BusContactnoticeBo;
|
import org.dromara.cory.domain.bo.BusContactnoticeBo;
|
||||||
|
import org.dromara.cory.domain.dto.BusContactnoticeAppDto;
|
||||||
import org.dromara.cory.domain.vo.BusContactnoticeVo;
|
import org.dromara.cory.domain.vo.BusContactnoticeVo;
|
||||||
import org.dromara.cory.mapper.BusContactnoticeMapper;
|
import org.dromara.cory.mapper.BusContactnoticeMapper;
|
||||||
import org.dromara.cory.service.IBusContactnoticeService;
|
import org.dromara.cory.service.IBusContactnoticeService;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -158,6 +162,28 @@ public class BusContactnoticeServiceImpl implements IBusContactnoticeService {
|
|||||||
return baseMapper.deleteByIds(ids) > 0;
|
return baseMapper.deleteByIds(ids) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableDataInfo<BusContactnoticeVo> queryAppPageList(BusContactnoticeAppDto dto, PageQuery pageQuery) {
|
||||||
|
LambdaQueryWrapper<BusContactnotice> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(BusContactnotice::getProjectId, dto.getProjectId());
|
||||||
|
lqw.eq(BusContactnotice::getType, dto.getType());
|
||||||
|
// 处理查询参数(避免空值)
|
||||||
|
String queryParam = dto.getQueryParam();
|
||||||
|
if (StrUtil.isNotBlank(queryParam)) {
|
||||||
|
// 使用JSON函数+参数绑定,避免SQL注入
|
||||||
|
lqw.and(wrapper -> wrapper
|
||||||
|
// 对volumeNumber进行模糊查询
|
||||||
|
.apply("detail->>'$.volumeNumber' LIKE CONCAT('%', {0}, '%')", queryParam)
|
||||||
|
// 或对volumeName进行模糊查询
|
||||||
|
.or()
|
||||||
|
.apply("detail->>'$.volumeName' LIKE CONCAT('%', {0}, '%')", queryParam)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Page<BusContactnoticeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||||
|
|
||||||
|
return TableDataInfo.build(result);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
|
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
|
||||||
* 正常使用只需#processEvent.flowCode=='leave1'
|
* 正常使用只需#processEvent.flowCode=='leave1'
|
||||||
|
|||||||
@ -0,0 +1,143 @@
|
|||||||
|
package org.dromara.design.controller.app;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.common.core.enums.BusinessStatusEnum;
|
||||||
|
import org.dromara.common.core.validate.AddGroup;
|
||||||
|
import org.dromara.common.core.validate.EditGroup;
|
||||||
|
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||||
|
import org.dromara.common.log.annotation.Log;
|
||||||
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.design.domain.DesVolumeFile;
|
||||||
|
import org.dromara.design.domain.dto.designchange.DesDesignChangeCreateReq;
|
||||||
|
import org.dromara.design.domain.dto.designchange.DesDesignChangeQueryReq;
|
||||||
|
import org.dromara.design.domain.dto.designchange.DesDesignChangeUpdateReq;
|
||||||
|
import org.dromara.design.domain.vo.designchange.DesDesignChangeVo;
|
||||||
|
import org.dromara.design.domain.vo.volumecatalog.DesVolumeCatalogVo;
|
||||||
|
import org.dromara.design.service.IDesDesignChangeService;
|
||||||
|
import org.dromara.design.service.IDesVolumeCatalogService;
|
||||||
|
import org.dromara.design.service.IDesVolumeFileService;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设计变更管理
|
||||||
|
*
|
||||||
|
* @author lilemy
|
||||||
|
* @date 2025-07-03
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/app/design/designChange")
|
||||||
|
public class DesDesignChangeAppController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IDesDesignChangeService desDesignChangeService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IDesVolumeCatalogService desVolumeCatalogService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IDesVolumeFileService desVolumeFileService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设计变更管理列表
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("design:designChange:list")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<DesDesignChangeVo> list(DesDesignChangeQueryReq req, PageQuery pageQuery) {
|
||||||
|
return desDesignChangeService.queryPageList(req, pageQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据主键导出设计变更单
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("design:designChange:exportWord")
|
||||||
|
@Log(title = "设计变更管理", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/export/word")
|
||||||
|
public void exportWordById(@NotNull(message = "主键不能为空") Long id,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
desDesignChangeService.exportWordById(id, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设计变更管理详细信息
|
||||||
|
*
|
||||||
|
* @param id 主键
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("design:designChange:query")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public R<DesDesignChangeVo> getInfo(@NotNull(message = "主键不能为空")
|
||||||
|
@PathVariable Long id) {
|
||||||
|
return R.ok(desDesignChangeService.queryById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增设计变更管理
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("design:designChange:add")
|
||||||
|
@Log(title = "设计变更管理", businessType = BusinessType.INSERT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PostMapping()
|
||||||
|
public R<DesDesignChangeVo> add(@Validated(AddGroup.class) @RequestBody DesDesignChangeCreateReq req) {
|
||||||
|
return R.ok(desDesignChangeService.insertByBo(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改设计变更管理
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("design:designChange:edit")
|
||||||
|
@Log(title = "设计变更管理", businessType = BusinessType.UPDATE)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping()
|
||||||
|
public R<DesDesignChangeVo> edit(@Validated(EditGroup.class) @RequestBody DesDesignChangeUpdateReq req) {
|
||||||
|
return R.ok(desDesignChangeService.updateByBo(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除设计变更管理
|
||||||
|
*
|
||||||
|
* @param ids 主键串
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("design:designChange:remove")
|
||||||
|
@Log(title = "设计变更管理", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
|
@PathVariable Long[] ids) {
|
||||||
|
return toAjax(desDesignChangeService.deleteByIds(List.of(ids)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询选择卷册目录
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("design:designChange:catalogList")
|
||||||
|
@GetMapping("/catalogList/{projectId}")
|
||||||
|
public R<List<DesVolumeCatalogVo>> catalogList(@PathVariable("projectId") Long projectId) {
|
||||||
|
return R.ok(desVolumeCatalogService.catalogList(projectId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询选择目录下的蓝图
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("design:designChange:blueprint")
|
||||||
|
@GetMapping("/blueprint/{volumeCatalogId}")
|
||||||
|
public R<List<DesVolumeFile>> blueprint(@PathVariable("volumeCatalogId") Long volumeCatalogId) {
|
||||||
|
List<DesVolumeFile> list = desVolumeFileService.list(Wrappers.lambdaQuery(DesVolumeFile.class)
|
||||||
|
.eq(DesVolumeFile::getVolumeCatalogId, volumeCatalogId)
|
||||||
|
.eq(DesVolumeFile::getType, DesVolumeFile.BLUEPRINT)
|
||||||
|
.eq(DesVolumeFile::getAuditStatus, BusinessStatusEnum.FINISH.getStatus()));
|
||||||
|
return R.ok(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
package org.dromara.design.controller.app;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaIgnore;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||||
|
import org.dromara.common.log.annotation.Log;
|
||||||
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.design.domain.bo.DesVolumeFileBo;
|
||||||
|
import org.dromara.design.domain.dto.volumefile.DesVolumeFileAppPageDto;
|
||||||
|
import org.dromara.design.domain.dto.volumefile.DesVolumeFileCreateReq;
|
||||||
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileAppVo;
|
||||||
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileCodeVo;
|
||||||
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileJoinVo;
|
||||||
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileVo;
|
||||||
|
import org.dromara.design.service.IDesVolumeFileService;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App图纸
|
||||||
|
*
|
||||||
|
* @author lilemy
|
||||||
|
* @date 2025-07-30
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/app/design/volumeFile")
|
||||||
|
public class DesVolumeFileAppController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IDesVolumeFileService desVolumeFileService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app图纸管理分页查询
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<DesVolumeFileAppVo> list(DesVolumeFileAppPageDto dto, PageQuery pageQuery) {
|
||||||
|
return desVolumeFileService.queryAppPageList(dto, pageQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package org.dromara.design.domain.dto.volumefile;
|
||||||
|
|
||||||
|
|
||||||
|
import io.github.linpeilie.annotations.AutoMapper;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.dromara.common.core.validate.AddGroup;
|
||||||
|
import org.dromara.common.core.validate.EditGroup;
|
||||||
|
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||||
|
import org.dromara.design.domain.DesVolumeFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卷册文件业务对象 des_volume_file
|
||||||
|
*
|
||||||
|
* @author lilemy
|
||||||
|
* @date 2025-08-19
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DesVolumeFileAppPageDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目ID
|
||||||
|
*/
|
||||||
|
private Long projectId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图纸类型(1-过程,3-蓝图,4-作废)
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询参数
|
||||||
|
*/
|
||||||
|
private String queryParam;
|
||||||
|
}
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
package org.dromara.design.domain.vo.volumefile;
|
||||||
|
|
||||||
|
import io.github.linpeilie.annotations.AutoMapper;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.dromara.common.translation.annotation.Translation;
|
||||||
|
import org.dromara.common.translation.constant.TransConstant;
|
||||||
|
import org.dromara.design.domain.DesVolumeFile;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卷册文件视图对象 des_volume_file
|
||||||
|
*
|
||||||
|
* @author lilemy
|
||||||
|
* @date 2025-07-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DesVolumeFileAppVo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卷册目录ID
|
||||||
|
*/
|
||||||
|
private Long volumeCatalogId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卷册号
|
||||||
|
*/
|
||||||
|
private String volumeNumber;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设计子项
|
||||||
|
*/
|
||||||
|
private String designSubitem;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件ID
|
||||||
|
*/
|
||||||
|
private Long fileId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件名
|
||||||
|
*/
|
||||||
|
private String fileName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(1正常 2变更)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 专业
|
||||||
|
*/
|
||||||
|
private String specialty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 专业
|
||||||
|
*/
|
||||||
|
@Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "specialty",other = "des_user_major")
|
||||||
|
private String specialtyName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图纸类型(1-过程,3-蓝图,4-作废)
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本号
|
||||||
|
*/
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态
|
||||||
|
*/
|
||||||
|
private String auditStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 负责人
|
||||||
|
*/
|
||||||
|
private String principal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 负责人
|
||||||
|
*/
|
||||||
|
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "principal")
|
||||||
|
private String principalName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资料名称
|
||||||
|
*/
|
||||||
|
private String documentName;
|
||||||
|
}
|
||||||
@ -62,7 +62,7 @@ public class DesVolumeFileVo implements Serializable {
|
|||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图纸类型(1-过程,2-变更,3-蓝图,4-作废)
|
* 图纸类型(1-过程,3-蓝图,4-作废)
|
||||||
*/
|
*/
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import org.apache.ibatis.annotations.Param;
|
|||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
import org.dromara.design.domain.DesVolumeFile;
|
import org.dromara.design.domain.DesVolumeFile;
|
||||||
import org.dromara.design.domain.bo.DesVolumeFileBo;
|
import org.dromara.design.domain.bo.DesVolumeFileBo;
|
||||||
|
import org.dromara.design.domain.dto.volumefile.DesVolumeFileAppPageDto;
|
||||||
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileAppVo;
|
||||||
import org.dromara.design.domain.vo.volumefile.DesVolumeFileJoinVo;
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileJoinVo;
|
||||||
import org.dromara.design.domain.vo.volumefile.DesVolumeFileVo;
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileVo;
|
||||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||||
@ -20,4 +22,7 @@ public interface DesVolumeFileMapper extends BaseMapperPlus<DesVolumeFile, DesVo
|
|||||||
|
|
||||||
|
|
||||||
Page<DesVolumeFileJoinVo> queryJoinPageList(@Param("page")Page<DesVolumeFileJoinVo> page, @Param("bo")DesVolumeFileBo bo);
|
Page<DesVolumeFileJoinVo> queryJoinPageList(@Param("page")Page<DesVolumeFileJoinVo> page, @Param("bo")DesVolumeFileBo bo);
|
||||||
|
|
||||||
|
|
||||||
|
Page<DesVolumeFileAppVo> queryAppPageList(@Param("page")Page<DesVolumeFileJoinVo> page, @Param("dto") DesVolumeFileAppPageDto dto);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,9 @@ import org.dromara.common.mybatis.core.page.PageQuery;
|
|||||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
import org.dromara.design.domain.DesVolumeFile;
|
import org.dromara.design.domain.DesVolumeFile;
|
||||||
import org.dromara.design.domain.bo.DesVolumeFileBo;
|
import org.dromara.design.domain.bo.DesVolumeFileBo;
|
||||||
|
import org.dromara.design.domain.dto.volumefile.DesVolumeFileAppPageDto;
|
||||||
import org.dromara.design.domain.dto.volumefile.DesVolumeFileCreateReq;
|
import org.dromara.design.domain.dto.volumefile.DesVolumeFileCreateReq;
|
||||||
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileAppVo;
|
||||||
import org.dromara.design.domain.vo.volumefile.DesVolumeFileCodeVo;
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileCodeVo;
|
||||||
import org.dromara.design.domain.vo.volumefile.DesVolumeFileJoinVo;
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileJoinVo;
|
||||||
import org.dromara.design.domain.vo.volumefile.DesVolumeFileVo;
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileVo;
|
||||||
@ -93,4 +95,9 @@ public interface IDesVolumeFileService extends IService<DesVolumeFile> {
|
|||||||
* 二维码获取卷册文件详细信息
|
* 二维码获取卷册文件详细信息
|
||||||
*/
|
*/
|
||||||
DesVolumeFileCodeVo getCodeInfo(Long id);
|
DesVolumeFileCodeVo getCodeInfo(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* app分页查询
|
||||||
|
*/
|
||||||
|
TableDataInfo<DesVolumeFileAppVo> queryAppPageList(DesVolumeFileAppPageDto dto, PageQuery pageQuery);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,8 +27,10 @@ import org.dromara.common.sse.utils.SseMessageUtils;
|
|||||||
import org.dromara.design.domain.DesVolumeCatalog;
|
import org.dromara.design.domain.DesVolumeCatalog;
|
||||||
import org.dromara.design.domain.DesVolumeFile;
|
import org.dromara.design.domain.DesVolumeFile;
|
||||||
import org.dromara.design.domain.bo.DesVolumeFileBo;
|
import org.dromara.design.domain.bo.DesVolumeFileBo;
|
||||||
|
import org.dromara.design.domain.dto.volumefile.DesVolumeFileAppPageDto;
|
||||||
import org.dromara.design.domain.dto.volumefile.DesVolumeFileCreateReq;
|
import org.dromara.design.domain.dto.volumefile.DesVolumeFileCreateReq;
|
||||||
import org.dromara.design.domain.vo.BusDrawingreviewReceiptsVo;
|
import org.dromara.design.domain.vo.BusDrawingreviewReceiptsVo;
|
||||||
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileAppVo;
|
||||||
import org.dromara.design.domain.vo.volumefile.DesVolumeFileCodeVo;
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileCodeVo;
|
||||||
import org.dromara.design.domain.vo.volumefile.DesVolumeFileJoinVo;
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileJoinVo;
|
||||||
import org.dromara.design.domain.vo.volumefile.DesVolumeFileVo;
|
import org.dromara.design.domain.vo.volumefile.DesVolumeFileVo;
|
||||||
@ -469,6 +471,12 @@ public class DesVolumeFileServiceImpl extends ServiceImpl<DesVolumeFileMapper, D
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableDataInfo<DesVolumeFileAppVo> queryAppPageList(DesVolumeFileAppPageDto dto, PageQuery pageQuery) {
|
||||||
|
Page<DesVolumeFileAppVo> result = baseMapper.queryAppPageList(pageQuery.build(), dto);
|
||||||
|
return TableDataInfo.build(result);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
|
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
|
||||||
* 正常使用只需#processEvent.flowCode=='leave1'
|
* 正常使用只需#processEvent.flowCode=='leave1'
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public class BusAttendanceController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 查询施工人员月份考勤列表
|
* 查询施工人员月份考勤列表
|
||||||
*/
|
*/
|
||||||
@SaCheckPermission("project:attendance:list")
|
// @SaCheckPermission("project:attendance:list")
|
||||||
@GetMapping("/list/month/byUserId")
|
@GetMapping("/list/month/byUserId")
|
||||||
public R<List<BusAttendanceMonthByUserIdVo>> listAttendanceMonthListByUserId(BusAttendanceMonthByUserIdReq req) {
|
public R<List<BusAttendanceMonthByUserIdVo>> listAttendanceMonthListByUserId(BusAttendanceMonthByUserIdReq req) {
|
||||||
return R.ok(busAttendanceService.listAttendanceMonthListByUserId(req));
|
return R.ok(busAttendanceService.listAttendanceMonthListByUserId(req));
|
||||||
|
|||||||
@ -7,11 +7,13 @@ import lombok.Data;
|
|||||||
import org.dromara.common.translation.annotation.Translation;
|
import org.dromara.common.translation.annotation.Translation;
|
||||||
import org.dromara.common.translation.constant.TransConstant;
|
import org.dromara.common.translation.constant.TransConstant;
|
||||||
import org.dromara.quality.domain.QltQualityConstructionLog;
|
import org.dromara.quality.domain.QltQualityConstructionLog;
|
||||||
|
import org.dromara.system.domain.vo.SysOssVo;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,8 +78,7 @@ public class QltQualityConstructionLogVo implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 附件列表
|
* 附件列表
|
||||||
*/
|
*/
|
||||||
@Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "file")
|
private List<SysOssVo> fileList;
|
||||||
private String fileList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建者
|
* 创建者
|
||||||
|
|||||||
@ -196,6 +196,13 @@ public class QltQualityConstructionLogServiceImpl extends ServiceImpl<QltQuality
|
|||||||
if (qualityConstructionLog == null) {
|
if (qualityConstructionLog == null) {
|
||||||
return qualityConstructionLogVo;
|
return qualityConstructionLogVo;
|
||||||
}
|
}
|
||||||
|
// 关联附件信息
|
||||||
|
String file = qualityConstructionLog.getFile();
|
||||||
|
if (StringUtils.isNotBlank(file)) {
|
||||||
|
List<Long> ossIdList = Arrays.stream(file.split(",")).map(Long::parseLong).toList();
|
||||||
|
List<SysOssVo> ossVoList = ossService.listByIds(ossIdList);
|
||||||
|
qualityConstructionLogVo.setFileList(ossVoList);
|
||||||
|
}
|
||||||
BeanUtils.copyProperties(qualityConstructionLog, qualityConstructionLogVo);
|
BeanUtils.copyProperties(qualityConstructionLog, qualityConstructionLogVo);
|
||||||
return qualityConstructionLogVo;
|
return qualityConstructionLogVo;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,4 +17,29 @@
|
|||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="queryAppPageList" resultType="org.dromara.design.domain.vo.volumefile.DesVolumeFileAppVo">
|
||||||
|
select f.id,
|
||||||
|
f.volume_catalog_id,
|
||||||
|
f.type,
|
||||||
|
f.status,
|
||||||
|
f.audit_status,
|
||||||
|
f.version,
|
||||||
|
f.file_id,
|
||||||
|
c.design_subitem,
|
||||||
|
c.specialty,
|
||||||
|
c.principal,
|
||||||
|
c.document_name,
|
||||||
|
c.volume_number,
|
||||||
|
o.url
|
||||||
|
from des_volume_file f
|
||||||
|
left join des_volume_catalog c on f.volume_catalog_id = c.design
|
||||||
|
left join sys_oss o on f.file_id = o.oss_id
|
||||||
|
where c.project_id = #{dto.projectId}
|
||||||
|
and f.type = #{dto.type}
|
||||||
|
<if test="dto.queryParam != null and dto.queryParam != '' ">
|
||||||
|
and (c.document_name like concat('%',#{dto.queryParam},'%') or c.volume_number like concat('%',#{dto.queryParam},'%'))
|
||||||
|
</if>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user