Merge branch 'dev' of http://git.znkjfw.com/ak/zn-cloud into crm-业绩目标

This commit is contained in:
aikai 2025-03-11 10:15:17 +08:00
commit 32309d2842
13 changed files with 265 additions and 42 deletions

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.bpm.controller.admin.definition;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@ -85,27 +86,31 @@ public class BpmProcessCcController {
PageResult<BpmProcessCcDO> pageResult = processCcService.getProcessCcPage(pageReqVO);
PageResult<BpmProcessCcRespVO> respVOPageResult = BeanUtils.toBean(pageResult, BpmProcessCcRespVO.class);
// 获取公司部门Map
Map<Long, DeptRespDTO> deptMap = convertMap(deptApi.getCompanyDept().getCheckedData(), DeptRespDTO::getId);
// 获取列表中所有用户组详情
List<BpmUserGroupDO> groupDOS = groupService.getUserGroupList(
respVOPageResult.getList().stream()
.flatMap(item -> item.getUserGroupId().stream())
.collect(Collectors.toSet()));
// 转换Map
Map<Long, String> groupNameMap = convertMap(groupDOS, BpmUserGroupDO::getId, BpmUserGroupDO::getName);
if (CollUtil.isNotEmpty(respVOPageResult.getList())) {
respVOPageResult.getList().forEach(data -> {
// 获取公司部门Map
Map<Long, DeptRespDTO> deptMap = convertMap(deptApi.getCompanyDept().getCheckedData(), DeptRespDTO::getId);
// 获取列表中所有用户组详情
List<BpmUserGroupDO> groupDOS = groupService.getUserGroupList(
respVOPageResult.getList().stream()
.flatMap(item -> item.getUserGroupId().stream())
.collect(Collectors.toSet()));
// 转换Map
Map<Long, String> groupNameMap = convertMap(groupDOS, BpmUserGroupDO::getId, BpmUserGroupDO::getName);
respVOPageResult.getList().forEach(data -> {
// 设置用户组名称
data.setGroupName(data.getUserGroupId().stream()
.map(groupNameMap::get)
.collect(Collectors.joining("")));
// 设置公司名称
data.setCompanyName(data.getCompanyDeptId().stream()
.map(item -> deptMap.get(item) != null ? deptMap.get(item).getName() : "")
.collect(Collectors.joining("")));
});
}
// 设置用户组名称
data.setGroupName(data.getUserGroupId().stream()
.map(groupNameMap::get)
.collect(Collectors.joining("")));
// 设置公司名称
data.setCompanyName(data.getCompanyDeptId().stream()
.map(item -> deptMap.get(item) != null ? deptMap.get(item).getName() : "")
.collect(Collectors.joining("")));
});
return success(respVOPageResult);
}
}

View File

@ -58,12 +58,14 @@ public class BpmOAImprestController {
BpmOAImprestDO imprest = imprestService.getImprest(id);
BpmOAImprestRespVO respVO = BpmOAImprestConvert.INSTANCE.convert(imprest);
if (respVO != null) {
// 获取收款账号信息
BankRespDTO bankRespDTO = bankApi.getBank(respVO.getBankId()).getCheckedData();
if (bankRespDTO != null) {
respVO.setBankName(bankRespDTO.getBankName());
respVO.setNickname(bankRespDTO.getNickname());
respVO.setBankNo(bankRespDTO.getBankNo());
if (respVO.getBankId() != null) {
// 获取收款账号信息
BankRespDTO bankRespDTO = bankApi.getBank(respVO.getBankId()).getCheckedData();
if (bankRespDTO != null) {
respVO.setBankName(bankRespDTO.getBankName());
respVO.setNickname(bankRespDTO.getNickname());
respVO.setBankNo(bankRespDTO.getBankNo());
}
}
// 获取公司信息

View File

@ -35,6 +35,7 @@
WHERE
a.deleted = 0
AND b.deleted = 0
AND b.result = 2
<if test="pageReqVO.userId != null">
AND b.user_id = #{pageReqVO.userId}
</if>

View File

@ -2,10 +2,8 @@ package cn.iocoder.yudao.module.system.controller.admin.worklog;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO;
@ -21,10 +19,20 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import cn.iocoder.yudao.module.system.service.worklog.LogInstanceService;
import cn.iocoder.yudao.module.system.service.worklog.LogReadService;
import cn.iocoder.yudao.module.system.service.worklog.LogUseService;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -33,10 +41,9 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -306,12 +313,69 @@ public class LogInstanceController {
@Operation(summary = "导出日志实例 Excel")
@PreAuthorize("@ss.hasPermission('system:log-instance:export')")
@OperateLog(type = EXPORT)
public void exportLogInstanceExcel(@Valid LogInstancePageReqVO pageReqVO,
public void exportLogInstanceExcel(@Valid LogExportVO reqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<LogInstanceRespVO> list = logInstanceService.getLogInstancePage(pageReqVO, null).getRecords();
// 导出 Excel
ExcelUtils.write(response, "日志实例的拓展.xls", "数据", LogInstanceRespVO.class,
BeanUtils.toBean(list, LogInstanceRespVO.class));
List<LogExportExcelVO> list = logInstanceService.getLogInstanceExport(reqVO);
// 输出excel
ExcelWriterBuilder writer = EasyExcel.write(response.getOutputStream(), LogExportExcelVO.class);
List<OnceAbsoluteMergeStrategy> strategies = getMergeStrategy(list);
strategies.forEach(writer::registerWriteHandler);
writer.autoCloseStream(false); // 不要自动关闭交给 Servlet 自己处理
writer.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()); // 基于 column 长度自动适配最大 255 宽度
writer.registerWriteHandler(new HorizontalCellStyleStrategy(getHeadStyle(), getContentStyle()));
writer.registerConverter(new LongStringConverter()); // 避免 Long 类型丢失精度
writer.excelType(ExcelTypeEnum.XLS);
writer.sheet("数据").doWrite(list);
// 设置 header contentType写在最后的原因是避免报错时响应 contentType 已经被修改了
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("日志实例的拓展.xls", StandardCharsets.UTF_8.name()));
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
// // 导出 Excel
// ExcelUtils.write(response, "日志实例的拓展.xls", "数据", LogExportExcelVO.class,
// list);
}
public static List<OnceAbsoluteMergeStrategy> getMergeStrategy(List<LogExportExcelVO> dataList) {
List<OnceAbsoluteMergeStrategy> strategies = new ArrayList<>();
List<Integer> mergeCols = Arrays.asList(0, 1); // 需要合并的列索引
// 遍历数据生成合并区间
for (int i = 0; i < dataList.size(); i++) {
if (i > 0 && dataList.get(i).getNickname().equals(dataList.get(i - 1).getNickname()) && dataList.get(i).getTime().equals(dataList.get(i - 1).getTime())) {
continue;
}
int startRow = i + 1;
while (i < dataList.size() - 1 && dataList.get(i).getNickname().equals(dataList.get(i + 1).getNickname()) && dataList.get(i).getTime().equals(dataList.get(i + 1).getTime())) {
i++;
}
for (int col : mergeCols) {
strategies.add(new OnceAbsoluteMergeStrategy(startRow, i + 1, col, col));
}
}
return strategies;
}
// 表头样式居中
public static WriteCellStyle getHeadStyle() {
WriteCellStyle headStyle = new WriteCellStyle();
headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
return headStyle;
}
// 内容样式居中
public static WriteCellStyle getContentStyle() {
WriteCellStyle contentStyle = new WriteCellStyle();
contentStyle.setWrapped(true); // 启用自动换行
contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
return contentStyle;
}
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.system.controller.admin.worklog.vo.loginstance;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* 日志Excel 导出 VO
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false避免用户导入有问题
public class LogExportExcelVO {
@ExcelProperty("用户名称")
private String nickname;
@ExcelProperty("日期")
private String time;
@ExcelProperty("标题")
private String title;
@ExcelProperty("内容")
private String content;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.system.controller.admin.worklog.vo.loginstance;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 日志实例导出 Response VO")
@Data
public class LogExportVO {
@Schema(description = "部门编号")
private Long companyDeptId;
@Schema(description = "日志模版编号")
private Long formId;
@Schema(description = "时间范围")
private String[] time;
}

View File

@ -41,6 +41,7 @@ import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import cn.iocoder.yudao.module.system.service.worklog.LogUseService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.annotations.VisibleForTesting;
@ -100,6 +101,9 @@ public class AdminUserServiceImpl implements AdminUserService {
@Resource
private FileApi fileApi;
@Resource
private LogUseService logUseService;
@Override
@Transactional(rollbackFor = Exception.class)
public void updateUserOpenId(Long id, String openId) {
@ -155,9 +159,14 @@ public class AdminUserServiceImpl implements AdminUserService {
userMapper.updateById(updateObj);
// 更新岗位
updateUserPost(updateReqVO, updateObj);
// 更新日志使用人信息
logUseService.updateUseDeptId(updateObj.getId(), updateObj.getDeptId());
}
private void updateUserPost(UserSaveReqVO reqVO, AdminUserDO updateObj) {
Long userId = reqVO.getId();
Set<Long> dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId);
// 计算新增和删除的岗位编号

View File

@ -92,4 +92,11 @@ public interface LogInstanceService {
* @return
*/
LogInstanceNextOrUpVO getNextOrUp(LogInstancePageReqVO dto, Long id, Integer pagingType);
/**
* 获取日志导出列表
* @param reqVO 请求参数
* @return 日志列表
*/
List<LogExportExcelVO> getLogInstanceExport(LogExportVO reqVO);
}

View File

@ -1,11 +1,13 @@
package cn.iocoder.yudao.module.system.service.worklog;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptRespVO;
import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.loginstance.*;
import cn.iocoder.yudao.module.system.convert.worklog.LogInstanceConvert;
@ -140,7 +142,8 @@ public class LogInstanceServiceImpl implements LogInstanceService {
List<LogReadUserRespDTO> respDTOS = logInstanceMapper.selectRaedUser(userId, adminUserDO.getDeptId());
//特殊情况 日志发起人为研发部时 手动添加查看者
if (adminUserDO.getDeptId() == 128L && adminUserDO.getId() != 126L) {
List<Long> deptIds = convertList(deptService.getChildDept(128L), DeptDO::getId);
if (deptIds.contains(adminUserDO.getDeptId()) && adminUserDO.getId() != 126L) {
LogReadUserRespDTO dto = new LogReadUserRespDTO();
dto.setUserId(126L);
@ -286,7 +289,7 @@ public class LogInstanceServiceImpl implements LogInstanceService {
item.setAvatar(userDO.getAvatar());
}
//设置日志内部分
//设置日志内部分an
LogFormDO logFormDO = formMap.get(item.getFormId());
List<String> fields = logFormDO.getFields();
StringBuilder workLogContent = new StringBuilder();
@ -445,6 +448,73 @@ public class LogInstanceServiceImpl implements LogInstanceService {
return vo;
}
@Override
public List<LogExportExcelVO> getLogInstanceExport(LogExportVO reqVO) {
// 获取所有部门及下级部门信息
List<DeptDO> deptDOS = deptService.getChildDept(reqVO.getCompanyDeptId());
List<LogInstanceDO> list = logInstanceMapper.selectList(new LambdaQueryWrapperX<LogInstanceDO>()
.inIfPresent(LogInstanceDO::getDeptId, convertList(deptDOS, DeptDO::getId))
.eqIfPresent(LogInstanceDO::getFormId, reqVO.getFormId())
.betweenIfPresent(LogInstanceDO::getTime, reqVO.getTime()));
List<LogExportExcelVO> result = new ArrayList<>();
if (CollUtil.isNotEmpty(list)) {
//模版ids过滤
Set<Long> workFormIds = list.stream().map(LogInstanceDO::getFormId).collect(Collectors.toSet());
// 查询模版列表
List<LogFormDO> formList = logFormService.getFormList(workFormIds);
Map<Long, LogFormDO> formMap = formList.stream().collect(Collectors.toMap(LogFormDO::getId, item -> item));
//查询用户信息列表
Set<Long> userIds = list.stream().map(LogInstanceDO::getStartUserId).collect(Collectors.toSet());
Map<Long, AdminUserDO> userMap = adminUserService.getUserMap(userIds);
//遍历
for (LogInstanceDO item : list) {
//设置日志内部分an
LogFormDO logFormDO = formMap.get(item.getFormId());
List<String> fields = logFormDO.getFields();
if (!item.getFormVariables().isEmpty()) {
JSONObject workLogContentJson = new JSONObject(item.getFormVariables());
for (String fieldItem : fields) {
JSONObject fieldJson = new JSONObject(fieldItem);
if ("upload".equals(fieldJson.getStr("type"))) {
continue;
}
String fieldStr = fieldJson.getStr("field");
String title = fieldJson.getStr("title");
if (fieldStr == null || title == null) {
continue;
}
String field = workLogContentJson.getStr(fieldStr);
LogExportExcelVO logExportExcelVO = new LogExportExcelVO();
// 设置时间
logExportExcelVO.setTime(item.getTime());
//设置发起人用户名称和头像
AdminUserDO userDO = userMap.get(item.getStartUserId());
if (userDO != null) {
logExportExcelVO.setNickname(userDO.getNickname());
}
logExportExcelVO.setTitle(title);
logExportExcelVO.setContent(field);
result.add(logExportExcelVO);
}
}
}
}
return result;
}
@Override
public List<LogInstanceDO> getNeedWriteLogInstanceByTimeRange(Long fromId, List<String> time, Long userId) {
return logInstanceMapper.selectList(new LambdaQueryWrapper<LogInstanceDO>()

View File

@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.worklog.LogFormMapper;
import cn.iocoder.yudao.module.system.dal.mysql.worklog.LogRuleMapper;
import cn.iocoder.yudao.module.system.service.worklog.dto.LogUseSaveReqDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -132,5 +133,4 @@ public class LogRuleServiceImpl implements LogRuleService {
return logRuleMapper.selectOne(new LambdaQueryWrapper<LogRuleDO>()
.eq(LogRuleDO::getFormId, formId));
}
}

View File

@ -74,4 +74,11 @@ public interface LogUseService {
* @return 模版列表
*/
List<Long> getFormIdList(List<Long> deptIds);
/**
* 更新日志规则使用部门id
* @param userId 用户编号
* @param deptId 部门编号
*/
void updateUseDeptId(Long userId, Long deptId);
}

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.dal.dataobject.worklog.LogUseDO;
import cn.iocoder.yudao.module.system.dal.mysql.worklog.LogUseMapper;
import cn.iocoder.yudao.module.system.service.worklog.dto.LogUseSaveReqDTO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -106,4 +107,12 @@ public class LogUseServiceImpl implements LogUseService {
List<LogUseDO> logUseDOS = logUseMapper.selectList(LogUseDO::getUseUserDept, deptIds);
return logUseDOS.stream().map(LogUseDO::getFormId).distinct().collect(Collectors.toList());
}
@Override
public void updateUseDeptId(Long userId, Long deptId) {
logUseMapper.update(null, new LambdaUpdateWrapper<LogUseDO>()
.set(LogUseDO::getUseUserDept, deptId)
.eq(LogUseDO::getUseUserId, userId));
}
}

View File

@ -116,8 +116,8 @@ public class StaffServiceImpl implements StaffService {
});
vo.setTotal(dos.size());
vo.setMaleTotal((int) dos.stream().filter(a -> a.getSex() == 0).count());
vo.setFemaleTotal((int) dos.stream().filter(a -> a.getSex() == 1).count());
vo.setMaleTotal((int) dos.stream().filter(a -> a.getSex() != null && a.getSex() == 0).count());
vo.setFemaleTotal((int) dos.stream().filter(a -> a.getSex() != null && a.getSex() == 1).count());
vo.setStaffInfos(dos);
return vo;
}