From 3b9c113720c74db190284014b7c407842c6bcc17 Mon Sep 17 00:00:00 2001 From: PQZ Date: Sat, 12 Oct 2024 13:15:47 +0800 Subject: [PATCH 1/3] 1 --- .../yudao/module/custom/service/impl/UserCarServiceImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/UserCarServiceImpl.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/UserCarServiceImpl.java index b2c9ea16..030b618f 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/UserCarServiceImpl.java +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/UserCarServiceImpl.java @@ -90,6 +90,5 @@ public class UserCarServiceImpl extends ServiceImpl impl **/ @Override public void empowerUserInfo(String tenantId) { - } } \ No newline at end of file From 533097151f80409f31f5cba5a09e09abbf83148a Mon Sep 17 00:00:00 2001 From: Vinjor Date: Sat, 12 Oct 2024 16:13:06 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E9=82=80=E8=AF=B7?= =?UTF-8?q?=E6=B3=A8=E5=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/common/BaseConstants.java | 2 + .../iocoder/yudao/common/InviterTypeEnum.java | 32 +++++++++ .../iocoder/yudao/common/PromotionEnum.java | 28 ++++++++ .../cn/iocoder/yudao/common/SystemEnum.java | 4 +- .../custom/service/BasePromotionService.java | 8 --- .../impl/BasePromotionServiceImpl.java | 15 ---- .../service/impl/CustomerMainServiceImpl.java | 42 +++++++++-- .../staff/service/CompanyStaffService.java | 15 +++- .../service/impl/CompanyStaffServiceImpl.java | 72 ++++++++++++++++++- .../controller/WechatLoginController.java | 4 +- .../module}/wechat/service/WechatService.java | 2 +- .../service/impl/WechatServiceImpl.java | 13 +++- .../app/controller/LoginController.java | 2 +- .../module/system/api/user/AdminUserApi.java | 10 ++- .../system/api/user/AdminUserApiImpl.java | 15 +++- .../system/service/user/AdminUserService.java | 7 ++ .../service/user/AdminUserServiceImpl.java | 11 +++ .../src/main/resources/application.yaml | 1 + 18 files changed, 242 insertions(+), 41 deletions(-) create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/common/InviterTypeEnum.java create mode 100644 dl-module-base/src/main/java/cn/iocoder/yudao/common/PromotionEnum.java rename {dl-module-base/src/main/java/cn/iocoder/yudao/module/app => dl-module-company/src/main/java/cn/iocoder/yudao/module}/wechat/controller/WechatLoginController.java (92%) rename {dl-module-base/src/main/java/cn/iocoder/yudao/module/app => dl-module-company/src/main/java/cn/iocoder/yudao/module}/wechat/service/WechatService.java (94%) rename {dl-module-base/src/main/java/cn/iocoder/yudao/module/app => dl-module-company/src/main/java/cn/iocoder/yudao/module}/wechat/service/impl/WechatServiceImpl.java (91%) diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/common/BaseConstants.java b/dl-module-base/src/main/java/cn/iocoder/yudao/common/BaseConstants.java index bbb18eca..564a4167 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/common/BaseConstants.java +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/common/BaseConstants.java @@ -23,6 +23,8 @@ public class BaseConstants { public static final String TABLE_BASE_CAR_MAIN = "base_car_main"; /**新增标识*/ public static final String SIGN_CREATE = "create"; + /**邀请注册/授权给某个租户*/ + public static final String INVITE_CREATE = "invite_create"; /**编辑标识*/ public static final String SIGN_UPDATE = "update"; /**默认密码*/ diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/common/InviterTypeEnum.java b/dl-module-base/src/main/java/cn/iocoder/yudao/common/InviterTypeEnum.java new file mode 100644 index 00000000..8947d0c8 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/common/InviterTypeEnum.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.common; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 邀请者类型枚举 + * + * @author vinjor + */ +@AllArgsConstructor +@Getter +public enum InviterTypeEnum { + /** + * 员工邀请 + */ + STAFF("1","员工邀请"), + /** + * 客户邀请 + */ + CUSTOMER("2","客户邀请"); + + /** + * code + */ + private String code; + /** + * 名称 + */ + private String name; + +} diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/common/PromotionEnum.java b/dl-module-base/src/main/java/cn/iocoder/yudao/common/PromotionEnum.java new file mode 100644 index 00000000..b6e70dd9 --- /dev/null +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/common/PromotionEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.common; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 推广渠道枚举 + * + * @author vinjor + */ +@AllArgsConstructor +@Getter +public enum PromotionEnum { + /** + * 微信小程序 + */ + WeChat("WeChat","微信小程序"); + + /** + * code + */ + private String code; + /** + * 名称 + */ + private String name; + +} diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/common/SystemEnum.java b/dl-module-base/src/main/java/cn/iocoder/yudao/common/SystemEnum.java index 40e75ac4..ba8b8191 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/common/SystemEnum.java +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/common/SystemEnum.java @@ -4,9 +4,9 @@ import lombok.AllArgsConstructor; import lombok.Getter; /** - * Bpm 消息的枚举 + * 系统枚举 * - * @author 芋道源码 + * @author vinjor-m */ @AllArgsConstructor @Getter diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/BasePromotionService.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/BasePromotionService.java index c34384f2..d0fe09ea 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/BasePromotionService.java +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/BasePromotionService.java @@ -22,12 +22,4 @@ public interface BasePromotionService extends IService { * @param page 分页规则 **/ IPage queryListPage(BasePromotionReqVO pageReqVO, Page page); - - /** - * 新增推广记录 - * @author 小李 - * @date 12:26 2024/8/14 - * @param promotionRespVO 新增对象 - **/ - Boolean createPromotion(BasePromotionRespVO promotionRespVO); } diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/BasePromotionServiceImpl.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/BasePromotionServiceImpl.java index 21b96343..7153e0e5 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/BasePromotionServiceImpl.java +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/BasePromotionServiceImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.custom.service.impl; -import cn.hutool.core.bean.BeanUtil; import cn.iocoder.yudao.module.custom.entity.BasePromotion; import cn.iocoder.yudao.module.custom.mapper.BasePromotionMapper; import cn.iocoder.yudao.module.custom.service.BasePromotionService; @@ -18,7 +17,6 @@ import org.springframework.stereotype.Service; **/ @Service public class BasePromotionServiceImpl extends ServiceImpl implements BasePromotionService { - /** * 分页查询推广记录 * @@ -30,17 +28,4 @@ public class BasePromotionServiceImpl extends ServiceImpl queryListPage(BasePromotionReqVO pageReqVO, Page page) { return baseMapper.queryListPage(pageReqVO, page); } - - /** - * 新增推广记录 - * @author 小李 - * @date 12:26 2024/8/14 - * @param promotionRespVO 新增对象 - **/ - @Override - public Boolean createPromotion(BasePromotionRespVO promotionRespVO){ - BasePromotion basePromotion = new BasePromotion(); - BeanUtil.copyProperties(promotionRespVO, basePromotion); - return baseMapper.insert(basePromotion) > 0; - } } diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/CustomerMainServiceImpl.java b/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/CustomerMainServiceImpl.java index 9e3dce3a..3892b26b 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/CustomerMainServiceImpl.java +++ b/dl-module-base/src/main/java/cn/iocoder/yudao/module/custom/service/impl/CustomerMainServiceImpl.java @@ -34,14 +34,15 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import static cn.iocoder.yudao.common.BaseConstants.*; import static cn.iocoder.yudao.common.DictBaseConstants.DICT_CUS_TYPE; @@ -113,6 +114,8 @@ public class CustomerMainServiceImpl extends ServiceImpl roleCodes = new HashSet<>(); roleCodes.add(dict.getRemark()); permissionApi.assignUserRole(userId, roleCodes); + }else if(INVITE_CREATE.equals(sign)){ + //邀请注册/授权给某个租户 + //查询数据字典,根据客户类型匹配出预设角色code; + DictDataRespDTO dict = dictDataApi.getDictData(DICT_CUS_TYPE, main.getTypeCode()); + if (CUS_TYPE_CORP.equals(main.getTypeCode())) { + //查询当前登录用户所属租户的政企客户部门id(父级部门) + DeptRespDTO parentDept = deptApi.getDeptByName(DEPT_NAME_CORP_NAME); + //在部门表下新增一个部门 + DeptRespDTO deptRespDTO = new DeptRespDTO(); + deptRespDTO.setName(main.getCusName()); + deptRespDTO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + //上级部门为本租户顶级部门 + deptRespDTO.setParentId(parentDept.getId()); + Long deptId = deptApi.saveDept(deptRespDTO); + //客户信息表绑定deptCode + main.setDeptCode(deptId); + }else{ + //私人客户和代办客户归属到默认的部门中 + String deptName = ""; + if(CUS_TYPE_PRIVATE.equals(main.getTypeCode())){ + deptName =DEPT_NAME_PRIVATE_NAME; + }else if(CUS_TYPE_AGENT.equals(main.getTypeCode())){ + deptName = DEPT_NAME_AGENT_NAME; + } + DeptRespDTO parentDept = deptApi.getDeptByName(deptName); + main.setDeptCode(parentDept.getId()); + } + //绑定角色 + Set roleCodes = new HashSet<>(); + roleCodes.add(dict.getRemark()); + permissionApi.assignUserRole(main.getUserId(), roleCodes); } - /*3、保存客户主表信息*/ //暂时写死会员id TODO main.setMemberLevelId("9d4567b7e68803933f4917a4aab6b745"); diff --git a/dl-module-company/src/main/java/cn/iocoder/yudao/module/staff/service/CompanyStaffService.java b/dl-module-company/src/main/java/cn/iocoder/yudao/module/staff/service/CompanyStaffService.java index 4354da58..6bc071ad 100644 --- a/dl-module-company/src/main/java/cn/iocoder/yudao/module/staff/service/CompanyStaffService.java +++ b/dl-module-company/src/main/java/cn/iocoder/yudao/module/staff/service/CompanyStaffService.java @@ -1,15 +1,17 @@ package cn.iocoder.yudao.module.staff.service; -import cn.iocoder.yudao.module.staff.entity.CompanyStaff; import cn.iocoder.yudao.module.label.entity.Label; +import cn.iocoder.yudao.module.staff.entity.CompanyStaff; import cn.iocoder.yudao.module.staff.vo.CompanyStaffReqVO; import cn.iocoder.yudao.module.staff.vo.CompanyStaffRespVO; import cn.iocoder.yudao.module.system.api.permission.dto.RoleReqDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import javax.validation.Valid; +import java.util.Date; import java.util.List; /** @@ -110,4 +112,15 @@ public interface CompanyStaffService extends IService { * @date 14:53 2024/8/14 **/ List getRoleList(); + + /** + * 新增推广记录 + * @author vinjor-m + * @date 12:26 2024/8/14 + * @param uniqueCode 推广码 + * @param user 被推广用户 + * @param promotionChannel 推广渠道 + * @param registerTime 被推广用户注册的时间 + **/ + Boolean createPromotion(String uniqueCode, AdminUserDO user, String promotionChannel, Date registerTime); } diff --git a/dl-module-company/src/main/java/cn/iocoder/yudao/module/staff/service/impl/CompanyStaffServiceImpl.java b/dl-module-company/src/main/java/cn/iocoder/yudao/module/staff/service/impl/CompanyStaffServiceImpl.java index 279499a4..145704c9 100644 --- a/dl-module-company/src/main/java/cn/iocoder/yudao/module/staff/service/impl/CompanyStaffServiceImpl.java +++ b/dl-module-company/src/main/java/cn/iocoder/yudao/module/staff/service/impl/CompanyStaffServiceImpl.java @@ -4,7 +4,14 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.common.BaseConstants; import cn.iocoder.yudao.common.CommonErrorCodeConstants; +import cn.iocoder.yudao.common.InviterTypeEnum; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; +import cn.iocoder.yudao.module.custom.entity.BasePromotion; +import cn.iocoder.yudao.module.custom.service.BasePromotionService; +import cn.iocoder.yudao.module.custom.service.CustomerMainService; +import cn.iocoder.yudao.module.custom.vo.CustomerMainSaveReqVO; import cn.iocoder.yudao.module.label.entity.BusiLabel; import cn.iocoder.yudao.module.label.entity.Label; import cn.iocoder.yudao.module.label.service.BusiLabelService; @@ -24,13 +31,14 @@ import cn.iocoder.yudao.module.system.api.permission.dto.RoleReqDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.UserDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import com.baomidou.dynamic.datasource.annotation.DSTransactional; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import org.springframework.context.annotation.Lazy; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -38,10 +46,12 @@ import java.math.BigDecimal; import java.time.LocalDate; import java.time.Period; import java.time.ZoneId; +import java.util.Date; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import static cn.iocoder.yudao.common.BaseConstants.INVITE_CREATE; import static cn.iocoder.yudao.framework.common.config.CommonStr.USER_TYPE_STAFF; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -80,6 +90,10 @@ public class CompanyStaffServiceImpl extends ServiceImpl getRoleList() { return roleApi.getRoleList(); } + + /** + * 新增推广记录---忽略租户 + * + * @param uniqueCode 推广码 + * @param user 被推广用户 + * @param promotionChannel 推广渠道 + * @param registerTime 被推广用户注册的时间 + * @author vinjor-m + * @date 12:26 2024/8/14 + **/ + @Override + @TenantIgnore + public Boolean createPromotion(String uniqueCode, AdminUserDO user, String promotionChannel, Date registerTime) { + /*1.先查是否是员工推广 */ + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(CompanyStaff::getUniqueCode,uniqueCode); + List staffList = this.list(queryWrapper); + if(!staffList.isEmpty()){ + //员工推广 + CompanyStaff staff = staffList.get(0); + // 插入推广记录 + BasePromotion basePromotion = new BasePromotion(); + basePromotion.setOldUserId(staff.getUserId()); + basePromotion.setOldUserName(staff.getName()); + basePromotion.setPromotionChannel(promotionChannel); + basePromotion.setNewUserId(user.getId()); + basePromotion.setNewUserName(user.getNickname()); + basePromotion.setRegisterTime(registerTime); + basePromotion.setUniqueCode(uniqueCode); + basePromotionService.save(basePromotion); + //取到该员工的租户,以该租户的角度去保存客户数据 + TenantUtils.execute(staff.getTenantId(), () -> { + CustomerMainSaveReqVO saveReqVO = new CustomerMainSaveReqVO(); + saveReqVO.setUserId(user.getId()); + saveReqVO.setPhoneNumber(user.getMobile()); + saveReqVO.setSex(user.getSex().toString()); + saveReqVO.setCusName(user.getNickname()); + //客户类型,统一为私人客户 + saveReqVO.setTypeCode("01"); + //客户来源,统一为04-维修 + saveReqVO.setDataFrom("04"); + //注册方式,统一为自主创建 + saveReqVO.setInviterType("01"); + //邀请者id + saveReqVO.setInviter(staff.getUserId().toString()); + //邀请者类型 + saveReqVO.setInviterType(InviterTypeEnum.STAFF.getCode()); + //邀请注册添加客户 + customerMainService.saveCustomer(saveReqVO,INVITE_CREATE); + }); + }else{ + /*2.不是员工推广,再查是否是客户推广*/ + } + return true; + } } diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/controller/WechatLoginController.java b/dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/controller/WechatLoginController.java similarity index 92% rename from dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/controller/WechatLoginController.java rename to dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/controller/WechatLoginController.java index 3029bdab..81ed8ee1 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/controller/WechatLoginController.java +++ b/dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/controller/WechatLoginController.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.module.app.wechat.controller; +package cn.iocoder.yudao.module.wechat.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.app.wechat.service.WechatService; +import cn.iocoder.yudao.module.wechat.service.WechatService; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginReqVO; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO; import cn.iocoder.yudao.module.system.service.auth.AdminAuthService; diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/service/WechatService.java b/dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/service/WechatService.java similarity index 94% rename from dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/service/WechatService.java rename to dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/service/WechatService.java index 29280b72..3ad779d2 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/service/WechatService.java +++ b/dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/service/WechatService.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.app.wechat.service; +package cn.iocoder.yudao.module.wechat.service; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; diff --git a/dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/service/impl/WechatServiceImpl.java b/dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/service/impl/WechatServiceImpl.java similarity index 91% rename from dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/service/impl/WechatServiceImpl.java rename to dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/service/impl/WechatServiceImpl.java index 067f087f..7781dca9 100644 --- a/dl-module-base/src/main/java/cn/iocoder/yudao/module/app/wechat/service/impl/WechatServiceImpl.java +++ b/dl-module-company/src/main/java/cn/iocoder/yudao/module/wechat/service/impl/WechatServiceImpl.java @@ -1,10 +1,12 @@ -package cn.iocoder.yudao.module.app.wechat.service.impl; +package cn.iocoder.yudao.module.wechat.service.impl; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.common.PromotionEnum; import cn.iocoder.yudao.common.SystemEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.app.wechat.service.WechatService; +import cn.iocoder.yudao.module.staff.service.CompanyStaffService; +import cn.iocoder.yudao.module.wechat.service.WechatService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO; @@ -18,6 +20,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -40,6 +43,8 @@ public class WechatServiceImpl implements WechatService { private AdminUserService userService; @Resource private PasswordEncoder passwordEncoder; + @Autowired + private CompanyStaffService companyStaffService; /** * 微信自动登录 * @@ -159,8 +164,10 @@ public class WechatServiceImpl implements WechatService { wxUser.setUsername(user.getUsername()); wxUser.setNickname(user.getNickname()); } + /*如果携带了邀请码,需要插入邀请记录并自动复制用户信息到邀请者的租户下 */ if(!StringUtils.isEmpty(inviteId)){ - //那邀请者的码查邀请者的信息 + //邀请注册,自动注册客户信息 + companyStaffService.createPromotion(inviteId,wxUser, PromotionEnum.WeChat.getCode(), new Date()); } return wxUser; } diff --git a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/app/controller/LoginController.java b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/app/controller/LoginController.java index bac8b0d1..8108925a 100644 --- a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/app/controller/LoginController.java +++ b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/app/controller/LoginController.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.security.config.SecurityProperties; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.app.vo.WxLoginBody; -import cn.iocoder.yudao.module.app.wechat.service.WechatService; +import cn.iocoder.yudao.module.wechat.service.WechatService; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.auth.AdminAuthService; diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java index bb12285e..f6bd0795 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.UserDTO; -import javax.validation.Valid; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -52,12 +51,19 @@ public interface AdminUserApi { AdminUserRespDTO getUserByOpenId(String openId,String tenantId); /** - * 通过用户 登录账户 查询用户 + * 通过用户 登录账户 查询用户---自动拼租户 * * @param username 用户登录账户 * @return 用户对象信息 */ AdminUserRespDTO getUserByUsername(String username); + /** + * 通过用户 登录账户 查询用户---不带租户 + * + * @param username 用户登录账户 + * @return 用户对象信息 + */ + AdminUserRespDTO getUserByUsernameNoTenantId(String username); /** * 通过用户 ID 查询用户下属 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java index a7bf43c0..719b2e4c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.UserDTO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO; @@ -80,7 +81,7 @@ public class AdminUserApiImpl implements AdminUserApi { } /** - * 通过用户 登录账户 查询用户 + * 通过用户 登录账户 查询用户---自动拼租户 * * @param username 用户登录账户 * @return 用户对象信息 @@ -90,6 +91,18 @@ public class AdminUserApiImpl implements AdminUserApi { AdminUserDO user = userService.getUserByUsername(username); return BeanUtils.toBean(user, AdminUserRespDTO.class); } + /** + * 通过用户 登录账户 查询用户---不带租户 + * + * @param username 用户登录账户 + * @return 用户对象信息 + */ + @Override + @TenantIgnore + public AdminUserRespDTO getUserByUsernameNoTenantId(String username) { + AdminUserDO user = userService.getUserByUsernameNoTenantId(username); + return BeanUtils.toBean(user, AdminUserRespDTO.class); + } @Override public List getUserListBySubordinate(Long id) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java index a1c4b266..a1b23b8d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java @@ -120,6 +120,13 @@ public interface AdminUserService { * @return 用户对象信息 */ AdminUserDO getUserByUsername(String username); + /** + * 通过用户名查询用户---不带租户ID + * + * @param username 用户名 + * @return 用户对象信息 + */ + AdminUserDO getUserByUsernameNoTenantId(String username); /** * 通过手机号获取用户 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index cf55e617..0706cae2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -10,6 +10,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import cn.iocoder.yudao.module.infra.api.config.ConfigApi; import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; @@ -278,6 +280,15 @@ public class AdminUserServiceImpl implements AdminUserService { return userMapper.selectByUsername(username); } + @Override + @TenantIgnore + public AdminUserDO getUserByUsernameNoTenantId(String username) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(AdminUserDO::getUsername,username) + .isNull(TenantBaseDO::getTenantId); + return userMapper.selectOne(queryWrapper); + } + @Override public AdminUserDO getUserByMobile(String mobile) { return userMapper.selectByMobile(mobile); diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 444015e0..02c2eb9d 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -345,6 +345,7 @@ yudao: - system_users - dl_base_notice - base_user_car + - base_car_brand ignore-caches: - permission_menu_ids - oauth_client From 22418e657d9b8517ad3606cb09d989d9b9d4e974 Mon Sep 17 00:00:00 2001 From: PQZ Date: Sat, 12 Oct 2024 17:43:46 +0800 Subject: [PATCH 3/3] 1 --- dl-module-repair/pom.xml | 24 +-- .../admin/DlRepairTicketsController.java | 121 ++++++----- .../service/DlRepairTicketsService.java | 24 ++- .../impl/DlRepairTicketsServiceImpl.java | 36 +++- .../tickets/tools/TOperaDocRequestUtil.java | 190 +++++++++--------- .../yudao/module/tickets/tools/WordUtil.java | 50 +++++ .../yudao-module-infra-biz/pom.xml | 6 - .../infra/service/file/FileService.java | 16 -- .../infra/service/file/FileServiceImpl.java | 40 ---- .../src/main/resources/application.yaml | 4 + .../src/main/resources/templates/gdmb.docx | Bin 0 -> 14825 bytes 11 files changed, 259 insertions(+), 252 deletions(-) create mode 100644 dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/tools/WordUtil.java create mode 100644 yudao-server/src/main/resources/templates/gdmb.docx diff --git a/dl-module-repair/pom.xml b/dl-module-repair/pom.xml index a6ee9701..c28df541 100644 --- a/dl-module-repair/pom.xml +++ b/dl-module-repair/pom.xml @@ -29,30 +29,8 @@ com.deepoove poi-tl - 1.12.2 + 1.10.0 - - io.minio - minio - 8.4.0 - - - cn.iocoder.boot - dl-module-knowledge - 2.1.0-jdk8-snapshot - compile - - - cn.iocoder.boot - yudao-module-infra-biz - 2.1.0-jdk8-snapshot - compile - - - org.springframework - spring-test - - 8 diff --git a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/controller/admin/DlRepairTicketsController.java b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/controller/admin/DlRepairTicketsController.java index c3fae8bf..553e4a73 100644 --- a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/controller/admin/DlRepairTicketsController.java +++ b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/controller/admin/DlRepairTicketsController.java @@ -1,41 +1,27 @@ package cn.iocoder.yudao.module.tickets.controller.admin; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; -import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient; -import cn.iocoder.yudao.module.infra.service.file.FileConfigService; -import cn.iocoder.yudao.module.infra.service.file.FileService; -import cn.iocoder.yudao.module.knowledge.constants.Result; -import cn.iocoder.yudao.module.knowledge.controller.requestdto.TOperationDocRequest; import cn.iocoder.yudao.module.tickets.entity.DlRepairTickets; import cn.iocoder.yudao.module.tickets.service.DlRepairTicketsService; -import cn.iocoder.yudao.module.tickets.tools.TOperaDocRequestUtil; import cn.iocoder.yudao.module.tickets.vo.CustomerAndCarVO; import cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsReqVO; import cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsRespVO; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.tencentcloudapi.ess.v20201111.models.FileInfo; import io.swagger.v3.oas.annotations.Operation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; - -import java.io.IOException; +import javax.servlet.http.HttpServletResponse; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; /** * 维修工单表(DlRepairTickets)表控制层 + * * @author 小李 * @date 18:21 2024/9/13 -**/ + **/ @RestController @RequestMapping("/repair/tickets") public class DlRepairTicketsController { @@ -44,26 +30,19 @@ public class DlRepairTicketsController { */ @Resource private DlRepairTicketsService dlRepairTicketsService; - @Autowired - private TOperaDocRequestUtil tOperaDocRequestUtil; - @Autowired - private FileService fileService; - @Resource - private FileConfigService fileConfigService; - /** * 维修工单表 新增 * + * @param ticketsRespVO 新增对象 * @author 小李 * @date 11:33 2024/9/20 - * @param ticketsRespVO 新增对象 - **/ + **/ @PostMapping("/create") @Operation(summary = "维修工单表 新增") - public CommonResult createTicket(@RequestBody DlRepairTicketsRespVO ticketsRespVO){ + public CommonResult createTicket(@RequestBody DlRepairTicketsRespVO ticketsRespVO) { dlRepairTicketsService.createTickets(ticketsRespVO); return CommonResult.ok(); } @@ -71,17 +50,17 @@ public class DlRepairTicketsController { /** * 维修工单表 分页 * + * @param repairTicketsReqVO 查询对象 + * @param pageNo 页码 + * @param pageSize 条数 * @author 小李 * @date 20:51 2024/9/20 - * @param repairTicketsReqVO 查询对象 - * @param pageNo 页码 - * @param pageSize 条数 - **/ + **/ @GetMapping("/page") @Operation(summary = "维修工单表 分页") public CommonResult getTicketsPage(DlRepairTicketsReqVO repairTicketsReqVO, - @RequestParam(value = "pageNo", defaultValue = "1")Integer pageNo, - @RequestParam(value = "pageSize", defaultValue = "10")Integer pageSize){ + @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) { Page page = new Page<>(pageNo, pageSize); return success(dlRepairTicketsService.getTicketsPage(repairTicketsReqVO, page)); } @@ -89,26 +68,26 @@ public class DlRepairTicketsController { /** * 获得一个工单的详细信息 * + * @param id 工单ID * @author 小李 * @date 16:05 2024/9/21 - * @param id 工单ID - **/ + **/ @GetMapping("/get") @Operation(summary = "查看一个工单的详细信息") - public CommonResult getTicketsById(@RequestParam("id") String id){ + public CommonResult getTicketsById(@RequestParam("id") String id) { return success(dlRepairTicketsService.getTicketsById(id)); } /** * 维修工单表 作废 * + * @param repairTicketsReqVO 工单对象 * @author 小李 * @date 19:46 2024/9/22 - * @param repairTicketsReqVO 工单对象 - **/ + **/ @PostMapping("/void") @Operation(summary = "维修工单表 作废") - public CommonResult setTicketsVoid(@RequestBody DlRepairTicketsReqVO repairTicketsReqVO){ + public CommonResult setTicketsVoid(@RequestBody DlRepairTicketsReqVO repairTicketsReqVO) { dlRepairTicketsService.setTicketsVoid(repairTicketsReqVO); return CommonResult.ok(); } @@ -116,49 +95,63 @@ public class DlRepairTicketsController { /** * 维修工单表 结算 * + * @param repairTicketsRespVO 工单 * @author 小李 * @date 8:50 2024/9/23 - * @param repairTicketsRespVO 工单 - **/ + **/ @PostMapping("/paid") @Operation(summary = "维修工单表 结算") - public CommonResult setTicketsPaid(@RequestBody DlRepairTicketsRespVO repairTicketsRespVO){ + public CommonResult setTicketsPaid(@RequestBody DlRepairTicketsRespVO repairTicketsRespVO) { dlRepairTicketsService.setTicketsPaid(repairTicketsRespVO); return CommonResult.ok(); } - /** - * 维修工单表 导出 - * - * @author lzt - * @date 2024年10月11日 - * @param file 导出文件 - */ - @PostMapping("/print") - @Operation(summary = "维修工单表 导出") - public ResponseEntity> printDocument(@RequestParam("file") MultipartFile file) { - if (file.isEmpty()) { - return ResponseEntity.badRequest().body(new Result<>(null, "文件不能为空")); - } +// /** +// * 维修工单表 导出 +// * +// * @param file 导出文件 +// * @author lzt +// * @date 2024年10月11日 +// */ +// @PostMapping("/print") +// @Operation(summary = "维修工单表 导出") +// public ResponseEntity> printDocument(@RequestParam("file") MultipartFile file) { +// if (file.isEmpty()) { +// return ResponseEntity.badRequest().body(new Result<>(null, "文件不能为空")); +// } +// +// try { +// FileDO fileInfo = fileService.createFileDetail(file.getOriginalFilename(), "/ticket", IoUtil.readBytes(file.getInputStream())); +// return ResponseEntity.ok(new Result<>(fileInfo, "文件上传成功")); +// } catch (Exception e) { +// return ResponseEntity.status(500).body(new Result<>(null, "文件上传失败: " + e.getMessage())); +// } +// } - try { - FileDO fileInfo = fileService.createFileDetail(file.getOriginalFilename(), "/ticket", IoUtil.readBytes(file.getInputStream())); - return ResponseEntity.ok(new Result<>(fileInfo, "文件上传成功")); - } catch (Exception e) { - return ResponseEntity.status(500).body(new Result<>(null, "文件上传失败: " + e.getMessage())); - } + /** + * 维修工单打印 + * + * @param response HttpServletResponse + * @param id 维修工单id + * @author PQZ + * @date 13:48 2024/10/12 + **/ + @GetMapping("/print/{id}") + @Operation(summary = "维修工单打印") + public void printDocument(HttpServletResponse response, @PathVariable String id) { + dlRepairTicketsService.print(response,id); } /** * 客户信息和车辆信息 新增、修改 * + * @param customerAndCarVO 用户信息和车辆信息 * @author 小李 * @date 9:25 2024/10/8 - * @param customerAndCarVO 用户信息和车辆信息 - **/ + **/ @PostMapping("/updateUserAndCar") @Operation(summary = "客户信息和车辆信息 新增、修改") - public CommonResult updateCustomerAndCar(@RequestBody CustomerAndCarVO customerAndCarVO){ + public CommonResult updateCustomerAndCar(@RequestBody CustomerAndCarVO customerAndCarVO) { dlRepairTicketsService.updateCustomerAndCar(customerAndCarVO); return CommonResult.ok(); } diff --git a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/service/DlRepairTicketsService.java b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/service/DlRepairTicketsService.java index e1fd55fd..80bcefba 100644 --- a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/service/DlRepairTicketsService.java +++ b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/service/DlRepairTicketsService.java @@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import javax.servlet.http.HttpServletResponse; + /** * 针对表【dl_repair_tickets(维修工单表)】的数据库操作Service * @@ -19,54 +21,64 @@ public interface DlRepairTicketsService extends IService { /** * 维修工单表 新增 * + * @param ticketsRespVO 新增对象 * @author 小李 * @date 11:33 2024/9/20 - * @param ticketsRespVO 新增对象 **/ void createTickets(DlRepairTicketsRespVO ticketsRespVO); /** * 维修工单表 分页 * + * @param repairTicketsReqVO 查询对象 * @author 小李 * @date 20:51 2024/9/20 - * @param repairTicketsReqVO 查询对象 **/ IPage getTicketsPage(DlRepairTicketsReqVO repairTicketsReqVO, Page page); /** * 获得一个工单的详细信息 * + * @param id 工单ID * @author 小李 * @date 16:05 2024/9/21 - * @param id 工单ID **/ DlRepairTicketsRespVO getTicketsById(String id); /** * 维修工单表 作废 * + * @param repairTicketsReqVO 工单对象 * @author 小李 * @date 19:46 2024/9/22 - * @param repairTicketsReqVO 工单对象 **/ void setTicketsVoid(DlRepairTicketsReqVO repairTicketsReqVO); /** * 维修工单表 结算 * + * @param repairTicketsRespVO 工单 * @author 小李 * @date 8:50 2024/9/23 - * @param repairTicketsRespVO 工单 **/ void setTicketsPaid(DlRepairTicketsRespVO repairTicketsRespVO); /** * 客户信息和车辆信息 新增、修改 * + * @param customerAndCarVO 用户信息和车辆信息 * @author 小李 * @date 9:25 2024/10/8 - * @param customerAndCarVO 用户信息和车辆信息 **/ void updateCustomerAndCar(CustomerAndCarVO customerAndCarVO); + + /** + * 打印工单 + * + * @param response HttpServletResponse + * @param id String + * @author PQZ + * @date 14:00 2024/10/12 + **/ + void print(HttpServletResponse response, String id); } diff --git a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/service/impl/DlRepairTicketsServiceImpl.java b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/service/impl/DlRepairTicketsServiceImpl.java index 5bdc8694..d909d286 100644 --- a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/service/impl/DlRepairTicketsServiceImpl.java +++ b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/service/impl/DlRepairTicketsServiceImpl.java @@ -32,6 +32,7 @@ import cn.iocoder.yudao.module.tickets.entity.DlRepairTitem; import cn.iocoder.yudao.module.tickets.mapper.DlRepairTicketsMapper; import cn.iocoder.yudao.module.tickets.service.DlRepairTicketsService; import cn.iocoder.yudao.module.tickets.service.DlRepairTitemService; +import cn.iocoder.yudao.module.tickets.tools.WordUtil; import cn.iocoder.yudao.module.tickets.vo.CustomerAndCarVO; import cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsReqVO; import cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsRespVO; @@ -41,13 +42,18 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.deepoove.poi.XWPFTemplate; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.FileOutputStream; +import java.io.InputStream; import java.math.BigDecimal; +import java.util.HashMap; import java.util.List; -import java.util.Optional; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -325,6 +331,34 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl params = new HashMap<>(); + params.put("jobNumber","123456789"); + String fileName = "结算单.docx"; + String tmpPath = "D:\\"+fileName; + try{ + InputStream inputStream = XWPFTemplate.class.getResourceAsStream("/templates/gdmb.docx"); + XWPFTemplate template = XWPFTemplate.compile(inputStream); + template.render(params); + FileOutputStream fos = new FileOutputStream(tmpPath); + template.write(fos); + fos.flush(); + template.close(); + WordUtil.down(response,tmpPath,fileName); + }catch (Exception e){ + e.printStackTrace(); + } + } } diff --git a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/tools/TOperaDocRequestUtil.java b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/tools/TOperaDocRequestUtil.java index cd7581c6..dbcda8fd 100644 --- a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/tools/TOperaDocRequestUtil.java +++ b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/tools/TOperaDocRequestUtil.java @@ -1,96 +1,94 @@ -package cn.iocoder.yudao.module.tickets.tools; - -import cn.iocoder.yudao.module.infra.service.file.FileService; -import cn.iocoder.yudao.module.knowledge.constants.Result; -import cn.iocoder.yudao.module.tickets.controller.admin.DlRepairTicketsController; -import cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsReqVO; -import com.deepoove.poi.XWPFTemplate; -import com.deepoove.poi.config.Configure; -import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; -import com.tencentcloudapi.ess.v20201111.models.FileInfo; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.stereotype.Component; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; - -import static com.fhs.core.trans.util.ConvertUtil.convert; - - -/** - * 工单导出工具类 - * @author lzt - * @date 9:27 2024年10月11日 - */ -@Component(value = "TOperaDocRequestUtil" ) -public class TOperaDocRequestUtil { - - @Resource - private FileService fileService; - @Value("${minio.bucketName:dev}") - private String bucketName; - - public TOperaDocRequestUtil() throws FileNotFoundException { - } - - - private static String TEMPLATE_PATH = "/templates/gdmb.docx"; - - @Autowired - private DlRepairTicketsController dlRepairTicketsController; - - public FileInfo export(DlRepairTicketsReqVO request) throws IOException { - String fileStr = TEMPLATE_PATH; - - if (fileStr != null) { - byte[] inputStream = fileService.downloadFile(bucketName, fileStr); - - // 数据循环填充 - LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy(); - Configure configure = Configure.builder().bind("czTable", loopRowTableRenderPolicy).build(); - - // word导出到本地 - MultipartFile convert = null; - if (fileStr.contains("gdmb.docx")) { - // 操作模板文件-数据填充 - XWPFTemplate template = XWPFTemplate.compile(String.valueOf(inputStream), configure).render( - new HashMap() {{ - // 填充数据 TODO - //put("requestData", request); - - }} - ); - ByteArrayOutputStream outputStreamWord = new ByteArrayOutputStream();; - template.writeAndClose(outputStreamWord); - //IConverter converter = LocalConverter.builder().build(); - byte[] bytes = outputStreamWord.toByteArray(); - ByteArrayInputStream inputStreamWord = new ByteArrayInputStream(bytes); - - ByteArrayOutputStream outputStreamPdf = new ByteArrayOutputStream(); - - //converter.convert(inputStreamWord).as(DocumentType.DOCX).to(outputStreamPdf).as(DocumentType.PDF).execute(); - byte[] bytesPdf = outputStreamPdf.toByteArray(); - ByteArrayInputStream inputStreamPdf = new ByteArrayInputStream(bytesPdf); - - // convert = new MultipartFile(fileStr.replace(".docx", ".pdf"), "application/pdf", inputStreamPdf.readAllBytes()); - convert = new MockMultipartFile("gdmb.pdf", bytes); - } - ResponseEntity> responseEntity = dlRepairTicketsController.printDocument(convert); - -// 获取 Result 对象 - Result fileupload = responseEntity.getBody(); - if (fileupload != null) { - return fileupload.getData(); - } - } - return null; - } -} +//package cn.iocoder.yudao.module.tickets.tools; +// +//import cn.iocoder.yudao.module.infra.service.file.FileService; +//import cn.iocoder.yudao.module.knowledge.constants.Result; +//import cn.iocoder.yudao.module.tickets.controller.admin.DlRepairTicketsController; +//import cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsReqVO; +//import com.deepoove.poi.XWPFTemplate; +//import com.deepoove.poi.config.Configure; +//import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; +//import com.tencentcloudapi.ess.v20201111.models.FileInfo; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.beans.factory.annotation.Value; +//import org.springframework.http.ResponseEntity; +//import org.springframework.mock.web.MockMultipartFile; +//import org.springframework.stereotype.Component; +//import org.springframework.web.multipart.MultipartFile; +// +//import javax.annotation.Resource; +//import java.io.ByteArrayInputStream; +//import java.io.ByteArrayOutputStream; +//import java.io.FileNotFoundException; +//import java.io.IOException; +//import java.util.HashMap; +// +// +///** +// * 工单导出工具类 +// * @author lzt +// * @date 9:27 2024年10月11日 +// */ +//@Component(value = "TOperaDocRequestUtil" ) +//public class TOperaDocRequestUtil { +// +// @Resource +// private FileService fileService; +// @Value("${minio.bucketName:dev}") +// private String bucketName; +// +// public TOperaDocRequestUtil() throws FileNotFoundException { +// } +// +// +// private static String TEMPLATE_PATH = "/templates/gdmb.docx"; +// +// @Autowired +// private DlRepairTicketsController dlRepairTicketsController; +// +// public FileInfo export(DlRepairTicketsReqVO request) throws IOException { +// String fileStr = TEMPLATE_PATH; +// +// if (fileStr != null) { +// byte[] inputStream = fileService.downloadFile(bucketName, fileStr); +// +// // 数据循环填充 +// LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy(); +// Configure configure = Configure.builder().bind("czTable", loopRowTableRenderPolicy).build(); +// +// // word导出到本地 +// MultipartFile convert = null; +// if (fileStr.contains("gdmb.docx")) { +// // 操作模板文件-数据填充 +// XWPFTemplate template = XWPFTemplate.compile(String.valueOf(inputStream), configure).render( +// new HashMap() {{ +// // 填充数据 TODO +// //put("requestData", request); +// +// }} +// ); +// ByteArrayOutputStream outputStreamWord = new ByteArrayOutputStream();; +// template.writeAndClose(outputStreamWord); +// //IConverter converter = LocalConverter.builder().build(); +// byte[] bytes = outputStreamWord.toByteArray(); +// ByteArrayInputStream inputStreamWord = new ByteArrayInputStream(bytes); +// +// ByteArrayOutputStream outputStreamPdf = new ByteArrayOutputStream(); +// +// //converter.convert(inputStreamWord).as(DocumentType.DOCX).to(outputStreamPdf).as(DocumentType.PDF).execute(); +// byte[] bytesPdf = outputStreamPdf.toByteArray(); +// ByteArrayInputStream inputStreamPdf = new ByteArrayInputStream(bytesPdf); +// +// // convert = new MultipartFile(fileStr.replace(".docx", ".pdf"), "application/pdf", inputStreamPdf.readAllBytes()); +// convert = new MockMultipartFile("gdmb.pdf", bytes); +// } +// ResponseEntity> responseEntity = dlRepairTicketsController.printDocument(convert); +// +// // 获取 Result 对象 +// Result fileupload = responseEntity.getBody(); +// if (fileupload != null) { +// return fileupload.getData(); +// } +// } +// return null; +// } +//} diff --git a/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/tools/WordUtil.java b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/tools/WordUtil.java new file mode 100644 index 00000000..5bb579db --- /dev/null +++ b/dl-module-repair/src/main/java/cn/iocoder/yudao/module/tickets/tools/WordUtil.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.tickets.tools; + +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +/** + * POI-TL工具类 + * @author PQZ + * @date 13:49 2024/10/12 +**/ +public class WordUtil { + /**模版路径*/ + public static String TEMPLATE_PATH = "/templates/gdmb.docx"; + + public static void down(HttpServletResponse response, String filePath, String fileName) { + String encodeName = null; + try { + encodeName = encodeStr(fileName); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + response.addHeader("Access-Control-Allow-Origin", "*"); + response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); + response.setHeader("Content-disposition", "attachment; filename=" + encodeName + ";" + "filename*=" + "utf-8''" + encodeName); + response.setHeader("download-filename", encodeName); + try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); + // 输出流 + BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());) { + byte[] buff = new byte[1024]; + int len = 0; + while ((len = bis.read(buff)) > 0) { + bos.write(buff, 0, len); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 编码工具方法 + */ + public static String encodeStr(String fileName) throws UnsupportedEncodingException { + return URLEncoder.encode(fileName,"UTF-8"); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/pom.xml b/yudao-module-infra/yudao-module-infra-biz/pom.xml index ada189a0..a12f078a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/pom.xml +++ b/yudao-module-infra/yudao-module-infra-biz/pom.xml @@ -124,12 +124,6 @@ org.apache.tika tika-core - - com.aliyun.oss - aliyun-sdk-oss - 3.11.2 - compile - diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java index 98bcaaa0..cf40e74e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java @@ -5,10 +5,6 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReq import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; -import org.apache.tomcat.jni.FileInfo; -import org.springframework.web.multipart.MultipartFile; - -import javax.xml.ws.Response; /** * 文件 Service 接口 @@ -67,16 +63,4 @@ public interface FileService { */ FilePresignedUrlRespVO getFilePresignedUrl(String path) throws Exception; - /** - * 下载文件 - * - * @author lzt - * @date 2024年10月11日 - * @param bucketName 存储桶名称 - * @param fileName 文件名称 - * @return 文件下载响应 - */ - byte[] downloadFile(String bucketName, String fileName); - -// FileInfo uploadFile(MultipartFile file); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index a1d8d38e..54cf38ca 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -144,44 +144,4 @@ public class FileServiceImpl implements FileService { return BeanUtils.toBean(presignedObjectUrl, FilePresignedUrlRespVO.class, object -> object.setConfigId(fileClient.getId())); } - - @Override - @SneakyThrows - public byte[] downloadFile(String bucketName, String fileStr) { - // 获取文件存储客户端 - FileClient client = fileConfigService.getFileClient(Long.valueOf(bucketName)); - Assert.notNull(client, "客户端({}) 不能为空", bucketName); - - // 获取文件内容 - return client.getContent(fileStr); - } - -// @Override -// public FileInfo uploadFile(MultipartFile file) { -// String bucketName = "xxxxx"; // 存储桶名称 -// String fileName = file.getOriginalFilename(); -// -// try { -// // 上传文件到 OSS -// PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, file.getInputStream()); -// ossClient.putObject(putObjectRequest); -// -// // 创建并返回 FileInfo 对象 -// FileInfo fileInfo = new FileInfo(); -// fileInfo.setFileName(fileName); -// fileInfo.setBucketName(bucketName); -// return fileInfo; -// -// } catch (IOException e) { -// e.printStackTrace(); -// throw new RuntimeException("文件上传到 OSS 失败: " + e.getMessage()); -// } finally { -// // 关闭 OSS 客户端 -// ossClient.shutdown(); -// } -// } - - - - } diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 444015e0..ed551dd6 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -237,6 +237,8 @@ yudao: - /admin-api/rescue/driverLogin - /admin-api/rescuePayApi/payNotify - /admin-api/payApi/payNotify + - /repair/tickets/print/** + - /admin-api/repair/tickets/print/** websocket: enable: true # websocket的开关 path: /infra/ws # 路径 @@ -298,6 +300,8 @@ yudao: - /admin-api/payApi/payNotify - /admin-api/base/notice/** - /app-api/** #小程序端接口,不区分租户 + - /repair/tickets/print/** + - /admin-api/repair/tickets/print/** ignore-tables: - system_tenant - system_tenant_package diff --git a/yudao-server/src/main/resources/templates/gdmb.docx b/yudao-server/src/main/resources/templates/gdmb.docx new file mode 100644 index 0000000000000000000000000000000000000000..6d061efae58adb65ca9daace959f7ea8bddae9e9 GIT binary patch literal 14825 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 literal 0 HcmV?d00001