Просмотр исходного кода

小程序端完善二维码红包接口

cgp 17 часов назад
Родитель
Сommit
7ddab20060
18 измененных файлов с 449 добавлено и 96 удалено
  1. 45 1
      fs-company/src/main/java/com/fs/company/controller/qw/FsCompanyCustomerController.java
  2. 12 7
      fs-doctor-app/src/main/java/com/fs/app/controller/FsPrescribeDataScrmController.java
  3. 18 1
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java
  4. 2 2
      fs-service/src/main/java/com/fs/his/dto/CollectionUserPhoneDTO.java
  5. 15 0
      fs-service/src/main/java/com/fs/his/dto/ShareQRCRedPackageDto.java
  6. 5 0
      fs-service/src/main/java/com/fs/his/param/WxSendRedPacketParam.java
  7. 4 1
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  8. 1 1
      fs-service/src/main/java/com/fs/qw/domain/FsCompanyQrcPhone.java
  9. 10 5
      fs-service/src/main/java/com/fs/qw/domain/FsCompanyQrcRedPackageRecord.java
  10. 1 1
      fs-service/src/main/java/com/fs/qw/mapper/FsCompanyQrcPhoneMapper.java
  11. 7 1
      fs-service/src/main/java/com/fs/qw/mapper/FsCompanyQrcRedPackageRecordMapper.java
  12. 17 0
      fs-service/src/main/java/com/fs/qw/service/IFsCompanyCustomerService.java
  13. 4 2
      fs-service/src/main/java/com/fs/qw/service/IFsCompanyQrcRedPackageRecordService.java
  14. 134 48
      fs-service/src/main/java/com/fs/qw/service/impl/FsCompanyCustomerServiceImpl.java
  15. 1 1
      fs-service/src/main/java/com/fs/qw/service/impl/FsCompanyQrcPhoneServiceImpl.java
  16. 132 10
      fs-service/src/main/java/com/fs/qw/service/impl/FsCompanyQrcRedPackageRecordServiceImpl.java
  17. 25 8
      fs-service/src/main/resources/mapper/qw/FsCompanyQrcRedPackageRecordMapper.xml
  18. 16 7
      fs-user-app/src/main/java/com/fs/app/controller/ShareMaterialController.java

+ 45 - 1
fs-company/src/main/java/com/fs/company/controller/qw/FsCompanyCustomerController.java

@@ -134,7 +134,7 @@ public class FsCompanyCustomerController extends BaseController {
             customer.setMyCustomerFlag(
                     customer.getCompanyUserId() != null && customer.getCompanyUserId().equals(currentUserId)
             );
-            customer.setPhone(maskPhoneMiddleFive(customer.getPhone()));
+            customer.setPhone(maskPhoneFirstSeven(customer.getPhone()));
             if (isAdmin != null) {
             customer.setMyCustomerFlag(true);  // 如果是管理员全部为自己的客户
             }
@@ -156,6 +156,20 @@ public class FsCompanyCustomerController extends BaseController {
         // (\\d{3}) 匹配前3位并作为分组1,\\d{5} 匹配中间5位,(\\d{3}) 匹配后3位并作为分组2
         return phone.replaceAll("(\\d{3})\\d{5}(\\d{3})", "$1*****$2");
     }
+    /**
+     * 手机号前7位脱敏处理 (例如: 13812345678 -> *******5678)
+     * @param phone 原始手机号
+     * @return 脱敏后的手机号
+     */
+    public static String maskPhoneFirstSeven(String phone) {
+        // 判断是否为空,不为空才进行替换处理
+        if (phone == null || phone.isEmpty()) {
+            return phone;
+        }
+        // 使用正则表达式将前7位数字替换为 *******
+        // \\d{7} 匹配前7位,(\\d{4}) 匹配后4位并作为分组1
+        return phone.replaceAll("\\d{7}(\\d{4})", "*******$1");
+    }
 
     /**
      * 导出客户信息
@@ -532,6 +546,36 @@ public class FsCompanyCustomerController extends BaseController {
         return fsCompanyCustomerService.getShareMaterialWxCode(companyUserId, appId, shareMaterialId);
     }
 
+    /**
+     * 是否符合快捷认领
+     */
+    @GetMapping("/canClaimCustomer/{id}")
+    public AjaxResult canClaimCustomer(@PathVariable("id") Long id) {
+        CompanyUser user = SecurityUtils.getLoginUser().getUser();
+        if (user == null) {
+            log.error("获取当前登录用户信息失败");
+            throw new CustomException("登录信息已过期,请重新登录");
+        }
+        return AjaxResult.success(fsCompanyCustomerService.canClaimCustomer(id, user));
+    }
+
+    /**
+     * 快捷认领并完善信息
+     * */
+    @PutMapping("/quickClaimAndImprove")
+    public AjaxResult quickClaimAndImprove(@RequestBody FsCompanyCustomer customer) {
+        CompanyUser user = SecurityUtils.getLoginUser().getUser();
+        if (user == null) {
+            throw new CustomException("登录信息已过期,请重新登录");
+        }
+        try {
+            return toAjax(fsCompanyCustomerService.quickClaimAndImprove(customer, user));
+        } catch (CustomException e) {
+            log.error("快捷认领并完善信息异常: {}", e.getMessage());
+            return AjaxResult.error(e.getMessage());
+        }
+    }
+
     /**
      * 获取 appId 的私有方法
      */

+ 12 - 7
fs-doctor-app/src/main/java/com/fs/app/controller/FsPrescribeDataScrmController.java

@@ -251,14 +251,19 @@ public class FsPrescribeDataScrmController extends BaseController
     public AjaxResult getAuditRecordList(@PathVariable("prescribeId") Long prescribeId) {
         return AjaxResult.success(recordDataScrmService.getAuditScrmPrescribeRecordListByPrescribeId(prescribeId));
     }
+
     /**
      * 获取当前登录医生id
-     * */
-    private String getDoctorId()
-    {
-        String headValue =  ServletUtils.getRequest().getHeader("APPToken");
-        Claims claims=jwtUtils.getClaimByToken(headValue);
-        String doctorId = claims.getSubject().toString();
-        return doctorId;
+     */
+    private String getDoctorId() {
+        try {
+            String headValue = ServletUtils.getRequest().getHeader("APPToken");
+            Claims claims = jwtUtils.getClaimByToken(headValue);
+            String doctorId = claims.getSubject();
+            return doctorId;
+        } catch (Exception e) {
+            throw new CustomException("登录已过期,请重新登录");
+        }
+
     }
 }

+ 18 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java

@@ -24,8 +24,10 @@ import com.fs.his.service.IFsStorePaymentService;
 import com.fs.patient.domain.FsProjectRedPacketRecord;
 import com.fs.patient.mapper.FsProjectRedPacketRecordMapper;
 import com.fs.qw.domain.BindPhoneRedPacketRecord;
+import com.fs.qw.domain.FsCompanyQrcRedPackageRecord;
 import com.fs.qw.domain.SignRedPacketRecord;
 import com.fs.qw.mapper.BindPhoneRedPacketRecordMapper;
+import com.fs.qw.mapper.FsCompanyQrcRedPackageRecordMapper;
 import com.fs.qw.mapper.SignRedPacketRecordMapper;
 import com.fs.system.service.ISysConfigService;
 import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
@@ -64,6 +66,9 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
 
     @Autowired
     private FsProjectRedPacketRecordMapper projectRedPacketRecordMapper;
+
+    @Autowired
+    private FsCompanyQrcRedPackageRecordMapper qrcRedPackageRecordMapper;
     /**
      * 查询短链课程看课记录
      *
@@ -183,7 +188,19 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
                 projectRedPacketRecordMapper.updateFsProjectRedPacketRecord(redPacketRecord);
                 return R.ok();
             }
-        } else {
+        } else if (outBatchNo.contains("qrcRedPackage")) {
+            // 收集手机号二维码红包的回调
+            FsCompanyQrcRedPackageRecord record=qrcRedPackageRecordMapper.selectQrcRedPackageRecordByOutBatchNo(outBatchNo);
+            if (record!=null){
+                record.setCollectType(1);
+                record.setUpdateTime(new Date());
+                record.setCollectTime(new Date());
+                record.setBatchId(batchId);
+                qrcRedPackageRecordMapper.updateById(record);
+                return R.ok();
+            }
+        }
+        else {
             //看课红包回调
             FsCourseRedPacketLog log = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByBatchNo(outBatchNo);
             if (log!=null){

+ 2 - 2
fs-service/src/main/java/com/fs/his/dto/CollectionUserPhoneDTO.java

@@ -5,9 +5,9 @@ import lombok.Data;
 @Data
 public class CollectionUserPhoneDTO {
     /**
-     * 微信用户id
+     * 用户id
      * */
-    private String userId;
+    private Long userId;
 
     /**
      * 用户手机号码

+ 15 - 0
fs-service/src/main/java/com/fs/his/dto/ShareQRCRedPackageDto.java

@@ -0,0 +1,15 @@
+package com.fs.his.dto;
+
+import lombok.Data;
+
+@Data
+public class ShareQRCRedPackageDto {
+    //用户id fs_user表主键
+    private Long userId;
+
+    //公司用户id fs_company_user表
+    private Long companyUserId;
+
+    //小程序id
+    private String appId;
+}

+ 5 - 0
fs-service/src/main/java/com/fs/his/param/WxSendRedPacketParam.java

@@ -41,4 +41,9 @@ public class WxSendRedPacketParam implements Serializable {
 
     private boolean projectFlag;
 
+    /**
+     * 收集手机号二维码红包标识
+     * */
+    private boolean collectionPhoneQrCodeFlag;
+
 }

+ 4 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -709,7 +709,10 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             request.setOutBillNo("articlePacket" + code);
         } else if (ObjectUtil.isNotNull(param.isProjectFlag()) && param.isProjectFlag()) {
             request.setOutBillNo("projectPacket" + code);
-        } else {
+        }
+        else if (ObjectUtil.isNotNull(param.isCollectionPhoneQrCodeFlag()) && param.isCollectionPhoneQrCodeFlag()) {
+            request.setOutBillNo("qrcRedPackage" + code);
+        }else {
             request.setOutBillNo("fsCourse" + code);
         }
 //        String code = String.valueOf(IdUtil.getSnowflake(0, 0).nextId());

+ 1 - 1
fs-service/src/main/java/com/fs/qw/domain/FsCompanyQrcPhone.java

@@ -16,7 +16,7 @@ public class FsCompanyQrcPhone {
     private Long companyUserId;
     /** 客户手机号 */
     private String userPhone;
-    /** 微信用户id(微信那边生成的) */
+    /** 用户id(fs_user表主键) */
     private String userId;
     /** 创建时间 */
     private Date createTime;

+ 10 - 5
fs-service/src/main/java/com/fs/qw/domain/FsCompanyQrcRedPackageRecord.java

@@ -6,13 +6,13 @@ import java.util.Date;
 
 /**
  * 分享二维码客户领取红包记录表
- * 
+ *
  * @author fs
  */
 @Data
 public class FsCompanyQrcRedPackageRecord {
     /** 主键ID */
-    private Integer id;
+    private Long id;
     /** 红包金额 */
     private BigDecimal amount;
     /** 发放时间 */
@@ -20,9 +20,9 @@ public class FsCompanyQrcRedPackageRecord {
     /** 领取时间 */
     private Date collectTime;
     /** 领取状态(0-已发放 1-已领取 2-已失效) */
-    private String collectType;
-    /** 微信用户id(微信那边生成的) */
-    private String userId;
+    private Integer collectType;
+    /** 用户id(fs_user表主键) */
+    private Long userId;
     /** 领取手机号 */
     private String userPhone;
     /** 销售人员id */
@@ -37,4 +37,9 @@ public class FsCompanyQrcRedPackageRecord {
     private Date createTime;
     /** 更新时间 */
     private Date updateTime;
+
+    /** 发放结果(如微信返回信息) */
+    private String result;
+    /** 批次单号 */
+    private String outBatchNo;
 }

+ 1 - 1
fs-service/src/main/java/com/fs/qw/mapper/FsCompanyQrcPhoneMapper.java

@@ -19,7 +19,7 @@ public interface FsCompanyQrcPhoneMapper {
     /**
      * 查询全部记录
      */
-    List<FsCompanyQrcPhone> selectList(FsCompanyQrcPhone record);
+    List<FsCompanyQrcPhone> selectList(FsCompanyQrcPhone qrcPhone);
 
     /**
      * 新增记录

+ 7 - 1
fs-service/src/main/java/com/fs/qw/mapper/FsCompanyQrcRedPackageRecordMapper.java

@@ -40,5 +40,11 @@ public interface FsCompanyQrcRedPackageRecordMapper {
      * 根据用户id查询用户是领取分享二维码红包详情
      * 一个用户id只能领取一次红包
      * */
-    FsCompanyQrcRedPackageRecord getRedPackageRecordByUserId(String userId);
+    FsCompanyQrcRedPackageRecord getRedPackageRecordByUserId(Long userId);
+
+    /**
+     * 根据商户订单号查询商户红包领取详情
+     * 一个商户订单号只能领取一次红包
+     * */
+    FsCompanyQrcRedPackageRecord selectQrcRedPackageRecordByOutBatchNo(String outBatchNo);
 }

+ 17 - 0
fs-service/src/main/java/com/fs/qw/service/IFsCompanyCustomerService.java

@@ -1,5 +1,6 @@
 package com.fs.qw.service;
 
+import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.company.domain.CompanyUser;
 import com.fs.his.vo.CustomerInfoVO;
@@ -70,4 +71,20 @@ public interface IFsCompanyCustomerService {
     R createPhoneQRCode(CreatePhoneQRCodeDTO qrCodeDTO,Long companyUserId, String appId);
 
     R getShareMaterialWxCode(Long companyUserId, String appId, Long shareMaterialId);
+
+    /**
+     * 判断当前用户是否可以快捷认领该客户
+     * @param id 客户信息表id
+     * @param user 当前登录销售
+     * @return 结果
+     */
+    int canClaimCustomer(Long id,CompanyUser user);
+
+    /**
+     * 快捷认领客户信息并完善客户信息
+     * @param customer 客户信息
+     * @param user 当前登录销售
+     * @return 认领结果
+     */
+    int quickClaimAndImprove(FsCompanyCustomer customer, CompanyUser user);
 }

+ 4 - 2
fs-service/src/main/java/com/fs/qw/service/IFsCompanyQrcRedPackageRecordService.java

@@ -1,6 +1,8 @@
 package com.fs.qw.service;
 
+import com.fs.common.core.domain.R;
 import com.fs.his.dto.CollectionUserPhoneDTO;
+import com.fs.his.dto.ShareQRCRedPackageDto;
 import com.fs.qw.domain.FsCompanyQrcRedPackageRecord;
 import java.util.List;
 
@@ -40,10 +42,10 @@ public interface IFsCompanyQrcRedPackageRecordService {
      * 根据用户id查询用户是领取分享二维码红包详情
      * 一个用户id只能领取一次红包
      * */
-    FsCompanyQrcRedPackageRecord getRedPackageRecordByUserId(String userId);
+    FsCompanyQrcRedPackageRecord getRedPackageRecordByUserId(Long userId);
 
     /**
      * 领取红包
      */
-    int claimRedPacket(String userId);
+    R claimRedPacket(ShareQRCRedPackageDto shareQRCRedPackageDto);
 }

+ 134 - 48
fs-service/src/main/java/com/fs/qw/service/impl/FsCompanyCustomerServiceImpl.java

@@ -31,10 +31,12 @@ import com.fs.hisStore.vo.FsStoreOrderItemVO;
 import com.fs.hisStore.vo.FsStoreOrderVO;
 import com.fs.qw.domain.FsCompanyCustomer;
 import com.fs.qw.domain.FsCompanyCustomerLog;
+import com.fs.qw.domain.FsCompanyQrcPhone;
 import com.fs.qw.dto.ImportCustomerDTO;
 import com.fs.qw.mapper.FsCompanyCustomerLogMapper;
 import com.fs.qw.mapper.FsCompanyCustomerMapper;
 import com.fs.qw.mapper.FsCompanyExternalPayReceiptMapper;
+import com.fs.qw.mapper.FsCompanyQrcPhoneMapper;
 import com.fs.qw.param.TransferCustomerParam;
 import com.fs.qw.service.IFsCompanyCustomerService;
 import com.fs.qw.vo.ImportResult;
@@ -52,6 +54,7 @@ import org.springframework.transaction.annotation.Transactional;
 import java.math.BigDecimal;
 import java.util.*;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * 客户基础信息Service业务层处理
@@ -92,6 +95,9 @@ public class FsCompanyCustomerServiceImpl implements IFsCompanyCustomerService {
     @Autowired
     private CompanyUserMapper companyUserMapper;
 
+    @Autowired
+    private FsCompanyQrcPhoneMapper fsCompanyQrcPhoneMapper;
+
     private static final Set<Integer> ALLOWED_STATUSES =
             Collections.unmodifiableSet(new HashSet<>(Arrays.asList(0, 5, 6))); // 允许操作完善客户信息的状态
 
@@ -257,60 +263,30 @@ public class FsCompanyCustomerServiceImpl implements IFsCompanyCustomerService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int claimCustomer(FsCompanyCustomer fsCompanyCustomer, CompanyUser companyUser) {
-        // 使用行锁查询客户信息(阻塞直到获得锁)
+        // 行锁查询
         FsCompanyCustomer oldCustomer = fsCompanyCustomerMapper.selectByIdForUpdate(fsCompanyCustomer.getId());
-        //校验认领号码与客户号码是否一致(优先匹配完整号码,其次匹配号码后4位,满足一个即可)
-        if (!fsCompanyCustomer.getClaimPhone().equals(oldCustomer.getPhone())){
-            String oldFourNumber = oldCustomer.getPhone().substring(7);
-            String newFourNumber = fsCompanyCustomer.getClaimPhone().substring(fsCompanyCustomer.getClaimPhone().length()-4);
-            if (!oldFourNumber.equals(newFourNumber)){
-                log.error("认领号码:{},客户号码:{}",fsCompanyCustomer.getClaimPhone(),oldCustomer.getPhone());
-                throw new CustomException("认领号码与客户号码不一致,请重试");
+        if (oldCustomer == null) {
+            throw new CustomException("客户不存在");
+        }
+        // 校验电话号码(完整匹配或后四位)
+        String claimPhone = fsCompanyCustomer.getClaimPhone();
+        if (!claimPhone.equals(oldCustomer.getPhone())) {
+            String oldLast4 = oldCustomer.getPhone().substring(7); // 11位手机号后4位
+            String newLast4 = claimPhone.substring(claimPhone.length() - 4);
+            if (!oldLast4.equals(newLast4)) {
+                log.error("认领号码:{},客户号码:{}", claimPhone, oldCustomer.getPhone());
+                throw new CustomException("认领号码与客户号码不一致,请重试");
             }
         }
 
-        //校验加微状态
-        if (fsCompanyCustomer.getKdzlAddWechatStatus()==null){
-            throw new CustomException("未选择加微,请选择");
+        // 校验加微状态
+        if (fsCompanyCustomer.getKdzlAddWechatStatus() == null) {
+            throw new CustomException("未选择加微请选择");
         }
-        FsImportMember fsImportMember=new FsImportMember();
-        fsImportMember.setId(oldCustomer.getImportMemberId());
-        fsImportMember.setCompanyId(companyUser.getCompanyId());
-        fsImportMember.setCompanyUserId(companyUser.getUserId());
-        //更新关联的导入会员表信息
-        importMemberMapper.updateFsImportMember(fsImportMember);
 
-        FsCompanyCustomerLog claimLog = new FsCompanyCustomerLog();
-        claimLog.setCompanyCustomerId(fsCompanyCustomer.getId());
-        claimLog.setCompanyUserId(companyUser.getUserId());
-        claimLog.setCompanyUserName(companyUser.getNickName());
-        claimLog.setDeptId(companyUser.getDeptId());
-        claimLog.setClaimTime(DateUtils.getNowDate());
-        CompanyDept companyDept = companyDeptMapper.selectCompanyDeptById(companyUser.getDeptId());
-        if (companyDept!=null&&companyDept.getDeptName()!=null){
-            claimLog.setDeptName(companyDept.getDeptName());
-            fsCompanyCustomer.setDeptName(companyDept.getDeptName());
-        }
-        //增加认领记录
-        companyCustomerLogMapper.insertFsCompanyCustomerLog(claimLog);
-        //认领的同时修改销售相关信息
-        fsCompanyCustomer.setDeptId(companyUser.getDeptId());
-        fsCompanyCustomer.setCompanyUserId(companyUser.getUserId());
-        fsCompanyCustomer.setCompanyUserName(companyUser.getNickName());
-        fsCompanyCustomer.setClaimStatus(BigDecimal.ONE.intValue());//已认领
-        //获取销售绑定医生信息
-        companyUser = companyUserMapper.selectCompanyUserById(companyUser.getUserId());
-        if (companyUser==null||companyUser.getDoctorId()==null){
-            throw new CustomException("销售未绑定医生");
-        }
-        //查询医生信息
-        FsDoctor fsDoctor = fsDoctorMapper.selectFsDoctorByDoctorId(companyUser.getDoctorId());
-        fsCompanyCustomer.setDoctorId(fsDoctor.getDoctorId());
-        fsCompanyCustomer.setDoctorName(fsDoctor.getDoctorName());
-        if (fsDoctor.getStatus()==0){
-            throw new CustomException("医生已停用,请更换医生!");
-        }
-        return fsCompanyCustomerMapper.updateFsCompanyCustomer(fsCompanyCustomer);
+        // 执行认领逻辑
+        performClaim(oldCustomer, companyUser, fsCompanyCustomer.getKdzlAddWechatStatus());
+        return 1; // 成功返回1
     }
 
     @Override
@@ -535,4 +511,114 @@ public class FsCompanyCustomerServiceImpl implements IFsCompanyCustomerService {
             return R.error("微信接口调用失败: " + e.getMessage());
         }
     }
+
+    @Override
+    public int canClaimCustomer(Long id, CompanyUser user) {
+        FsCompanyCustomer oldCustomer = fsCompanyCustomerMapper.selectByIdForUpdate(id);
+        if (oldCustomer == null) {
+            throw new CustomException("客户不存在");
+        }
+        // 查询中间表,判断是否可快捷认领
+        FsCompanyQrcPhone query = new FsCompanyQrcPhone();
+        query.setUserPhone(oldCustomer.getPhone());
+        query.setCompanyUserId(user.getUserId());
+        List<FsCompanyQrcPhone> list = fsCompanyQrcPhoneMapper.selectList(query);
+        if (CollectionUtils.isEmpty(list)) {
+            return 0; // 不能快捷认领
+        }
+        return 1;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int quickClaimAndImprove(FsCompanyCustomer customer, CompanyUser user) {
+        // 1. 行锁查询客户
+        FsCompanyCustomer oldCustomer = fsCompanyCustomerMapper.selectByIdForUpdate(customer.getId());
+        if (oldCustomer == null) {
+            throw new CustomException("客户不存在");
+        }
+
+        // 2. 校验四个字段至少有一个非空
+        String symptom = customer.getPatientMainComplaint();
+        String presentIllness = customer.getPresentIllness();
+        String currentMedication = customer.getCurrentMedication();
+        String allergyHistory = customer.getAllergyHistory();
+
+        boolean anyNotEmpty = Stream.of(symptom, presentIllness, currentMedication, allergyHistory)
+                .anyMatch(s -> s != null && !s.trim().isEmpty());
+        if (!anyNotEmpty) {
+            throw new CustomException("病情主诉、现病史、现用药情况、过敏史至少填写一项");
+        }
+
+        // 3. 将前端传入的所有字段复制到 oldCustomer(除了 id)
+        BeanUtils.copyProperties(customer, oldCustomer, "id");
+
+        // 4. 更新完善状态
+        setCompleteStatus(oldCustomer);
+
+        // 5. 执行认领核心逻辑(加微状态默认=1)
+        performClaim(oldCustomer, user, 1);
+
+        return 1;
+    }
+
+    /**
+     * 执行认领核心逻辑(需在事务内调用)
+     * @param customer        行锁查询出的客户对象(将被修改并更新)
+     * @param companyUser     当前操作销售
+     * @param addWechatStatus 加微状态(1-已加,0-未加)
+     */
+    private void performClaim(FsCompanyCustomer customer, CompanyUser companyUser, Integer addWechatStatus) {
+        if (companyUser == null) {
+            throw new CustomException("登录信息已过期,请重新登录");
+        }
+        Long companyId = companyUser.getCompanyId();
+        Long userId = companyUser.getUserId();
+        Long deptId = companyUser.getDeptId();
+        String nickName = companyUser.getNickName();
+
+        // 1. 更新导入会员
+        if (customer.getImportMemberId() != null) {
+            FsImportMember updateMember = new FsImportMember();
+            updateMember.setId(customer.getImportMemberId());
+            updateMember.setCompanyId(companyId);
+            updateMember.setCompanyUserId(userId);
+            importMemberMapper.updateFsImportMember(updateMember);
+        }
+
+        // 2. 创建认领日志
+        FsCompanyCustomerLog claimLog = new FsCompanyCustomerLog();
+        claimLog.setCompanyCustomerId(customer.getId());
+        claimLog.setCompanyUserId(userId);
+        claimLog.setCompanyUserName(nickName);
+        claimLog.setDeptId(deptId);
+        claimLog.setClaimTime(DateUtils.getNowDate());
+        CompanyDept companyDept = companyDeptMapper.selectCompanyDeptById(deptId);
+        if (companyDept != null && companyDept.getDeptName() != null) {
+            claimLog.setDeptName(companyDept.getDeptName());
+            customer.setDeptName(companyDept.getDeptName());
+        }
+        companyCustomerLogMapper.insertFsCompanyCustomerLog(claimLog);
+
+        // 3. 填充客户认领信息
+        customer.setDeptId(deptId);
+        customer.setCompanyUserId(userId);
+        customer.setCompanyUserName(nickName);
+        customer.setClaimStatus(1); // 已认领
+        customer.setKdzlAddWechatStatus(addWechatStatus);
+
+        // 4. 获取销售绑定的医生信息
+        if (companyUser.getDoctorId() == null) {
+            throw new CustomException("销售未绑定医生,请绑定后再操作!");
+        }
+        FsDoctor fsDoctor = fsDoctorMapper.selectFsDoctorByDoctorId(companyUser.getDoctorId());
+        if (fsDoctor.getStatus() == 0) {
+            throw new CustomException("医生已停用,请更换医生!");
+        }
+        customer.setDoctorId(fsDoctor.getDoctorId());
+        customer.setDoctorName(fsDoctor.getDoctorName());
+
+        // 5. 更新客户
+        fsCompanyCustomerMapper.updateFsCompanyCustomer(customer);
+    }
 }

+ 1 - 1
fs-service/src/main/java/com/fs/qw/service/impl/FsCompanyQrcPhoneServiceImpl.java

@@ -105,7 +105,7 @@ public class FsCompanyQrcPhoneServiceImpl implements IFsCompanyQrcPhoneService {
         if (BigDecimal.ONE.intValue()==qrcRedPackageConfigAmount.getOpen()){
             redPackageRecord.setAmount(qrcRedPackageConfigAmount.getAmount());//红包金额
         }else {
-            redPackageRecord.setAmount(BigDecimal.ZERO);
+            redPackageRecord.setAmount(BigDecimal.valueOf(0.1));
         }
         redPackageRecord.setCreateTime(DateUtils.getNowDate());
         return redPackageRecord;

+ 132 - 10
fs-service/src/main/java/com/fs/qw/service/impl/FsCompanyQrcRedPackageRecordServiceImpl.java

@@ -1,15 +1,32 @@
 package com.fs.qw.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserWx;
+import com.fs.his.dto.ShareQRCRedPackageDto;
+import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.param.WxSendRedPacketParam;
+import com.fs.his.service.IFsStorePaymentService;
+import com.fs.his.service.IFsUserWxService;
 import com.fs.qw.domain.FsCompanyQrcRedPackageRecord;
 import com.fs.qw.mapper.FsCompanyQrcRedPackageRecordMapper;
 import com.fs.qw.service.IFsCompanyQrcRedPackageRecordService;
+import com.fs.system.service.ISysConfigService;
+import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -21,9 +38,26 @@ import java.util.List;
 @Service
 public class FsCompanyQrcRedPackageRecordServiceImpl implements IFsCompanyQrcRedPackageRecordService {
 
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+
     @Autowired
     private FsCompanyQrcRedPackageRecordMapper recordMapper;
 
+    @Autowired
+    private IFsStorePaymentService fsStorePaymentService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    private IFsUserWxService fsUserWxService;
+
+    @Autowired
+    private FsUserMapper userMapper;
+
+    private static final String QRC_RED_PACKAGE_CONFIG_KEY = "qrcRedPackage.config";
+
     @Override
     public FsCompanyQrcRedPackageRecord selectById(Integer id) {
         return recordMapper.selectById(id);
@@ -54,22 +88,110 @@ public class FsCompanyQrcRedPackageRecordServiceImpl implements IFsCompanyQrcRed
     }
 
     @Override
-    public FsCompanyQrcRedPackageRecord getRedPackageRecordByUserId(String userId) {
+    public FsCompanyQrcRedPackageRecord getRedPackageRecordByUserId(Long userId) {
         return recordMapper.getRedPackageRecordByUserId(userId);
     }
 
     @Override
-    public int claimRedPacket(String userId) {
-        FsCompanyQrcRedPackageRecord record=recordMapper.getRedPackageRecordByUserId(userId);
-        if (record==null){
-            throw new CustomException("用户没有待领取的红包记录");
+    public R claimRedPacket(ShareQRCRedPackageDto param) {
+        // 1. 查询红包记录
+        FsCompanyQrcRedPackageRecord record = recordMapper.getRedPackageRecordByUserId(param.getUserId());
+        if (record == null) {
+            return R.error("用户没有待领取的红包记录");
         }
-        if (("1").equals(record.getCollectType())){
-            throw new CustomException("用户已领取过红包,请勿重复领取");
+        if ("1".equals(record.getCollectType())) {
+            return R.error("用户已领取过红包,请勿重复领取");
         }
-        //TODO 真实发送红包逻辑待完善
-        record.setUpdateTime(DateUtils.getNowDate());
-        return recordMapper.updateById(record);
 
+        // 2. 获取用户信息
+        FsUser user = userMapper.selectFsUserByUserId(param.getUserId());
+        if (user == null) {
+            return R.error("用户信息缺失,无法领取");
+        }
+        if (user.getStatus() == 0) {
+            return R.error("会员被停用,无权限,请联系客服!");
+        }
+
+        // 3. 获取销售信息
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(param.getCompanyUserId());
+        if (companyUser == null) {
+            return R.error("销售信息错误,领取失败");
+        }
+
+        // 4. 校验红包配置(是否开启)
+        String configJson = configService.selectConfigByKey(QRC_RED_PACKAGE_CONFIG_KEY);
+        if (StringUtils.isEmpty(configJson)) {
+            return R.error("获取红包配置错误,请联系管理员");
+        }
+        try {
+            JSONObject config = JSON.parseObject(configJson);
+            if (!"1".equals(config.getString("open"))) {
+                return R.error("未开启领取功能,领取失败");
+            }
+        } catch (Exception e) {
+            log.error("解析红包配置失败, json={}", configJson, e);
+            return R.error("红包配置解析异常,领取失败");
+        }
+
+        // 5. 准备微信支付参数
+        BigDecimal amount = record.getAmount(); // 直接从记录取金额
+        WxSendRedPacketParam packetParam = new WxSendRedPacketParam();
+        packetParam.setRedPacketMode(1);
+        packetParam.setAppId(param.getAppId());
+        packetParam.setMpAppId(param.getAppId());
+        packetParam.setUser(user);
+        packetParam.setAmount(amount);
+        packetParam.setSource(2);
+        packetParam.setCompanyId(companyUser.getCompanyId());
+
+        // 6. 获取或创建用户-小程序绑定,并设置 openId
+        FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(), user.getUserId(), 1);
+        if (fsUserWx == null) {
+            // 插入绑定关系(openId 使用用户表中的 courseMaOpenId)
+            FsUserWx newBind = new FsUserWx();
+            newBind.setType(1);
+            newBind.setFsUserId(user.getUserId());
+            newBind.setAppId(param.getAppId());
+            newBind.setOpenId(user.getCourseMaOpenId());
+            newBind.setUnionId(user.getUnionId());
+            newBind.setCreateTime(new Date());
+            newBind.setUpdateTime(new Date());
+            fsUserWxService.saveOrUpdateByUniqueKey(newBind);
+            log.info("【更新或插入用户与小程序{}的绑定关系】:{}", param.getAppId(), user.getUserId());
+            // 直接使用 user 中的 openId
+            packetParam.setOpenId(user.getCourseMaOpenId());
+        } else {
+            packetParam.setOpenId(fsUserWx.getOpenId());
+        }
+
+        // 7. 调用微信发收集手机号红包
+        packetParam.setCollectionPhoneQrCodeFlag(Boolean.TRUE);
+        R sendResult = fsStorePaymentService.sendRedPacket(packetParam);
+        if (!sendResult.get("code").equals(200)) {
+            return R.error("红包领取失败,请联系客服");
+        }
+
+        // 8. 发红包成功,更新记录
+        // 根据返回结果设置记录字段(直接复用 record 对象)
+        if (sendResult.get("isNew").equals(1)) {
+            TransferBillsResult transferResult = (TransferBillsResult) sendResult.get("data");
+            record.setResult(JSON.toJSONString(sendResult));
+            record.setOutBatchNo(transferResult.getOutBillNo());
+        } else {
+            record.setOutBatchNo(sendResult.get("orderCode").toString());
+            record.setBatchId(sendResult.get("batchId").toString());
+        }
+        // 设置其他必要字段(如果 record 已存在这些值,可省略部分,但安全起见保留)
+        record.setCompanyId(companyUser.getCompanyId());
+        record.setCompanyUserId(companyUser.getUserId());
+        record.setCompanyName(companyUser.getCompanyName());
+        record.setUserId(param.getUserId());
+        Date now = DateUtils.getNowDate();
+        record.setSendTime(now);
+        record.setUpdateTime(now);
+        record.setAmount(amount);
+        recordMapper.updateById(record);
+
+        return sendResult;
     }
 }

+ 25 - 8
fs-service/src/main/resources/mapper/qw/FsCompanyQrcRedPackageRecordMapper.xml

@@ -17,12 +17,16 @@
         <result column="company_name" property="companyName" />
         <result column="create_time" property="createTime" />
         <result column="update_time" property="updateTime" />
+        <!-- 新增字段映射 -->
+        <result column="result" property="result" />
+        <result column="out_batch_no" property="outBatchNo" />
     </resultMap>
 
-    <!-- 基础字段 -->
+    <!-- 基础字段(包含新字段) -->
     <sql id="Base_Column_List">
         id, amount, send_time, collect_time, collect_type, user_id, user_phone,
-        company_user_id, batch_id, company_id, company_name, create_time, update_time
+        company_user_id, batch_id, company_id, company_name,
+        create_time, update_time, result, out_batch_no
     </sql>
 
     <!-- 根据主键查询 -->
@@ -32,7 +36,7 @@
         WHERE id = #{id}
     </select>
 
-    <!-- 条件查询(非空字段作为条件) -->
+    <!-- 条件查询(非空字段作为条件,新增字段也加入) -->
     <select id="selectList" resultMap="BaseResultMap">
         SELECT <include refid="Base_Column_List" />
         FROM fs_company_qrc_red_package_record
@@ -47,30 +51,40 @@
             <if test="batchId != null and batchId != ''">AND batch_id = #{batchId}</if>
             <if test="companyId != null">AND company_id = #{companyId}</if>
             <if test="companyName != null and companyName != ''">AND company_name = #{companyName}</if>
+            <!-- 新增字段作为条件 -->
+            <if test="result != null and result != ''">AND result = #{result}</if>
+            <if test="outBatchNo != null and outBatchNo != ''">AND out_batch_no = #{outBatchNo}</if>
         </where>
         ORDER BY create_time DESC
     </select>
 
+    <!-- 按用户ID查询 -->
     <select id="getRedPackageRecordByUserId" resultType="com.fs.qw.domain.FsCompanyQrcRedPackageRecord">
         SELECT <include refid="Base_Column_List" />
-            FROM fs_company_qrc_red_package_record
+        FROM fs_company_qrc_red_package_record
         WHERE user_id = #{userId}
     </select>
+    <select id="selectQrcRedPackageRecordByOutBatchNo"
+            resultType="com.fs.qw.domain.FsCompanyQrcRedPackageRecord">
+        SELECT <include refid="Base_Column_List" />
+            FROM fs_company_qrc_red_package_record
+        WHERE out_batch_no = #{outBatchNo}
+    </select>
 
-    <!-- 新增(所有字段,主键需自行赋值或使用自增) -->
+    <!-- 新增(所有字段,主键自增,可忽略id或使用数据库生成) -->
     <insert id="insert" parameterType="com.fs.qw.domain.FsCompanyQrcRedPackageRecord">
         INSERT INTO fs_company_qrc_red_package_record (
             id, amount, send_time, collect_time, collect_type, user_id,
             user_phone, company_user_id, batch_id, company_id, company_name,
-            create_time, update_time
+            create_time, update_time, result, out_batch_no
         ) VALUES (
                      #{id}, #{amount}, #{sendTime}, #{collectTime}, #{collectType}, #{userId},
                      #{userPhone}, #{companyUserId}, #{batchId}, #{companyId}, #{companyName},
-                     #{createTime}, #{updateTime}
+                     #{createTime}, #{updateTime}, #{result}, #{outBatchNo}
                  )
     </insert>
 
-    <!-- 动态更新(根据主键,非空字段更新) -->
+    <!-- 动态更新(根据主键,非空字段更新,包含新字段) -->
     <update id="updateById" parameterType="com.fs.qw.domain.FsCompanyQrcRedPackageRecord">
         UPDATE fs_company_qrc_red_package_record
         <set>
@@ -85,6 +99,9 @@
             <if test="companyId != null">company_id = #{companyId},</if>
             <if test="companyName != null and companyName != ''">company_name = #{companyName},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
+            <!-- 新增字段动态更新 -->
+            <if test="result != null and result != ''">result = #{result},</if>
+            <if test="outBatchNo != null and outBatchNo != ''">out_batch_no = #{outBatchNo},</if>
         </set>
         WHERE id = #{id}
     </update>

+ 16 - 7
fs-user-app/src/main/java/com/fs/app/controller/ShareMaterialController.java

@@ -4,6 +4,7 @@ package com.fs.app.controller;
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsShareMaterial;
 import com.fs.his.dto.CollectionUserPhoneDTO;
+import com.fs.his.dto.ShareQRCRedPackageDto;
 import com.fs.his.service.IFsShareMaterialService;
 import com.fs.qw.service.IFsCompanyQrcPhoneService;
 import com.fs.qw.service.IFsCompanyQrcRedPackageRecordService;
@@ -19,7 +20,7 @@ import org.springframework.web.bind.annotation.*;
  */
 @RestController
 @RequestMapping("/app/shareMaterial")
-public class ShareMaterialController
+public class ShareMaterialController extends AppBaseController
 {
     @Autowired
     private IFsShareMaterialService shareMaterialService;
@@ -49,21 +50,29 @@ public class ShareMaterialController
     }
 
     /**
-     * 根据微信用户id查询用户是领取分享二维码红包详情
+     * 根据用户id查询用户是领取分享二维码红包详情
      * 一个用户id只能领取一次红包
      * */
     @GetMapping("/getRedPackageRecord/{userId}")
-    public R getRedPackageRecord(@PathVariable String userId){
+    public R getRedPackageRecord(@PathVariable Long userId){
         return R.ok().put("data",companyQrcRedPackageRecordService.getRedPackageRecordByUserId(userId));
     }
 
     /**
      * 客户点击领取红包
      * */
-    @GetMapping("/claimRedPacket/{userId}")
-    public R claimRedPacket(@PathVariable String userId){
-        int result = companyQrcRedPackageRecordService.claimRedPacket(userId);
-        return result>0?R.ok():R.error("领取失败");
+    @PostMapping("/claimRedPacket")
+    public R claimRedPacket(@RequestBody ShareQRCRedPackageDto param){
+        long userId;
+        try {
+            userId = Long.parseLong(getUserId());
+        }catch (Exception e){
+            return R.error("用户登录信息异常");
+        }
+
+        param.setUserId(userId);
+        R result = companyQrcRedPackageRecordService.claimRedPacket(param);
+        return result;
     }
 
 }