Compare commits

...

56 Commits

Author SHA1 Message Date
0126d44761 ws注解放开 2025-10-27 20:42:03 +08:00
dbefd88e41 添加客户详情权限 2025-10-27 20:09:39 +08:00
9a3b7ebe54 添加审核 2025-10-27 20:00:56 +08:00
81be4a862c 10-27-添加审核完善 2025-10-27 19:57:35 +08:00
lg
43f2db9f7e 审核数据添加 2025-10-27 19:51:55 +08:00
abefa90408 10-27-添加审核完善 2025-10-27 19:14:24 +08:00
08f48b7817 10-27-添加审核 2025-10-27 18:45:49 +08:00
lcj
6b8ace60d4 车辆管理,修改材料 2025-10-27 17:10:41 +08:00
lg
b997dd5f00 详情权限取消 2025-10-27 15:35:49 +08:00
6174743858 Merge remote-tracking branch 'origin/dev' into dev 2025-10-27 15:25:19 +08:00
82d55d7188 10-27-修改bug 2025-10-27 15:25:06 +08:00
lg
aec5eacd0b 采购详情权限取消 2025-10-27 15:25:04 +08:00
zt
a320b85965 考勤机 2025-10-27 15:14:29 +08:00
lg
b61a7c153d 投标文件-项目类型中文返回 2025-10-27 14:44:50 +08:00
fb9b01cf34 修改物资跟踪管理台账查询列表修改 2025-10-27 14:27:11 +08:00
lg
32f134873a 采购合同金额字段 2025-10-27 11:37:41 +08:00
f4220be9d6 10-27-修改bug 2025-10-27 10:29:27 +08:00
lg
8252fd7216 标后分析返回对象增加字段 2025-10-27 09:44:11 +08:00
lg
57855f4307 bug修改 2025-10-25 22:18:10 +08:00
6784eafe6e 供应商-客户中间表引用表的新增修改删除修改 2025-10-25 22:17:26 +08:00
0b42c1d6a6 Merge remote-tracking branch 'origin/dev' into dev 2025-10-25 22:16:07 +08:00
4b37a7327f 10-25-修改 2025-10-25 22:16:00 +08:00
lg
0287f1e4ce bug修改 2025-10-25 21:58:47 +08:00
5d8af1cab8 10-25-供应商删除修改 2025-10-25 21:57:13 +08:00
123896f08b Merge remote-tracking branch 'origin/dev' into dev 2025-10-25 21:25:40 +08:00
a8a198b51f 10-25-增加校验 2025-10-25 21:25:33 +08:00
lg
f00b98714a Merge remote-tracking branch 'origin/dev' into dev 2025-10-25 21:24:39 +08:00
lg
4ff87f3996 bug修改 2025-10-25 21:23:58 +08:00
5f3ae0f9f1 10-25-供应商地域绑定及搜索 2025-10-25 21:22:36 +08:00
786c864a27 供应商-客户中间表引用表的新增修改删除修改 2025-10-25 21:21:48 +08:00
lg
c61e802b85 bug修改 2025-10-25 21:09:26 +08:00
lg
9a568799f4 bug修改 2025-10-25 21:05:26 +08:00
8aa38063bf 供应商-客户中间表引用表的新增修改删除 2025-10-25 20:58:07 +08:00
c4a11ec245 10-25-解除继承 2025-10-25 20:28:40 +08:00
lg
169b76589c bug修改 2025-10-25 20:23:02 +08:00
lg
199f51ea21 bug修改 2025-10-25 20:19:21 +08:00
lg
23572dfc07 bug修改 2025-10-25 20:14:03 +08:00
570b0ce316 10-25-供应商新增、删除添加校验 2025-10-25 20:11:14 +08:00
lg
f953a96c36 bug修改 2025-10-25 20:05:43 +08:00
zt
25c4eee464 bug 2025-10-25 20:01:28 +08:00
lg
b209ef1fab 中间表数据添加 2025-10-25 19:20:32 +08:00
lg
77e9f4d9a2 中间表数据添加 2025-10-25 19:18:09 +08:00
lg
e73c808bc3 xzd前缀添加 2025-10-25 17:21:16 +08:00
zt
edf0d1a5db 设计导出 2025-10-25 17:10:43 +08:00
lcj
cc23a308c1 修改配置,车辆管理 2025-10-25 17:01:15 +08:00
bc891327c9 10-25-字段调整 2025-10-25 16:51:17 +08:00
39bedfeb92 10-25-字段调整 2025-10-25 16:44:33 +08:00
56fc4ff83e 10-24-修复 2025-10-24 22:16:26 +08:00
524ed30728 Merge remote-tracking branch 'origin/dev' into dev 2025-10-24 22:16:13 +08:00
584304e744 供应商-客户中间表初始化 2025-10-24 22:07:16 +08:00
zt
56418600c5 1 2025-10-24 20:17:03 +08:00
40e57b18cb 10-24-修复 2025-10-24 20:05:45 +08:00
lg
ced6cb219c deptid添加 2025-10-24 20:01:03 +08:00
218ec5ea95 gps接口修改 2025-10-24 19:40:54 +08:00
zt
1c601bd68e 设计导出 2025-10-24 19:32:20 +08:00
lg
7d6eba719b 投标保证金收回 2025-10-24 17:50:15 +08:00
374 changed files with 10470 additions and 1212 deletions

View File

@ -321,8 +321,8 @@ ys7:
app-key: xxx
app-secret: xxx
job:
capture-enabled: true # 控制是否启用萤石抓拍任务
device-sync-enabled: true # 控制是否同步萤石设备
capture-enabled: false # 控制是否启用萤石抓拍任务
device-sync-enabled: false # 控制是否同步萤石设备
# 斯巴达算法
sparta:
url: http://119.3.204.120:8040

View File

@ -289,6 +289,8 @@ springdoc:
packages-to-scan: org.dromara.websocket
- group: 27.新中大模块
packages-to-scan: org.dromara.xzd
- group: 28.车辆模块
packages-to-scan: org.dromara.vehicle
# knife4j的增强配置不需要增强可以不配
knife4j:
enable: true
@ -306,12 +308,12 @@ xss:
- /project/project
- /xzd/contractDetails/**
- /xzd/contractChange/**
- /comprehensive/csContractChange/**
- /comprehensive/csContractInformation/**
- /hetongbiangeng/**
- /fenbaohetongbiangg/**
- /fenbaohetongxinxi/**
- /contractManagement/**
- /xzd/comprehensive/csContractChange/**
- /xzd/comprehensive/csContractInformation/**
- /xzd/hetongbiangeng/**
- /xzd/fenbaohetongbiangg/**
- /xzd/fenbaohetongxinxi/**
- /xzd/contractManagement/**
# 全局线程池相关配置
# 如使用JDK21请直接使用虚拟线程 不要开启此配置

View File

@ -1,9 +1,17 @@
package org.dromara.test;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateDto;
import org.dromara.safety.service.IHseViolationRecordService;
import org.dromara.system.domain.SysMenu;
import org.dromara.system.domain.vo.SysMenuVo;
import org.dromara.system.mapper.SysMenuMapper;
import org.dromara.system.service.ISysMenuService;
import org.hamcrest.core.Is;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
@ -20,6 +28,9 @@ public class ViolationRecordTest {
@Resource
private IHseViolationRecordService violationRecordService;
@Autowired
private SysMenuMapper sysMenuMapper;
@Test
void test() {
List<HseViolationRecordCreateDto> list = new ArrayList<>();
@ -55,4 +66,26 @@ public class ViolationRecordTest {
list.add(dto5);
violationRecordService.insertByMonitor(list);
}
@Test
void contextLoads() {
SysMenuVo sysMenuVo = sysMenusByList(1972500768346673154L);
System.out.println(sysMenuVo.toString());
}
SysMenuVo sysMenusByList(Long id) {
SysMenuVo sysMenus = new SysMenuVo();
List<SysMenu> res = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, id));
if (res != null && res.size() > 0 ) {
sysMenus.setChildren(MapstructUtils.convert(res, SysMenuVo.class));
res.forEach(sysMenu -> {
sysMenusByList(sysMenu.getMenuId());
});
}
return sysMenus;
}
}

View File

@ -0,0 +1,32 @@
package org.dromara.common.core.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class XzdCustomerSupplierVos implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
private Long id;
/**
* 类型1、供应商2、客户
*/
private String type;
/**
* 供应商-客户id
*/
private Long cSId;
}

View File

@ -0,0 +1,14 @@
package org.dromara.common.core.service;
import org.dromara.common.core.domain.vo.XzdCustomerSupplierVos;
public interface XzdCustomerSupplierService {
/**
* 查询供应商-客户中间
*
* @param id 主键
* @return 供应商-客户中间
*/
XzdCustomerSupplierVos queryByIdone(Long id);
}

View File

@ -3,4 +3,6 @@ package org.dromara.common.core.service;
public interface XzdCustomerinformationService {
String selectNmaeByIds(String id);
String selectNmaeById(Long id);
}

View File

@ -3,4 +3,7 @@ package org.dromara.common.core.service;
public interface XzdSupplierInfoService {
String selectNmaeByIds(String ids);
String selectNmaeById(Long id);
}

View File

@ -44,10 +44,10 @@ public interface TransConstant {
String XZD_KHXX_ID_TO_NAME = "khxx_id_to_name";
/**
* 供应商id转名称
*/
String XZD_GYSXX_ID_TO_NAME = "gysxx_id_to_name";
// /**
// * 供应商id转名称
// */
// String XZD_KHXX_ID_TO_NAME = "gysxx_id_to_name";
/**
* 新中大项目id转名称

View File

@ -7,7 +7,7 @@ import org.dromara.common.translation.constant.TransConstant;
import org.dromara.common.translation.core.TranslationInterface;
@AllArgsConstructor
@TranslationType(type = TransConstant.XZD_GYSXX_ID_TO_NAME)
//@TranslationType(type = TransConstant.XZD_KHXX_ID_TO_NAME)
public class XzdSupplierInfoImpl implements TranslationInterface<String> {
private final XzdSupplierInfoService xzdSupplierInfoService;

View File

@ -1,12 +1,21 @@
package org.dromara.common.utils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.mobileAttendanceMachine.DeviceMessageSender;
import org.dromara.mobileAttendanceMachine.KqjEntity;
import org.dromara.project.domain.BusAttendanceMachine;
import org.dromara.project.service.IBusAttendanceMachineService;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@ -17,6 +26,16 @@ import java.util.List;
@Slf4j
public class AsyncUtil {
@Resource
@Lazy
private DeviceMessageSender deviceMessageSender;
@Resource
@Lazy
private ISysOssService ossService;
@Resource
@Lazy
private IBusAttendanceMachineService attendanceMachineService;
//发送短信
@Async
public void sendSms(List<String> mobileList, String config) {
@ -39,4 +58,27 @@ public class AsyncUtil {
}
//下发考勤人员
@Async
public void sendPersonnel(Long teamId, SubConstructionUser constructionUser) {
SysOssVo byId = ossService.getById(Long.valueOf(constructionUser.getFacePic()));
List<BusAttendanceMachine> list = attendanceMachineService.lambdaQuery().apply("FIND_IN_SET({0}, teams)", teamId).list();
for (BusAttendanceMachine machine : list) {
deviceMessageSender.sendPersonnelInformation(machine.getSn(), constructionUser.getSysUserId().toString(), constructionUser.getUserName(), byId.getUrl());
}
}
//删除考勤人员
@Async
public void deletePersonnel(SubConstructionUser constructionUser) {
List<BusAttendanceMachine> list = attendanceMachineService.lambdaQuery().apply("FIND_IN_SET({0}, teams)", constructionUser.getTeamId()).list();
for (BusAttendanceMachine machine : list) {
try {
deviceMessageSender.deleteUser(machine.getSn(), constructionUser.getSysUserId().toString());
} catch (Exception e) {
log.error("删除考勤人员异常", e);
}
}
}
}

View File

@ -101,4 +101,7 @@ public class SubConstructionUserQueryReq implements Serializable {
*/
private String userId;
private String phone;
}

View File

@ -26,6 +26,7 @@ import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.exception.OssException;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.utils.AsyncUtil;
import org.dromara.common.utils.IdCardEncryptorUtil;
import org.dromara.common.utils.baiduUtil.BaiDuFace;
import org.dromara.common.utils.baiduUtil.BaiDuOCR;
@ -46,6 +47,7 @@ import org.dromara.contractor.mapper.SubConstructionUserMapper;
import org.dromara.contractor.service.ISubConstructionUserFileService;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.contractor.service.ISubContractorService;
import org.dromara.mobileAttendanceMachine.DeviceMessageSender;
import org.dromara.project.domain.*;
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
@ -151,6 +153,11 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
@Resource
private ISysRoleService roleService;
@Resource
private AsyncUtil asyncUtil;
/**
* 查询施工人员
*
@ -202,8 +209,10 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
LambdaQueryWrapper<SubConstructionUser> lqw = Wrappers.lambdaQuery();
// 从对象中取值
String userName = req.getUserName();
String phone = req.getPhone();
// 模糊查询
lqw.like(StringUtils.isNotBlank(phone), SubConstructionUser::getPhone, phone);
lqw.like(StringUtils.isNotBlank(userName), SubConstructionUser::getUserName, userName);
lqw.isNull(SubConstructionUser::getProjectId);
lqw.isNull(SubConstructionUser::getTeamId);
@ -290,6 +299,8 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
//强退
roleService.cleanOnlineUser(Collections.singletonList(constructionUser.getSysUserId()));
asyncUtil.sendPersonnel(dto.getTeamId(), constructionUser);
return i > 0;
}

View File

@ -1,17 +1,40 @@
package org.dromara.design.controller;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.hutool.core.util.StrUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.design.domain.BusDrawingreviewReceipts;
import org.dromara.design.domain.DesCollectFile;
import org.dromara.design.domain.DesDesignChange;
import org.dromara.design.domain.bo.DesUserBo;
import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto;
import org.dromara.design.domain.vo.DesCollectFileWordVo;
import org.dromara.design.domain.vo.DesUserVo;
import org.dromara.design.domain.vo.designchange.DesDesignChangeVo;
import org.dromara.design.service.IDesDesignChangeService;
import org.dromara.design.service.IDesUserService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.vo.project.BusSubProjectVo;
import org.dromara.project.service.IBusProjectService;
import org.dromara.system.service.ISysDictDataService;
import org.dromara.system.service.ISysUserService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@ -44,6 +67,12 @@ public class BusDrawingreviewReceiptsController extends BaseController {
private final IDesUserService desUserService;
private final IDesDesignChangeService desDesignChangeService;
private final ISysDictDataService dictDataService;
private final ISysUserService userService;
/**
* 查询设计-图纸评审验证列表
*/
@ -132,4 +161,85 @@ public class BusDrawingreviewReceiptsController extends BaseController {
return R.ok(desUserService.queryList(bo));
}
private static final String TEMPLATE_PATH = "template/设计验证表.docx";
@PostMapping("/downloadWord")
public void generateDesignLeaderDoc(Long id, HttpServletResponse response) {
OutputStream outputStream = null;
try {
// 1. 调用Service生成目标模板的Word字节流
byte[] docBytes = generateDocBytes(id);
// 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型)
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型
// 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”此处用projectId拼接真实场景可从数据中获取项目名
String downloadFileName = URLEncoder.encode(
"设计验证表.docx",
"UTF-8"
);
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验)
// 3. 将Word字节流写入响应
outputStream = response.getOutputStream();
outputStream.write(docBytes);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
// 异常处理返回500错误状态码
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
// 关闭流,避免资源泄漏
if (outputStream != null) {
try {
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public byte[] generateDocBytes(Long id) throws Exception {
// -------------------------- 步骤1按projectId查询项目数据模拟真实业务 --------------------------
// 实际场景替换为数据库查询如调用DAO获取项目名称、负责人等
DesDesignChangeVo desDesignChangeVo = desDesignChangeService.queryById(id);
BusDrawingreviewReceipts receipts = busDrawingreviewReceiptsService.lambdaQuery()
.eq(BusDrawingreviewReceipts::getDrawingreviewId, id)
.last("limit 1")
.one();
DesDesignExtendDetailDto extendDetail = desDesignChangeVo.getExtendDetail();
String s = dictDataService.selectDictLabel("des_user_major", receipts.getProfessional());
String designerName = null;
if(StrUtil.isNotBlank(receipts.getDesigner())){
Long userId = Long.parseLong(receipts.getDesigner());
designerName= userService.queryNameById(userId);
}
Map<String, Object> placeholderData = new HashMap<>();
placeholderData.put("projectName", receipts.getProjectName());
placeholderData.put("subName",extendDetail.getSubName());
placeholderData.put("stage", receipts.getStage());
placeholderData.put("professionalName", s);
placeholderData.put("volume", receipts.getVolume());
placeholderData.put("designerName", designerName);
placeholderData.put("verificationOpinion", receipts.getVerificationOpinion());
placeholderData.put("executionOpinion", receipts.getExecutionOpinion());
// -------------------------- 步骤2用poi-tl加载目标模板并替换占位符 --------------------------
// 读取resources下的“设计项目负责人任命通知单.docx”模板
ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH);
try (InputStream templateIs = templateResource.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
XWPFTemplate template = XWPFTemplate.compile(templateIs).render(placeholderData);
// -------------------------- 步骤3将生成的文档写入字节流 --------------------------
template.write(outputStream);
template.close(); // 关闭模板资源
return outputStream.toByteArray();
}
}
}

View File

@ -1,15 +1,31 @@
package org.dromara.design.controller;
import java.util.List;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.design.domain.DesCollectFile;
import org.dromara.design.domain.bo.DesCollectFileBo;
import org.dromara.design.domain.dto.ExportDto;
import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto;
import org.dromara.design.domain.vo.DesCollectFileVo;
import org.dromara.design.domain.vo.DesCollectFileWordVo;
import org.dromara.design.domain.vo.designchange.DesDesignChangeVo;
import org.dromara.design.service.IDesCollectFileService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@ -39,6 +55,8 @@ public class DesCollectFileController extends BaseController {
private final IDesCollectFileService desCollectFileService;
private final IBusProjectService projectService;
/**
* 查询收资文件列表
*/
@ -106,7 +124,6 @@ public class DesCollectFileController extends BaseController {
return toAjax(desCollectFileService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 上传资料文件
*/
@ -119,10 +136,92 @@ public class DesCollectFileController extends BaseController {
return toAjax(desCollectFileService.addFile(file, catalogueId, projectId));
}
@PostMapping("/exportZip")
public void exportZip(ExportDto dto, HttpServletResponse response) throws Exception {
desCollectFileService.exportAsZip(dto, response);
}
private static final String TEMPLATE_PATH = "template/设计输入资料清单及评审表.docx";
@PostMapping("/downloadWord")
public void generateDesignLeaderDoc(Long projectId, HttpServletResponse response) {
OutputStream outputStream = null;
try {
// 1. 调用Service生成目标模板的Word字节流
byte[] docBytes = generateDocBytes(projectId);
// 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型)
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型
// 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”此处用projectId拼接真实场景可从数据中获取项目名
String downloadFileName = URLEncoder.encode(
"设计输入资料清单及评审表.docx",
"UTF-8"
);
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验)
// 3. 将Word字节流写入响应
outputStream = response.getOutputStream();
outputStream.write(docBytes);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
// 异常处理返回500错误状态码
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
// 关闭流,避免资源泄漏
if (outputStream != null) {
try {
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public byte[] generateDocBytes(Long projectId) throws Exception {
// -------------------------- 步骤1按projectId查询项目数据模拟真实业务 --------------------------
// 实际场景替换为数据库查询如调用DAO获取项目名称、负责人等
List<DesCollectFile> list = desCollectFileService.lambdaQuery()
.eq(DesCollectFile::getProjectId, projectId).list();
List<DesCollectFileWordVo> files = new ArrayList<>();
int i = 1;
for (DesCollectFile desCollectFile : list) {
DesCollectFileWordVo desCollectFileWordVo = new DesCollectFileWordVo();
desCollectFileWordVo.setNum(i);
i++;
desCollectFileWordVo.setFileName(desCollectFile.getFileName());
files.add(desCollectFileWordVo);
}
BusProject project = projectService.getById(projectId);
Map<String, Object> placeholderData = new HashMap<>();
placeholderData.put("projectName", project.getProjectName());
placeholderData.put("files",files);
// -------------------------- 步骤2用poi-tl加载目标模板并替换占位符 --------------------------
// 读取resources下的“设计项目负责人任命通知单.docx”模板
ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH);
try (InputStream templateIs = templateResource.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
Configure config = Configure.builder()
.bind("files", policy).build();
XWPFTemplate template = XWPFTemplate.compile(templateIs, config).render(placeholderData);
// -------------------------- 步骤3将生成的文档写入字节流 --------------------------
template.write(outputStream);
template.close(); // 关闭模板资源
return outputStream.toByteArray();
}
}
}

View File

@ -2,10 +2,13 @@ package org.dromara.design.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
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.apache.poi.xwpf.usermodel.*;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@ -13,18 +16,37 @@ import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.design.domain.DesConstructionSchedulePlan;
import org.dromara.design.domain.DesUser;
import org.dromara.design.domain.dto.constructionscheduleplan.*;
import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo;
import org.dromara.design.exportUtil.plan.AttachmentPersonnel;
import org.dromara.design.service.IDesConstructionSchedulePlanService;
import org.dromara.design.service.IDesUserService;
import org.dromara.system.domain.vo.SysDictDataVo;
import org.dromara.system.service.ISysDictDataService;
import org.dromara.system.service.ISysDictTypeService;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/**
* 设计计划
*
@ -38,7 +60,10 @@ public class DesConstructionSchedulePlanController extends BaseController {
@Resource
private IDesConstructionSchedulePlanService desConstructionSchedulePlanService;
@Resource
private IDesUserService desUserService;
@Resource
private ISysDictTypeService dictTypeService;
/**
* 查询设计计划列表
*/
@ -150,4 +175,168 @@ public class DesConstructionSchedulePlanController extends BaseController {
desConstructionSchedulePlanService.exportSchedule(response,projectId);
}
private static final String TEMPLATE_RESOURCE_PATH = "template/CCCET-JL-CX-25设计计划表.docx";
// -------------------------- 2. 核心接口:修复单元格清空逻辑与数据填充 --------------------------
@PostMapping("/downloadWord")
public void fillCccetTemplate(Long projectId, HttpServletResponse response) {
// 1. 基础参数校验(避免空数据)
// 2. 读取resource中的模板+填充数据
try (
// 关键通过ClassPathResource读取resource/template下的模板
InputStream templateIs = new ClassPathResource(TEMPLATE_RESOURCE_PATH).getInputStream();
XWPFDocument doc = new XWPFDocument(templateIs); // 加载模板
OutputStream out = response.getOutputStream() // 响应流
) {
// --------------------------
// 步骤1填充第1页-主信息表索引0固定6列
// --------------------------
// XWPFTable mainTable = doc.getTables().get(0);
// // 工程名称第1行第0列
// if (mainTable.getRows().size() > 1 && mainTable.getRow(1).getCell(0) != null) {
// mainTable.getRow(1).getCell(0).setText(request.getProjectName() == null ? "" : request.getProjectName());
// }
// // 工程号第1行第1列
// if (mainTable.getRows().size() > 1 && mainTable.getRow(1).getCell(1) != null) {
// mainTable.getRow(1).getCell(1).setText(request.getProjectNo());
// }
// // 编制日期第2行第3列
// if (mainTable.getRows().size() > 2 && mainTable.getRow(2).getCell(3) != null) {
// mainTable.getRow(2).getCell(3).setText(request.getCompileDate() == null ? "" : request.getCompileDate());
// }
// // 编制人第3行第0列
// if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(0) != null) {
// mainTable.getRow(3).getCell(0).setText(request.getCompiler() == null ? "" : request.getCompiler());
// }
// // 批准人第3行第2列
// if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(2) != null) {
// mainTable.getRow(3).getCell(2).setText(request.getApprover() == null ? "" : request.getApprover());
// }
// // 设计阶段第3行第4列
// if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(4) != null) {
// mainTable.getRow(3).getCell(4).setText(request.getDesignStage() == null ? "" : request.getDesignStage());
// }
// // 设计规模第4行第0列
// if (mainTable.getRows().size() > 4 && mainTable.getRow(4).getCell(0) != null) {
// mainTable.getRow(4).getCell(0).setText(request.getDesignScale() == null ? "" : request.getDesignScale());
// }
// --------------------------
// 步骤2填充第3页-附件1人员配置表索引2固定11列
// --------------------------
XWPFTable staffTable = doc.getTables().get(2);
// 删除模板中附件1的空数据行保留第0行表头
while (staffTable.getRows().size() > 2) {
staffTable.removeRow(1);
}
List<AttachmentPersonnel> list = getPersonnelDataByProjectId(projectId);
for (AttachmentPersonnel staff : list) {
XWPFTableRow newRow = staffTable.createRow();
// 补全11列避免POI默认列数不足导致null
while (newRow.getTableCells().size() < 11) {
newRow.createCell();
}
// 按附件1列顺序填充
newRow.getCell(0).setText(staff.getProfessional() == null ? "" : staff.getProfessional());
newRow.getCell(1).setText(staff.getLeaderName() == null ? "" : staff.getLeaderName());
newRow.getCell(2).setText(staff.getLeaderTitle() == null ? "" : staff.getLeaderTitle());
newRow.getCell(3).setText(staff.getDesignerName() == null ? "" : staff.getDesignerName());
newRow.getCell(4).setText(staff.getDesignerTitle() == null ? "" : staff.getDesignerTitle());
newRow.getCell(5).setText(staff.getReviewerName() == null ? "" : staff.getReviewerName());
newRow.getCell(6).setText(staff.getReviewerTitle() == null ? "" : staff.getReviewerTitle());
newRow.getCell(7).setText(staff.getCheckerName() == null ? "" : staff.getCheckerName());
newRow.getCell(8).setText(staff.getCheckerTitle() == null ? "" : staff.getCheckerTitle());
newRow.getCell(9).setText(staff.getApproverName() == null ? "" : staff.getApproverName());
newRow.getCell(10).setText(staff.getApproverTitle() == null ? "" : staff.getApproverTitle());
}
// --------------------------
// 步骤3设置响应头触发前端下载
// --------------------------
response.setContentType("application/octet-stream");
// 文件名填充后_工程号_CCCET-JL-CX-25设计计划表.docx
String fileName = "CCCET-JL-CX-25设计计划表.docx";
response.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); // 允许前端获取文件名
// --------------------------
// 步骤4写出文件到前端
// --------------------------
doc.write(out);
out.flush();
} catch (Exception e) {
// 异常封装(前端可捕获具体错误)
throw new RuntimeException("CCCET-JL-CX-25模板填充失败" + e.getMessage());
}
}
/**
* 根据projectId获取数据仅针对CCCET-JL-CX-25设计计划表.docx附件1
*/
private List<AttachmentPersonnel> getPersonnelDataByProjectId(Long projectId) {
// 模拟数据库查询实际项目替换为真实Service调用
List<DesUser> userList = desUserService.list(Wrappers.<DesUser>lambdaQuery()
.eq(DesUser::getProjectId, projectId)
);
if (userList.isEmpty()) {
return Collections.emptyList();
}
// 专业字典映射(编码→名称)
List<SysDictDataVo> majorDict = dictTypeService.selectDictDataByType("des_user_major");
Map<String, String> majorMap = majorDict.stream()
.collect(Collectors.toMap(SysDictDataVo::getDictValue, SysDictDataVo::getDictLabel));
// 按角色分组1-专业负责人2-设计人3-校审人4-审定人5-审核人)
DesUser leader = userList.stream().filter(u -> "1".equals(u.getUserType())).findFirst().orElse(null);
Map<String, List<DesUser>> designerMap = userList.stream()
.filter(u -> "2".equals(u.getUserType()))
.collect(Collectors.groupingBy(DesUser::getUserMajor));
Map<String, List<DesUser>> reviewerMap = userList.stream()
.filter(u -> "3".equals(u.getUserType()))
.collect(Collectors.groupingBy(DesUser::getUserMajor));
Map<String, List<DesUser>> checkerMap = userList.stream()
.filter(u -> "5".equals(u.getUserType()))
.collect(Collectors.groupingBy(DesUser::getUserMajor));
Map<String, List<DesUser>> approverMap = userList.stream()
.filter(u -> "4".equals(u.getUserType()))
.collect(Collectors.groupingBy(DesUser::getUserMajor));
// 构建附件1数据一个专业一行避免重复
List<AttachmentPersonnel> dataList = new ArrayList<>();
for (Map.Entry<String, List<DesUser>> entry : designerMap.entrySet()) {
String majorCode = entry.getKey();
String majorName = majorMap.getOrDefault(majorCode, majorCode);
List<DesUser> designers = entry.getValue();
// 获取对应专业的其他角色
DesUser reviewer = reviewerMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null);
DesUser checker = checkerMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null);
DesUser approver = approverMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null);
// 封装数据(多个设计人用顿号分隔)
AttachmentPersonnel data = new AttachmentPersonnel();
data.setProfessional(majorName);
data.setLeaderName(leader != null ? leader.getUserName() : "");
//data.setLeadeTitle(leader != null ? leader.getUserTitle() : "");
data.setDesignerName(designers.stream().map(DesUser::getUserName).collect(Collectors.joining("")));
//data.setDesignerTitle(designers.stream().map(DesUser::getUserTitle).collect(Collectors.joining("、")));
data.setReviewerName(reviewer != null ? reviewer.getUserName() : "");
//data.setReviewerTitle(reviewer != null ? reviewer.getUserTitle() : "");
data.setCheckerName(checker != null ? checker.getUserName() : "");
//data.setCheckerTitle(checker != null ? checker.getUserTitle() : "");
data.setApproverName(approver != null ? approver.getUserName() : "");
//data.setApproverTitle(approver != null ? approver.getUserTitle() : "");
dataList.add(data);
}
return dataList;
}
}

View File

@ -2,6 +2,7 @@ package org.dromara.design.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.deepoove.poi.XWPFTemplate;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
@ -16,24 +17,36 @@ 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.DesUser;
import org.dromara.design.domain.DesVolumeCatalog;
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.dto.designchange.DesDesignExtendDetailDto;
import org.dromara.design.domain.dto.volumecatalog.DesVolumeCatalogQueryReq;
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.dromara.project.domain.BusProject;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysDictDataService;
import org.dromara.system.service.ISysOssService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -56,6 +69,9 @@ public class DesDesignChangeController extends BaseController {
@Resource
private IDesVolumeFileService desVolumeFileService;
@Resource
private ISysDictDataService dictDataService;
/**
* 查询设计变更管理列表
*/
@ -146,4 +162,92 @@ public class DesDesignChangeController extends BaseController {
return R.ok(list);
}
private static final String TEMPLATE_PATH = "template/设计更改通知单.docx";
@PostMapping("/downloadWord")
public void generateDesignLeaderDoc(Long id, HttpServletResponse response) {
OutputStream outputStream = null;
try {
// 1. 调用Service生成目标模板的Word字节流
byte[] docBytes = generateDocBytes(id);
// 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型)
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型
// 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”此处用projectId拼接真实场景可从数据中获取项目名
String downloadFileName = URLEncoder.encode(
"设计更改通知单.docx",
"UTF-8"
);
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验)
// 3. 将Word字节流写入响应
outputStream = response.getOutputStream();
outputStream.write(docBytes);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
// 异常处理返回500错误状态码
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
// 关闭流,避免资源泄漏
if (outputStream != null) {
try {
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public byte[] generateDocBytes(Long id) throws Exception {
// -------------------------- 步骤1按projectId查询项目数据模拟真实业务 --------------------------
// 实际场景替换为数据库查询如调用DAO获取项目名称、负责人等
DesDesignChangeVo vo = desDesignChangeService.queryById(id);
DesDesignExtendDetailDto extendDetail = vo.getExtendDetail()==null?new DesDesignExtendDetailDto():vo.getExtendDetail();
Map<String, Object> placeholderData = new HashMap<>();
placeholderData.put("projectName", vo.getProjectName());
placeholderData.put("designPhase",extendDetail.getDesignPhase());
placeholderData.put("subName",extendDetail.getSubName());
String s = dictDataService.selectDictLabel("des_user_major", vo.getSpecialty());
placeholderData.put("specialty",s);
placeholderData.put("volumeNo",vo.getVolumeNo());
String changeReason = vo.getChangeReason();
List<String> reasons = Arrays.asList("设计漏项", "设计改进", "设计差错", "接口差错",
"业主要求", "施工承包商要求", "外部资料与最终情况不符", "材料代用或其他");
String reason = reasons.stream()
.map(item -> changeReason.contains(String.valueOf(reasons.indexOf(item) + 1)) ? "" + item : "" + item)
.collect(Collectors.joining());
placeholderData.put("changeReason", reason);
placeholderData.put("designDisposal1", "1".equals(extendDetail.getDesignDisposal())?"" : "");
placeholderData.put("designDisposal2", "2".equals(extendDetail.getDesignDisposal())?"" : "");
placeholderData.put("designDisposal3", "3".equals(extendDetail.getDesignDisposal())?"" : "");
placeholderData.put("changeContent",vo.getChangeContent());
placeholderData.put("changeCategory1", "1".equals(extendDetail.getChangeCategory())?"" : "");
placeholderData.put("changeCategory2", "2".equals(extendDetail.getChangeCategory())?"" : "");
placeholderData.put("involvingProfessions", extendDetail.getInvolvingProfessions());
// -------------------------- 步骤2用poi-tl加载目标模板并替换占位符 --------------------------
// 读取resources下的“设计项目负责人任命通知单.docx”模板
ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH);
try (InputStream templateIs = templateResource.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
// 1. 加载模板 2. 注入替换数据 3. 渲染生成新文档
XWPFTemplate template = XWPFTemplate.compile(templateIs)
.render(placeholderData); // 自动匹配{{变量名}}占位符
// -------------------------- 步骤3将生成的文档写入字节流 --------------------------
template.write(outputStream);
template.close(); // 关闭模板资源
return outputStream.toByteArray();
}
}
}

View File

@ -1,16 +1,18 @@
package org.dromara.design.controller;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.rmi.ServerException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.*;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.deepoove.poi.XWPFTemplate;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
@ -22,8 +24,15 @@ import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
//import org.dromara.design.domain.DesUserExcelData;
import org.dromara.design.domain.DesUser;
import org.dromara.design.domain.DesUserExcelData;
import org.dromara.design.domain.dto.desUser.DesUserBatchDto;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@ -54,6 +63,7 @@ import org.springframework.web.multipart.MultipartFile;
public class DesUserController extends BaseController {
private final IDesUserService desUserService;
private final IBusProjectService projectService;
/**
* 查询设计人员列表
@ -142,5 +152,75 @@ public class DesUserController extends BaseController {
return toAjax(desUserService.batchAddOrUpdate(dto));
}
private static final String TEMPLATE_PATH = "template/设计项目负责人任命通知单.docx";
@PostMapping("/downloadWord")
public void generateDesignLeaderDoc( Long projectId,
HttpServletResponse response
) {
OutputStream outputStream = null;
try {
// 1. 调用Service生成目标模板的Word字节流
byte[] docBytes = generateDocBytes(projectId);
// 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型)
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型
// 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”此处用projectId拼接真实场景可从数据中获取项目名
String downloadFileName = URLEncoder.encode(
"设计负责人任命通知单.docx",
"UTF-8"
);
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验)
// 3. 将Word字节流写入响应
outputStream = response.getOutputStream();
outputStream.write(docBytes);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
// 异常处理返回500错误状态码
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
// 关闭流,避免资源泄漏
if (outputStream != null) {
try {
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public byte[] generateDocBytes(Long projectId) throws Exception {
// -------------------------- 步骤1按projectId查询项目数据模拟真实业务 --------------------------
// 实际场景替换为数据库查询如调用DAO获取项目名称、负责人等
BusProject byId = projectService.getById(projectId);
DesUser desUser = desUserService.lambdaQuery().eq(DesUser::getProjectId, projectId)
.eq(DesUser::getUserType, "1")
.last("limit 1").one();
Map<String, Object> placeholderData = new HashMap<>();
placeholderData.put("projectName", byId==null?"" :byId.getProjectName());
placeholderData.put("leaderName",desUser==null?"": desUser.getUserName());
// -------------------------- 步骤2用poi-tl加载目标模板并替换占位符 --------------------------
// 读取resources下的“设计项目负责人任命通知单.docx”模板
ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH);
try (InputStream templateIs = templateResource.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
// 1. 加载模板 2. 注入替换数据 3. 渲染生成新文档
XWPFTemplate template = XWPFTemplate.compile(templateIs)
.render(placeholderData); // 自动匹配{{变量名}}占位符
// -------------------------- 步骤3将生成的文档写入字节流 --------------------------
template.write(outputStream);
template.close(); // 关闭模板资源
return outputStream.toByteArray();
}
}
}

View File

@ -0,0 +1,15 @@
package org.dromara.design.domain.vo;
import lombok.Data;
@Data
public class DesCollectFileWordVo {
private Integer num;
private String fileName;
private String opinion;
}

View File

@ -0,0 +1,25 @@
package org.dromara.design.exportUtil.plan;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AttachmentPersonnel {
String professional; // 专业及人员分工
String leaderName; // 专业负责人姓名
String leaderTitle; // 专业负责人职称
String designerName; // 设计人姓名
String designerTitle; // 设计人职称
String reviewerName; // 校审人姓名
String reviewerTitle; // 校审人职称
String checkerName; // 审核人姓名
String checkerTitle; // 审核人职称
String approverName; // 审定人姓名
String approverTitle; // 审定人职称
}

View File

@ -23,7 +23,10 @@ import org.dromara.facility.constant.FacRedisKeyConstant;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.domain.dto.geojson.*;
import org.dromara.facility.domain.dto.photovoltaicpanel.*;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelCreateByGeoJsonReq;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelCreateReq;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelQueryReq;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelUpdateReq;
import org.dromara.facility.domain.enums.FacFinishStatusEnum;
import org.dromara.facility.domain.enums.FacFinishTypeEnum;
import org.dromara.facility.domain.vo.photovoltaicpanel.FacPhotovoltaicPanelVo;
@ -329,10 +332,10 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
}
Long matrixId = matrix.getId();*/
// 去掉首字母 (T/G)
String withoutPrefix = name.substring(2);
String withoutPrefix = name.substring(1);
// 如果包含".",只取第一个"."前的数字
int dotIndex = withoutPrefix.indexOf("#");
int dotIndex = withoutPrefix.indexOf(".");
if (dotIndex != -1) {
withoutPrefix = withoutPrefix.substring(0, dotIndex);
}

View File

@ -61,7 +61,7 @@ public class GpsEquipmentSonController extends BaseController {
/**
* 查询GPS设备定位日期信息列表
*/
@SaCheckPermission("gps:equipmentSon:getRlList")
// @SaCheckPermission("gps:equipmentSon:getRlList")
@GetMapping("/getRlList")
public R<List<GpsStatusVo>> getRlList(GpsEquipmentSonBo bo) {
return R.ok(gpsEquipmentSonService.getRlList(bo));

View File

@ -81,31 +81,15 @@ public interface GpsEquipmentSonMapper extends BaseMapperPlus<GpsEquipmentSon, G
" rn = 1;")
List<GpsEquipmentSonVo> getUserListByProjectId(@Param("projectId") Long projectId, @Param("startTime") LocalDateTime startOfDay, @Param("endTime") LocalDateTime now);
@Select("WITH RECURSIVE date_range AS (\n" +
" -- 1. 初始化开始日期取startTime的“年月日”部分忽略时分秒\n" +
" SELECT DATE(#{bo.startTime}) AS stat_date\n" +
" UNION ALL\n" +
" -- 2. 递归生成后续日期直到不超过endTime的“年月日”\n" +
" SELECT DATE_ADD(stat_date, INTERVAL 1 DAY)\n" +
" FROM date_range\n" +
" WHERE stat_date < DATE(#{bo.endTime})\n" +
")\n" +
"\n" +
"SELECT \n" +
" dr.stat_date AS riqi, -- 统计日期格式YYYY-MM-DD\n" +
" COUNT(ges.id) AS count -- 当天符合条件的记录数\n" +
"FROM date_range dr\n" +
"LEFT JOIN (\n" +
" SELECT \n" +
" DATE(create_time) AS data_date, -- 提取创建时间的“年月日”\n" +
" id -- 仅需主键用于计数(减少数据传输)\n" +
" FROM gps_equipment_son\n" +
" WHERE \n" +
" project_id = #{bo.projectId} -- 匹配项目ID\n" +
" AND client_id =#{bo.clientId} -- 客户端ID为空\n" +
" AND create_time BETWEEN #{bo.startTime} AND #{bo.endTime} -- 时间范围\n" +
") ges ON dr.stat_date = ges.data_date -- 按日期关联\n" +
"GROUP BY dr.stat_date -- 按统计日期分组\n" +
"ORDER BY dr.stat_date; -- 按日期升序排列")
@Select("SELECT\n" +
" DATE(create_time) AS riqi,\n" +
" COUNT(id) AS count \n" +
"FROM\n" +
" gps_equipment_son\n" +
"WHERE\n" +
" project_id = #{bo.projectId}\n" +
" AND client_id = #{bo.clientId}\n" +
" AND create_time BETWEEN #{bo.startTime} AND #{bo.endTime}\n" +
" GROUP BY DATE(create_time)")
List<GpsStatusVo> getRlList(@Param("bo") GpsEquipmentSonBo bo);
}

View File

@ -1,45 +0,0 @@
package org.dromara.job.once;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.manager.ys7manager.Ys7Manager;
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
import org.dromara.other.service.IOthYs7DeviceService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 同步摄像头设备数据
*
* @author lilemy
* @date 2025/6/13 11:08
*/
@Slf4j
@Component
public class FullSyncYs7DeviceData implements CommandLineRunner {
@Resource
private Ys7Manager ys7Manager;
@Resource
private IOthYs7DeviceService ys7DeviceService;
@Override
public void run(String... args) throws Exception {
log.info("开始同步摄像头设备数据");
try {
List<Ys7QueryDeviceResponseVo> ys7QueryDeviceList = ys7Manager.queryAllDeviceList();
Boolean result = ys7DeviceService.saveOrUpdateByDeviceList(ys7QueryDeviceList);
if (result) {
log.info("摄像头设备数据同步成功");
} else {
log.info("没有需要同步的设备");
}
} catch (Exception e) {
log.info("摄像头设备数据同步失败", e);
}
}
}

View File

@ -26,16 +26,20 @@ import org.dromara.common.utils.DocumentUtil;
import org.dromara.materials.constants.MatMaterialsConstant;
import org.dromara.materials.domain.MatMaterialReceive;
import org.dromara.materials.domain.MatMaterialReceiveItem;
import org.dromara.materials.domain.MatMaterials;
import org.dromara.materials.domain.MatMaterialsInventory;
import org.dromara.materials.domain.dto.materialreceive.MatMaterialReceiveCreateReq;
import org.dromara.materials.domain.dto.materialreceive.MatMaterialReceiveQueryReq;
import org.dromara.materials.domain.dto.materialreceive.MatMaterialReceiveUpdateReq;
import org.dromara.materials.domain.dto.materialreceive.MatMaterialReceiveWordDto;
import org.dromara.materials.domain.dto.materialreceiveitem.MatMaterialReceiveItemDto;
import org.dromara.materials.domain.dto.materialreceiveitem.MatMaterialReceiveItemWordDto;
import org.dromara.materials.domain.enums.MatMaterialsInventoryOutPutEnum;
import org.dromara.materials.domain.vo.materialreceive.MatMaterialReceiveVo;
import org.dromara.materials.mapper.MatMaterialReceiveMapper;
import org.dromara.materials.service.IMatMaterialReceiveItemService;
import org.dromara.materials.service.IMatMaterialReceiveService;
import org.dromara.materials.service.IMatMaterialsInventoryService;
import org.dromara.materials.service.IMatMaterialsService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.system.domain.vo.SysOssVo;
@ -53,6 +57,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipOutputStream;
/**
@ -81,6 +86,9 @@ public class MatMaterialReceiveServiceImpl extends ServiceImpl<MatMaterialReceiv
@Resource
private IMatMaterialsService materialsService;
@Resource
private IMatMaterialsInventoryService materialsInventoryService;
/**
* 查询物料接收单
*
@ -366,12 +374,37 @@ public class MatMaterialReceiveServiceImpl extends ServiceImpl<MatMaterialReceiv
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteByIds(Collection<Long> ids) {
List<MatMaterialReceive> receiveList = this.listByIds(ids);
List<MatMaterialReceiveItem> itemList = materialReceiveItemService.lambdaQuery()
.in(MatMaterialReceiveItem::getReceiveId, ids)
.list();
if (CollUtil.isNotEmpty(itemList)) {
materialReceiveItemService.removeBatchByIds(itemList);
}
// 关联删除材料数据
Set<String> formCode = receiveList.stream().map(MatMaterialReceive::getFormCode).collect(Collectors.toSet());
List<MatMaterials> materials = materialsService.lambdaQuery()
.in(MatMaterials::getFormCode, formCode)
.list();
if (CollUtil.isNotEmpty(materials)) {
for (MatMaterials material : materials) {
List<MatMaterialsInventory> inventoryList = materialsInventoryService.lambdaQuery()
.eq(MatMaterialsInventory::getMaterialsId, material.getId())
.eq(MatMaterialsInventory::getOutPut, MatMaterialsInventoryOutPutEnum.OUT.getValue())
.list();
if (CollUtil.isNotEmpty(inventoryList)) {
throw new ServiceException("存在关联的库存数据,无法删除", HttpStatus.BAD_REQUEST);
}
Set<Long> materialIds = materials.stream().map(MatMaterials::getId).collect(Collectors.toSet());
List<MatMaterialsInventory> allInventoryList = materialsInventoryService.lambdaQuery()
.in(MatMaterialsInventory::getMaterialsId, materialIds)
.list();
if (CollUtil.isNotEmpty(allInventoryList)) {
materialsInventoryService.removeBatchByIds(allInventoryList);
}
}
materialsService.removeBatchByIds(materials);
}
return this.removeBatchByIds(ids);
}

View File

@ -668,11 +668,13 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
BeanUtils.copyProperties(material, vo);
Long id = material.getId();
MatMaterialsInventory put = putMap.get(id);
vo.setSupplier(put.getRecipient());
vo.setInventoryId(put.getId());
vo.setNumber(put.getNumber());
vo.setOperator(put.getOperator());
vo.setEnterTime(put.getCreateTime());
if (put != null) {
vo.setSupplier(put.getRecipient());
vo.setInventoryId(put.getId());
vo.setNumber(put.getNumber());
vo.setOperator(put.getOperator());
vo.setEnterTime(put.getCreateTime());
}
if (CollUtil.isNotEmpty(outList)) {
List<MatMaterialsInventory> outs = outList.stream()
.filter(inventory -> inventory.getMaterialsId().equals(id))

View File

@ -5,8 +5,10 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import java.util.stream.Stream;
//@Configuration
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {

View File

@ -162,6 +162,12 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
Long id = progressPlan.getId();
List<PgsProgressPlanDetailCreateDto> detailList = req.getDetailList();
if (CollUtil.isNotEmpty(detailList)) {
// 判断详情数量是否合法
boolean isAnyEmpty = detailList.stream()
.allMatch(detail -> detail.getPlanNumber().compareTo(BigDecimal.ZERO) <= 0);
if (isAnyEmpty) {
throw new ServiceException("新增进度计划详情失败,请进行均分", HttpStatus.BAD_REQUEST);
}
List<PgsProgressPlanDetail> newDetailList = detailList.stream().map(detail -> {
PgsProgressPlanDetail progressPlanDetail = new PgsProgressPlanDetail();
BeanUtils.copyProperties(detail, progressPlanDetail);

View File

@ -91,4 +91,17 @@ public class BusAttendanceMachineController extends BaseController {
@PathVariable Long[] ids) {
return toAjax(busAttendanceMachineService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 批量重新下发
*/
@SaCheckPermission("project:attendanceMachine:reissue")
@RepeatSubmit()
@PostMapping("/reissue/{ids}")
public R<Void> reissue(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids){
busAttendanceMachineService.reissue(List.of(ids));
return R.ok("已开始执行,请稍后刷新");
}
}

View File

@ -128,8 +128,8 @@ public class BusAttendanceAppController extends BaseController {
* 获取用户打卡异常记录
*/
@GetMapping("/getAbnormalAttendance/{projectId}")
public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId, PageQuery pageQuery){
return attendanceService.getAbnormalAttendance(projectId,pageQuery);
public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId,String handle, PageQuery pageQuery){
return attendanceService.getAbnormalAttendance(projectId,handle,pageQuery);
}
/**

View File

@ -1,12 +1,15 @@
package org.dromara.project.service;
import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.validation.constraints.NotEmpty;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.project.domain.BusAttendanceMachine;
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq;
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq;
import org.dromara.project.domain.vo.BusAttendanceMachineVo;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.Collection;
import java.util.List;
@ -75,4 +78,7 @@ public interface IBusAttendanceMachineService extends IService<BusAttendanceMach
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
void reissue(Collection<Long> ids);
}

View File

@ -131,7 +131,7 @@ public interface IBusAttendanceService extends IService<BusAttendance>{
/**
* 获取用户打卡异常记录
*/
TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId, PageQuery pageQuery);
TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId,String handle, PageQuery pageQuery);
/**
* 统计指定日期的打卡人员

View File

@ -1,6 +1,7 @@
package org.dromara.project.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -28,13 +29,14 @@ import org.dromara.project.service.IBusAttendanceMachineService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusProjectTeamMemberService;
import org.dromara.project.service.IBusProjectTeamService;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -61,8 +63,14 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
private DeviceMessageSender deviceMessageSender;
@Resource
@Lazy
private ISubConstructionUserService constructionUserService;
@Resource
@Lazy
private ISysOssService ossService;
/**
* 查询考勤机
*
@ -300,4 +308,57 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
}
return baseMapper.deleteByIds(ids) > 0;
}
@Async
@Override
public void reissue(Collection<Long> ids) {
List<BusAttendanceMachine> busAttendanceMachines = baseMapper.selectByIds(ids);
for (BusAttendanceMachine machine : busAttendanceMachines) {
String sn = machine.getSn();
try {
deviceMessageSender.deleteAllUsers(sn);
} catch (Exception e) {
log.error("删除考勤人员异常", e);
}
String teams = machine.getTeams();
if (StrUtil.isBlank(teams)) {
continue;
}
List<Long> oldTeamIds = Arrays.stream(teams.split(","))
.map(Long::parseLong)
.distinct()
.toList();
List<Long> userIds = projectTeamMemberService.lambdaQuery()
.select(BusProjectTeamMember::getMemberId)
.in(BusProjectTeamMember::getTeamId, oldTeamIds)
.list()
.stream().map(BusProjectTeamMember::getMemberId)
.toList();
if (CollUtil.isEmpty(userIds)) {
continue;
}
List<SubConstructionUser> users = constructionUserService.lambdaQuery()
.in(SubConstructionUser::getSysUserId, userIds)
.list();
Map<Long, String> faceMap = new HashMap<>();
List<String> list = users.stream().map(SubConstructionUser::getFacePic).filter(StrUtil::isNotBlank).toList();
if (CollUtil.isNotEmpty(list)) {
//转成Long的集合
List<Long> list1 = list.stream().map(Long::parseLong).toList();
List<SysOssVo> sysOssVos = ossService.listByIds(list1);
faceMap = sysOssVos.stream().collect(Collectors.toMap(SysOssVo::getOssId, SysOssVo::getUrl));
}
for (SubConstructionUser user : users) {
String facePic = StrUtil.isBlank(user.getFacePic()) ? "" : faceMap.get(Long.valueOf(user.getFacePic()));
deviceMessageSender.sendPersonnelInformation(sn, user.getSysUserId().toString()
, user.getUserName(), facePic);
}
}
}
}

View File

@ -333,10 +333,11 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
}
//打卡范围
if (!checkInRange(req)) {
throw new ServiceException("打卡位置不在范围内", HttpStatus.ERROR);
if (!"1".equals(req.getSource())){
if (!checkInRange(req)) {
throw new ServiceException("打卡位置不在范围内", HttpStatus.ERROR);
}
}
//用户信息校验
SubConstructionUser constructionUser = constructionUserService.getBySysUserId(userId);
if ("1".equals(constructionUser.getStatus())) {
@ -792,7 +793,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
@Override
public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId, PageQuery pageQuery) {
public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId,String handle, PageQuery pageQuery) {
List<String> abnormalList = Arrays.asList(BusAttendanceClockStatusEnum.LATE.getValue(),
BusAttendanceClockStatusEnum.LEAVEEARLY.getValue(),
@ -809,6 +810,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
IPage<BusAttendanceVo> busAttendanceVoIPage = baseMapper.selectVoPage(pageQuery.build(), Wrappers.lambdaQuery(BusAttendance.class)
.eq(BusAttendance::getUserId, userId)
.eq(StrUtil.isNotBlank(handle), BusAttendance::getHandle, handle)
.eq(b, BusAttendance::getProjectId, projectId)
.in(BusAttendance::getClockStatus, abnormalList)
.ge(BusAttendance::getClockDate, LocalDate.now().minusDays(29))

View File

@ -603,7 +603,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
.eq(BusAttendance::getUserId, busLeave.getUserId())
);
for (BusAttendance attendance : list) {
attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue());
attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue());
}
if(!list.isEmpty()){
attendanceService.updateBatchById(list);
@ -619,7 +619,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
.eq(BusAttendance::getUserId, busLeave.getUserId())
);
for (BusAttendance attendance : list) {
attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue());
attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue());
}
if(!list.isEmpty()){
attendanceService.updateBatchById(list);
@ -635,7 +635,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
.eq(BusAttendance::getUserId, busLeave.getUserId())
);
for (BusAttendance attendance : list) {
attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue());
attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue());
}
if(!list.isEmpty()){
attendanceService.updateBatchById(list);

View File

@ -17,6 +17,7 @@ import org.dromara.common.enums.AppUserTypeEnum;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.utils.AsyncUtil;
import org.dromara.common.utils.IdCardEncryptorUtil;
import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.service.ISubConstructionUserService;
@ -90,6 +91,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
@Resource
private ISysOssService ossService;
@Resource
private AsyncUtil asyncUtil;
/**
* 查询项目班组下的成员
@ -219,6 +222,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
userService.updateFb(constructionUser.getSysUserId(),req.getContractorId(),false);
}
asyncUtil.sendPersonnel(req.getTeamId(), constructionUser);
return projectTeamMember.getId();
}
@ -356,6 +361,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
.set(SubConstructionUser::getTeamId, null)
.set(SubConstructionUser::getLeaveDate, new Date());
constructionUserService.update(constructionUserLuw);
asyncUtil.deletePersonnel(constructionUser);
return true;
}

View File

@ -0,0 +1,118 @@
package org.dromara.vehicle.controller;
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.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.vehicle.domain.dto.vehicleapply.VehVehicleApplyCreateReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyQueryReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyReviewReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyUpdateReq;
import org.dromara.vehicle.domain.vo.VehVehicleApplyVo;
import org.dromara.vehicle.service.IVehVehicleApplyService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 乘车申请
*
* @author lilemy
* @date 2025-10-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/vehicle/vehicleApply")
public class VehVehicleApplyController extends BaseController {
private final IVehVehicleApplyService vehVehicleApplyService;
/**
* 查询乘车申请列表
*/
@SaCheckPermission("vehicle:vehicleApply:list")
@GetMapping("/list")
public TableDataInfo<VehVehicleApplyVo> list(VehVehicleApplyQueryReq req, PageQuery pageQuery) {
return vehVehicleApplyService.queryPageList(req, pageQuery);
}
/**
* 导出乘车申请列表
*/
@SaCheckPermission("vehicle:vehicleApply:export")
@Log(title = "乘车申请", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(VehVehicleApplyQueryReq req, HttpServletResponse response) {
List<VehVehicleApplyVo> list = vehVehicleApplyService.queryList(req);
ExcelUtil.exportExcel(list, "乘车申请", VehVehicleApplyVo.class, response);
}
/**
* 获取乘车申请详细信息
*
* @param id 主键
*/
@SaCheckPermission("vehicle:vehicleApply:query")
@GetMapping("/{id}")
public R<VehVehicleApplyVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(vehVehicleApplyService.queryById(id));
}
/**
* 新增乘车申请
*/
@SaCheckPermission("vehicle:vehicleApply:add")
@Log(title = "乘车申请", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated @RequestBody VehVehicleApplyCreateReq req) {
return toAjax(vehVehicleApplyService.insertByBo(req));
}
/**
* 修改乘车申请
*/
@SaCheckPermission("vehicle:vehicleApply:edit")
@Log(title = "乘车申请", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated @RequestBody VehVehicleApplyUpdateReq req) {
return toAjax(vehVehicleApplyService.updateByBo(req));
}
/**
* 车主审核
*/
@SaCheckPermission("vehicle:vehicleApply:edit")
@Log(title = "乘车申请", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/vehicleOwnerReview")
public R<Void> vehicleOwnerReview(@Validated @RequestBody VehVehicleApplyReviewReq req) {
return toAjax(vehVehicleApplyService.vehicleOwnerReview(req));
}
/**
* 删除乘车申请
*
* @param ids 主键串
*/
@SaCheckPermission("vehicle:vehicleApply:remove")
@Log(title = "乘车申请", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(vehVehicleApplyService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,106 @@
package org.dromara.vehicle.controller;
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.vehicle.domain.bo.VehVehicleInfoBo;
import org.dromara.vehicle.domain.vo.VehVehicleInfoVo;
import org.dromara.vehicle.service.IVehVehicleInfoService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 车辆信息
*
* @author lilemy
* @date 2025-10-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/vehicle/vehicleInfo")
public class VehVehicleInfoController extends BaseController {
private final IVehVehicleInfoService vehVehicleInfoService;
/**
* 查询车辆信息列表
*/
@SaCheckPermission("vehicle:vehicleInfo:list")
@GetMapping("/list")
public TableDataInfo<VehVehicleInfoVo> list(VehVehicleInfoBo bo, PageQuery pageQuery) {
return vehVehicleInfoService.queryPageList(bo, pageQuery);
}
/**
* 导出车辆信息列表
*/
@SaCheckPermission("vehicle:vehicleInfo:export")
@Log(title = "车辆信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(VehVehicleInfoBo bo, HttpServletResponse response) {
List<VehVehicleInfoVo> list = vehVehicleInfoService.queryList(bo);
ExcelUtil.exportExcel(list, "车辆信息", VehVehicleInfoVo.class, response);
}
/**
* 获取车辆信息详细信息
*
* @param id 主键
*/
@SaCheckPermission("vehicle:vehicleInfo:query")
@GetMapping("/{id}")
public R<VehVehicleInfoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(vehVehicleInfoService.queryById(id));
}
/**
* 新增车辆信息
*/
@SaCheckPermission("vehicle:vehicleInfo:add")
@Log(title = "车辆信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody VehVehicleInfoBo bo) {
return toAjax(vehVehicleInfoService.insertByBo(bo));
}
/**
* 修改车辆信息
*/
@SaCheckPermission("vehicle:vehicleInfo:edit")
@Log(title = "车辆信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody VehVehicleInfoBo bo) {
return toAjax(vehVehicleInfoService.updateByBo(bo));
}
/**
* 删除车辆信息
*
* @param ids 主键串
*/
@SaCheckPermission("vehicle:vehicleInfo:remove")
@Log(title = "车辆信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(vehVehicleInfoService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,118 @@
package org.dromara.vehicle.controller;
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.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.vehicle.domain.dto.vehicletrip.VehVehicleTripCancelReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripCreateReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripQueryReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripUpdateReq;
import org.dromara.vehicle.domain.vo.VehVehicleTripVo;
import org.dromara.vehicle.service.IVehVehicleTripService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 车辆出行记录
*
* @author lilemy
* @date 2025-10-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/vehicle/vehicleTrip")
public class VehVehicleTripController extends BaseController {
private final IVehVehicleTripService vehVehicleTripService;
/**
* 查询车辆出行记录列表
*/
@SaCheckPermission("vehicle:vehicleTrip:list")
@GetMapping("/list")
public TableDataInfo<VehVehicleTripVo> list(VehVehicleTripQueryReq req, PageQuery pageQuery) {
return vehVehicleTripService.queryPageList(req, pageQuery);
}
/**
* 导出车辆出行记录列表
*/
@SaCheckPermission("vehicle:vehicleTrip:export")
@Log(title = "车辆出行记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(VehVehicleTripQueryReq req, HttpServletResponse response) {
List<VehVehicleTripVo> list = vehVehicleTripService.queryList(req);
ExcelUtil.exportExcel(list, "车辆出行记录", VehVehicleTripVo.class, response);
}
/**
* 获取车辆出行记录详细信息
*
* @param id 主键
*/
@SaCheckPermission("vehicle:vehicleTrip:query")
@GetMapping("/{id}")
public R<VehVehicleTripVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(vehVehicleTripService.queryById(id));
}
/**
* 新增车辆出行记录
*/
@SaCheckPermission("vehicle:vehicleTrip:add")
@Log(title = "车辆出行记录", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated @RequestBody VehVehicleTripCreateReq req) {
return toAjax(vehVehicleTripService.insertByBo(req));
}
/**
* 修改车辆出行记录
*/
@SaCheckPermission("vehicle:vehicleTrip:edit")
@Log(title = "车辆出行记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated @RequestBody VehVehicleTripUpdateReq req) {
return toAjax(vehVehicleTripService.updateByBo(req));
}
/**
* 取消车辆出行记录
*/
@SaCheckPermission("vehicle:vehicleTrip:edit")
@Log(title = "车辆出行记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/cancel")
public R<Void> cancel(@Validated @RequestBody VehVehicleTripCancelReq req) {
return toAjax(vehVehicleTripService.cancel(req));
}
/**
* 删除车辆出行记录
*
* @param ids 主键串
*/
@SaCheckPermission("vehicle:vehicleTrip:remove")
@Log(title = "车辆出行记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(vehVehicleTripService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,91 @@
package org.dromara.vehicle.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
/**
* 乘车申请对象 veh_vehicle_apply
*
* @author lilemy
* @date 2025-10-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("veh_vehicle_apply")
public class VehVehicleApply extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 项目ID
*/
private Long projectId;
/**
* 关联行程ID
*/
private Long tripId;
/**
* 申请人数
*/
private Integer peopleNum;
/**
* 联系电话
*/
private String passengerPhone;
/**
* 出发地
*/
private String startPlace;
/**
* 目的地
*/
private String endPlace;
/**
* 出发地经度
*/
private String startLat;
/**
* 出发地纬度
*/
private String startLng;
/**
* 目的地经度
*/
private String endLat;
/**
* 目的地纬度
*/
private String endLng;
/**
* 乘车状态
*/
private String status;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,148 @@
package org.dromara.vehicle.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* 车辆信息对象 veh_vehicle_info
*
* @author lilemy
* @date 2025-10-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("veh_vehicle_info")
public class VehVehicleInfo extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 项目ID
*/
private Long projectId;
/**
* 车牌号
*/
private String plateNumber;
/**
* 车辆品牌
*/
private String vehicleBrand;
/**
* 车辆类型
*/
private String vehicleType;
/**
* 车辆颜色
*/
private String vehicleColor;
/**
* 座位数
*/
private Integer seatCount;
/**
* 燃料类型
*/
private String fuelType;
/**
* 车辆状态
*/
private String vehicleStatus;
/**
* 车长(米)
*/
private BigDecimal vehicleLength;
/**
* 车宽(米)
*/
private BigDecimal vehicleWidth;
/**
* 车高(米)
*/
private BigDecimal vehicleHeight;
/**
* 轴距(米)
*/
private BigDecimal wheelBase;
/**
* 轮距(米)
*/
private BigDecimal wheelTrack;
/**
* 车辆性质
*/
private String ownerType;
/**
* 租赁方信息
*/
private String rentalCompany;
/**
* 登记证书编号(车管所登记凭证)
*/
private String registrationCertNo;
/**
* 登记日期
*/
private LocalDate registerDate;
/**
* 购置日期
*/
private LocalDate purchaseDate;
/**
* 购置价格
*/
private BigDecimal purchasePrice;
/**
* 保险到期时间
*/
private LocalDate insuranceExpiry;
/**
* 年检到期时间
*/
private LocalDate inspectionExpiry;
/**
* 附件ID
*/
private String fileIds;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,122 @@
package org.dromara.vehicle.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 车辆出行记录对象 veh_vehicle_trip
*
* @author lilemy
* @date 2025-10-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("veh_vehicle_trip")
public class VehVehicleTrip extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 项目ID
*/
private Long projectId;
/**
* 车辆ID
*/
private Long vehicleId;
/**
* 车牌号
*/
private String plateNumber;
/**
* 联系电话
*/
private String passengerPhone;
/**
* 出行事由
*/
private String tripReason;
/**
* 出发地
*/
private String startPlace;
/**
* 目的地
*/
private String endPlace;
/**
* 出发地经度
*/
private String startLat;
/**
* 出发地纬度
*/
private String startLng;
/**
* 目的地经度
*/
private String endLat;
/**
* 目的地纬度
*/
private String endLng;
/**
* 计划出发时间
*/
private Date startTime;
/**
* 计划到达时间
*/
private Date endTime;
/**
* 申请人数
*/
private Integer peopleNum;
/**
* 剩余座位数
*/
private Integer leftSeat;
/**
* 审核状态
*/
private String reviewStatus;
/**
* 状态
*/
private String tripStatus;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,158 @@
package org.dromara.vehicle.domain.bo;
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.mybatis.core.domain.BaseEntity;
import org.dromara.vehicle.domain.VehVehicleInfo;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* 车辆信息业务对象 veh_vehicle_info
*
* @author lilemy
* @date 2025-10-25
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = VehVehicleInfo.class, reverseConvertGenerate = false)
public class VehVehicleInfoBo extends BaseEntity {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
private Long id;
/**
* 项目ID
*/
@NotNull(message = "项目ID不能为空", groups = {AddGroup.class, EditGroup.class})
private Long projectId;
/**
* 车牌号
*/
@NotBlank(message = "车牌号不能为空", groups = {AddGroup.class, EditGroup.class})
private String plateNumber;
/**
* 车辆品牌
*/
@NotBlank(message = "车辆品牌不能为空", groups = {AddGroup.class, EditGroup.class})
private String vehicleBrand;
/**
* 车辆类型
*/
@NotBlank(message = "车辆类型不能为空", groups = {AddGroup.class, EditGroup.class})
private String vehicleType;
/**
* 车辆颜色
*/
@NotBlank(message = "车辆颜色不能为空", groups = {AddGroup.class, EditGroup.class})
private String vehicleColor;
/**
* 座位数
*/
@NotNull(message = "座位数不能为空", groups = {AddGroup.class, EditGroup.class})
private Integer seatCount;
/**
* 燃料类型
*/
@NotBlank(message = "燃料类型不能为空", groups = {AddGroup.class, EditGroup.class})
private String fuelType;
/**
* 车辆状态
*/
@NotBlank(message = "车辆状态不能为空", groups = {AddGroup.class, EditGroup.class})
private String vehicleStatus;
/**
* 车长(米)
*/
private BigDecimal vehicleLength;
/**
* 车宽(米)
*/
private BigDecimal vehicleWidth;
/**
* 车高(米)
*/
private BigDecimal vehicleHeight;
/**
* 轴距(米)
*/
private BigDecimal wheelBase;
/**
* 轮距(米)
*/
private BigDecimal wheelTrack;
/**
* 车辆性质
*/
@NotBlank(message = "车辆性质不能为空", groups = {AddGroup.class, EditGroup.class})
private String ownerType;
/**
* 租赁方信息
*/
private String rentalCompany;
/**
* 登记证书编号(车管所登记凭证)
*/
private String registrationCertNo;
/**
* 登记日期
*/
private LocalDate registerDate;
/**
* 购置日期
*/
private LocalDate purchaseDate;
/**
* 购置价格
*/
private BigDecimal purchasePrice;
/**
* 保险到期时间
*/
private LocalDate insuranceExpiry;
/**
* 年检到期时间
*/
private LocalDate inspectionExpiry;
/**
* 附件ID
*/
private String fileIds;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,80 @@
package org.dromara.vehicle.domain.dto.vehicleapply;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-10-27 14:15
*/
@Data
public class VehVehicleApplyCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = 1199219811382958686L;
/**
* 项目ID
*/
@NotNull(message = "项目ID不能为空")
private Long projectId;
/**
* 关联行程ID
*/
@NotNull(message = "关联行程ID不能为空")
private Long tripId;
/**
* 申请人数
*/
@NotNull(message = "申请人数不能为空")
private Integer peopleNum;
/**
* 联系电话
*/
private String passengerPhone;
/**
* 出发地
*/
private String startPlace;
/**
* 目的地
*/
@NotBlank(message = "目的地不能为空")
private String endPlace;
/**
* 出发地经度
*/
private String startLat;
/**
* 出发地纬度
*/
private String startLng;
/**
* 目的地经度
*/
@NotBlank(message = "目的地经度不能为空")
private String endLat;
/**
* 目的地纬度
*/
@NotBlank(message = "目的地纬度不能为空")
private String endLng;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,52 @@
package org.dromara.vehicle.domain.dto.vehicleapply;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-10-27 14:48
*/
@Data
public class VehVehicleApplyQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -7148064523789231728L;
/**
* 项目ID
*/
private Long projectId;
/**
* 关联行程ID
*/
private Long tripId;
/**
* 申请人数
*/
private Integer peopleNum;
/**
* 联系电话
*/
private String passengerPhone;
/**
* 出发地
*/
private String startPlace;
/**
* 目的地
*/
private String endPlace;
/**
* 乘车状态
*/
private String status;
}

View File

@ -0,0 +1,31 @@
package org.dromara.vehicle.domain.dto.vehicleapply;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-10-27 15:00
*/
@Data
public class VehVehicleApplyReviewReq implements Serializable {
@Serial
private static final long serialVersionUID = -5881272503469997069L;
/**
* 主键
*/
@NotNull(message = "主键不能为空")
private Long id;
/**
* 乘车状态
*/
@NotBlank(message = "乘车状态不能为空")
private String status;
}

View File

@ -0,0 +1,79 @@
package org.dromara.vehicle.domain.dto.vehicleapply;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-10-27 15:30
*/
@Data
public class VehVehicleApplyUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = 7272254511495824388L;
/**
* 主键ID
*/
@NotNull(message = "主键不能为空")
private Long id;
/**
* 项目ID
*/
private Long projectId;
/**
* 关联行程ID
*/
private Long tripId;
/**
* 申请人数
*/
private Integer peopleNum;
/**
* 联系电话
*/
private String passengerPhone;
/**
* 出发地
*/
private String startPlace;
/**
* 目的地
*/
private String endPlace;
/**
* 出发地经度
*/
private String startLat;
/**
* 出发地纬度
*/
private String startLng;
/**
* 目的地经度
*/
private String endLat;
/**
* 目的地纬度
*/
private String endLng;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,24 @@
package org.dromara.vehicle.domain.dto.vehicletrip;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-10-27 09:22
*/
@Data
public class VehVehicleTripCancelReq implements Serializable {
@Serial
private static final long serialVersionUID = 7690656986769836247L;
/**
* 主键ID
*/
@NotNull(message = "主键不能为空")
private Long id;
}

View File

@ -0,0 +1,109 @@
package org.dromara.vehicle.domain.dto.vehicletrip;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lilemy
* @date 2025-10-27 10:05
*/
@Data
public class VehVehicleTripCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = 7691668678158594767L;
/**
* 项目ID
*/
private Long projectId;
/**
* 车辆ID
*/
private Long vehicleId;
/**
* 车牌号
*/
private String plateNumber;
/**
* 联系电话
*/
private String passengerPhone;
/**
* 出行事由
*/
private String tripReason;
/**
* 出发地
*/
@NotBlank(message = "出发地不能为空")
private String startPlace;
/**
* 目的地
*/
@NotBlank(message = "目的地不能为空")
private String endPlace;
/**
* 出发地经度
*/
@NotBlank(message = "出发地经度不能为空")
private String startLat;
/**
* 出发地纬度
*/
@NotBlank(message = "出发地纬度不能为空")
private String startLng;
/**
* 目的地经度
*/
@NotBlank(message = "目的地经度不能为空")
private String endLat;
/**
* 目的地纬度
*/
@NotBlank(message = "目的地纬度不能为空")
private String endLng;
/**
* 计划出发时间
*/
@NotNull(message = "计划出发时间不能为空")
private Date startTime;
/**
* 计划到达时间
*/
private Date endTime;
/**
* 申请人数
*/
@NotNull(message = "申请人数不能为空")
private Integer peopleNum;
/**
* 剩余座位数
*/
@NotNull(message = "剩余座位数不能为空")
private Integer leftSeat;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,54 @@
package org.dromara.vehicle.domain.dto.vehicletrip;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lilemy
* @date 2025-10-25 19:40
*/
@Data
public class VehVehicleTripQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -7795154504461471208L;
/**
* 项目ID
*/
private Long projectId;
/**
* 目的地
*/
private String endPlace;
/**
* 目的地经度
*/
private String endLat;
/**
* 目的地纬度
*/
private String endLng;
/**
* 计划出发时间
*/
private Date startTime;
/**
* 出行人数
*/
private Integer peopleNum;
/**
* 审核状态
*/
private String reviewStatus;
}

View File

@ -0,0 +1,105 @@
package org.dromara.vehicle.domain.dto.vehicletrip;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lilemy
* @date 2025-10-27 11:33
*/
@Data
public class VehVehicleTripUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = 3855392201273235078L;
/**
* 主键ID
*/
@NotNull(message = "主键不能为空")
private Long id;
/**
* 项目ID
*/
private Long projectId;
/**
* 车辆ID
*/
private Long vehicleId;
/**
* 车牌号
*/
private String plateNumber;
/**
* 联系电话
*/
private String passengerPhone;
/**
* 出行事由
*/
private String tripReason;
/**
* 出发地
*/
private String startPlace;
/**
* 目的地
*/
private String endPlace;
/**
* 出发地经度
*/
private String startLat;
/**
* 出发地纬度
*/
private String startLng;
/**
* 目的地经度
*/
private String endLat;
/**
* 目的地纬度
*/
private String endLng;
/**
* 计划出发时间
*/
private Date startTime;
/**
* 计划到达时间
*/
private Date endTime;
/**
* 申请人数
*/
private Integer peopleNum;
/**
* 剩余座位数
*/
private Integer leftSeat;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,27 @@
package org.dromara.vehicle.domain.enums;
import lombok.Getter;
/**
* @author lilemy
* @date 2025-10-27 09:39
*/
@Getter
public enum VehApplyStatusEnum {
APPLYING("申请中", "1"),
CONFIRMED("已确认", "2"),
REJECTED("已拒绝", "3"),
ALREADY("已上车", "4"),
ARRIVED("已到达", "5"),
CANCELED("已取消", "6");
private final String text;
private final String value;
VehApplyStatusEnum(String text, String value) {
this.text = text;
this.value = value;
}
}

View File

@ -0,0 +1,25 @@
package org.dromara.vehicle.domain.enums;
import lombok.Getter;
/**
* @author lilemy
* @date 2025-10-27 09:32
*/
@Getter
public enum VehTripStatusEnum {
READY_DEPART("待出发","1"),
UNDERWAY("进行中","2"),
COMPLETED("已完成","3"),
CANCELED("已取消","4" );
private final String text;
private final String value;
VehTripStatusEnum(String text, String value) {
this.text = text;
this.value = value;
}
}

View File

@ -0,0 +1,25 @@
package org.dromara.vehicle.domain.enums;
import lombok.Getter;
/**
* @author lilemy
* @date 2025-10-27 11:42
*/
@Getter
public enum VehVehicleInfoStatusEnum {
AVAILABLE("可用", "1"),
IN_USE("使用中", "2"),
UNDER_MAINTENANCE("维护中", "3"),
DISABLE("停用", "4");
private final String text;
private final String value;
VehVehicleInfoStatusEnum(String text, String value) {
this.text = text;
this.value = value;
}
}

View File

@ -0,0 +1,111 @@
package org.dromara.vehicle.domain.vo;
import org.dromara.vehicle.domain.VehVehicleApply;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 乘车申请视图对象 veh_vehicle_apply
*
* @author lilemy
* @date 2025-10-25
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = VehVehicleApply.class)
public class VehVehicleApplyVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 项目ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
* 关联行程ID
*/
@ExcelProperty(value = "关联行程ID")
private Long tripId;
/**
* 申请人数
*/
@ExcelProperty(value = "申请人数")
private Integer peopleNum;
/**
* 联系电话
*/
@ExcelProperty(value = "联系电话")
private String passengerPhone;
/**
* 出发地
*/
@ExcelProperty(value = "出发地")
private String startPlace;
/**
* 目的地
*/
@ExcelProperty(value = "目的地")
private String endPlace;
/**
* 出发地经度
*/
@ExcelProperty(value = "出发地经度")
private String startLat;
/**
* 出发地纬度
*/
@ExcelProperty(value = "出发地纬度")
private String startLng;
/**
* 目的地经度
*/
@ExcelProperty(value = "目的地经度")
private String endLat;
/**
* 目的地纬度
*/
@ExcelProperty(value = "目的地纬度")
private String endLng;
/**
* 乘车状态
*/
@ExcelProperty(value = "乘车状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "veh_vehicle_apply_status")
private String status;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,185 @@
package org.dromara.vehicle.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.vehicle.domain.VehVehicleInfo;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* 车辆信息视图对象 veh_vehicle_info
*
* @author lilemy
* @date 2025-10-25
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = VehVehicleInfo.class)
public class VehVehicleInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 项目ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
* 车牌号
*/
@ExcelProperty(value = "车牌号")
private String plateNumber;
/**
* 车辆品牌
*/
@ExcelProperty(value = "车辆品牌")
private String vehicleBrand;
/**
* 车辆类型
*/
@ExcelProperty(value = "车辆类型")
private String vehicleType;
/**
* 车辆颜色
*/
@ExcelProperty(value = "车辆颜色")
private String vehicleColor;
/**
* 座位数
*/
@ExcelProperty(value = "座位数")
private Integer seatCount;
/**
* 燃料类型
*/
@ExcelProperty(value = "燃料类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "veh_vehicle_fuel_type")
private String fuelType;
/**
* 车辆状态
*/
@ExcelProperty(value = "车辆状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "veh_vehicle_status")
private String vehicleStatus;
/**
* 车长(米)
*/
@ExcelProperty(value = "车长", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "米=")
private BigDecimal vehicleLength;
/**
* 车宽(米)
*/
@ExcelProperty(value = "车宽", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "米=")
private BigDecimal vehicleWidth;
/**
* 车高(米)
*/
@ExcelProperty(value = "车高", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "米=")
private BigDecimal vehicleHeight;
/**
* 轴距(米)
*/
@ExcelProperty(value = "轴距", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "米=")
private BigDecimal wheelBase;
/**
* 轮距(米)
*/
@ExcelProperty(value = "轮距", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "米=")
private BigDecimal wheelTrack;
/**
* 车辆性质
*/
@ExcelProperty(value = "车辆性质", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "veh_vehicle_owner_type")
private String ownerType;
/**
* 租赁方信息
*/
@ExcelProperty(value = "租赁方信息")
private String rentalCompany;
/**
* 登记证书编号(车管所登记凭证)
*/
@ExcelProperty(value = "登记证书编号", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "车=管所登记凭证")
private String registrationCertNo;
/**
* 登记日期
*/
@ExcelProperty(value = "登记日期")
private LocalDate registerDate;
/**
* 购置日期
*/
@ExcelProperty(value = "购置日期")
private LocalDate purchaseDate;
/**
* 购置价格
*/
@ExcelProperty(value = "购置价格")
private BigDecimal purchasePrice;
/**
* 保险到期时间
*/
@ExcelProperty(value = "保险到期时间")
private LocalDate insuranceExpiry;
/**
* 年检到期时间
*/
@ExcelProperty(value = "年检到期时间")
private LocalDate inspectionExpiry;
/**
* 附件ID
*/
@ExcelProperty(value = "附件ID")
private String fileIds;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,183 @@
package org.dromara.vehicle.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.vehicle.domain.VehVehicleTrip;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 车辆出行记录视图对象 veh_vehicle_trip
*
* @author lilemy
* @date 2025-10-25
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = VehVehicleTrip.class)
public class VehVehicleTripVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 项目ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
* 车辆ID
*/
@ExcelProperty(value = "车辆ID")
private Long vehicleId;
/**
* 车牌号
*/
@ExcelProperty(value = "车牌号")
private String plateNumber;
/**
* 联系电话
*/
@ExcelProperty(value = "联系电话")
private String passengerPhone;
/**
* 出行事由
*/
@ExcelProperty(value = "出行事由")
private String tripReason;
/**
* 出发地
*/
@ExcelProperty(value = "出发地")
private String startPlace;
/**
* 目的地
*/
@ExcelProperty(value = "目的地")
private String endPlace;
/**
* 出发地经度
*/
@ExcelProperty(value = "出发地经度")
private String startLat;
/**
* 出发地纬度
*/
@ExcelProperty(value = "出发地纬度")
private String startLng;
/**
* 目的地经度
*/
@ExcelProperty(value = "目的地经度")
private String endLat;
/**
* 目的地纬度
*/
@ExcelProperty(value = "目的地纬度")
private String endLng;
/**
* 计划出发时间
*/
@ExcelProperty(value = "计划出发时间")
private Date startTime;
/**
* 计划到达时间
*/
@ExcelProperty(value = "计划到达时间")
private Date endTime;
/**
* 申请人数
*/
@ExcelProperty(value = "申请人数")
private Integer peopleNum;
/**
* 剩余座位数
*/
@ExcelProperty(value = "剩余座位数")
private Integer leftSeat;
/**
* 审核状态
*/
@ExcelProperty(value = "审核状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "wf_business_status")
private String reviewStatus;
/**
* 状态
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "veh_vehicle_trip_status")
private String tripStatus;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 距离(米)
*/
private String distanceM;
/**
* 距离评分
*/
private String distanceScore;
/**
* 时间评分
*/
private String timeScore;
/**
* 人数评分
*/
private String peopleScore;
/**
* 总评分
*/
private String totalScore;
/**
* 创建者
*/
private Long createBy;
/**
* 创建者名称
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy")
private String createByName;
}

View File

@ -0,0 +1,15 @@
package org.dromara.vehicle.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.vehicle.domain.VehVehicleApply;
import org.dromara.vehicle.domain.vo.VehVehicleApplyVo;
/**
* 乘车申请Mapper接口
*
* @author lilemy
* @date 2025-10-25
*/
public interface VehVehicleApplyMapper extends BaseMapperPlus<VehVehicleApply, VehVehicleApplyVo> {
}

View File

@ -0,0 +1,15 @@
package org.dromara.vehicle.mapper;
import org.dromara.vehicle.domain.VehVehicleInfo;
import org.dromara.vehicle.domain.vo.VehVehicleInfoVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 车辆信息Mapper接口
*
* @author lilemy
* @date 2025-10-25
*/
public interface VehVehicleInfoMapper extends BaseMapperPlus<VehVehicleInfo, VehVehicleInfoVo> {
}

View File

@ -0,0 +1,21 @@
package org.dromara.vehicle.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.vehicle.domain.VehVehicleTrip;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripQueryReq;
import org.dromara.vehicle.domain.vo.VehVehicleTripVo;
/**
* 车辆出行记录Mapper接口
*
* @author lilemy
* @date 2025-10-25
*/
public interface VehVehicleTripMapper extends BaseMapperPlus<VehVehicleTrip, VehVehicleTripVo> {
Page<VehVehicleTripVo> selectVehicleTripPage(@Param("page") Page<VehVehicleTrip> page,
@Param("req") VehVehicleTripQueryReq req);
}

View File

@ -0,0 +1,81 @@
package org.dromara.vehicle.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.vehicle.domain.VehVehicleApply;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyCreateReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyQueryReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyReviewReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyUpdateReq;
import org.dromara.vehicle.domain.vo.VehVehicleApplyVo;
import java.util.Collection;
import java.util.List;
/**
* 乘车申请Service接口
*
* @author lilemy
* @date 2025-10-25
*/
public interface IVehVehicleApplyService extends IService<VehVehicleApply> {
/**
* 查询乘车申请
*
* @param id 主键
* @return 乘车申请
*/
VehVehicleApplyVo queryById(Long id);
/**
* 分页查询乘车申请列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 乘车申请分页列表
*/
TableDataInfo<VehVehicleApplyVo> queryPageList(VehVehicleApplyQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的乘车申请列表
*
* @param req 查询条件
* @return 乘车申请列表
*/
List<VehVehicleApplyVo> queryList(VehVehicleApplyQueryReq req);
/**
* 新增乘车申请
*
* @param req 乘车申请
* @return 是否新增成功
*/
Boolean insertByBo(VehVehicleApplyCreateReq req);
/**
* 修改乘车申请
*
* @param req 乘车申请
* @return 是否修改成功
*/
Boolean updateByBo(VehVehicleApplyUpdateReq req);
/**
* 车主审核
*
* @param req 审核信息
* @return 是否审核成功
*/
Boolean vehicleOwnerReview(VehVehicleApplyReviewReq req);
/**
* 校验并批量删除乘车申请信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,70 @@
package org.dromara.vehicle.service;
import org.dromara.vehicle.domain.vo.VehVehicleInfoVo;
import org.dromara.vehicle.domain.bo.VehVehicleInfoBo;
import org.dromara.vehicle.domain.VehVehicleInfo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.Collection;
import java.util.List;
/**
* 车辆信息Service接口
*
* @author lilemy
* @date 2025-10-25
*/
public interface IVehVehicleInfoService extends IService<VehVehicleInfo>{
/**
* 查询车辆信息
*
* @param id 主键
* @return 车辆信息
*/
VehVehicleInfoVo queryById(Long id);
/**
* 分页查询车辆信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 车辆信息分页列表
*/
TableDataInfo<VehVehicleInfoVo> queryPageList(VehVehicleInfoBo bo, PageQuery pageQuery);
/**
* 查询符合条件的车辆信息列表
*
* @param bo 查询条件
* @return 车辆信息列表
*/
List<VehVehicleInfoVo> queryList(VehVehicleInfoBo bo);
/**
* 新增车辆信息
*
* @param bo 车辆信息
* @return 是否新增成功
*/
Boolean insertByBo(VehVehicleInfoBo bo);
/**
* 修改车辆信息
*
* @param bo 车辆信息
* @return 是否修改成功
*/
Boolean updateByBo(VehVehicleInfoBo bo);
/**
* 校验并批量删除车辆信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,81 @@
package org.dromara.vehicle.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.vehicle.domain.VehVehicleTrip;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripCancelReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripCreateReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripQueryReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripUpdateReq;
import org.dromara.vehicle.domain.vo.VehVehicleTripVo;
import java.util.Collection;
import java.util.List;
/**
* 车辆出行记录Service接口
*
* @author lilemy
* @date 2025-10-25
*/
public interface IVehVehicleTripService extends IService<VehVehicleTrip> {
/**
* 查询车辆出行记录
*
* @param id 主键
* @return 车辆出行记录
*/
VehVehicleTripVo queryById(Long id);
/**
* 分页查询车辆出行记录列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 车辆出行记录分页列表
*/
TableDataInfo<VehVehicleTripVo> queryPageList(VehVehicleTripQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的车辆出行记录列表
*
* @param req 查询条件
* @return 车辆出行记录列表
*/
List<VehVehicleTripVo> queryList(VehVehicleTripQueryReq req);
/**
* 新增车辆出行记录
*
* @param req 车辆出行记录
* @return 是否新增成功
*/
Boolean insertByBo(VehVehicleTripCreateReq req);
/**
* 修改车辆出行记录
*
* @param req 车辆出行记录
* @return 是否修改成功
*/
Boolean updateByBo(VehVehicleTripUpdateReq req);
/**
* 取消车辆出行记录
*
* @param req 车辆出行记录
* @return 是否取消成功
*/
Boolean cancel(VehVehicleTripCancelReq req);
/**
* 校验并批量删除车辆出行记录信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -0,0 +1,233 @@
package org.dromara.vehicle.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.vehicle.domain.VehVehicleApply;
import org.dromara.vehicle.domain.VehVehicleTrip;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyCreateReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyQueryReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyReviewReq;
import org.dromara.vehicle.domain.dto.vehicleapply.VehVehicleApplyUpdateReq;
import org.dromara.vehicle.domain.enums.VehApplyStatusEnum;
import org.dromara.vehicle.domain.vo.VehVehicleApplyVo;
import org.dromara.vehicle.mapper.VehVehicleApplyMapper;
import org.dromara.vehicle.service.IVehVehicleApplyService;
import org.dromara.vehicle.service.IVehVehicleTripService;
import org.dromara.websocket.ChatServerHandler;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
/**
* 乘车申请Service业务层处理
*
* @author lilemy
* @date 2025-10-25
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class VehVehicleApplyServiceImpl extends ServiceImpl<VehVehicleApplyMapper, VehVehicleApply>
implements IVehVehicleApplyService {
private final IVehVehicleTripService vehicleTripService;
private final ChatServerHandler chatServerHandler;
/**
* 查询乘车申请
*
* @param id 主键
* @return 乘车申请
*/
@Override
public VehVehicleApplyVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询乘车申请列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 乘车申请分页列表
*/
@Override
public TableDataInfo<VehVehicleApplyVo> queryPageList(VehVehicleApplyQueryReq req, PageQuery pageQuery) {
LambdaQueryWrapper<VehVehicleApply> lqw = buildQueryWrapper(req);
Page<VehVehicleApplyVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的乘车申请列表
*
* @param req 查询条件
* @return 乘车申请列表
*/
@Override
public List<VehVehicleApplyVo> queryList(VehVehicleApplyQueryReq req) {
LambdaQueryWrapper<VehVehicleApply> lqw = buildQueryWrapper(req);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<VehVehicleApply> buildQueryWrapper(VehVehicleApplyQueryReq req) {
LambdaQueryWrapper<VehVehicleApply> lqw = Wrappers.lambdaQuery();
lqw.orderByDesc(VehVehicleApply::getId);
lqw.eq(req.getProjectId() != null, VehVehicleApply::getProjectId, req.getProjectId());
lqw.eq(req.getTripId() != null, VehVehicleApply::getTripId, req.getTripId());
lqw.eq(req.getPeopleNum() != null, VehVehicleApply::getPeopleNum, req.getPeopleNum());
lqw.eq(StringUtils.isNotBlank(req.getPassengerPhone()), VehVehicleApply::getPassengerPhone, req.getPassengerPhone());
lqw.eq(StringUtils.isNotBlank(req.getStartPlace()), VehVehicleApply::getStartPlace, req.getStartPlace());
lqw.eq(StringUtils.isNotBlank(req.getEndPlace()), VehVehicleApply::getEndPlace, req.getEndPlace());
lqw.eq(StringUtils.isNotBlank(req.getStatus()), VehVehicleApply::getStatus, req.getStatus());
return lqw;
}
/**
* 新增乘车申请
*
* @param req 乘车申请
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(VehVehicleApplyCreateReq req) {
VehVehicleApply apply = new VehVehicleApply();
BeanUtils.copyProperties(req, apply);
validEntityBeforeSave(apply);
VehVehicleTrip vehicleTrip = vehicleTripService.getById(req.getTripId());
if (vehicleTrip == null) {
throw new ServiceException("行程不存在", HttpStatus.NOT_FOUND);
}
boolean save = this.save(apply);
if (!save) {
throw new ServiceException("新增失败");
}
// 发送消息
CompletableFuture.runAsync(() -> {
Long createBy = vehicleTrip.getCreateBy();
String title = "有乘客申请乘车,请及时查看!";
try {
chatServerHandler.sendSystemMessageToUser(createBy, title, "4");
} catch (Exception e) {
log.error("异步发送系统消息失败用户ID: {}, 消息: {}", createBy, title, e);
}
});
return true;
}
/**
* 修改乘车申请
*
* @param req 乘车申请
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(VehVehicleApplyUpdateReq req) {
// 获取旧数据
VehVehicleApply oldApply = this.getById(req.getId());
if (oldApply == null) {
throw new ServiceException("数据不存在", HttpStatus.NOT_FOUND);
}
VehVehicleApply apply = new VehVehicleApply();
BeanUtils.copyProperties(req, apply);
validEntityBeforeSave(apply);
return this.updateById(apply);
}
/**
* 车主审核
*
* @param req 审核信息
* @return 是否审核成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean vehicleOwnerReview(VehVehicleApplyReviewReq req) {
Long id = req.getId();
String status = req.getStatus();
// 获取数据
VehVehicleApply apply = this.getById(id);
if (apply == null) {
throw new ServiceException("数据不存在", HttpStatus.NOT_FOUND);
}
String applyStatus = apply.getStatus();
if (Objects.equals(applyStatus, VehApplyStatusEnum.CANCELED.getValue())) {
throw new ServiceException("该申请已取消,无需审核", HttpStatus.BAD_REQUEST);
}
if (Objects.equals(applyStatus, VehApplyStatusEnum.ALREADY.getValue())
|| Objects.equals(applyStatus, VehApplyStatusEnum.ARRIVED.getValue())) {
throw new ServiceException("该申请已上车,无需审核", HttpStatus.BAD_REQUEST);
}
// 获取行程信息
VehVehicleTrip vehicleTrip = vehicleTripService.getById(apply.getTripId());
if (vehicleTrip == null) {
throw new ServiceException("行程不存在", HttpStatus.NOT_FOUND);
}
if (Objects.equals(status, VehApplyStatusEnum.CONFIRMED.getValue())) {
// 修改行程信息
int left = vehicleTrip.getLeftSeat() - apply.getPeopleNum();
if (left < 0) {
throw new ServiceException("座位不足", HttpStatus.BAD_REQUEST);
}
vehicleTrip.setLeftSeat(left);
boolean updateTrip = vehicleTripService.updateById(vehicleTrip);
if (!updateTrip) {
throw new ServiceException("行程信息更新失败", HttpStatus.ERROR);
}
}
apply.setStatus(status);
boolean updateApply = this.updateById(apply);
if (!updateApply) {
throw new ServiceException("行程信息更新失败", HttpStatus.ERROR);
}
// 通知申请人
CompletableFuture.runAsync(() -> {
Long createBy = apply.getCreateBy();
String title = Objects.equals(status, VehApplyStatusEnum.CONFIRMED.getValue()) ?
"您申请的行程已通过审核,请及时查看!" : "您申请的行程未通过审核,请及时查看!";
try {
chatServerHandler.sendSystemMessageToUser(createBy, title, "4");
} catch (Exception e) {
log.error("异步发送系统消息失败用户ID: {}, 消息: {}", createBy, title, e);
}
});
return true;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(VehVehicleApply entity) {
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除乘车申请信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,153 @@
package org.dromara.vehicle.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.vehicle.domain.VehVehicleInfo;
import org.dromara.vehicle.domain.bo.VehVehicleInfoBo;
import org.dromara.vehicle.domain.vo.VehVehicleInfoVo;
import org.dromara.vehicle.mapper.VehVehicleInfoMapper;
import org.dromara.vehicle.service.IVehVehicleInfoService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 车辆信息Service业务层处理
*
* @author lilemy
* @date 2025-10-25
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class VehVehicleInfoServiceImpl extends ServiceImpl<VehVehicleInfoMapper, VehVehicleInfo>
implements IVehVehicleInfoService {
/**
* 查询车辆信息
*
* @param id 主键
* @return 车辆信息
*/
@Override
public VehVehicleInfoVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询车辆信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 车辆信息分页列表
*/
@Override
public TableDataInfo<VehVehicleInfoVo> queryPageList(VehVehicleInfoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<VehVehicleInfo> lqw = buildQueryWrapper(bo);
Page<VehVehicleInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的车辆信息列表
*
* @param bo 查询条件
* @return 车辆信息列表
*/
@Override
public List<VehVehicleInfoVo> queryList(VehVehicleInfoBo bo) {
LambdaQueryWrapper<VehVehicleInfo> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<VehVehicleInfo> buildQueryWrapper(VehVehicleInfoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<VehVehicleInfo> lqw = Wrappers.lambdaQuery();
lqw.orderByDesc(VehVehicleInfo::getId);
lqw.eq(bo.getProjectId() != null, VehVehicleInfo::getProjectId, bo.getProjectId());
lqw.eq(StringUtils.isNotBlank(bo.getPlateNumber()), VehVehicleInfo::getPlateNumber, bo.getPlateNumber());
lqw.eq(StringUtils.isNotBlank(bo.getVehicleBrand()), VehVehicleInfo::getVehicleBrand, bo.getVehicleBrand());
lqw.eq(StringUtils.isNotBlank(bo.getVehicleType()), VehVehicleInfo::getVehicleType, bo.getVehicleType());
lqw.eq(StringUtils.isNotBlank(bo.getVehicleColor()), VehVehicleInfo::getVehicleColor, bo.getVehicleColor());
lqw.eq(bo.getSeatCount() != null, VehVehicleInfo::getSeatCount, bo.getSeatCount());
lqw.eq(StringUtils.isNotBlank(bo.getFuelType()), VehVehicleInfo::getFuelType, bo.getFuelType());
lqw.eq(StringUtils.isNotBlank(bo.getVehicleStatus()), VehVehicleInfo::getVehicleStatus, bo.getVehicleStatus());
lqw.eq(bo.getVehicleLength() != null, VehVehicleInfo::getVehicleLength, bo.getVehicleLength());
lqw.eq(bo.getVehicleWidth() != null, VehVehicleInfo::getVehicleWidth, bo.getVehicleWidth());
lqw.eq(bo.getVehicleHeight() != null, VehVehicleInfo::getVehicleHeight, bo.getVehicleHeight());
lqw.eq(bo.getWheelBase() != null, VehVehicleInfo::getWheelBase, bo.getWheelBase());
lqw.eq(bo.getWheelTrack() != null, VehVehicleInfo::getWheelTrack, bo.getWheelTrack());
lqw.eq(StringUtils.isNotBlank(bo.getOwnerType()), VehVehicleInfo::getOwnerType, bo.getOwnerType());
lqw.eq(StringUtils.isNotBlank(bo.getRentalCompany()), VehVehicleInfo::getRentalCompany, bo.getRentalCompany());
lqw.eq(StringUtils.isNotBlank(bo.getRegistrationCertNo()), VehVehicleInfo::getRegistrationCertNo, bo.getRegistrationCertNo());
lqw.eq(bo.getRegisterDate() != null, VehVehicleInfo::getRegisterDate, bo.getRegisterDate());
lqw.eq(bo.getPurchaseDate() != null, VehVehicleInfo::getPurchaseDate, bo.getPurchaseDate());
lqw.eq(bo.getPurchasePrice() != null, VehVehicleInfo::getPurchasePrice, bo.getPurchasePrice());
lqw.eq(bo.getInsuranceExpiry() != null, VehVehicleInfo::getInsuranceExpiry, bo.getInsuranceExpiry());
lqw.eq(bo.getInspectionExpiry() != null, VehVehicleInfo::getInspectionExpiry, bo.getInspectionExpiry());
lqw.eq(StringUtils.isNotBlank(bo.getFileIds()), VehVehicleInfo::getFileIds, bo.getFileIds());
return lqw;
}
/**
* 新增车辆信息
*
* @param bo 车辆信息
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(VehVehicleInfoBo bo) {
VehVehicleInfo add = MapstructUtils.convert(bo, VehVehicleInfo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改车辆信息
*
* @param bo 车辆信息
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(VehVehicleInfoBo bo) {
VehVehicleInfo update = MapstructUtils.convert(bo, VehVehicleInfo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(VehVehicleInfo entity) {
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除车辆信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@ -0,0 +1,345 @@
package org.dromara.vehicle.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.PhoneUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysUserService;
import org.dromara.vehicle.domain.VehVehicleApply;
import org.dromara.vehicle.domain.VehVehicleInfo;
import org.dromara.vehicle.domain.VehVehicleTrip;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripCancelReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripCreateReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripQueryReq;
import org.dromara.vehicle.domain.dto.vehicletrip.VehVehicleTripUpdateReq;
import org.dromara.vehicle.domain.enums.VehApplyStatusEnum;
import org.dromara.vehicle.domain.enums.VehTripStatusEnum;
import org.dromara.vehicle.domain.enums.VehVehicleInfoStatusEnum;
import org.dromara.vehicle.domain.vo.VehVehicleTripVo;
import org.dromara.vehicle.mapper.VehVehicleTripMapper;
import org.dromara.vehicle.service.IVehVehicleApplyService;
import org.dromara.vehicle.service.IVehVehicleInfoService;
import org.dromara.vehicle.service.IVehVehicleTripService;
import org.dromara.websocket.ChatServerHandler;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* 车辆出行记录Service业务层处理
*
* @author lilemy
* @date 2025-10-25
*/
@Slf4j
@Service
public class VehVehicleTripServiceImpl extends ServiceImpl<VehVehicleTripMapper, VehVehicleTrip>
implements IVehVehicleTripService {
@Lazy
@Resource
private IVehVehicleInfoService vehicleInfoService;
@Lazy
@Resource
private IVehVehicleApplyService vehicleApplyService;
@Resource
private ISysUserService userService;
@Resource
private ChatServerHandler chatServerHandler;
/**
* 查询车辆出行记录
*
* @param id 主键
* @return 车辆出行记录
*/
@Override
public VehVehicleTripVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询车辆出行记录列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 车辆出行记录分页列表
*/
@Override
public TableDataInfo<VehVehicleTripVo> queryPageList(VehVehicleTripQueryReq req, PageQuery pageQuery) {
Page<VehVehicleTripVo> result;
if (StringUtils.isNotBlank(req.getEndLat()) && StringUtils.isNotBlank(req.getEndLng())
&& ObjectUtils.isNotNull(req.getEndLat()) && ObjectUtils.isNotNull(req.getEndLng())) {
result = baseMapper.selectVehicleTripPage(pageQuery.build(), req);
} else {
result = baseMapper.selectVoPage(pageQuery.build(), buildQueryWrapper(req));
}
return TableDataInfo.build(result);
}
/**
* 查询符合条件的车辆出行记录列表
*
* @param req 查询条件
* @return 车辆出行记录列表
*/
@Override
public List<VehVehicleTripVo> queryList(VehVehicleTripQueryReq req) {
LambdaQueryWrapper<VehVehicleTrip> lqw = buildQueryWrapper(req);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<VehVehicleTrip> buildQueryWrapper(VehVehicleTripQueryReq req) {
LambdaQueryWrapper<VehVehicleTrip> lqw = Wrappers.lambdaQuery();
lqw.eq(req.getProjectId() != null, VehVehicleTrip::getProjectId, req.getProjectId());
lqw.eq(StringUtils.isNotBlank(req.getEndPlace()), VehVehicleTrip::getEndPlace, req.getEndPlace());
lqw.eq(StringUtils.isNotBlank(req.getEndLat()), VehVehicleTrip::getEndLat, req.getEndLat());
lqw.eq(StringUtils.isNotBlank(req.getEndLng()), VehVehicleTrip::getEndLng, req.getEndLng());
lqw.eq(req.getStartTime() != null, VehVehicleTrip::getStartTime, req.getStartTime());
lqw.eq(req.getPeopleNum() != null, VehVehicleTrip::getPeopleNum, req.getPeopleNum());
lqw.eq(req.getReviewStatus() != null, VehVehicleTrip::getReviewStatus, req.getReviewStatus());
return lqw;
}
/**
* 新增车辆出行记录
*
* @param req 车辆出行记录
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(VehVehicleTripCreateReq req) {
VehVehicleTrip trip = new VehVehicleTrip();
BeanUtils.copyProperties(req, trip);
validEntityBeforeSave(trip);
// 判断车辆是否被占用
Long vehicleId = trip.getVehicleId();
if (vehicleId != null) {
// 获取车辆信息
VehVehicleInfo vehicle = vehicleInfoService.getById(vehicleId);
if (vehicle == null) {
throw new ServiceException("车辆不存在", HttpStatus.NOT_FOUND);
}
if (!vehicle.getVehicleStatus().equals(VehVehicleInfoStatusEnum.AVAILABLE.getValue())) {
throw new ServiceException("车辆已被占用", HttpStatus.BAD_REQUEST);
}
}
return this.save(trip);
}
/**
* 修改车辆出行记录
*
* @param req 车辆出行记录
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(VehVehicleTripUpdateReq req) {
// 获取旧数据
VehVehicleTrip oldEntity = this.getById(req.getId());
if (oldEntity == null) {
throw new ServiceException("数据不存在", HttpStatus.NOT_FOUND);
}
if (ObjectUtils.isNotEmpty(req.getVehicleId()) && !Objects.equals(req.getVehicleId(), oldEntity.getVehicleId())) {
// 车辆id不一致需要判断车辆是否被占用
VehVehicleInfo vehicle = vehicleInfoService.getById(req.getVehicleId());
if (vehicle == null) {
throw new ServiceException("车辆不存在", HttpStatus.NOT_FOUND);
}
if (!vehicle.getVehicleStatus().equals(VehVehicleInfoStatusEnum.AVAILABLE.getValue())) {
throw new ServiceException("当前车辆无法使用", HttpStatus.CONFLICT);
}
}
VehVehicleTrip trip = new VehVehicleTrip();
BeanUtils.copyProperties(req, trip);
validEntityBeforeSave(trip);
return this.updateById(trip);
}
/**
* 取消车辆出行记录
*
* @param req 车辆出行记录
* @return 是否取消成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean cancel(VehVehicleTripCancelReq req) {
// 数据校验
VehVehicleTrip trip = this.getById(req.getId());
if (trip == null) {
throw new ServiceException("车辆出行记录不存在", HttpStatus.NOT_FOUND);
}
if (trip.getTripStatus().equals(VehTripStatusEnum.CANCELED.getValue())) {
throw new ServiceException("该记录已取消", HttpStatus.BAD_REQUEST);
}
// 权限校验
Long userId = LoginHelper.getUserId();
if (!LoginHelper.isSuperAdmin() && !userId.equals(trip.getCreateBy())) {
throw new ServiceException("没有权限取消该记录", HttpStatus.FORBIDDEN);
}
// 设置取消状态
trip.setTripStatus(VehTripStatusEnum.CANCELED.getValue());
// 通知已预约用户
List<VehVehicleApply> applyList = vehicleApplyService.lambdaQuery()
.eq(VehVehicleApply::getTripId, trip.getId())
.list();
if (CollUtil.isNotEmpty(applyList)) {
// 通知
for (VehVehicleApply apply : applyList) {
CompletableFuture.runAsync(() -> {
Long createBy = apply.getCreateBy();
String title = "司机已取消您预约的行程,请及时查看!";
try {
chatServerHandler.sendSystemMessageToUser(createBy, title, "4");
} catch (Exception e) {
log.error("异步发送系统消息失败用户ID: {}, 消息: {}", createBy, title, e);
}
});
}
// 修改申请状态
applyList.forEach(apply -> apply.setStatus(VehApplyStatusEnum.CANCELED.getValue()));
boolean updateApply = vehicleApplyService.updateBatchById(applyList);
if (!updateApply) {
throw new ServiceException("修改申请状态失败");
}
}
// 更新数据
return this.updateById(trip);
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(VehVehicleTrip entity) {
Long vehicleId = entity.getVehicleId();
String plateNumber = entity.getPlateNumber();
String passengerPhone = entity.getPassengerPhone();
if (vehicleId == null && StringUtils.isBlank(plateNumber)) {
throw new ServiceException("车辆不能为空");
}
// 如果手机号为空,则使用用户手机号
if (StringUtils.isBlank(passengerPhone)) {
Long userId = LoginHelper.getUserId();
SysUserVo userVo = userService.selectUserById(userId);
passengerPhone = userVo.getPhonenumber();
}
if (!PhoneUtil.isPhone(passengerPhone)) {
throw new ServiceException("手机号格式错误", HttpStatus.BAD_REQUEST);
}
}
/**
* 校验并批量删除车辆出行记录信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
// 获取数据列表
List<VehVehicleTrip> list = this.listByIds(ids);
if (isValid) {
// 获取登录用户
Long userId = LoginHelper.getUserId();
Set<Long> userIds = list.stream().map(VehVehicleTrip::getCreateBy).collect(Collectors.toSet());
if (!userIds.contains(userId)) {
throw new ServiceException("没有权限删除该记录", HttpStatus.FORBIDDEN);
}
// 获取出现状态
for (VehVehicleTrip trip : list) {
if (!trip.getTripStatus().equals(VehTripStatusEnum.CANCELED.getValue())
|| !trip.getTripStatus().equals(VehTripStatusEnum.READY_DEPART.getValue())) {
throw new ServiceException("该记录已开始,不能删除", HttpStatus.BAD_REQUEST);
}
}
}
// 同步删除用户申请记录
List<VehVehicleApply> applyList = vehicleApplyService.lambdaQuery()
.in(VehVehicleApply::getTripId, ids)
.list();
if (CollUtil.isNotEmpty(applyList)) {
boolean deleteApply = vehicleApplyService.removeByIds(applyList);
if (!deleteApply) {
throw new ServiceException("删除用户申请记录失败");
}
}
return this.removeBatchByIds(ids);
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@EventListener(condition = "#processEvent.flowCode.endsWith('vehVehicleTrip')")
@Transactional
public void processPlansHandler(ProcessEvent processEvent) {
log.info("车辆出行审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId();
VehVehicleTrip vehicleTrip = this.getById(Long.valueOf(id));
if (vehicleTrip == null) {
return;
}
vehicleTrip.setReviewStatus(processEvent.getStatus());
this.updateById(vehicleTrip);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@EventListener(condition = "#processTaskEvent.flowCode.endsWith('vehVehicleTrip')")
public void processTaskPlansHandler(ProcessTaskEvent processTaskEvent) {
log.info("车辆出行审核任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@EventListener(condition = "#processDeleteEvent.flowCode.endsWith('vehVehicleTrip')")
public void processDeletePlansHandler(ProcessDeleteEvent processDeleteEvent) {
log.info("车辆出行审核删除流程任务执行了{}", processDeleteEvent.toString());
}
}

View File

@ -12,7 +12,6 @@ import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.vo.SysOssVo;
@ -44,20 +43,24 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
private static ChatGroupServiceImpl chatGroupService;
private static SysUserServiceImpl sysUserService;
private static SysOssServiceImpl sysOssService;
@Autowired
public void setChatHistoryService(ChatHistoryServiceImpl service) {
chatHistoryService = service;
}
@Autowired
public void setChatGroupService(ChatGroupServiceImpl service){
public void setChatGroupService(ChatGroupServiceImpl service) {
chatGroupService = service;
}
@Autowired
public void setSysUserService(SysUserServiceImpl service){
public void setSysUserService(SysUserServiceImpl service) {
sysUserService = service;
}
@Autowired
public void setSysOssService(SysOssServiceImpl service){
public void setSysOssService(SysOssServiceImpl service) {
sysOssService = service;
}
@ -72,7 +75,8 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
private static final ConcurrentHashMap<String, Integer> userRoomCountMap = new ConcurrentHashMap<>();
//维护一个在线用户列表
private static final List<String> onlineUserList = new ArrayList<>();
public static List<String> getOnlineUserList(){
public static List<String> getOnlineUserList() {
return onlineUserList;
}
@ -99,13 +103,13 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
//建立双向映射关系
LoginUser loginUser = LoginHelper.getLoginUser(token.replace("Bearer%20", ""));
if (loginUser == null){
if (loginUser == null) {
throw new RuntimeException("token获取信息失败");
}
//判断是否存在该账号的通道实例列表
userChannelMap.computeIfAbsent(loginUser.getUserId().toString(), k -> new ArrayList<>());
List<ChannelHandlerContext> channelHandlerContexts = userChannelMap.get(loginUser.getUserId().toString());
if (!channelHandlerContexts.contains( ctx)){
if (!channelHandlerContexts.contains(ctx)) {
channelHandlerContexts.add(ctx);
}
//把该账号的通道实例列表跟账号id关联 一个账号有多个通道实例
@ -131,7 +135,7 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
//构建各个聊天房间未读 数量
LambdaQueryWrapper<ChatGroup> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(ChatGroup::getMembers, loginUser.getUserId()+",").or().like(ChatGroup::getMembers,loginUser.getUserId()+"]");
queryWrapper.like(ChatGroup::getMembers, loginUser.getUserId() + ",").or().like(ChatGroup::getMembers, loginUser.getUserId() + "]");
//拿到该用户所参与的房间列表
List<ChatGroup> chatGroups = chatGroupService.list(queryWrapper);
boolean isHaveSystemRoom = false;
@ -150,12 +154,12 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
historyLambdaQueryWrapper.eq(ChatHistory::getIsRead, "1");
List<ChatHistory> list = chatHistoryService.list(historyLambdaQueryWrapper);
if (list != null && !list.isEmpty()) {
roomCounts.put(loginUser.getUserId()+"+"+chatGroup.getId().toString(), list.size());
roomCounts.put(loginUser.getUserId() + "+" + chatGroup.getId().toString(), list.size());
//连接后同步未读消息到内存中
userRoomCountMap.put(loginUser.getUserId()+"+"+chatGroup.getId().toString(), list.size());
userRoomCountMap.put(loginUser.getUserId() + "+" + chatGroup.getId().toString(), list.size());
}
//在遍历的同时寻找是否有系统消息房间
if (!isHaveSystemRoom && chatGroup.getMembers().contains("["+ ChatRoomEnum.SYSTEM.getRoomId())){
if (!isHaveSystemRoom && chatGroup.getMembers().contains("[" + ChatRoomEnum.SYSTEM.getRoomId())) {
isHaveSystemRoom = true;
}
// if (!isHaveAttendanceRoom && chatGroup.getMembers().contains("["+ChatRoomEnum.ATTENDANCE.getRoomId())){
@ -170,18 +174,18 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
}
JSONObject message = new JSONObject();
message.put("type", "3");
message.put("messageType","txt");
message.put("messageType", "txt");
message.put("unReadCount", roomCounts);
log.info("发送所有未读消息:{}",message);
if(message.get("unReadCount") != null && !roomCounts.isEmpty()) {
log.info("发送所有未读消息:{}", message);
if (message.get("unReadCount") != null && !roomCounts.isEmpty()) {
sendMessage(ctx, message.toJSONString());
}
}
//认证完成后开始构建系统消息房间 判断是否有系统消息房间 没有则增加
if (!isHaveSystemRoom){
if (!isHaveSystemRoom) {
ChatGroup chatGroup = new ChatGroup();
chatGroup.setType(String.valueOf(2));
chatGroup.setMembers("["+ChatRoomEnum.SYSTEM.getRoomId()+", " + loginUser.getUserId()+"]");
chatGroup.setMembers("[" + ChatRoomEnum.SYSTEM.getRoomId() + ", " + loginUser.getUserId() + "]");
chatGroupService.save(chatGroup);
}
@ -310,9 +314,9 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
//来自哪个用户
jsonObject.put("from", sysUserVo.getUserId().toString());
jsonObject.put("nickName", sysUserVo.getNickName());
if(sysUserVo.getAvatar() != null){
if (sysUserVo.getAvatar() != null) {
SysOssVo byId = sysOssService.getById(sysUserVo.getAvatar());
if(byId != null){
if (byId != null) {
jsonObject.put("avatar", byId.getUrl());
}
}
@ -329,7 +333,7 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
//只要发送一条数据,就要给接收方推送所有未读消息
if (!userRoomCountMap.containsKey(id + "+" + RoomId)) {
userRoomCountMap.put(id + "+" + RoomId, 1);
}else {
} else {
userRoomCountMap.put(id + "+" + RoomId, userRoomCountMap.get(id + "+" + RoomId) + 1);
}
//发送消息完成后添加聊天记录
@ -340,7 +344,7 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
chatHistory.setIsRead("1");
chatHistory.setMessageType(jsonObject.get("messageType").toString());
if (!jsonObject.get("messageType").equals("txt")){
if (!jsonObject.get("messageType").equals("txt")) {
//将携带base64转为文件然后进行存储 赋值url
String base64Data = jsonObject.get("message").toString();
@ -352,7 +356,7 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
byte[] fileBytes = Base64.getDecoder().decode(base64Data);
// 创建临时文件
File tempFile = File.createTempFile("", jsonObject.get("fileName").toString());
File tempFile = File.createTempFile("", jsonObject.get("fileName").toString());
tempFile.deleteOnExit();
// 写入文件
@ -390,37 +394,37 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
}
}
}else if ("1".equals(type)){
} else if ("1".equals(type)) {
log.info("收到客户端确认消息:{}", jsonObject);
//前端接收方收到消息返回1 说明此时处于聊天框内 可以清空该房间的所有未读消息 将此房间聊天记录全部已读
//现在是用户发送消息 ctx为接收方用户
LambdaQueryWrapper<ChatHistory> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper
.ne(ChatHistory::getSenderId,sysUserVo.getUserId().toString())
.eq(ChatHistory::getGeterId,jsonObject.get("roomId"))
.eq(ChatHistory::getIsRead,"1");
.ne(ChatHistory::getSenderId, sysUserVo.getUserId().toString())
.eq(ChatHistory::getGeterId, jsonObject.get("roomId"))
.eq(ChatHistory::getIsRead, "1");
List<ChatHistory> list = chatHistoryService.list(lambdaQueryWrapper);
if (list != null && !list.isEmpty()){
if (list != null && !list.isEmpty()) {
for (ChatHistory chatHistory : list) {
chatHistory.setIsRead("0");
}
}
chatHistoryService.updateBatchById( list);
chatHistoryService.updateBatchById(list);
//将该房间未读消息 清空
userRoomCountMap.put(sysUserVo.getUserId() + "+" + jsonObject.get("roomId"), 0);
//清空过后返回其余房间未读消息
HashMap<String,Object> temp = new HashMap<>();
userRoomCountMap.forEachKey(0,key ->{
if (key.contains(sysUserVo.getUserId().toString())){
temp.put(key,userRoomCountMap.get(key));
HashMap<String, Object> temp = new HashMap<>();
userRoomCountMap.forEachKey(0, key -> {
if (key.contains(sysUserVo.getUserId().toString())) {
temp.put(key, userRoomCountMap.get(key));
}
});
//构建消息
JSONObject message = new JSONObject();
message.put("type", "1");
message.put("unReadCount", temp);
message.put("messageType","txt");
message.put("messageType", "txt");
//发送
sendMessage(ctx, message.toString());
}
@ -435,21 +439,21 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
}
//给固定的人发消息
private void sendMessage(ChannelHandlerContext ctx,String message) {
private void sendMessage(ChannelHandlerContext ctx, String message) {
ctx.channel().writeAndFlush(new TextWebSocketFrame(message));
}
//发送群消息,此时其他客户端也能收到群消息
private void sendAllMessage(){
private void sendAllMessage() {
String message = "我是服务器,这里发送的是群消息";
channelGroup.writeAndFlush( new TextWebSocketFrame(message));
channelGroup.writeAndFlush(new TextWebSocketFrame(message));
}
//通过userId进行发送消息
@Transactional
public void sendSystemMessageToUser(Long userId, String message,String value){
public void sendSystemMessageToUser(Long userId, String message, String value) {
// /现在已用type0 1 3 (暂定为0)
// {
// "type":"4",
@ -465,94 +469,116 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
ChatGroup groupServiceOne = null;
ChatHistory chatHistory = null;
switch (value){
switch (value) {
//1:系统消息
case "0" ->{
case "0" -> {
//生成系统消息的聊天记录
lambdaQueryWrapper.eq(ChatGroup::getMembers,"["+ChatRoomEnum.SYSTEM.getRoomId()+", "+userId+"]");
lambdaQueryWrapper.eq(ChatGroup::getMembers, "[" + ChatRoomEnum.SYSTEM.getRoomId() + ", " + userId + "]");
groupServiceOne = chatGroupService.getOne(lambdaQueryWrapper);
//如果给成员发送系统消息 而该成员还没有建立过连接从而没有群聊房间 则创建该成员系统消息房间
if (groupServiceOne == null){
if (groupServiceOne == null) {
groupServiceOne = new ChatGroup();
groupServiceOne.setType(String.valueOf(2));
groupServiceOne.setMembers("["+ChatRoomEnum.SYSTEM.getRoomId()+", "+userId+"]");
groupServiceOne.setMembers("[" + ChatRoomEnum.SYSTEM.getRoomId() + ", " + userId + "]");
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}else {
} else {
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}
chatHistory = new ChatHistory();
//发送方设置为99 表示系统消息
chatHistory.setSenderId(99L);
jsonObject.put("nickName","系统消息");
jsonObject.put("roomType",2);
jsonObject.put("nickName", "系统消息");
jsonObject.put("roomType", 2);
}
//2:考勤消息
case "1" ->{
lambdaQueryWrapper.eq(ChatGroup::getMembers,"["+ChatRoomEnum.ATTENDANCE.getRoomId()+", "+userId+"]");
case "1" -> {
lambdaQueryWrapper.eq(ChatGroup::getMembers, "[" + ChatRoomEnum.ATTENDANCE.getRoomId() + ", " + userId + "]");
groupServiceOne = chatGroupService.getOne(lambdaQueryWrapper);
//如果给成员发送考勤消息 而该成员还没有建立过连接从而没有考勤房间 则创建该成员考勤消息房间
if (groupServiceOne == null){
if (groupServiceOne == null) {
groupServiceOne = new ChatGroup();
groupServiceOne.setType(String.valueOf(3));
groupServiceOne.setMembers("["+ChatRoomEnum.ATTENDANCE.getRoomId()+", "+userId+"]");
groupServiceOne.setMembers("[" + ChatRoomEnum.ATTENDANCE.getRoomId() + ", " + userId + "]");
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}else {
} else {
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}
chatHistory = new ChatHistory();
//发送方设置为100 表示系统消息中的考勤消息
chatHistory.setSenderId(100L);
jsonObject.put("nickName","考勤消息");
jsonObject.put("roomType",3);
jsonObject.put("nickName", "考勤消息");
jsonObject.put("roomType", 3);
}
//安全消息
case "2" ->{
lambdaQueryWrapper.eq(ChatGroup::getMembers,"["+ChatRoomEnum.SAFE.getRoomId()+", "+userId+"]");
case "2" -> {
lambdaQueryWrapper.eq(ChatGroup::getMembers, "[" + ChatRoomEnum.SAFE.getRoomId() + ", " + userId + "]");
groupServiceOne = chatGroupService.getOne(lambdaQueryWrapper);
//如果给成员发送安全消息 而该成员还没有建立过连接从而没有安全消息 则创建该成员安全消息房间
if (groupServiceOne == null){
if (groupServiceOne == null) {
groupServiceOne = new ChatGroup();
groupServiceOne.setType(String.valueOf(4));
groupServiceOne.setMembers("["+ChatRoomEnum.SAFE.getRoomId()+", "+userId+"]");
groupServiceOne.setMembers("[" + ChatRoomEnum.SAFE.getRoomId() + ", " + userId + "]");
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}else {
} else {
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}
chatHistory = new ChatHistory();
//发送方设置为101 表示系统消息中的安全消息
chatHistory.setSenderId(101L);
jsonObject.put("nickName","安全消息");
jsonObject.put("roomType",4);
jsonObject.put("nickName", "安全消息");
jsonObject.put("roomType", 4);
}
//质量消息
case "3" ->{
lambdaQueryWrapper.eq(ChatGroup::getMembers,"["+ChatRoomEnum.QUALITY.getRoomId()+", "+userId+"]");
case "3" -> {
lambdaQueryWrapper.eq(ChatGroup::getMembers, "[" + ChatRoomEnum.QUALITY.getRoomId() + ", " + userId + "]");
groupServiceOne = chatGroupService.getOne(lambdaQueryWrapper);
//如果给成员发送质量消息 而该成员还没有建立过连接从而没有质量消息 则创建该成员质量消息房间
if (groupServiceOne == null){
if (groupServiceOne == null) {
groupServiceOne = new ChatGroup();
groupServiceOne.setType(String.valueOf(5));
groupServiceOne.setMembers("["+ChatRoomEnum.QUALITY.getRoomId()+", "+userId+"]");
groupServiceOne.setMembers("[" + ChatRoomEnum.QUALITY.getRoomId() + ", " + userId + "]");
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}else {
} else {
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}
chatHistory = new ChatHistory();
//发送方设置为102 表示系统消息中的质量消息
chatHistory.setSenderId(102L);
jsonObject.put("nickName","质量消息");
jsonObject.put("roomType",5);
jsonObject.put("nickName", "质量消息");
jsonObject.put("roomType", 5);
}
// 车辆消息
case "4" -> {
lambdaQueryWrapper.eq(ChatGroup::getMembers, "[" + ChatRoomEnum.VEHICLE.getRoomId() + ", " + userId + "]");
groupServiceOne = chatGroupService.getOne(lambdaQueryWrapper);
//如果给成员发送车辆消息 而该成员还没有建立过连接从而没有车辆消息 则创建该成员车辆消息房间
if (groupServiceOne == null) {
groupServiceOne = new ChatGroup();
groupServiceOne.setType(String.valueOf(6));
groupServiceOne.setMembers("[" + ChatRoomEnum.VEHICLE.getRoomId() + ", " + userId + "]");
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
} else {
groupServiceOne.setLastMessage(message);
groupServiceOne.setLastMessageTime(new Date());
}
chatHistory = new ChatHistory();
//发送方设置为103 表示系统消息中的车辆消息
chatHistory.setSenderId(103L);
jsonObject.put("nickName", "车辆消息");
jsonObject.put("roomType", 6);
}
default -> {
@ -572,12 +598,12 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
chatHistoryService.save(chatHistory);
//发送消息后 将该房间未读消息数加1
if (userRoomCountMap.containsKey(userId+"+"+groupServiceOne.getId())){
if (userRoomCountMap.containsKey(userId + "+" + groupServiceOne.getId())) {
//该房间未读消息数加1
userRoomCountMap.put(userId+"+"+groupServiceOne.getId(), userRoomCountMap.get(userId+"+"+groupServiceOne.getId())+1);
}else{
userRoomCountMap.put(userId + "+" + groupServiceOne.getId(), userRoomCountMap.get(userId + "+" + groupServiceOne.getId()) + 1);
} else {
//将该房间未读消息数设置为1
userRoomCountMap.put(userId+"+"+groupServiceOne.getId(), 1);
userRoomCountMap.put(userId + "+" + groupServiceOne.getId(), 1);
}
//通过userId拿到该用户所有通道实例
@ -595,10 +621,10 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
//设置未读消息数
private void setUnReadCount(Long userId, JSONObject jsonObject) {
HashMap<String,Object> temp = new HashMap<>();
HashMap<String, Object> temp = new HashMap<>();
userRoomCountMap.forEachKey(0, (value) -> {
if (value.contains(userId.toString())){
temp.put(value,userRoomCountMap.get(value));
if (value.contains(userId.toString())) {
temp.put(value, userRoomCountMap.get(value));
}
});
jsonObject.put("unReadCount", temp);
@ -606,23 +632,23 @@ public class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocket
//用于房间创建后发送确认消息
public void sendRoomInfo(Long userId,ChatGroup chatGroup){
public void sendRoomInfo(Long userId, ChatGroup chatGroup) {
//通过ID找到所有通道 发送消息
List<ChannelHandlerContext> channelHandlerContexts = userChannelMap.get(userId.toString());
if (channelHandlerContexts == null||channelHandlerContexts.isEmpty()){
if (channelHandlerContexts == null || channelHandlerContexts.isEmpty()) {
return;
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", "5");
jsonObject.put("messageType","txt");
jsonObject.put("messageType", "txt");
jsonObject.put("roomInfo", chatGroup);
for (ChannelHandlerContext channelHandlerContext : channelHandlerContexts) {
sendMessage(channelHandlerContext, String.valueOf(jsonObject));
}
log.info("发送房间创建确认消息:{}",jsonObject);
log.info("发送房间创建确认消息:{}", jsonObject);
}

View File

@ -14,7 +14,9 @@ public enum ChatRoomEnum {
SAFE("101", "安全消息"),
QUALITY("102", "质量消息");
QUALITY("102", "质量消息"),
VEHICLE("103", "车辆消息");
/**
* ID

View File

@ -35,7 +35,7 @@ import org.dromara.xzd.biddingManagement.biaoqianlixiang.service.IXzdBidPreProje
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/biddingManagement/bidPreProject")
@RequestMapping("/xzd/biddingManagement/bidPreProject")
public class XzdBidPreProjectController extends BaseController {
private final IXzdBidPreProjectService xzdBidPreProjectService;
@ -81,7 +81,7 @@ public class XzdBidPreProjectController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingManagement:bidPreProject:query")
//@SaCheckPermission("biddingManagement:bidPreProject:query")
@GetMapping("/{id}")
public R<QuerListXzdBidPreVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -62,7 +62,7 @@ public class XzdProjectRiskAssessmentController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("xzd:projectRiskAssessment:query")
//@SaCheckPermission("xzd:projectRiskAssessment:query")
@GetMapping("/{id}")
public R<XzdProjectRiskAssessmentVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -147,7 +147,7 @@ public class XzdBidPreProjectVo implements Serializable {
/**
* 联投单位
*/
@Translation(type = TransConstant.XZD_GYSXX_ID_TO_NAME, mapper = "jointInvestmentEntity")
@Translation(type = TransConstant.XZD_KHXX_ID_TO_NAME, mapper = "jointInvestmentEntity")
private String jointInvestmentEntityName;
/**

View File

@ -184,7 +184,7 @@ public class XzdBqlxProjectInfoVo implements Serializable {
* 建设单位
*/
@ExcelProperty(value = "建设单位")
@Translation(type = TransConstant.XZD_GYSXX_ID_TO_NAME, mapper = "constructionUnit")
@Translation(type = TransConstant.XZD_KHXX_ID_TO_NAME, mapper = "constructionUnit")
private String constructionUnitName;
/**
@ -208,7 +208,7 @@ public class XzdBqlxProjectInfoVo implements Serializable {
* 招标单位
*/
@ExcelProperty(value = "招标单位")
@Translation(type = TransConstant.XZD_GYSXX_ID_TO_NAME, mapper = "biddingUnit")
@Translation(type = TransConstant.XZD_KHXX_ID_TO_NAME, mapper = "biddingUnit")
private String biddingUnitName;
/**

View File

@ -2,6 +2,10 @@ package org.dromara.xzd.biddingManagement.biaoqianlixiang.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -10,6 +14,7 @@ import lombok.RequiredArgsConstructor;
import org.dromara.common.utils.BatchNumberGenerator;
import org.dromara.system.service.impl.SysOssServiceImpl;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.XzdBqlxProjectInfo;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.XzdProjectRiskAssessment;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.bo.XzdBqlxProjectInfoBo;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.dto.BiddingManagementDto;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.dto.QuerBiddingManagementDto;
@ -19,6 +24,7 @@ import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.vo.XzdBqlxProjec
import org.dromara.xzd.biddingManagement.biaoqianlixiang.service.IXzdBqlxProjectInfoService;
import org.dromara.xzd.utilS.AreaUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.bo.XzdBidPreProjectBo;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.vo.XzdBidPreProjectVo;
@ -40,6 +46,7 @@ import java.util.stream.Collectors;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class XzdBidPreProjectServiceImpl extends ServiceImpl<XzdBidPreProjectMapper, XzdBidPreProject> implements IXzdBidPreProjectService {
private final XzdBidPreProjectMapper baseMapper;
@ -246,6 +253,50 @@ public class XzdBidPreProjectServiceImpl extends ServiceImpl<XzdBidPreProjectMap
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@org.springframework.context.event.EventListener(condition = "#processEvent.flowCode.endsWith('xzdbqlx')")
public void processPlansHandlErequipmentList(ProcessEvent processEvent) {
log.info("标前立项审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId();
XzdBidPreProject vo = baseMapper.selectById(Long.valueOf(id));
if (vo != null) {
return;
}
vo.setAuditStatus(processEvent.getStatus());
this.updateById(vo);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@org.springframework.context.event.EventListener(condition = "#processTaskEvent.flowCode.endsWith('xzdbqlx')")
public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) {
log.info("标前立项审核任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@EventListener(condition = "#processDeleteEvent.flowCode.endsWith('xzdbqlx')")
public void processDeletePlansHandlerEquipmentList(ProcessDeleteEvent processDeleteEvent) {
log.info("标前立项删除流程事件,标前立项审核任务执行了{}", processDeleteEvent.toString());
}
}

View File

@ -1,6 +1,10 @@
package org.dromara.xzd.biddingManagement.biaoqianlixiang.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -20,7 +24,9 @@ import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.vo.XzdProjectRis
import org.dromara.xzd.biddingManagement.biaoqianlixiang.mapper.XzdProjectRiskAssessmentMapper;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.service.IXzdBidPreProjectService;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.service.IXzdProjectRiskAssessmentService;
import org.dromara.xzd.comprehensive.domain.XzdCsContractInformation;
import org.dromara.xzd.utilS.AreaUtil;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@ -37,6 +43,7 @@ import java.util.stream.Collectors;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class XzdProjectRiskAssessmentServiceImpl extends ServiceImpl<XzdProjectRiskAssessmentMapper, XzdProjectRiskAssessment> implements IXzdProjectRiskAssessmentService {
private final XzdProjectRiskAssessmentMapper baseMapper;
@ -216,4 +223,51 @@ public class XzdProjectRiskAssessmentServiceImpl extends ServiceImpl<XzdProjectR
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@EventListener(condition = "#processEvent.flowCode.endsWith('xzdxmfxpg')")
public void processPlansHandlErequipmentList(ProcessEvent processEvent) {
log.info("项目风险评估签审意见审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId();
XzdProjectRiskAssessment vo = baseMapper.selectById(Long.valueOf(id));
if (vo != null) {
return;
}
vo.setAuditStatus(processEvent.getStatus());
this.updateById(vo);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@EventListener(condition = "#processTaskEvent.flowCode.endsWith('xzdxmfxpg')")
public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) {
log.info("项目风险评估签审意见审核任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@EventListener(condition = "#processDeleteEvent.flowCode.endsWith('xzdxmfxpg')")
public void processDeletePlansHandlerEquipmentList(ProcessDeleteEvent processDeleteEvent) {
log.info("项目风险评估签审意见删除流程事件,项目风险评估签审意见审核任务执行了{}", processDeleteEvent.toString());
}
}

View File

@ -31,7 +31,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/biddingDocument/biddingFileEstimate")
@RequestMapping("/xzd/biddingDocument/biddingFileEstimate")
public class XzdBiddingFileEstimateController extends BaseController {
private final IXzdBiddingFileEstimateService xzdBiddingFileEstimateService;
@ -61,7 +61,7 @@ public class XzdBiddingFileEstimateController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingDocument:biddingFileEstimate:query")
// @SaCheckPermission("biddingDocument:biddingFileEstimate:query")
@GetMapping("/{id}")
public R<XzdBiddingFileEstimateVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -127,4 +127,7 @@ public class XzdBiddingFileEstimate extends BaseEntity {
private String auditStatus;
private Long deptId;
}

View File

@ -123,5 +123,7 @@ public class XzdBiddingFileEstimateBo extends BaseEntity {
*/
private String auditStatus;
private Long deptId;
}

View File

@ -82,6 +82,13 @@ public class XzdBiddingFileEstimateVo implements Serializable {
@ExcelProperty(value = "招标单位")
private String biddingUnit;
/**
* 招标单位
*/
@ExcelProperty(value = "招标单位")
@Translation(type = TransConstant.XZD_KHXX_ID_TO_NAME, mapper = "biddingUnit")
private String biddingUnitName;
/**
* 招标方式
*/
@ -176,6 +183,9 @@ public class XzdBiddingFileEstimateVo implements Serializable {
@TableField(fill = FieldFill.INSERT)
private Date createTime;
private Long deptId;
}

View File

@ -1,6 +1,10 @@
package org.dromara.xzd.biddingManagement.biddingDocument.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -11,10 +15,12 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.utils.BatchNumberGenerator;
import org.dromara.system.service.impl.SysOssServiceImpl;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.XzdProjectRiskAssessment;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.vo.QuerListXzdBidPreVo;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.vo.XzdBidPreProjectVo;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.service.IXzdBidPreProjectService;
import org.dromara.xzd.utilS.AreaUtil;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.dromara.xzd.biddingManagement.biddingDocument.domain.bo.XzdBiddingFileEstimateBo;
import org.dromara.xzd.biddingManagement.biddingDocument.domain.vo.XzdBiddingFileEstimateVo;
@ -38,6 +44,7 @@ import java.util.stream.Collectors;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class XzdBiddingFileEstimateServiceImpl extends ServiceImpl<XzdBiddingFileEstimateMapper, XzdBiddingFileEstimate> implements IXzdBiddingFileEstimateService {
private final XzdBiddingFileEstimateMapper baseMapper;
@ -108,6 +115,7 @@ public class XzdBiddingFileEstimateServiceImpl extends ServiceImpl<XzdBiddingFil
lqw.orderByDesc(XzdBiddingFileEstimate::getId);
lqw.eq(StringUtils.isNotBlank(bo.getDocumentCode()), XzdBiddingFileEstimate::getDocumentCode, bo.getDocumentCode());
lqw.eq(bo.getDocumentDate() != null, XzdBiddingFileEstimate::getDocumentDate, bo.getDocumentDate());
lqw.eq(bo.getDeptId() != null, XzdBiddingFileEstimate::getDeptId, bo.getDeptId());
lqw.like(bo.getProjectName() !=null, XzdBiddingFileEstimate::getProjectName, bo.getProjectName());
lqw.eq(StringUtils.isNotBlank(bo.getTitle()), XzdBiddingFileEstimate::getTitle, bo.getTitle());
lqw.eq(StringUtils.isNotBlank(bo.getProjectLocation()), XzdBiddingFileEstimate::getProjectLocation, bo.getProjectLocation());
@ -194,4 +202,52 @@ public class XzdBiddingFileEstimateServiceImpl extends ServiceImpl<XzdBiddingFil
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@EventListener(condition = "#processEvent.flowCode.endsWith('xzdztbwj')")
public void processPlansHandlErequipmentList(ProcessEvent processEvent) {
log.info("招标文件审估审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId();
XzdBiddingFileEstimate vo = baseMapper.selectById(Long.valueOf(id));
if (vo != null) {
return;
}
vo.setAuditStatus(processEvent.getStatus());
this.updateById(vo);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@EventListener(condition = "#processTaskEvent.flowCode.endsWith('xzdztbwj')")
public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) {
log.info("招标文件审估审核任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@EventListener(condition = "#processDeleteEvent.flowCode.endsWith('xzdztbwj')")
public void processDeletePlansHandlerEquipmentList(ProcessDeleteEvent processDeleteEvent) {
log.info("招标文件审估删除流程事件,招标文件审估审核任务执行了{}", processDeleteEvent.toString());
}
}

View File

@ -34,7 +34,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/biddingDocument/biddingDocument")
@RequestMapping("/xzd/biddingDocument/biddingDocument")
public class XzdBiddingDocumentController extends BaseController {
private final IXzdBiddingDocumentService xzdBiddingDocumentService;
@ -64,7 +64,7 @@ public class XzdBiddingDocumentController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingDocument:biddingDocument:query")
// @SaCheckPermission("biddingDocument:biddingDocument:query")
@GetMapping("/{id}")
public R<XzdBiddingDocumentVoBylist> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -62,7 +62,7 @@ public class XzdTbwjBusinessBidController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingDocument:tbwjBusinessBid:query")
// @SaCheckPermission("biddingDocument:tbwjBusinessBid:query")
@GetMapping("/{id}")
public R<XzdTbwjBusinessBidVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -62,7 +62,7 @@ public class XzdTbwjBusinessBidRequirementsController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingDocument:tbwjBusinessBidRequirements:query")
// @SaCheckPermission("biddingDocument:tbwjBusinessBidRequirements:query")
@GetMapping("/{id}")
public R<XzdTbwjBusinessBidRequirementsVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -62,7 +62,7 @@ public class XzdTbwjQualificationRequirementsController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingDocument:tbwjQualificationRequirements:query")
// @SaCheckPermission("biddingDocument:tbwjQualificationRequirements:query")
@GetMapping("/{id}")
public R<XzdTbwjQualificationRequirementsVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -62,7 +62,7 @@ public class XzdTbwjTechnicalBidController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingDocument:tbwjTechnicalBid:query")
// @SaCheckPermission("biddingDocument:tbwjTechnicalBid:query")
@GetMapping("/{id}")
public R<XzdTbwjTechnicalBidVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -62,7 +62,7 @@ public class XzdTbwjTechnicalBidRequirementsController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingDocument:tbwjTechnicalBidRequirements:query")
// @SaCheckPermission("biddingDocument:tbwjTechnicalBidRequirements:query")
@GetMapping("/{id}")
public R<XzdTbwjTechnicalBidRequirementsVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -74,12 +74,26 @@ public class XzdBiddingDocumentVo implements Serializable {
@ExcelProperty(value = "项目类型ID")
private Long projectType;
/**
* 项目类型ID
*/
@ExcelProperty(value = "项目类型ID")
private String projectTypeName;
/**
* 投标单位
*/
@ExcelProperty(value = "投标单位")
private String bidUnit;
/**
* 投标单位
*/
@ExcelProperty(value = "投标单位")
@Translation(type = TransConstant.XZD_KHXX_ID_TO_NAME, mapper = "bidUnit")
private String bidUnitName;
/**
* 单据日期
*/

View File

@ -1,6 +1,10 @@
package org.dromara.xzd.biddingManagement.biddingDocumentList.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -25,9 +29,13 @@ import org.dromara.xzd.biddingManagement.biddingDocumentList.service.IXzdBidding
import org.dromara.xzd.biddingManagement.biddingDocumentList.service.IXzdTbwjBusinessBidService;
import org.dromara.xzd.biddingManagement.biddingDocumentList.service.IXzdTbwjTechnicalBidService;
import org.dromara.xzd.biddingManagement.biddingDocumentList.service.IXzdTbwjZsyqService;
import org.dromara.xzd.biddingManagement.earnestMoneyWithdraw.domain.XzdBidDepositRecovery;
import org.dromara.xzd.domain.vo.XzdProjectTypeVo;
import org.dromara.xzd.service.IXzdProjectTypeService;
import org.dromara.xzd.utilS.AreaUtil;
import org.locationtech.jts.edgegraph.HalfEdge;
import org.springframework.beans.BeanUtils;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@ -45,6 +53,7 @@ import java.util.Collection;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class XzdBiddingDocumentServiceImpl extends ServiceImpl<XzdBiddingDocumentMapper, XzdBiddingDocument> implements IXzdBiddingDocumentService {
private final XzdBiddingDocumentMapper baseMapper;
@ -59,6 +68,8 @@ public class XzdBiddingDocumentServiceImpl extends ServiceImpl<XzdBiddingDocumen
private final IXzdTbwjZsyqService iXzdTbwjZsyqService;
private final IXzdProjectTypeService xzdProjectTypeService;
/**
* 查询投标文件
*
@ -94,9 +105,25 @@ public class XzdBiddingDocumentServiceImpl extends ServiceImpl<XzdBiddingDocumen
public TableDataInfo<XzdBiddingDocumentVo> queryPageList(XzdBiddingDocumentBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<XzdBiddingDocument> lqw = buildQueryWrapper(bo);
Page<XzdBiddingDocumentVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
result.getRecords().forEach(this::getName);
return TableDataInfo.build(result);
}
private void getName(XzdBiddingDocumentVo xzdBiddingDocumentVo) {
if (xzdBiddingDocumentVo != null){
Long projectType = xzdBiddingDocumentVo.getProjectType();
if (projectType != null){
XzdProjectTypeVo xzdProjectTypeVo = xzdProjectTypeService.queryById(projectType);
if (xzdProjectTypeVo != null){
xzdBiddingDocumentVo.setProjectTypeName(xzdProjectTypeVo.getTypeName());
}
}
}
}
/**
* 查询符合条件的投标文件列表
*
@ -246,4 +273,56 @@ public class XzdBiddingDocumentServiceImpl extends ServiceImpl<XzdBiddingDocumen
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@EventListener(condition = "#processEvent.flowCode.endsWith('xzdtbwj')")
public void processPlansHandlErequipmentList(ProcessEvent processEvent) {
log.info("投标文件审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId();
XzdBiddingDocument vo = baseMapper.selectById(Long.valueOf(id));
if (vo != null) {
return;
}
vo.setAuditStatus(processEvent.getStatus());
this.updateById(vo);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@EventListener(condition = "#processTaskEvent.flowCode.endsWith('xzdtbwj')")
public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) {
log.info("投标文件审核任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@EventListener(condition = "#processDeleteEvent.flowCode.endsWith('xzdtbwj')")
public void processDeletePlansHandlerEquipmentList(ProcessDeleteEvent processDeleteEvent) {
log.info("投标文件删除流程事件,投标文件审核任务执行了{}", processDeleteEvent.toString());
}
}

View File

@ -33,7 +33,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/earnestMoney/bidDepositPayment")
@RequestMapping("/xzd/earnestMoney/bidDepositPayment")
public class XzdBidDepositPaymentController extends BaseController {
private final IXzdBidDepositPaymentService xzdBidDepositPaymentService;
@ -63,7 +63,7 @@ public class XzdBidDepositPaymentController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("earnestMoney:bidDepositPayment:query")
//@SaCheckPermission("earnestMoney:bidDepositPayment:query")
@GetMapping("/{id}")
public R<XzdBidDepositPaymentByBqlx> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -1,6 +1,10 @@
package org.dromara.xzd.biddingManagement.earnestMoney.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -21,9 +25,11 @@ import org.dromara.xzd.biddingManagement.earnestMoney.domain.vo.XzdBidDepositPay
import org.dromara.xzd.biddingManagement.earnestMoney.domain.vo.XzdBidDepositPaymentVo;
import org.dromara.xzd.biddingManagement.earnestMoney.mapper.XzdBidDepositPaymentMapper;
import org.dromara.xzd.biddingManagement.earnestMoney.service.IXzdBidDepositPaymentService;
import org.dromara.xzd.biddingManagement.paymentapplication.domain.XzdBiddingAgencyFeePayment;
import org.dromara.xzd.service.impl.XzdSupplierInfoServiceImpl;
import org.dromara.xzd.utilS.AreaUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
@ -41,6 +47,7 @@ import java.util.stream.Collectors;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class XzdBidDepositPaymentServiceImpl extends ServiceImpl<XzdBidDepositPaymentMapper, XzdBidDepositPayment> implements IXzdBidDepositPaymentService {
private final XzdBidDepositPaymentMapper baseMapper;
@ -208,4 +215,52 @@ public class XzdBidDepositPaymentServiceImpl extends ServiceImpl<XzdBidDepositPa
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@EventListener(condition = "#processEvent.flowCode.endsWith('xzdtbbzjjn')")
public void processPlansHandlErequipmentList(ProcessEvent processEvent) {
log.info("投标保证金缴纳审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId();
XzdBidDepositPayment vo = baseMapper.selectById(Long.valueOf(id));
if (vo != null) {
return;
}
vo.setAuditStatus(processEvent.getStatus());
this.updateById(vo);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@EventListener(condition = "#processTaskEvent.flowCode.endsWith('xzdtbbzjjn')")
public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) {
log.info("投标保证金缴纳审核任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@EventListener(condition = "#processDeleteEvent.flowCode.endsWith('xzdtbbzjjn')")
public void processDeletePlansHandlerEquipmentList(ProcessDeleteEvent processDeleteEvent) {
log.info("投标保证金缴纳删除流程事件,投标保证金缴纳审核任务执行了{}", processDeleteEvent.toString());
}
}

View File

@ -33,7 +33,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/biddingManagement/bidDepositRecovery")
@RequestMapping("/xzd/biddingManagement/bidDepositRecovery")
public class XzdBidDepositRecoveryController extends BaseController {
private final IXzdBidDepositRecoveryService xzdBidDepositRecoveryService;
@ -63,7 +63,7 @@ public class XzdBidDepositRecoveryController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("biddingManagement:bidDepositRecovery:query")
// @SaCheckPermission("biddingManagement:bidDepositRecovery:query")
@GetMapping("/{id}")
public R<XzdBidDepositRecoveryXqVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@ -60,12 +61,12 @@ public class XzdBidDepositRecovery extends BaseEntity {
/**
* 工程造价
*/
private Long projectCost;
private BigDecimal projectCost;
/**
* 收回金额
*/
private Long recoveryAmount;
private BigDecimal recoveryAmount;
/**
* 收回金额大写
@ -75,7 +76,7 @@ public class XzdBidDepositRecovery extends BaseEntity {
/**
* 资料费
*/
private Long dataFee;
private BigDecimal dataFee;
/**
* 资料费大写
@ -85,7 +86,7 @@ public class XzdBidDepositRecovery extends BaseEntity {
/**
* 退款金额
*/
private Long refundAmount;
private BigDecimal refundAmount;
/**
* 收回日期
@ -97,10 +98,13 @@ public class XzdBidDepositRecovery extends BaseEntity {
*/
private String depositStatus;
private Long deptId;
/**
* 保证金金额
*/
private Long depositAmount;
private BigDecimal depositAmount;
/**
* 保证金金额大写

View File

@ -8,6 +8,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@ -60,12 +61,12 @@ public class XzdBidDepositRecoveryBo extends BaseEntity {
/**
* 工程造价
*/
private Long projectCost;
private BigDecimal projectCost;
/**
* 收回金额
*/
private Long recoveryAmount;
private BigDecimal recoveryAmount;
/**
* 收回金额大写
@ -75,7 +76,7 @@ public class XzdBidDepositRecoveryBo extends BaseEntity {
/**
* 资料费
*/
private Long dataFee;
private BigDecimal dataFee;
/**
* 资料费大写
@ -85,7 +86,7 @@ public class XzdBidDepositRecoveryBo extends BaseEntity {
/**
* 退款金额
*/
private Long refundAmount;
private BigDecimal refundAmount;
/**
* 收回日期
@ -100,7 +101,7 @@ public class XzdBidDepositRecoveryBo extends BaseEntity {
/**
* 保证金金额
*/
private Long depositAmount;
private BigDecimal depositAmount;
/**
* 保证金金额大写
@ -183,6 +184,8 @@ public class XzdBidDepositRecoveryBo extends BaseEntity {
*/
private Integer gatheringNumber;
private Long deptId;
/**
* 收款单位(供应商信息)
*/

View File

@ -1,5 +1,6 @@
package org.dromara.xzd.biddingManagement.earnestMoneyWithdraw.domain.vo;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@ -77,7 +78,7 @@ public class XzdBidDepositRecoveryVo implements Serializable {
* 工程造价
*/
@ExcelProperty(value = "工程造价")
private Long projectCost;
private BigDecimal projectCost;
/**
* 收回金额
@ -95,7 +96,7 @@ public class XzdBidDepositRecoveryVo implements Serializable {
* 资料费
*/
@ExcelProperty(value = "资料费")
private Long dataFee;
private BigDecimal dataFee;
/**
* 资料费大写
@ -107,7 +108,7 @@ public class XzdBidDepositRecoveryVo implements Serializable {
* 退款金额
*/
@ExcelProperty(value = "退款金额")
private Long refundAmount;
private BigDecimal refundAmount;
/**
* 收回日期
@ -125,7 +126,7 @@ public class XzdBidDepositRecoveryVo implements Serializable {
* 保证金金额
*/
@ExcelProperty(value = "保证金金额")
private Long depositAmount;
private BigDecimal depositAmount;
/**
* 保证金金额大写
@ -269,5 +270,7 @@ public class XzdBidDepositRecoveryVo implements Serializable {
*/
private String xmbm;
private Long deptId;
}

View File

@ -1,6 +1,10 @@
package org.dromara.xzd.biddingManagement.earnestMoneyWithdraw.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -11,6 +15,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.utils.BatchNumberGenerator;
import org.dromara.system.service.impl.SysOssServiceImpl;
import org.dromara.xzd.biddingManagement.earnestMoney.domain.XzdBidDepositPayment;
import org.dromara.xzd.biddingManagement.earnestMoney.domain.vo.XzdBidDepositPaymentByBqlx;
import org.dromara.xzd.biddingManagement.earnestMoney.service.IXzdBidDepositPaymentService;
import org.dromara.xzd.biddingManagement.earnestMoneyWithdraw.domain.XzdBidDepositRecovery;
@ -22,6 +27,7 @@ import org.dromara.xzd.biddingManagement.earnestMoneyWithdraw.service.IXzdBidDep
import org.dromara.xzd.domain.vo.XzdSupplierInfoVo;
import org.dromara.xzd.service.IXzdSupplierInfoService;
import org.dromara.xzd.utilS.AreaUtil;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.Arrays;
@ -39,6 +45,7 @@ import java.util.stream.Collectors;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class XzdBidDepositRecoveryServiceImpl extends ServiceImpl<XzdBidDepositRecoveryMapper, XzdBidDepositRecovery> implements IXzdBidDepositRecoveryService {
private final XzdBidDepositRecoveryMapper baseMapper;
@ -131,6 +138,7 @@ public class XzdBidDepositRecoveryServiceImpl extends ServiceImpl<XzdBidDepositR
lqw.eq(bo.getProjectType() != null, XzdBidDepositRecovery::getProjectType, bo.getProjectType());
lqw.eq(StringUtils.isNotBlank(bo.getBusinessMode()), XzdBidDepositRecovery::getBusinessMode, bo.getBusinessMode());
lqw.eq(bo.getProjectCost() != null, XzdBidDepositRecovery::getProjectCost, bo.getProjectCost());
lqw.eq(bo.getDeptId() != null, XzdBidDepositRecovery::getDeptId, bo.getDeptId());
lqw.eq(bo.getRecoveryAmount() != null, XzdBidDepositRecovery::getRecoveryAmount, bo.getRecoveryAmount());
lqw.eq(StringUtils.isNotBlank(bo.getRecoveryAmountCapital()), XzdBidDepositRecovery::getRecoveryAmountCapital, bo.getRecoveryAmountCapital());
lqw.eq(bo.getDataFee() != null, XzdBidDepositRecovery::getDataFee, bo.getDataFee());
@ -219,4 +227,51 @@ public class XzdBidDepositRecoveryServiceImpl extends ServiceImpl<XzdBidDepositR
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@EventListener(condition = "#processEvent.flowCode.endsWith('xzdtbbzjsh')")
public void processPlansHandlErequipmentList(ProcessEvent processEvent) {
log.info("投标保证金收回审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId();
XzdBidDepositRecovery vo = baseMapper.selectById(Long.valueOf(id));
if (vo != null) {
return;
}
vo.setAuditStatus(processEvent.getStatus());
this.updateById(vo);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@EventListener(condition = "#processTaskEvent.flowCode.endsWith('xzdtbbzjsh')")
public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) {
log.info("投标保证金收回审核任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@EventListener(condition = "#processDeleteEvent.flowCode.endsWith('xzdtbbzjsh')")
public void processDeletePlansHandlerEquipmentList(ProcessDeleteEvent processDeleteEvent) {
log.info("投标保证金收回删除流程事件,投标保证金收回审核任务执行了{}", processDeleteEvent.toString());
}
}

View File

@ -31,7 +31,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/paymentapplication/biddingAgencyFeePayment")
@RequestMapping("/xzd/paymentapplication/biddingAgencyFeePayment")
public class XzdBiddingAgencyFeePaymentController extends BaseController {
private final IXzdBiddingAgencyFeePaymentService xzdBiddingAgencyFeePaymentService;
@ -61,7 +61,7 @@ public class XzdBiddingAgencyFeePaymentController extends BaseController {
*
* @param id 主键
*/
@SaCheckPermission("paymentapplication:biddingAgencyFeePayment:query")
// @SaCheckPermission("paymentapplication:biddingAgencyFeePayment:query")
@GetMapping("/{id}")
public R<XzdBiddingAgencyFeePaymentVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {

View File

@ -1,6 +1,10 @@
package org.dromara.xzd.biddingManagement.paymentapplication.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -14,7 +18,9 @@ import org.dromara.system.service.impl.SysOssServiceImpl;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.vo.QuerListXzdBidPreVo;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.vo.XzdBidPreProjectVo;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.service.IXzdBidPreProjectService;
import org.dromara.xzd.biddingManagement.biddingDocument.domain.XzdBiddingFileEstimate;
import org.dromara.xzd.utilS.AreaUtil;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.dromara.xzd.biddingManagement.paymentapplication.domain.bo.XzdBiddingAgencyFeePaymentBo;
import org.dromara.xzd.biddingManagement.paymentapplication.domain.vo.XzdBiddingAgencyFeePaymentVo;
@ -38,6 +44,7 @@ import java.util.stream.Collectors;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class XzdBiddingAgencyFeePaymentServiceImpl extends ServiceImpl<XzdBiddingAgencyFeePaymentMapper, XzdBiddingAgencyFeePayment> implements IXzdBiddingAgencyFeePaymentService {
private final XzdBiddingAgencyFeePaymentMapper baseMapper;
@ -188,4 +195,51 @@ public class XzdBiddingAgencyFeePaymentServiceImpl extends ServiceImpl<XzdBiddin
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@EventListener(condition = "#processEvent.flowCode.endsWith('xzdzbdlfwfsq')")
public void processPlansHandlErequipmentList(ProcessEvent processEvent) {
log.info("招标代理服务费支付申请审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId();
XzdBiddingAgencyFeePayment vo = baseMapper.selectById(Long.valueOf(id));
if (vo != null) {
return;
}
vo.setAuditStatus(processEvent.getStatus());
this.updateById(vo);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@EventListener(condition = "#processTaskEvent.flowCode.endsWith('xzdzbdlfwfsq')")
public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) {
log.info("招标代理服务费支付申请审核任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@EventListener(condition = "#processDeleteEvent.flowCode.endsWith('xzdzbdlfwfsq')")
public void processDeletePlansHandlerEquipmentList(ProcessDeleteEvent processDeleteEvent) {
log.info("招标代理服务费支付申请删除流程事件,招标代理服务费支付申请审核任务执行了{}", processDeleteEvent.toString());
}
}

Some files were not shown because too many files have changed in this diff Show More