Browse Source

Merge branch 'refs/heads/master' into ScrmStore

chenguo 3 weeks ago
parent
commit
6cbeeb2bd2
28 changed files with 713 additions and 172 deletions
  1. 16 4
      fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java
  2. 7 1
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  3. 25 0
      fs-admin/src/main/java/com/fs/his/task/Task.java
  4. 6 0
      fs-common/src/main/java/com/fs/common/utils/DateUtils.java
  5. 120 0
      fs-company/src/main/java/com/fs/company/controller/store/FsCouponController.java
  6. 4 0
      fs-company/src/main/java/com/fs/company/controller/store/FsUserController.java
  7. 2 0
      fs-company/src/main/java/com/fs/company/controller/store/FsUserCouponController.java
  8. 0 49
      fs-qw-api-msg/src/main/java/com/fs/app/config/QWConfigProperties.java
  9. 6 4
      fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  10. 7 4
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  11. 16 4
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  12. 15 0
      fs-service/src/main/java/com/fs/company/vo/QwIpadTotalVo.java
  13. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java
  14. 11 11
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java
  15. 1 1
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
  16. 45 44
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  17. 3 2
      fs-service/src/main/java/com/fs/his/mapper/FsUserCouponMapper.java
  18. 2 0
      fs-service/src/main/java/com/fs/his/param/FsUserCouponParam.java
  19. 28 21
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  20. 12 15
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  21. 1 1
      fs-service/src/main/resources/application-config-druid-hzyy.yml
  22. 5 5
      fs-service/src/main/resources/application-config-druid-kyt.yml
  23. 87 0
      fs-service/src/main/resources/application-config-druid-syysy.yml
  24. 166 0
      fs-service/src/main/resources/application-druid-syysy.yml
  25. 22 0
      fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml
  26. 19 5
      fs-user-app/src/main/java/com/fs/app/controller/CouponController.java
  27. 16 0
      fs-user-app/src/main/java/com/fs/app/controller/UserController.java
  28. 70 0
      fs-user-app/src/main/java/com/fs/app/controller/WxH5MpController.java

+ 16 - 4
fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java

@@ -13,10 +13,7 @@ import com.fs.company.param.FsStoreStatisticsParam;
 import com.fs.company.service.ICompanySmsLogsService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.service.ICompanyVoiceLogsService;
-import com.fs.company.vo.CompanySmsLogsStatisticsVO;
-import com.fs.company.vo.CompanyVoiceLogsStatisticsVO;
-import com.fs.company.vo.FsStoreOrderStatisticsVO;
-import com.fs.company.vo.FsStorePaymentStatisticsVO;
+import com.fs.company.vo.*;
 import com.fs.crm.param.CrmCustomerStatisticsParam;
 import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.service.ICrmCustomerVisitService;
@@ -27,6 +24,7 @@ import com.fs.his.service.IFsStorePaymentService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -631,4 +629,18 @@ public class CompanyStatisticsController extends BaseController
         ExcelUtil<CrmCustomerVisitStatisticsVO> util = new ExcelUtil<CrmCustomerVisitStatisticsVO>(CrmCustomerVisitStatisticsVO.class);
         return util.exportExcel(list, "visit");
     }
+
+    @GetMapping("/ipadStaticTotal/{dateTime}")
+    public R ipadStaticTotal(@PathVariable("dateTime") String dateTime){
+        List<QwIpadTotalVo> qwIpadTotalVos = userService.selectCompanyByIpadStatus(dateTime);
+        return R.ok().put("list",qwIpadTotalVos);
+    }
+
+    @GetMapping("/exportIpadStaticByTime/{dateTime}")
+    public AjaxResult exportIpadStaticByTime(@PathVariable("dateTime") String dateTime){
+        List<QwIpadTotalVo> qwIpadTotalVos = userService.selectCompanyByIpadStatus(dateTime);
+        ExcelUtil<QwIpadTotalVo> util = new ExcelUtil<QwIpadTotalVo>(QwIpadTotalVo.class);
+        return util.exportExcel(qwIpadTotalVos, "visit");
+    }
+
 }

+ 7 - 1
fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java

@@ -604,7 +604,13 @@ public class FsStoreOrderController extends BaseController
             if (param.getUserPhoneMk() != null && !param.getUserPhoneMk().isEmpty()) {
                 param.setUserPhone(encryptPhone(param.getUserPhoneMk()));
             }
-            List<FsStoreOrderListVO> list = fsStoreOrderService.selectFsStoreOrderListVO(param);
+            List<FsStoreOrderListVO> list;
+            if (StringUtils.isNotBlank(param.getErpAccount())){
+                //金牛erp查询
+                list = fsStoreOrderService.selectFsStoreOrderListVOByErpAccount(param);
+            } else {
+                list = fsStoreOrderService.selectFsStoreOrderListVO(param);
+            }
             orderIds = list.stream().map(FsStoreOrderListVO::getOrderId).collect(Collectors.toList());
         }
         if (orderIds.isEmpty()){

+ 25 - 0
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -5,12 +5,15 @@ import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.service.impl.SmsServiceImpl;
+import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.SecurityUtils;
 import com.fs.company.domain.CompanyMoneyLogs;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.domain.CompanyVoiceCaller;
 import com.fs.company.mapper.*;
 import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.company.vo.QwIpadTotalVo;
 import com.fs.company.vo.RedPacketMoneyVO;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseWatchLogService;
@@ -48,6 +51,7 @@ import com.fs.qwApi.service.QwApiService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -59,6 +63,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
+@Slf4j
 @Component("task")
 public class Task {
     @Autowired
@@ -153,6 +158,26 @@ public class Task {
     @Autowired
     private IQwUserService qwUserService;
 
+    @Autowired
+    private ICompanyUserService userService;
+
+    //定时查询ipad主机使用情况,建议每天凌晨1点执行一次
+    public void totalIpadTask(){
+        String dateTime = DateUtils.addDateDays(-1); // 昨天
+        List<QwIpadTotalVo> qwIpadTotalVos = userService.selectCompanyByIpadStatusCount();
+        if(qwIpadTotalVos != null && !qwIpadTotalVos.isEmpty()){
+            qwIpadTotalVos.forEach(qwIpadTotalVo ->
+                    qwIpadTotalVo.setStatTime(dateTime)
+            );
+            int a = userService.insertQwIpadTotal(qwIpadTotalVos);
+            if(a == 0){
+                log.error("插入ipad主机失败");
+            }
+        }else{
+            log.error("查询没有数据");
+        }
+    }
+
     public void addQwUserName(){
         QwCompany qwCompany = new QwCompany();
         List<QwCompany> companyList = qwCompanyService.selectQwCompanyList(qwCompany);

+ 6 - 0
fs-common/src/main/java/com/fs/common/utils/DateUtils.java

@@ -264,5 +264,11 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         return endOfDay.format(OUTPUT_FORMATTER);
     }
 
+    // 返回昨天或明天的日期字符串(格式:yyyy-MM-dd)
+    public static String addDateDays(int days) {
+        Calendar cal = Calendar.getInstance();
+        cal.add(Calendar.DATE, days);
+        return new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
+    }
 
 }

+ 120 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsCouponController.java

@@ -0,0 +1,120 @@
+package com.fs.company.controller.store;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.his.domain.FsCoupon;
+import com.fs.his.param.FsCouponParam;
+import com.fs.his.service.IFsCouponService;
+import com.fs.his.vo.FsCouponAllListVO;
+import com.fs.his.vo.FsCouponListVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 优惠券Controller
+ *
+ * @author fs
+ * @date 2023-09-04
+ */
+@RestController
+@RequestMapping("/store/coupon")
+public class FsCouponController extends BaseController
+{
+    @Autowired
+    private IFsCouponService fsCouponService;
+
+    /**
+     * 查询优惠券列表订单查询
+     */
+    @PreAuthorize("@ss.hasPermi('store:coupon:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsCouponParam fsCoupon)
+    {
+        startPage();
+        List<FsCouponListVO> list = fsCouponService.selectFsCouponListVO(fsCoupon);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询优惠券列表订单查询
+     */
+    @GetMapping("/allList")
+    public AjaxResult allList()
+    {
+        List<FsCouponAllListVO> list = fsCouponService.selectFsCouponListAll();
+        return AjaxResult.success(list);
+    }
+
+
+
+    /**
+     * 导出优惠券列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:coupon:export')")
+    @Log(title = "优惠券", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsCoupon fsCoupon)
+    {
+        List<FsCoupon> list = fsCouponService.selectFsCouponList(fsCoupon);
+        ExcelUtil<FsCoupon> util = new ExcelUtil<FsCoupon>(FsCoupon.class);
+        return util.exportExcel(list, "优惠券数据");
+    }
+
+    /**
+     * 获取优惠券详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('store:coupon:query')")
+    @GetMapping(value = "/{couponId}")
+    public AjaxResult getInfo(@PathVariable("couponId") Long couponId)
+    {
+        return AjaxResult.success(fsCouponService.selectFsCouponByCouponId(couponId));
+    }
+
+//    /**
+//     * 新增优惠券
+//     */
+//    @PreAuthorize("@ss.hasPermi('store:coupon:add')")
+//    @Log(title = "优惠券", businessType = BusinessType.INSERT)
+//    @PostMapping
+//    public AjaxResult add(@RequestBody FsCoupon fsCoupon)
+//    {
+//        return toAjax(fsCouponService.insertFsCoupon(fsCoupon));
+//    }
+//
+//    /**
+//     * 修改优惠券
+//     */
+//    @PreAuthorize("@ss.hasPermi('store:coupon:edit')")
+//    @Log(title = "优惠券", businessType = BusinessType.UPDATE)
+//    @PutMapping
+//    public AjaxResult edit(@RequestBody FsCoupon fsCoupon)
+//    {
+//        FsCoupon c = fsCouponService.selectFsCouponByCouponId(fsCoupon.getCouponId());
+//        long l = c.getRemainNumber() + fsCoupon.getNumber() - c.getNumber();
+//        if (l<0){
+//            throw new CustomException("剩余卷不足");
+//        }
+//        fsCoupon.setRemainNumber(l);
+//        return toAjax(fsCouponService.updateFsCoupon(fsCoupon));
+//    }
+//
+//    /**
+//     * 删除优惠券
+//     */
+//    @PreAuthorize("@ss.hasPermi('store:coupon:remove')")
+//    @Log(title = "优惠券", businessType = BusinessType.DELETE)
+//	@DeleteMapping("/{couponIds}")
+//    public AjaxResult remove(@PathVariable Long[] couponIds)
+//    {
+//        return toAjax(fsCouponService.deleteFsCouponByCouponIds(couponIds));
+//    }
+}

+ 4 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsUserController.java

@@ -233,6 +233,10 @@ public class FsUserController extends BaseController
     public TableDataInfo userlist(@PathVariable("name")String name)
     {
         List<UserVo> list = fsUserService.selectUserVOList(name);
+        if (list==null|| list.isEmpty()){
+            String s = encryptPhone(name);
+            list = fsUserService.selectUserVOList(s);
+        }
         return getDataTable(list);
     }
 

+ 2 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsUserCouponController.java

@@ -40,6 +40,8 @@ public class FsUserCouponController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(FsUserCouponParam fsUserCoupon)
     {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsUserCoupon.setCompanyId(loginUser.getCompany().getCompanyId());
         startPage();
         List<FsUserCouponListVO> list = fsUserCouponService.selectFsUserCouponListVO(fsUserCoupon);
         return getDataTable(list);

+ 0 - 49
fs-qw-api-msg/src/main/java/com/fs/app/config/QWConfigProperties.java

@@ -1,49 +0,0 @@
-package com.fs.app.config;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-@Component
-public class QWConfigProperties {
-
-    @Value("${custom.token}")
-    private String token;
-
-    @Value("${custom.encoding-aes-key}")
-    private String encodingAesKey;
-
-    @Value("${custom.corp-id}")
-    private String corpId;
-    @Value("${custom.secret}")
-    private String secret;
-
-    @Value("${custom.private-key-path}")
-    private String privateKeyPath;
-
-    @Value("${custom.webhook-url}")
-    private String webhookUrl;
-
-    public String getToken() {
-        return token;
-    }
-
-    public String getEncodingAesKey() {
-        return encodingAesKey;
-    }
-
-    public String getCorpId() {
-        return corpId;
-    }
-
-    public String getSecret() {
-        return secret;
-    }
-
-    public String getPrivateKeyPath() {
-        return privateKeyPath;
-    }
-
-    public String getWebhookUrl() {
-        return webhookUrl;
-    }
-}

+ 6 - 4
fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java

@@ -5,10 +5,7 @@ import com.fs.common.enums.DataSourceType;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.param.CompanyUserAreaParam;
 import com.fs.company.param.CompanyUserQwParam;
-import com.fs.company.vo.CompanyQwUserByIdsVo;
-import com.fs.company.vo.CompanyUserQwListVO;
-import com.fs.company.vo.CompanyUserVO;
-import com.fs.company.vo.DocCompanyUserVO;
+import com.fs.company.vo.*;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.vo.CompanyUserQwVO;
 import com.fs.qw.vo.QwOptionsVO;
@@ -308,4 +305,9 @@ public interface CompanyUserMapper
 
     int updateAllowedAllRegister(@Param("status") boolean status, @Param("userIds")List<Long> userIds);
 
+    List<QwIpadTotalVo> selectCompanyByIpadStatus(@Param("dateTime") String dateTime);
+
+    List<QwIpadTotalVo> selectCompanyByIpadStatusCount();
+
+    int insertQwIpadTotal(List<QwIpadTotalVo> qwIpadTotalVos);
 }

+ 7 - 4
fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java

@@ -4,10 +4,7 @@ import com.fs.common.core.domain.R;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.param.CompanyUserAreaParam;
 import com.fs.company.param.CompanyUserQwParam;
-import com.fs.company.vo.CompanyQwUserByIdsVo;
-import com.fs.company.vo.CompanyUserQwListVO;
-import com.fs.company.vo.CompanyUserVO;
-import com.fs.company.vo.DocCompanyUserVO;
+import com.fs.company.vo.*;
 import com.fs.his.vo.CitysAreaVO;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.dto.UserProjectDTO;
@@ -220,4 +217,10 @@ public interface ICompanyUserService {
      */
     Boolean isAllowedAllRegister(boolean status,  List<Long> userIds);
 
+    List<QwIpadTotalVo> selectCompanyByIpadStatus(String dateTime);
+
+    List<QwIpadTotalVo> selectCompanyByIpadStatusCount();
+
+    int insertQwIpadTotal(List<QwIpadTotalVo> qwIpadTotalVos);
+
 }

+ 16 - 4
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -13,10 +13,7 @@ import com.fs.company.mapper.*;
 import com.fs.company.param.CompanyUserAreaParam;
 import com.fs.company.param.CompanyUserQwParam;
 import com.fs.company.service.ICompanyUserService;
-import com.fs.company.vo.CompanyQwUserByIdsVo;
-import com.fs.company.vo.CompanyUserQwListVO;
-import com.fs.company.vo.CompanyUserVO;
-import com.fs.company.vo.DocCompanyUserVO;
+import com.fs.company.vo.*;
 import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.service.IFsCityService;
@@ -624,4 +621,19 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         return true;
     }
 
+    @Override
+    public List<QwIpadTotalVo> selectCompanyByIpadStatus(String dateTime) {
+        return companyUserMapper.selectCompanyByIpadStatus(dateTime);
+    }
+
+    @Override
+    public List<QwIpadTotalVo> selectCompanyByIpadStatusCount() {
+        return companyUserMapper.selectCompanyByIpadStatusCount();
+    }
+
+    @Override
+    public int insertQwIpadTotal(List<QwIpadTotalVo> qwIpadTotalVos) {
+        return companyUserMapper.insertQwIpadTotal(qwIpadTotalVos);
+    }
+
 }

+ 15 - 0
fs-service/src/main/java/com/fs/company/vo/QwIpadTotalVo.java

@@ -0,0 +1,15 @@
+package com.fs.company.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwIpadTotalVo {
+    private Long id;
+    private Long companyId;
+    @Excel(name = "公司名称")
+    private String companyName;
+    @Excel(name = "绑定数")
+    private Long bindCount;
+    private String statTime;
+}

+ 1 - 1
fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java

@@ -64,7 +64,7 @@ public interface IFsCourseRedPacketLogService
      */
     public int deleteFsCourseRedPacketLogByLogId(Long logId);
 
-    R syncRedPacket(String outBatchNo);
+//    R syncRedPacket(String outBatchNo);
 
     R syncRedPacket(String outBatchNo, String batchId);
 

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

@@ -122,17 +122,17 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
         return fsCourseRedPacketLogMapper.deleteFsCourseRedPacketLogByLogId(logId);
     }
 
-    @Override
-    public R syncRedPacket(String outBatchNo) {
-        FsCourseRedPacketLog log = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByBatchNo(outBatchNo);
-        if (log!=null){
-            log.setStatus(1);
-            log.setUpdateTime(new Date());
-            fsCourseRedPacketLogMapper.updateFsCourseRedPacketLog(log);
-            return R.ok();
-        }
-        return R.error("批次不存在");
-    }
+//    @Override
+//    public R syncRedPacket(String outBatchNo) {
+//        FsCourseRedPacketLog log = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByBatchNo(outBatchNo);
+//        if (log!=null){
+//            log.setStatus(1);
+//            log.setUpdateTime(new Date());
+//            fsCourseRedPacketLogMapper.updateFsCourseRedPacketLog(log);
+//            return R.ok();
+//        }
+//        return R.error("批次不存在");
+//    }
 
     @Override
     public R syncRedPacket(String outBatchNo, String batchId) {

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

@@ -405,7 +405,7 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         if (videoDuration==null){
             FsUserCourseVideo video = courseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
             videoDuration=video.getDuration();
-            redisCache.setCacheObject(videoRedisKey,video.getDuration().toString());
+            redisCache.setCacheObject(videoRedisKey,video.getDuration());
         }
         return videoDuration;
     }

+ 45 - 44
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -72,6 +72,7 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
@@ -203,6 +204,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Autowired
     private SysDictDataMapper dictDataMapper;
 
+    @Autowired
+    private FsCourseAnswerLogsMapper courseAnswerLogsMapper;
+
 
     /**
      * 查询课堂视频
@@ -918,6 +922,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     }
 
     @Override
+    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
     public R sendRewardByFsUser(FsCourseSendRewardUParam param) {
         FsUser user = fsUserMapper.selectFsUserByUserId(param.getUserId());
         if (user == null){
@@ -927,6 +932,13 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (log == null) {
             return R.error("无记录");
         }
+
+        FsCourseAnswerLogs rightLog = courseAnswerLogsMapper.selectRightLogByCourseVideo(param.getVideoId(), param.getUserId(), param.getQwUserId());
+
+        if (rightLog == null) {
+            logger.error("未答题:{}",param.getUserId());
+            return R.error("未答题");
+        }
         if (log.getRewardType() != null) {
             FsCourseRedPacketLog fsCourseRedPacketLog = redPacketLogMapper.selectUserFsCourseRedPacketLog(param.getVideoId(), param.getUserId(),param.getPeriodId());
             if(fsCourseRedPacketLog != null && fsCourseRedPacketLog.getStatus() == 1) {
@@ -1108,27 +1120,17 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
 
     private void handleFsUserWx(FsUser user, String appId) {
-        // 尝试更新
-        boolean updated = fsUserWxService.lambdaUpdate()
-                .eq(FsUserWx::getFsUserId, user.getUserId())
-                .eq(FsUserWx::getAppId,appId )
-                .eq(FsUserWx::getOpenId, user.getMaOpenId())
-//                .set(FsUserWx::getUnionId, session.getUnionid() == null ? "" : session.getUnionid())
-                .set(FsUserWx::getUpdateTime, new Date())
-                .update();
-
-        // 如果更新失败(记录不存在),则插入
-        if (!updated) {
-            FsUserWx fsUserWx = new FsUserWx();
-            fsUserWx.setType(1);
-            fsUserWx.setFsUserId(user.getUserId());
-            fsUserWx.setAppId(appId);
-            fsUserWx.setOpenId(user.getMaOpenId());
-//            fsUserWx.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
-            fsUserWx.setCreateTime(new Date());
-            fsUserWx.setUpdateTime(new Date());
-            fsUserWxService.save(fsUserWx);
-        }
+        FsUserWx fsUserWx = new FsUserWx();
+        fsUserWx.setType(1);
+        fsUserWx.setFsUserId(user.getUserId());
+        fsUserWx.setAppId(appId);
+        fsUserWx.setOpenId(user.getCourseMaOpenId());
+        fsUserWx.setUnionId(user.getUnionId());
+        fsUserWx.setCreateTime(new Date());
+        fsUserWx.setUpdateTime(new Date());
+        fsUserWxService.saveOrUpdateByUniqueKey(fsUserWx);
+
+        logger.info("zyp \n 【更新或插入用户与小程序{}的绑定关系】:{}", appId, user.getUserId());
     }
 
     /**
@@ -1142,20 +1144,19 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
      * @return 处理结果
      */
     private R sendRedPacketRewardFsUser(FsCourseSendRewardUParam param, FsUser user, FsCourseWatchLog log, FsUserCourseVideo video, CourseConfig config) {
-        // 判断是否属于领取红包时间(会员看课发放红包)
-        if (param.getPeriodId()!=null && param.getPeriodId()>0) {
-            FsUserCoursePeriodDays periodDays = new FsUserCoursePeriodDays();
-            periodDays.setVideoId(param.getVideoId());
-            periodDays.setPeriodId(param.getPeriodId());
-            //正常情况是只能查询到一条,之前可能存在重复的脏数据,暂使用查询list的方式
-            List<FsUserCoursePeriodDays> fsUserCoursePeriodDays = fsUserCoursePeriodDaysMapper.selectFsUserCoursePeriodDaysList(periodDays);
-            if(fsUserCoursePeriodDays != null && !fsUserCoursePeriodDays.isEmpty()){
-                periodDays = fsUserCoursePeriodDays.get(0);
-            }
-            if(periodDays != null && periodDays.getLastJoinTime() !=null && LocalDateTime.now().isAfter(periodDays.getLastJoinTime())) {
-                return R.error(403,"已超过领取红包时间");
-            }
+
+        FsUserCoursePeriodDays periodDays = new FsUserCoursePeriodDays();
+        periodDays.setVideoId(param.getVideoId());
+        periodDays.setPeriodId(param.getPeriodId());
+        //正常情况是只能查询到一条,之前可能存在重复的脏数据,暂使用查询list的方式
+        List<FsUserCoursePeriodDays> fsUserCoursePeriodDays = fsUserCoursePeriodDaysMapper.selectFsUserCoursePeriodDaysList(periodDays);
+        if(fsUserCoursePeriodDays != null && !fsUserCoursePeriodDays.isEmpty()){
+            periodDays = fsUserCoursePeriodDays.get(0);
         }
+        if(periodDays != null && periodDays.getLastJoinTime() !=null && LocalDateTime.now().isAfter(periodDays.getLastJoinTime())) {
+            return R.error(403,"已超过领取红包时间");
+        }
+
 
         // 确定红包金额
         BigDecimal amount = BigDecimal.ZERO;
@@ -1169,7 +1170,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         // 准备发送红包参数
         WxSendRedPacketParam packetParam = new WxSendRedPacketParam();
-//        packetParam.setOpenId(getOpenId(user.getUserId(), param.getCompanyId(), param.getSource()));
         packetParam.setOpenId(user.getMpOpenId());
         // 来源是小程序切换openId
         if (param.getSource() == 2) {
@@ -1179,7 +1179,11 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 //                return R.error("销售公司参数错误,未绑定小程序");
 //            }
             FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(),user.getUserId(),1);
-            if (fsUserWx ==null || fsUserWx.getOpenId()==null){
+            if (fsUserWx ==null){
+                if (user.getCourseMaOpenId()==null){
+                    logger.error("zyp \n 【转账openId参数错误】:{}", user.getUserId());
+                    return R.error("openId参数错误");
+                }
                 packetParam.setOpenId(user.getCourseMaOpenId());
                 try {
                     handleFsUserWx(user,param.getAppId());
@@ -1190,21 +1194,18 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             }else {
                 packetParam.setOpenId(fsUserWx.getOpenId());
             }
-
-            System.out.println("小程序id"+user.getCourseMaOpenId());
-            //查出公司绑定openid并赋值
-//            packetParam.setOpenId(fsUserWx.getOpenId());
         }
         packetParam.setAmount(amount);
         packetParam.setSource(param.getSource());
         packetParam.setRedPacketMode(config.getRedPacketMode());
         packetParam.setCompanyId(param.getCompanyId());
+        packetParam.setAppId(param.getAppId());
 
         System.out.println("红包金额"+amount);
         System.out.println("红包商户号"+packetParam);
-        if (ObjectUtils.isNotEmpty(config.getIsNegative())&&config.getIsNegative() == 1) {
-            return processRedPacket(config, packetParam, param, amount, log);
-        }
+//        if (ObjectUtils.isNotEmpty(config.getIsNegative())&&config.getIsNegative() == 1) {
+//            return processRedPacket(config, packetParam, param, amount, log);
+//        }
         //2025.6.19 红包金额为0的时候
         if (amount.compareTo(BigDecimal.ZERO)>0){
 
@@ -1239,10 +1240,10 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                     redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
                 }else {
                     redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
+                    redPacketLog.setBatchId(sendRedPacket.get("batchId").toString());
                 }
                 // 添加红包记录
                 redPacketLog.setCourseId(param.getCourseId());
-//            redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
                 redPacketLog.setCompanyId(param.getCompanyId());
                 redPacketLog.setUserId(param.getUserId());
                 redPacketLog.setVideoId(param.getVideoId());

+ 3 - 2
fs-service/src/main/java/com/fs/his/mapper/FsUserCouponMapper.java

@@ -81,8 +81,9 @@ public interface FsUserCouponMapper
             "            <if test=\"businessId != null \"> and uc.business_id = #{businessId}</if>\n" +
             "            <if test=\"businessType != null \"> and uc.business_type = #{businessType}</if>\n" +
             "            <if test=\"status != null \"> and uc.status = #{status}</if>\n" +
-            "            <if test=\"companyName != null \">and com.company_name like concat('%', #{companyName}, '%') </if>\n" +
-            "            <if test=\"companyUserName != null \">and comu.user_name like concat('%', #{companyUserName}, '%') </if>\n" +
+            "            <if test=\"companyName != null and companyName != ''\">and com.company_name like concat('%', #{companyName}, '%') </if>\n" +
+            "            <if test=\"companyUserName != null and companyUserName != ''\">and comu.user_name like concat('%', #{companyUserName}, '%') </if>\n" +
+            "            <if test=\"companyId != null \">and uc.company_id = #{companyId} </if>\n" +
             "        </where> "+
             " order by id desc"+
             "</script>"})

+ 2 - 0
fs-service/src/main/java/com/fs/his/param/FsUserCouponParam.java

@@ -55,4 +55,6 @@ public class FsUserCouponParam {
     private String companyName;
     private String companyUserName;
 
+    private Long companyId;
+
 }

+ 28 - 21
fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java

@@ -3402,28 +3402,35 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
         DFApiResponse dfApiResponse = JSON.parseObject(body, DFApiResponse.class);
         Object result = dfApiResponse.getResult();
         if (result != null) {
+
             String jsonString = JSON.toJSONString(result);
-            List<DFOrderStatusResultRequest> requestList = JSON.parseArray(jsonString, DFOrderStatusResultRequest.class);
-            if (requestList != null && !requestList.isEmpty()) {
-                //0待揽收 1已揽收 2运输中 3派送中 4异常件 5退回件 6退回签收 7转寄件 8作废件 9已签收 10 已取消
-                for (DFOrderStatusResultRequest temp : requestList) {
-                    if (temp.getStatus() == 10) {
-                        //取消订单
-                        String mailNumber = temp.getMailNumber();
-                        List<FsStoreOrder> fsStoreOrders = fsStoreOrderMapper.selectFsStoreOrderListByDeliverySn(mailNumber);
-                        if (fsStoreOrders != null && !fsStoreOrders.isEmpty()) {
-                            fsStoreOrders.forEach(order -> {
-                                FsStoreOrderSalesParam afterSalesParam = new FsStoreOrderSalesParam();
-                                afterSalesParam.setOrderId(order.getOrderId());
-                                afterSalesParam.setReasons("代服管家取消订单");
-                                afterSalesParam.setOperator("代服管家");
-                                afterSales(afterSalesParam);
-                                FsStoreOrderDf df = new FsStoreOrderDf();
-                                df.setOrderId(order.getOrderId());
-                                df.setStatus(2);
-                                df.setUpdateTime(new Date());
-                                fsStoreOrderDfMapper.updateFsStoreOrderDf(df);
-                            });
+            log.info("ct1111111111111111111{}", jsonString);
+            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(jsonString);
+            if (jsonObject != null) {
+                Object listObj = jsonObject.get("list");
+                String listJson = JSON.toJSONString(listObj);
+                List<DFOrderStatusResultRequest> requestList = JSON.parseArray(listJson, DFOrderStatusResultRequest.class);
+                if (requestList != null && !requestList.isEmpty()) {
+                    //0待揽收 1已揽收 2运输中 3派送中 4异常件 5退回件 6退回签收 7转寄件 8作废件 9已签收 10 已取消
+                    for (DFOrderStatusResultRequest temp : requestList) {
+                        if (temp.getStatus() == 10) {
+                            //取消订单
+                            String mailNumber = temp.getMailNumber();
+                            List<FsStoreOrder> fsStoreOrders = fsStoreOrderMapper.selectFsStoreOrderListByDeliverySn(mailNumber);
+                            if (fsStoreOrders != null && !fsStoreOrders.isEmpty()) {
+                                fsStoreOrders.forEach(order -> {
+                                    FsStoreOrderSalesParam afterSalesParam = new FsStoreOrderSalesParam();
+                                    afterSalesParam.setOrderId(order.getOrderId());
+                                    afterSalesParam.setReasons("代服管家取消订单");
+                                    afterSalesParam.setOperator("代服管家");
+                                    afterSales(afterSalesParam);
+                                    FsStoreOrderDf df = new FsStoreOrderDf();
+                                    df.setOrderId(order.getOrderId());
+                                    df.setStatus(2);
+                                    df.setUpdateTime(new Date());
+                                    fsStoreOrderDfMapper.updateFsStoreOrderDf(df);
+                                });
+                            }
                         }
                     }
                 }

+ 12 - 15
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -471,6 +471,12 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                 config = JSONUtil.toBean(json, RedPacketConfig.class);
                 break;
         }
+        //H5的用公众号的appid发,小程序的用小程序的appid来发
+        if (param.getSource()==2){
+            // 传参appId为空时,仍然使用配置里面的
+            String appId = StringUtils.isBlank(param.getAppId()) ? config.getMiniappId() : param.getAppId();
+            config.setAppId(appId);
+        }
         System.out.println("最终传参"+config);
         //组合返回参数
         R result = new R();
@@ -495,12 +501,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         TransferService transferService = wxPayService.getTransferService();
 
         TransferBillsRequest request = new TransferBillsRequest();
-        if(param.getSource()==2){
-            request.setAppid(config.getMiniappId());
-        }else {
-            request.setAppid(config.getAppId());
-        }
-
+        request.setAppid(config.getAppId());
         request.setOpenid(param.getOpenId());
 
         String code = String.valueOf(IdUtil.getSnowflake(0, 0).nextId());
@@ -547,11 +548,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         TransferService transferService = wxPayService.getTransferService();
 
         TransferBatchesRequest request = new TransferBatchesRequest();
-        if (param.getSource() == 2){
-            request.setAppid(config.getMiniappId());
-        }else {
-            request.setAppid(config.getAppId());
-        }
+        request.setAppid(config.getAppId());
 
         String code = IdUtil.getSnowflake(0, 0).nextIdStr();
         request.setOutBatchNo("fsCourse" + code);
@@ -574,7 +571,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
 
         try {
             TransferBatchesResult transferBatchesResult = transferService.transferBatches(request);
-            return R.ok("发送红包成功").put("orderCode", transferBatchesResult.getOutBatchNo());
+            return R.ok("发送红包成功").put("orderCode", transferBatchesResult.getOutBatchNo()).put("batchId", transferBatchesResult.getBatchId());
         } catch (WxPayException e) {
             e.printStackTrace();
             return R.error("发送失败");
@@ -600,8 +597,8 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
             WxPayTransferBatchesNotifyV3Result result = wxPayService.parseTransferBatchesNotifyV3Result(notifyData,signatureHeader);
             logger.info("到零钱回调:{}",result.getResult());
-            if (result.getResult().getBatchStatus().equals("FINISHED")) {
-                R r = redPacketLogService.syncRedPacket(result.getResult().getOutBatchNo());
+            if (result.getResult().getBatchStatus().equals("FINISHED") && result.getResult().getFailNum()==0) {
+                R r = redPacketLogService.syncRedPacket(result.getResult().getOutBatchNo(),result.getResult().getBatchId());
                 logger.info("result:{}",r);
                 if (r.get("code").equals(200)){
                     return WxPayNotifyResponse.success("处理成功");
@@ -723,7 +720,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             TransferBillsNotifyResult result = wxPayService.parseTransferBillsNotifyV3Result(notifyData,signatureHeader);
             logger.info("到零钱回调:{}",result.getResult());
             if (result.getResult().getState().equals("SUCCESS")) {
-                R r = redPacketLogService.syncRedPacket(result.getResult().getOutBillNo());
+                R r = redPacketLogService.syncRedPacket(result.getResult().getOutBillNo(),result.getResult().getTransferBillNo());
                 logger.info("result:{}",r);
                 if (r.get("code").equals(200)){
                     return WxPayNotifyResponse.success("处理成功");

+ 1 - 1
fs-service/src/main/resources/application-config-druid-hzyy.yml

@@ -88,7 +88,7 @@ headerImg:
   imgUrl: https://hzyy.obs.cn-north-4.myhuaweicloud.com/fs/20250616/1750067609692.png
 ipad:
   ipadUrl: http://139.159.133.223:8667
-  aiApi: http://154.8.194.176:3000/api
+  aiApi: http://1.95.196.10:3000/api
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:

+ 5 - 5
fs-service/src/main/resources/application-config-druid-kyt.yml

@@ -42,10 +42,10 @@ wx:
       port: 6379
       timeout: 2000
     configs:
-      - appId:  # 第一个公众号的appid
-        secret:  # 公众号的appsecret
-        token:  # 接口配置里的Token值
-        aesKey:  # 接口配置里的EncodingAESKey值
+      - appId:  wxd0a67578869950ab # 第一个公众号的appid
+        secret: 645f649be6d748e33e71cefec2469e86  # 公众号的appsecret
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
 aifabu:  #爱链接
   appKey: 7b471be905ab17ef358c0dd117601d008
 watch:
@@ -77,7 +77,7 @@ cloud_host:
   company_name: 宽益堂
 #看课授权时显示的头像
 headerImg:
-  imgUrl: https://yztcourse-1325300895.cos.ap-guangzhou.myqcloud.com/yztcourse/20250523/e04871a98cc84be39a7f60c084698e21.jpg
+  imgUrl: https://kuanyitang-1317640934.cos.ap-shanghai.myqcloud.com/kuanyitang/20250813/6b3b62e01672407c98f0561b73e35f6a.jpg
 ipad:
   ipadUrl:
   aiApi:

+ 87 - 0
fs-service/src/main/resources/application-config-druid-syysy.yml

@@ -0,0 +1,87 @@
+baidu:
+  token: 1
+  back-domain: https://www.xxxx.com
+#配置
+logging:
+  level:
+    org.springframework.web: INFO
+    com.github.binarywang.demo.wx.cp: DEBUG
+    me.chanjar.weixin: DEBUG
+wx:
+  miniapp:
+    configs:
+      - appid: w   #中康智慧
+        secret: 5
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+      - appid: w   #中康未来智慧药房
+        secret: 9
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+  cp:
+    corpId: wwb
+    appConfigs:
+      - agentId: 100005
+        secret: ec7okROXJqkNafq66aKNv0asTzQIG0CYrj3vyBbo
+        token: PPKOdAloMO
+        aesKey: PKvaxtpSvNGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
+  pay:
+    appId: wx #微信公众号或者小程序等的appid
+    mchId: 1611045 #微信支付商户号
+    mchKey: 8cab128997a3547c10898b877f38 #微信支付商户密钥
+    subAppId:  #服务商模式下的子商户公众账号ID
+    subMchId:  #服务商模式下的子商户号
+    keyPath: c:\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
+    notifyUrl: https://usepp.his.runtzh.com/app/wxpay/wxPayNotify
+  mp:
+    useRedis: false
+    redisConfig:
+      host: 127.0.0.1
+      port: 6379
+      timeout: 2000
+    configs:
+      - appId: wx # 第一个公众号的appid  //公众号名称
+        secret: 5da9ae # 公众号的appsecret
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVcw03qZy6Wllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+aifabu:  #爱链接
+  appKey: 7b471be905ab17ef358c610dd117601d008
+watch:
+  watchUrl: watch.ylrzcloud.com/prod-api
+#  account: tcloud
+#  password: mdf-m2h_6yw2$hq
+  account1: ccif #866655060138751
+  password1: cp-t5or_6xw7$mt
+  account2: tcloud #rt500台
+  password2: mdf-m2h_6yw2$hq
+  account3: whr
+  password3: v9xsKuqn_$d2y
+
+fs :
+  commonApi: http://172.27.0.12:8010
+  h5CommonApi: http://172.27.0.12:8010
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+# 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: syysy-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: syysy
+cloud_host:
+  company_name: 益善缘
+#看课授权时显示的头像
+headerImg:
+  imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
+ipad:
+  ipadUrl: http://ipad.xintaihl.cn
+  aiApi:
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+

+ 166 - 0
fs-service/src/main/resources/application-druid-syysy.yml

@@ -0,0 +1,166 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-sxjz,common
+    # redis 配置
+    redis:
+        host: 172.27.0.13
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password: Sxdtcbm@#+!2025
+        # 连接超时时间
+        timeout: 10s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+    datasource:
+        #        clickhouse:
+        #            type: com.alibaba.druid.pool.DruidDataSource
+        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
+        #            url: jdbc:clickhouse://1.14.104.71:8123/sop_test?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
+        #            username: rt_2024
+        #            password: Yzx_19860213
+        #            initialSize: 10
+        #            maxActive: 100
+        #            minIdle: 10
+        #            maxWait: 6000
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://172.27.0.6:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Sxdtcbm@#+!2025
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 2000
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://172.27.0.6:3306/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Sxdtcbm@#+!2025
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 200
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: voice-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+custom:
+    token: "1o62d3YxvdHd4LEUiltnu7sK"
+    encoding-aes-key: "UJfTQ5qKTKlegjkXtp1YuzJzxeHlUKvq5GyFbERN1iU"
+    corp-id: "ww51717e2b71d5e2d3"
+    secret: "6ODAmw-8W4t6h9mdzHh2Z4Apwj8mnsyRnjEDZOHdA7k"
+    private-key-path: "privatekey.pem"
+    webhook-url: "https://your-server.com/wecom/archive"
+# token配置
+token:
+    # 令牌自定义标识
+    header: Authorization
+    # 令牌密钥
+    secret: abcdefghijklmnopqrstuvwxyz
+    # 令牌有效期(默认30分钟)
+    expireTime: 180
+openIM:
+    secret: openIM123
+    userID: imAdmin

+ 22 - 0
fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml

@@ -175,6 +175,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isAudit != null">#{isAudit},</if>
         </trim>
     </insert>
+    <insert id="insertQwIpadTotal">
+        insert into qw_ipad_total (company_id,company_name,bind_count,stat_time) values
+        <foreach item="item" collection="list" separator=",">
+            (#{item.companyId},#{item.companyName},#{item.bindCount},#{item.statTime})
+        </foreach>
+    </insert>
 
     <update id="updateCompanyUser" parameterType="CompanyUser">
         update company_user
@@ -531,6 +537,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectCompanyUserByCompanyUserId" resultMap="CompanyUserResult">
         select  * from company_user where user_id = #{companyUserId}
     </select>
+    <select id="selectCompanyByIpadStatus" resultType="com.fs.company.vo.QwIpadTotalVo">
+        select company_id companyId,company_name companyName,
+        sum(bind_count) bindCount,stat_time statTime from qw_ipad_total
+        <where>
+            <if test="dateTime != null">
+                and stat_time like concat(#{dateTime}, '%')
+            </if>
+        </where>
+        group by company_id,company_name
+    </select>
+    <select id="selectCompanyByIpadStatusCount" resultType="com.fs.company.vo.QwIpadTotalVo">
+        SELECT qw.company_id companyId,c.company_name companyName,count(1) bindCount
+        FROM `qw_user` qw left join company c on qw.company_id = c.company_id
+        where qw.ipad_status is not null
+        GROUP BY qw.company_id
+    </select>
 
     <update id="updateAllowedAllRegister" parameterType="Long">
         update company_user

+ 19 - 5
fs-user-app/src/main/java/com/fs/app/controller/CouponController.java

@@ -4,17 +4,17 @@ package com.fs.app.controller;
 import cn.hutool.Hutool;
 import cn.hutool.core.util.IdUtil;
 import com.fs.app.annotation.Login;
+import com.fs.common.annotation.Log;
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.enums.BusinessType;
 import com.fs.his.domain.FsCoupon;
-import com.fs.his.domain.FsPackage;
 import com.fs.his.param.*;
 import com.fs.his.service.IFsCouponService;
-import com.fs.his.service.IFsDoctorService;
-import com.fs.his.service.IFsPackageService;
+import com.fs.his.service.IFsUserCouponService;
 import com.fs.his.vo.FsCouponListUVO;
-import com.fs.his.vo.FsDoctorListUVO;
-import com.fs.his.vo.FsPackageListUVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
@@ -40,6 +40,9 @@ public class CouponController extends  AppBaseController {
     @Autowired
     private RedisCache redisCache;
 
+    @Autowired
+    private IFsUserCouponService fsUserCouponService;
+
     @ApiOperation("获取优惠券列表")
     @GetMapping("/getCouponList")
     public R getCouponList(FsCouponListUParam param)
@@ -84,5 +87,16 @@ public class CouponController extends  AppBaseController {
         return couponService.receive(param);
     }
 
+    /**
+     * 发送会员优惠券
+     */
+    @RepeatSubmit
+    @Log(title = "发送会员优惠券", businessType = BusinessType.INSERT)
+    @PostMapping("/sendCoupon")
+    public AjaxResult sendCoupon(@RequestBody FsUserCouponSendParam fsUserCoupon)
+    {
+        return toAjax(fsUserCouponService.sendFsUserCoupon(fsUserCoupon));
+    }
+
 
 }

+ 16 - 0
fs-user-app/src/main/java/com/fs/app/controller/UserController.java

@@ -6,6 +6,7 @@ import com.fs.app.annotation.Login;
 import com.fs.app.param.FsDoctorRegisterParam;
 import com.fs.app.param.FsUserEditParam;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.sign.Md5Utils;
@@ -23,6 +24,7 @@ import com.fs.his.utils.qrcode.QRCodeUtils;
 import com.fs.his.vo.FsDoctorListUVO;
 import com.fs.his.vo.FsUserCouponCountUVO;
 import com.fs.his.vo.FsUserCouponListUVO;
+import com.fs.his.vo.UserVo;
 import com.fs.qw.service.IQwAppContactWayService;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
@@ -277,4 +279,18 @@ public class UserController extends  AppBaseController {
         return userService.updateStatus(id);
     }
 
+    /**
+     * 查询用户
+     */
+    @GetMapping("/user/list/{name}")
+    public TableDataInfo userlist(@PathVariable("name")String name)
+    {
+        List<UserVo> list = userService.selectUserVOList(name);
+        if (list==null|| list.isEmpty()){
+            String s = encryptPhone(name);
+            list = userService.selectUserVOList(s);
+        }
+        return getDataTable(list);
+    }
+
 }

+ 70 - 0
fs-user-app/src/main/java/com/fs/app/controller/WxH5MpController.java

@@ -28,6 +28,7 @@ import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.mp.api.WxMpService;
 import org.apache.commons.lang3.StringUtils;
+import org.checkerframework.checker.units.qual.C;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -122,6 +123,45 @@ public class WxH5MpController {
         }
     }
 
+    @ApiOperation("炮灰小程序-公众号登录转小程序")
+    @PostMapping("/courseLoginByMp")
+    public R courseLoginByMp(@Valid @RequestBody FsUserLoginByMpParam param) {
+        log.info("=====================进入炮灰小程序-公众号授权登录, 入参: {}", param);
+
+        // 参数校验
+        if (StringUtils.isBlank(param.getCode())) {
+            return R.error("code不存在");
+        }
+
+        // 公司状态校验
+        Company company = companyService.selectCompanyById(param.getCompanyId());
+        if (company == null || company.getStatus() == 0) {
+            return R.error("注册失败团队已停用,或不存在!");
+        }
+
+        // 客服状态校验
+        CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());
+        if (companyUser == null || "1".equals(companyUser.getStatus())) {
+            return R.error("注册失败客服已停用,或不存在!");
+        }
+
+        try {
+            // 获取微信用户信息
+            WxOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(param.getCode());
+            WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(wxMpOAuth2AccessToken, null);
+
+            // 处理用户信息
+            FsUser user = processUserInfoByCourseLoginByMp(wxMpUser);
+
+            // 生成token并返回结果
+            return generateLoginResult(user);
+        } catch (WxErrorException e) {
+            this.logger.error(e.getMessage(), e);
+            return R.error("授权失败," + e.getMessage());
+        }
+    }
+
+
     private FsUser processUserInfo(WxOAuth2UserInfo wxMpUser, Company company,CompanyUser companyUser,FsUserLoginByMpParam param) {
         FsUser user = userService.selectFsUserByUnionId(wxMpUser.getUnionId());
 
@@ -158,6 +198,36 @@ public class WxH5MpController {
         }
     }
 
+    private FsUser processUserInfoByCourseLoginByMp(WxOAuth2UserInfo wxMpUser) {
+        FsUser user = userService.selectFsUserByUnionId(wxMpUser.getUnionId());
+
+        if (user != null) {
+            // 更新现有用户信息
+            FsUser userUpdate = new FsUser();
+            userUpdate.setUserId(user.getUserId());
+            userUpdate.setMpOpenId(wxMpUser.getOpenid());
+            userUpdate.setUnionId(wxMpUser.getUnionId());
+            userUpdate.setUpdateTime(new DateTime());
+            userUpdate.setNickName(wxMpUser.getNickname());
+            userUpdate.setAvatar(wxMpUser.getHeadImgUrl());
+            userService.updateFsUser(userUpdate);
+            return userUpdate;
+        } else {
+            // 创建新用户
+            FsUser newUser = new FsUser();
+            newUser.setNickName(wxMpUser.getNickname());
+            newUser.setAvatar(wxMpUser.getHeadImgUrl());
+            newUser.setStatus(1);
+            newUser.setMpOpenId(wxMpUser.getOpenid());
+//            newUser.setCompanyId(company.getCompanyId());
+//            newUser.setCompanyUserId(companyUser.getUserId());
+            newUser.setUnionId(wxMpUser.getUnionId());
+            newUser.setCreateTime(new Date());
+            userService.insertFsUser(newUser);
+            return newUser;
+        }
+    }
+
     private void processUserCompanyRelationship(FsUser user, FsUserLoginByMpParam param,
                                                 CompanyUser companyUser, Company company) {
         if ((companyUser.getIsAllowedAllRegister() == null || companyUser.getIsAllowedAllRegister() == 1)