浏览代码

Merge remote-tracking branch 'origin/master'

zyy 4 天之前
父节点
当前提交
8e9bf21834
共有 34 个文件被更改,包括 1372 次插入29 次删除
  1. 114 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyWithdrawDetailAdminController.java
  2. 2 1
      fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java
  3. 88 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyWithdrawDetailController.java
  4. 17 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyWithdrawDetailMapper.java
  5. 20 0
      fs-service/src/main/java/com/fs/company/param/CompanyWithdrawDetailAdminParam.java
  6. 1 0
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  7. 24 0
      fs-service/src/main/java/com/fs/company/service/ICompanyWithdrawDetailService.java
  8. 58 13
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  9. 5 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  10. 64 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyWithdrawDetailServiceImpl.java
  11. 1 1
      fs-service/src/main/java/com/fs/company/service/impl/call/node/AiQwAddWxTaskNode.java
  12. 90 0
      fs-service/src/main/java/com/fs/company/util/CompanyTuiMoneyCalc.java
  13. 57 0
      fs-service/src/main/java/com/fs/company/vo/CompanyWithdrawDetailVO.java
  14. 29 0
      fs-service/src/main/java/com/fs/course/domain/FsPublicCourseTrafficLog.java
  15. 42 0
      fs-service/src/main/java/com/fs/course/mapper/FsPublicCourseTrafficLogMapper.java
  16. 3 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  17. 62 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  18. 1 1
      fs-service/src/main/java/com/fs/his/config/StoreConfig.java
  19. 1 1
      fs-service/src/main/java/com/fs/hisStore/config/StoreConfig.java
  20. 1 1
      fs-service/src/main/java/com/fs/live/mapper/LiveCouponMapper.java
  21. 1 1
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  22. 1 1
      fs-service/src/main/java/com/fs/store/config/StoreConfig.java
  23. 0 2
      fs-service/src/main/resources/application-config-druid-bjzm.yml
  24. 1 1
      fs-service/src/main/resources/application-config-druid-mengniu.yml
  25. 4 0
      fs-service/src/main/resources/application-config-druid-sxjz.yml
  26. 112 0
      fs-service/src/main/resources/application-config-druid-sxtb.yml
  27. 7 3
      fs-service/src/main/resources/application-druid-bjzm-test.yml
  28. 5 2
      fs-service/src/main/resources/application-druid-bjzm.yml
  29. 48 0
      fs-service/src/main/resources/application-druid-sxjz.yml
  30. 221 0
      fs-service/src/main/resources/application-druid-sxtb.yml
  31. 177 0
      fs-service/src/main/resources/mapper/company/CompanyWithdrawDetailMapper.xml
  32. 102 0
      fs-service/src/main/resources/mapper/course/FsPublicCourseTrafficLogMapper.xml
  33. 12 0
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseFsUserController.java
  34. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java

+ 114 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyWithdrawDetailAdminController.java

@@ -0,0 +1,114 @@
+package com.fs.company.controller;
+
+import cn.hutool.json.JSONUtil;
+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.PageDomain;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.core.page.TableSupport;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.param.CompanyParam;
+import com.fs.company.param.CompanyWithdrawDetailAdminParam;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyWithdrawDetailService;
+import com.fs.company.vo.CompanyNameVO;
+import com.fs.company.vo.CompanyWithdrawDetailVO;
+import com.fs.course.config.CourseConfig;
+import com.fs.framework.web.service.TokenService;
+import com.fs.system.service.ISysConfigService;
+import com.github.pagehelper.PageHelper;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 管理后台-提现明细(多公司、类型筛选;与销售端数据源一致)
+ */
+@RestController
+@RequestMapping("/company/withdrawDetailAdmin")
+public class CompanyWithdrawDetailAdminController extends BaseController {
+
+    @Autowired
+    private ICompanyWithdrawDetailService companyWithdrawDetailService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    /**
+     * 分公司下拉:关键词模糊匹配公司名称(最多 500 条)
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogsDetail:list')")
+    @GetMapping("/companyOptions")
+    public AjaxResult companyOptions(@RequestParam(value = "keyword", required = false) String keyword) {
+        CompanyParam param = new CompanyParam();
+        if (StringUtils.isNotEmpty(keyword)) {
+            param.setCompanyName(keyword.trim());
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (!loginUser.isAdmin() && config.getDept() != null && config.getDept()) {
+            param.setDeptId(loginUser.getDeptId());
+        }
+        PageHelper.startPage(1, 500);
+        List<CompanyNameVO> list = companyService.selectCompanyNameVOList(param);
+        return AjaxResult.success(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogsDetail:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(
+            @RequestParam(required = false) List<Long> companyIds,
+            @RequestParam(required = false) List<Integer> detailTypes) {
+        PageDomain page = TableSupport.buildPageRequest();
+        int pageNum = page.getPageNum() != null && page.getPageNum() > 0 ? page.getPageNum() : 1;
+        int pageSize = page.getPageSize() != null && page.getPageSize() > 0 ? page.getPageSize() : 10;
+        PageHelper.startPage(pageNum, pageSize);
+
+        CompanyWithdrawDetailAdminParam p = new CompanyWithdrawDetailAdminParam();
+        p.setCompanyIds(companyIds);
+        p.setDetailTypes(detailTypes);
+
+        List<CompanyWithdrawDetailVO> list = companyWithdrawDetailService.selectWithdrawDetailListAdmin(p);
+        companyWithdrawDetailService.normalizeDisplayAmounts(list);
+        long start = (long) (pageNum - 1) * pageSize;
+        for (int i = 0; i < list.size(); i++) {
+            list.get(i).setSerialNo((int) (start + i + 1));
+        }
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogsDetail:export')")
+    @Log(title = "提现明细", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(
+            @RequestParam(required = false) List<Long> companyIds,
+            @RequestParam(required = false) List<Integer> detailTypes) {
+        CompanyWithdrawDetailAdminParam p = new CompanyWithdrawDetailAdminParam();
+        p.setCompanyIds(companyIds);
+        p.setDetailTypes(detailTypes);
+        List<CompanyWithdrawDetailVO> list = companyWithdrawDetailService.selectWithdrawDetailListAdmin(p);
+        companyWithdrawDetailService.normalizeDisplayAmounts(list);
+        for (int i = 0; i < list.size(); i++) {
+            list.get(i).setSerialNo(i + 1);
+        }
+        ExcelUtil<CompanyWithdrawDetailVO> util = new ExcelUtil<>(CompanyWithdrawDetailVO.class);
+        return util.exportExcel(list, "提现明细");
+    }
+}

+ 2 - 1
fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java

@@ -255,7 +255,8 @@ public class CompanyUserController extends AppBaseController {
         // 查询公司下销售
         CompanyUser companyUser = new CompanyUser();
         companyUser.setCompanyId(getCompanyId());
-        List<CompanyUser> companyUsers = companyUserService.selectCompanyUserList(companyUser);
+//        List<CompanyUser> companyUsers = companyUserService.selectCompanyUserList(companyUser);
+        List<CompanyUser> companyUsers = companyUserService.selectCompanyUserListByCompanyId(companyUser);
         return R.ok().put("data",companyUsers);
     }
 

+ 88 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyWithdrawDetailController.java

@@ -0,0 +1,88 @@
+package com.fs.company.controller.company;
+
+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.R;
+import com.fs.common.core.page.PageDomain;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.core.page.TableSupport;
+import com.github.pagehelper.PageHelper;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.service.ICompanyWithdrawDetailService;
+import com.fs.company.vo.CompanyWithdrawDetailVO;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.service.TokenService;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 销售端-提现明细(新接口,数据自 2026-03-27 起)
+ */
+@RestController
+@RequestMapping("/company/withdrawDetail")
+public class CompanyWithdrawDetailController extends BaseController {
+
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private ICompanyWithdrawDetailService companyWithdrawDetailService;
+
+    /**
+     * 分公司名称 + 可提现金额(实时,取 company.money)
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogsDetail:list')")
+    @GetMapping("/summary")
+    public R summary() {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        return R.ok(companyWithdrawDetailService.summary(companyId));
+    }
+
+    /**
+     * 分页列表:订单记录时间倒序,默认每页 10 条(由前端传 pageSize)
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogsDetail:list')")
+    @GetMapping("/list")
+    public TableDataInfo list() {
+        PageDomain page = TableSupport.buildPageRequest();
+        int pageNum = page.getPageNum() != null && page.getPageNum() > 0 ? page.getPageNum() : 1;
+        int pageSize = page.getPageSize() != null && page.getPageSize() > 0 ? page.getPageSize() : 10;
+        PageHelper.startPage(pageNum, pageSize);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        List<CompanyWithdrawDetailVO> list = companyWithdrawDetailService.selectWithdrawDetailList(companyId);
+        companyWithdrawDetailService.normalizeDisplayAmounts(list);
+        long start = (long) (pageNum - 1) * pageSize;
+        for (int i = 0; i < list.size(); i++) {
+            list.get(i).setSerialNo((int) (start + i + 1));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出全部字段(同列表,不受分页限制)
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogsDetail:export')")
+    @Log(title = "提现明细", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export() {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        List<CompanyWithdrawDetailVO> list = companyWithdrawDetailService.selectWithdrawDetailList(companyId);
+        companyWithdrawDetailService.normalizeDisplayAmounts(list);
+        for (int i = 0; i < list.size(); i++) {
+            list.get(i).setSerialNo(i + 1);
+        }
+        ExcelUtil<CompanyWithdrawDetailVO> util = new ExcelUtil<>(CompanyWithdrawDetailVO.class);
+        return util.exportExcel(list, "提现明细");
+    }
+}

+ 17 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyWithdrawDetailMapper.java

@@ -0,0 +1,17 @@
+package com.fs.company.mapper;
+
+import com.fs.company.param.CompanyWithdrawDetailAdminParam;
+import com.fs.company.vo.CompanyWithdrawDetailVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 提现明细(基于 company_money_logs 聚合展示)
+ */
+public interface CompanyWithdrawDetailMapper {
+
+    List<CompanyWithdrawDetailVO> selectWithdrawDetailList(@Param("companyId") Long companyId);
+
+    List<CompanyWithdrawDetailVO> selectWithdrawDetailListAdmin(@Param("p") CompanyWithdrawDetailAdminParam p);
+}

+ 20 - 0
fs-service/src/main/java/com/fs/company/param/CompanyWithdrawDetailAdminParam.java

@@ -0,0 +1,20 @@
+package com.fs.company.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 管理端-提现明细查询(多公司、多明细类型)
+ */
+@Data
+public class CompanyWithdrawDetailAdminParam {
+
+    /** 分公司 ID,空表示不限 */
+    private List<Long> companyIds;
+
+    /**
+     * 明细类型:1订单金额入账 2订单金额扣减 3总公司充值 4总公司扣款 5分公司提现 6总公司驳回;空表示全部
+     */
+    private List<Integer> detailTypes;
+}

+ 1 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java

@@ -48,6 +48,7 @@ public interface ICompanyUserService {
      * @return 物业公司管理员信息集合
      */
     public List<CompanyUser> selectCompanyUserList(CompanyUser companyUser);
+    public List<CompanyUser> selectCompanyUserListByCompanyId(CompanyUser companyUser);
 
     /**
      * 新增物业公司管理员信息

+ 24 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyWithdrawDetailService.java

@@ -0,0 +1,24 @@
+package com.fs.company.service;
+
+import com.fs.company.param.CompanyWithdrawDetailAdminParam;
+import com.fs.company.vo.CompanyWithdrawDetailVO;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 销售端提现明细
+ */
+public interface ICompanyWithdrawDetailService {
+
+    Map<String, Object> summary(Long companyId);
+
+    List<CompanyWithdrawDetailVO> selectWithdrawDetailList(Long companyId);
+
+    List<CompanyWithdrawDetailVO> selectWithdrawDetailListAdmin(CompanyWithdrawDetailAdminParam param);
+
+    /**
+     * PRD:订单金额扣减类中 logs_type=6 在库中为成本返还入账,展示为与「扣减」一致的符号口径
+     */
+    void normalizeDisplayAmounts(List<CompanyWithdrawDetailVO> list);
+}

+ 58 - 13
fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java

@@ -1,6 +1,7 @@
 package com.fs.company.service.impl;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalTime;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
@@ -20,6 +21,7 @@ import com.fs.company.mapper.*;
 import com.fs.company.param.CompanyLiveShowParam;
 import com.fs.company.param.CompanyParam;
 import com.fs.company.service.*;
+import com.fs.company.util.CompanyTuiMoneyCalc;
 import com.fs.company.vo.*;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.config.RedPacketConfig;
@@ -33,8 +35,10 @@ import com.fs.his.domain.FsStorePayment;
 import com.fs.his.dto.InquiryConfigDTO;
 import com.fs.his.mapper.FsStoreOrderMapper;
 import com.fs.his.vo.OptionsVO;
+import com.fs.hisStore.domain.FsStoreAfterSalesScrm;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.hisStore.domain.FsStorePaymentScrm;
+import com.fs.hisStore.mapper.FsStoreAfterSalesScrmMapper;
 import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
 import com.fs.live.domain.LiveOrder;
 import com.fs.live.mapper.LiveOrderMapper;
@@ -60,6 +64,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
@@ -143,6 +148,15 @@ public class CompanyServiceImpl implements ICompanyService
     @Autowired
     CompanyBindGatewayMapper companyBindGatewayMapper;
 
+    @Value("${cloud_host.company_name}")
+    private String companyName;
+
+
+    private static final BigDecimal BJZM_PARTIAL_REFUND_COMMISSION_RATE = new BigDecimal("0.20");
+
+    @Autowired
+    private FsStoreAfterSalesScrmMapper fsStoreAfterSalesScrmMapper;
+
     @Override
     public List<CompanyVO> liveShowList(CompanyParam param) {
         return companyMapper.liveShowList(param);
@@ -162,9 +176,12 @@ public class CompanyServiceImpl implements ICompanyService
             if(company!=null){
                 String json =configService.selectConfigByKey("store.config");
                 com.fs.store.config.StoreConfig config= JSONUtil.toBean(json, com.fs.store.config.StoreConfig.class);
-                //支付金额-(订单金额*rate%)
+                //(实付金额 - 运费)× 费率
                 Double rate=config.getTuiMoneyRate()/100d;
-                BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
+                BigDecimal base = CompanyTuiMoneyCalc.commissionBase(
+                        CompanyTuiMoneyCalc.paidAmount(order),
+                        CompanyTuiMoneyCalc.freight(order));
+                BigDecimal tuiMoney = CompanyTuiMoneyCalc.multiplyRate(base, rate);
                 logger.info("写入公司推广佣金:"+tuiMoney);
                 company.setTuiMoney(company.getTuiMoney().add(tuiMoney));
                 companyMapper.updateCompany(company);
@@ -626,9 +643,12 @@ public class CompanyServiceImpl implements ICompanyService
             if(company!=null){
                 String json =configService.selectConfigByKey("his.store");
                 StoreConfig config= JSONUtil.toBean(json,StoreConfig.class);
-                //支付金额-(订单金额*rate%)
+                //(实付金额 - 运费)× 费率
                 Double rate=config.getTuiMoneyRate()/100d;
-                BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
+                BigDecimal base = CompanyTuiMoneyCalc.commissionBase(
+                        CompanyTuiMoneyCalc.paidAmount(order),
+                        CompanyTuiMoneyCalc.freight(order));
+                BigDecimal tuiMoney = CompanyTuiMoneyCalc.multiplyRate(base, rate);
                 logger.info("写入公司推广佣金:"+tuiMoney);
                 company.setTuiMoney(company.getTuiMoney().add(tuiMoney));
                 companyMapper.updateCompany(company);
@@ -648,10 +668,13 @@ public class CompanyServiceImpl implements ICompanyService
             if(company!=null){
                 String json =configService.selectConfigByKey("his.store");
                 StoreConfig config= JSONUtil.toBean(json,StoreConfig.class);
-                //支付金额-(订单金额*rate%)
+                //(实付金额 - 运费)× 费率
                 if (config.getTuiMoneyRate()!=null){
                     Double rate=config.getTuiMoneyRate()/100d;
-                    BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
+                    BigDecimal base = CompanyTuiMoneyCalc.commissionBase(
+                            CompanyTuiMoneyCalc.paidAmount(order),
+                            CompanyTuiMoneyCalc.freight(order));
+                    BigDecimal tuiMoney = CompanyTuiMoneyCalc.multiplyRate(base, rate);
                     logger.info("写入公司推广佣金:"+tuiMoney);
                     company.setTuiMoney(company.getTuiMoney().add(tuiMoney));
                     companyMapper.updateCompany(company);
@@ -708,11 +731,14 @@ public class CompanyServiceImpl implements ICompanyService
                 // 卓美,按照润天进行百分比进行分佣
                 String json =configService.selectConfigByKey("store.config");
                 com.fs.store.config.StoreConfig config= JSONUtil.toBean(json, com.fs.store.config.StoreConfig.class);
-                //支付金额-(订单金额*rate%)
+                //(实付金额 - 运费)× 费率;未配置费率时仍为应付 payPrice
                 BigDecimal tuiMoney = BigDecimal.ZERO;
                 if (config != null && config.getTuiMoneyRate() != null) {
                     Double rate = config.getTuiMoneyRate() / 100d;
-                    tuiMoney = order.getTotalPrice().multiply(new BigDecimal(rate));
+                    BigDecimal base = CompanyTuiMoneyCalc.commissionBase(
+                            CompanyTuiMoneyCalc.paidAmount(order),
+                            CompanyTuiMoneyCalc.freight(order));
+                    tuiMoney = CompanyTuiMoneyCalc.multiplyRate(base, rate);
                 } else {
                     tuiMoney = order.getPayPrice();
                 }
@@ -731,6 +757,7 @@ public class CompanyServiceImpl implements ICompanyService
                 FsStoreOrderScrm fsStoreOrder = new FsStoreOrderScrm();
                 fsStoreOrder.setId(order.getId());
                 fsStoreOrder.setTuiMoneyStatus(1);
+                fsStoreOrder.setTuiMoney(tuiMoney);
                 storeOrderScrmMapper.updateFsStoreOrder(fsStoreOrder);
             }
         }
@@ -744,11 +771,14 @@ public class CompanyServiceImpl implements ICompanyService
                 // 卓美,按照润天进行百分比进行分佣
                 String json =configService.selectConfigByKey("store.config");
                 com.fs.store.config.StoreConfig config= JSONUtil.toBean(json, com.fs.store.config.StoreConfig.class);
-                //支付金额-(订单金额*rate%)
+                //(实付金额 - 运费)× 费率;未配置费率时仍为 payPrice
                 BigDecimal tuiMoney = BigDecimal.ZERO;
                 if (config != null && config.getTuiMoneyRate() != null) {
                     double rate = config.getTuiMoneyRate() / 100d;
-                    tuiMoney = order.getTotalPrice().multiply(new BigDecimal(rate));
+                    BigDecimal base = CompanyTuiMoneyCalc.commissionBase(
+                            CompanyTuiMoneyCalc.paidAmount(order),
+                            CompanyTuiMoneyCalc.freight(order));
+                    tuiMoney = CompanyTuiMoneyCalc.multiplyRate(base, rate);
                 } else {
                     tuiMoney = order.getPayPrice();
                 }
@@ -806,14 +836,29 @@ public class CompanyServiceImpl implements ICompanyService
         if(order.getCompanyId()>0){
             Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
             if(company!=null){
-                company.setMoney(company.getMoney().subtract(order.getTuiMoney()));
-                company.setTuiMoney(company.getTuiMoney().subtract(order.getTuiMoney()));
+                BigDecimal clawback = order.getTuiMoney();
+                BigDecimal logMoney = order.getTuiMoney().multiply(new BigDecimal(-1));
+
+                // 260415 卓美财务需求,希望部分退款:部分退款金额 * 20%
+                if ("北京卓美".equals(companyName)) {
+                    FsStoreAfterSalesScrm after = fsStoreAfterSalesScrmMapper.selectFsStoreAfterSalesByOrderCode(order.getOrderCode());
+                    BigDecimal payMoney = order.getPayMoney() != null ? order.getPayMoney() : BigDecimal.ZERO;
+                    BigDecimal refundAmount = after != null && after.getRefundAmount() != null ? after.getRefundAmount() : null;
+                    if (refundAmount != null && payMoney.compareTo(refundAmount) != 0) {
+                        // 部分退款:公司扣回金额 / 日志金额 = -(退款金额 × 20%)
+                        clawback = refundAmount.multiply(BJZM_PARTIAL_REFUND_COMMISSION_RATE).setScale(2, RoundingMode.HALF_UP);
+                        logMoney = clawback.negate();
+                    }
+                }
+
+                company.setMoney(company.getMoney().subtract(clawback));
+                company.setTuiMoney(company.getTuiMoney().subtract(clawback));
                 companyMapper.updateCompany(company);
                 //写入日志
                 CompanyMoneyLogs log=new CompanyMoneyLogs();
                 log.setCompanyId(order.getCompanyId());
                 log.setRemark("订单佣金退款");
-                log.setMoney(order.getTuiMoney().multiply(new BigDecimal(-1)));
+                log.setMoney(logMoney);
                 log.setLogsType(4);
                 log.setBalance(company.getMoney());
                 log.setCreateTime(new Date());

+ 5 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -179,6 +179,11 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         return companyUserMapper.selectCompanyUserList(companyUser);
     }
 
+    @Override
+    public List<CompanyUser> selectCompanyUserListByCompanyId(CompanyUser companyUser) {
+        return companyUserMapper.selectCompanyUserList(companyUser);
+    }
+
     /**
      * 新增物业公司管理员信息
      *

+ 64 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyWithdrawDetailServiceImpl.java

@@ -0,0 +1,64 @@
+package com.fs.company.service.impl;
+
+import com.fs.company.mapper.CompanyWithdrawDetailMapper;
+import com.fs.company.param.CompanyWithdrawDetailAdminParam;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyWithdrawDetailService;
+import com.fs.company.vo.CompanyWithdrawDetailVO;
+import com.fs.company.domain.Company;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class CompanyWithdrawDetailServiceImpl implements ICompanyWithdrawDetailService {
+
+    @Autowired
+    private CompanyWithdrawDetailMapper companyWithdrawDetailMapper;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @Override
+    public Map<String, Object> summary(Long companyId) {
+        Company company = companyService.selectCompanyById(companyId);
+        Map<String, Object> m = new HashMap<>(4);
+        if (company != null) {
+            m.put("companyName", company.getCompanyName());
+            m.put("withdrawableMoney", company.getMoney() != null ? company.getMoney() : BigDecimal.ZERO);
+        } else {
+            m.put("companyName", "");
+            m.put("withdrawableMoney", BigDecimal.ZERO);
+        }
+        return m;
+    }
+
+    @Override
+    public List<CompanyWithdrawDetailVO> selectWithdrawDetailList(Long companyId) {
+        return companyWithdrawDetailMapper.selectWithdrawDetailList(companyId);
+    }
+
+    @Override
+    public List<CompanyWithdrawDetailVO> selectWithdrawDetailListAdmin(CompanyWithdrawDetailAdminParam param) {
+        if (param == null) {
+            param = new CompanyWithdrawDetailAdminParam();
+        }
+        return companyWithdrawDetailMapper.selectWithdrawDetailListAdmin(param);
+    }
+
+    @Override
+    public void normalizeDisplayAmounts(List<CompanyWithdrawDetailVO> list) {
+        if (list == null) {
+            return;
+        }
+        for (CompanyWithdrawDetailVO vo : list) {
+            if (vo.getLogsType() != null && vo.getLogsType() == 6 && vo.getAmount() != null) {
+                vo.setAmount(vo.getAmount().negate());
+            }
+        }
+    }
+}

+ 1 - 1
fs-service/src/main/java/com/fs/company/service/impl/call/node/AiQwAddWxTaskNode.java

@@ -31,7 +31,7 @@ public class AiQwAddWxTaskNode extends AbstractWorkflowNode {
     private static final CompanyWxClientMapper companyWxClientMapper = SpringUtils.getBean(CompanyWxClientMapper.class);
     @SuppressWarnings("unchecked")
     private static final RedisCacheT<String> redisCache = SpringUtils.getBean(RedisCacheT.class);
-    public static final String DELAY_QW_ADD_WX_KEY = "qwAddWxTask:delay:%s:%s:";
+    public static final String DELAY_QW_ADD_WX_KEY = "qwAddWxTask:delay:%s:%s:%s:";
     /**
      * 默认加微超时时间(分钟)
      */

+ 90 - 0
fs-service/src/main/java/com/fs/company/util/CompanyTuiMoneyCalc.java

@@ -0,0 +1,90 @@
+package com.fs.company.util;
+
+import com.fs.his.domain.FsStoreOrder;
+import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.live.domain.LiveOrder;
+
+import java.math.BigDecimal;
+
+/**
+ * 分公司佣金/入账基数:(实付金额 - 运费)× 费率
+ */
+public final class CompanyTuiMoneyCalc {
+
+    private CompanyTuiMoneyCalc() {
+    }
+
+    /** 实付金额:优先取 payMoney,否则 payPrice */
+    public static BigDecimal paidAmount(FsStoreOrder order) {
+        if (order == null) {
+            return BigDecimal.ZERO;
+        }
+        if (order.getPayMoney() != null) {
+            return order.getPayMoney();
+        }
+        return order.getPayPrice() != null ? order.getPayPrice() : BigDecimal.ZERO;
+    }
+
+    /** 运费:his 订单取 freightPrice */
+    public static BigDecimal freight(FsStoreOrder order) {
+        if (order == null || order.getFreightPrice() == null) {
+            return BigDecimal.ZERO;
+        }
+        return order.getFreightPrice();
+    }
+
+    public static BigDecimal paidAmount(FsStoreOrderScrm order) {
+        if (order == null) {
+            return BigDecimal.ZERO;
+        }
+        if (order.getPayPrice() != null) {
+            return order.getPayPrice();
+        }
+        return order.getPayMoney() != null ? order.getPayMoney() : BigDecimal.ZERO;
+    }
+
+    /** 运费:商城 SCRM 订单取用户实付邮费 payPostage */
+    public static BigDecimal freight(FsStoreOrderScrm order) {
+        if (order == null || order.getPayPostage() == null) {
+            return BigDecimal.ZERO;
+        }
+
+        return order.getPayPostage();
+    }
+
+    public static BigDecimal paidAmount(LiveOrder order) {
+        if (order == null) {
+            return BigDecimal.ZERO;
+        }
+        if (order.getPayMoney() != null) {
+            return order.getPayMoney();
+        }
+        return order.getPayPrice() != null ? order.getPayPrice() : BigDecimal.ZERO;
+    }
+
+    /** 运费:直播单优先 payPostage,否则 totalPostage */
+    public static BigDecimal freight(LiveOrder order) {
+        if (order == null) {
+            return BigDecimal.ZERO;
+        }
+        if (order.getPayPostage() != null) {
+            return order.getPayPostage();
+        }
+        if (order.getTotalPostage() != null) {
+            return order.getTotalPostage();
+        }
+        return BigDecimal.ZERO;
+    }
+
+    /** 计佣基数:max(0, 实付 - 运费) */
+    public static BigDecimal commissionBase(BigDecimal paid, BigDecimal freightAmt) {
+        BigDecimal f = freightAmt != null ? freightAmt : BigDecimal.ZERO;
+        BigDecimal p = paid != null ? paid : BigDecimal.ZERO;
+        BigDecimal b = p.subtract(f);
+        return b.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : b;
+    }
+
+    public static BigDecimal multiplyRate(BigDecimal base, double rateFraction) {
+        return base.multiply(BigDecimal.valueOf(rateFraction));
+    }
+}

+ 57 - 0
fs-service/src/main/java/com/fs/company/vo/CompanyWithdrawDetailVO.java

@@ -0,0 +1,57 @@
+package com.fs.company.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 销售端-提现明细分页/导出
+ */
+@Data
+public class CompanyWithdrawDetailVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 内部用:原始 logs_type */
+    private Integer logsType;
+
+    private Long logsId;
+
+    @Excel(name = "序号", sort = 1)
+    private Integer serialNo;
+
+    @Excel(name = "公司名称", sort = 2)
+    private String companyName;
+
+    @Excel(name = "所属销售", sort = 3)
+    private String salesName;
+
+    @Excel(name = "订单号", sort = 4)
+    private String orderCode;
+
+    @Excel(name = "交易单号", sort = 5)
+    private String tradeNo;
+
+    @Excel(name = "订单状态", sort = 6)
+    private String orderStatusText;
+
+    /** 订单原始状态码,与商城订单列表字典 store_order_status 一致;非订单行无此值 */
+    private Integer orderStatus;
+
+    @Excel(name = "售后状态", sort = 7)
+    private String afterSalesStatusText;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "订单记录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", sort = 8)
+    private Date recordTime;
+
+    @Excel(name = "明细类型", sort = 9)
+    private String detailTypeText;
+
+    @Excel(name = "金额", sort = 10)
+    private BigDecimal amount;
+}

+ 29 - 0
fs-service/src/main/java/com/fs/course/domain/FsPublicCourseTrafficLog.java

@@ -0,0 +1,29 @@
+package com.fs.course.domain;
+
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 公开课流量记录对象 fs_public_course_traffic_log
+ */
+@Data
+public class FsPublicCourseTrafficLog extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    private Long logId;
+
+    private String uuId;
+
+    private Long userId;
+
+    private Long courseId;
+
+    private Long videoId;
+
+    private Long internetTraffic;
+
+    private Integer status;
+
+    private  Long projectId;
+}

+ 42 - 0
fs-service/src/main/java/com/fs/course/mapper/FsPublicCourseTrafficLogMapper.java

@@ -0,0 +1,42 @@
+package com.fs.course.mapper;
+
+import com.fs.course.domain.FsPublicCourseTrafficLog;
+import com.fs.course.param.FsCourseTrafficLogParam;
+import com.fs.course.vo.FsCourseTrafficLogListVO;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * 公开课流量记录Mapper接口
+ */
+@Repository
+public interface FsPublicCourseTrafficLogMapper {
+
+    FsPublicCourseTrafficLog selectFsPublicCourseTrafficLogByLogId(Long logId);
+
+    int insertFsPublicCourseTrafficLog(FsPublicCourseTrafficLog fsPublicCourseTrafficLog);
+
+    int updateFsPublicCourseTrafficLog(FsPublicCourseTrafficLog fsPublicCourseTrafficLog);
+
+    @Select("select * from fs_public_course_traffic_log where uu_id = #{uuId}")
+    FsPublicCourseTrafficLog selectFsPublicCourseTrafficLogByUuId(@Param("uuId") String uuId);
+
+    void insertOrUpdateTrafficLog(FsPublicCourseTrafficLog trafficLog);
+
+    @Select("SELECT IFNULL(SUM(internet_traffic), 0) FROM fs_public_course_traffic_log " +
+            "WHERE DATE(create_time) = DATE(CURDATE()) AND company_id = #{companyId}")
+    Long getTodayTrafficLogCompanyId(@Param("companyId") Long companyId);
+
+    @Select("SELECT IFNULL(SUM(internet_traffic), 0) FROM fs_public_course_traffic_log " +
+            "WHERE DATE(create_time) = DATE(CURDATE() - INTERVAL 1 DAY) AND company_id = #{companyId}")
+    Long getYesterdayTrafficLogCompanyId(@Param("companyId") Long companyId);
+
+    @Select("SELECT IFNULL(SUM(internet_traffic), 0) FROM fs_public_course_traffic_log " +
+            "WHERE YEAR(create_time) = YEAR(CURDATE()) AND MONTH(create_time) = MONTH(CURDATE()) AND company_id = #{companyId}")
+    Long getMonthTrafficLogCompanyId(@Param("companyId") Long companyId);
+
+    List<FsCourseTrafficLogListVO> selectTrafficNew(FsCourseTrafficLogParam param);
+}

+ 3 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java

@@ -99,6 +99,9 @@ public interface IFsUserCourseVideoService extends IService<FsUserCourseVideo> {
 
     R getInternetTraffic(FsUserCourseVideoFinishUParam param);
 
+    //公开课流量统计
+    R getPublicCourseInternetTraffic(FsUserCourseVideoFinishUParam param);
+
     R getIntegralByH5Video(FsUserCourseVideoFinishUParam param);
 
     R sendReward(FsCourseSendRewardUParam param);

+ 62 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -194,6 +194,8 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
     @Autowired
     private FsCourseTrafficLogMapper fsCourseTrafficLogMapper;
     @Autowired
+    private FsPublicCourseTrafficLogMapper fsPublicCourseTrafficLogMapper;
+    @Autowired
     private FsUserIntegralLogsMapper fsUserIntegralLogsMapper;
     @Autowired
     private FsUserMapper fsUserMapper;
@@ -1329,6 +1331,66 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         return R.ok();
     }
 
+    @Override
+    public R getPublicCourseInternetTraffic(FsUserCourseVideoFinishUParam param) {
+        try {
+            if (param.getBufferRate() == null) {
+                logger.error("【公开课缓冲值空】参数: {}", param);
+                return R.error("缓冲值空");
+            }
+            FsPublicCourseTrafficLog trafficLog = new FsPublicCourseTrafficLog();
+            trafficLog.setCreateTime(new Date());
+            BeanUtils.copyProperties(param, trafficLog);
+
+            FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());
+            if (video == null) {
+                return R.error("视频不存在");
+            }
+            FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(param.getCourseId());
+            if (fsUserCourse != null) {
+                trafficLog.setProjectId(fsUserCourse.getProject());
+            }
+            BigDecimal result = param.getBufferRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
+            BigDecimal longAsBigDecimal = BigDecimal.valueOf(video.getFileSize());
+            long roundedResult = result.multiply(longAsBigDecimal).setScale(0, RoundingMode.HALF_UP).longValue();
+            trafficLog.setInternetTraffic(roundedResult);
+
+            if (StringUtils.isNotEmpty(trafficLog.getUuId())) {
+                fsPublicCourseTrafficLogMapper.insertOrUpdateTrafficLog(trafficLog);
+//                asyncDeductPublicCourseTraffic(company, trafficLog);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            logger.error("【公开课插入或更新流量失败】参数: {}, 错误信息:{}", param, e.getMessage(), e);
+            return R.error();
+        }
+        return R.ok();
+    }
+
+//    public void asyncDeductPublicCourseTraffic(Company company, FsPublicCourseTrafficLog trafficLog) {
+//        try {
+//            FsPublicCourseTrafficLog existingLog = fsPublicCourseTrafficLogMapper.selectFsPublicCourseTrafficLogByUuId(trafficLog.getUuId());
+//            long recordedTraffic;
+//            if (existingLog != null) {
+//                recordedTraffic = trafficLog.getInternetTraffic() - existingLog.getInternetTraffic();
+//            } else {
+//                recordedTraffic = trafficLog.getInternetTraffic();
+//            }
+//            if (recordedTraffic <= 0) {
+//                return;
+//            }
+//            Long remainingTraffic = updateRedisCache(company, recordedTraffic / 1024);
+//
+//            if ("1".equals(configUtil.generateConfigByKey("watch.course.config").getString("doNotPlay")) && remainingTraffic <= 0) {
+//                logger.warn("公开课公司ID: {} 流量不足,当前剩余: {}", company.getCompanyId(), remainingTraffic);
+//                throw new Exception("流量不足");
+//            }
+//        } catch (Exception e) {
+//            logger.error("公开课异步扣除流量失败 - 公司ID: {}, 错误信息: {}",
+//                    company.getCompanyId(), e.getMessage(), e);
+//        }
+//    }
+
     public void asyncDeductTraffic(Company company, FsCourseTrafficLog trafficLog) {
         try {
             //根据uuid查询

+ 1 - 1
fs-service/src/main/java/com/fs/his/config/StoreConfig.java

@@ -11,7 +11,7 @@ public class StoreConfig implements Serializable {
 
     private Integer payRate;//支付比例
     private Integer unPayTime;//未支付订单自动取消时间
-    private Integer tuiMoneyRate;//公司佣金比例 支付金额-(订单金额*rate%)
+    private Integer tuiMoneyRate;// 公司佣金比例%:(实付金额-运费)× rate%
     private Integer deductMoneyRate;
     private Integer createMoneyRate;//公司制单金额最低比例
     private Integer storeAfterSalesDay;//已完成订单售后有效天数

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/config/StoreConfig.java

@@ -15,7 +15,7 @@ public class StoreConfig implements Serializable {
     private Integer payRate;//支付比例
     private Integer payAmount;//货到付款自定义金额
     private Integer unPayTime;//未支付订单自动取消时间
-    private Integer tuiMoneyRate;//公司佣金比例 支付金额-(订单金额*rate%)
+    private Integer tuiMoneyRate;// 公司佣金比例%:(实付金额-运费)× rate%
     private Integer createMoneyRate;//公司制单金额最低比例
     private Integer storeAfterSalesDay;//已完成订单售后有效天数
     private String refundConsignee;

+ 1 - 1
fs-service/src/main/java/com/fs/live/mapper/LiveCouponMapper.java

@@ -79,7 +79,7 @@ public interface LiveCouponMapper
 
     @Select("<script>" +
             "select lc.*,lci.id from live_coupon_issue lci left join live_coupon lc on lc.coupon_id=lci.coupon_id " +
-            "where lci.status=1" +
+            "where lci.status=1 and lc.status=1 " +
             " and lc.title like concat('%', #{couponName}, '%')" +
             " and id not in (select coupon_issue_id as id from live_coupon_issue_relation where live_id = #{liveId})" +
             "</script>"

+ 1 - 1
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -4396,7 +4396,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         liveOrder.setPayType("1");
         liveOrder.setTotalPrice(payPrice);
         liveOrder.setPayPrice(payPrice.subtract(liveOrder.getDiscountMoney()));
-        if(CloudHostUtils.hasCloudHostName("济世百康")) {
+        if(CloudHostUtils.hasCloudHostName("济世百康","蒙牛")) {
             liveOrder.setPayMoney(payPrice.subtract(liveOrder.getDiscountMoney()));
         }
         try {

+ 1 - 1
fs-service/src/main/java/com/fs/store/config/StoreConfig.java

@@ -15,7 +15,7 @@ public class StoreConfig implements Serializable {
     private Integer payRate;//支付比例
     private Integer payAmount;//货到付款自定义金额
     private Integer unPayTime;//未支付订单自动取消时间
-    private Integer tuiMoneyRate;//公司佣金比例 支付金额-(订单金额*rate%)
+    private Integer tuiMoneyRate;// 公司佣金比例%:(实付金额-运费)× rate%
     private Integer createMoneyRate;//公司制单金额最低比例
     private Integer storeAfterSalesDay;//已完成订单售后有效天数
     private String refundConsignee;

+ 0 - 2
fs-service/src/main/resources/application-config-druid-bjzm.yml

@@ -89,8 +89,6 @@ cloud_host:
   volcengineUrl: https://bjzmvolcengine.ylrztop.com
 headerImg:
   imgUrl:
-  download_poster_url: https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/security/2c47e4f105b641b4a49df50a77338e32.png
-
 
 ipad:
   ipadUrl: http://aipad.klbycp.com

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

@@ -68,7 +68,7 @@ fs :
   h5CommonApi: http://192.168.0.182:8010
   jwt:
     # 加密秘钥
-    secret: f4e2e52034348f86b67cde581c0f9eb5
+    secret: f4e2e52034348f86b67mne581c0f9eb5
     # token有效时长,7天,单位秒
     expire: 31536000
     header: AppToken

+ 4 - 0
fs-service/src/main/resources/application-config-druid-sxjz.yml

@@ -44,6 +44,8 @@ wx:
     configs:
       - appId: wxbc45c3882797e662 # 第一个公众号的appid  //公众号名称:成都九州在线互联网医院
         secret: 5da9ae6d354c130dc81cde1a6d097480 # 公众号的appsecret
+#      - appId: wx8e9574e8932f9e1d # 第一个公众号的appid  //公众号名称:挑宝连锁
+#        secret: 4504d4faa16d75a6551ad67a011d95cc # 公众号的appsecret
         token: PPKOdAlCoMO # 接口配置里的Token值
         aesKey: Eswa6VjwtVcw03qZy6Wllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
   # 开放平台app微信授权配置
@@ -92,6 +94,8 @@ cloud_host:
 #看课授权时显示的头像
 headerImg:
   imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
+  #下载海报地址
+  download_poster_url: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
 ipad:
   ipadUrl: http://ipad.xintaihl.cn
   aiApi: http://49.232.181.28:3000/api

+ 112 - 0
fs-service/src/main/resources/application-config-druid-sxtb.yml

@@ -0,0 +1,112 @@
+baidu:
+  token: 12313231232
+  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: wx4115995705bb0ea0   #中康智慧
+        secret: 58910ae743005c396012b029c7def579
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+      - appid: wxedde588767b358b1   #中康未来智慧药房
+        secret: 928d2961c81610d8f64b019597212fcd
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+  cp:
+    corpId: wwb2a10556c9a7c2
+    appConfigs:
+      - agentId: 100005
+        secret: ec7okROXJqkNafq66aKNv0asTzQIG0CYrj3vyBbo
+        token: PPKOdAloMO
+        aesKey: PKvaxtpSvNGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
+  pay:
+    appId: wx73f85f8d6119 #微信公众号或者小程序等的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: wxbc45c3882797e662 # 第一个公众号的appid  //公众号名称:成都九州在线互联网医院
+        secret: 5da9ae6d354c130dc81cde1a6d097480 # 公众号的appsecret
+#      - appId: wx8e9574e8932f9e1d # 第一个公众号的appid  //公众号名称:挑宝连锁
+#        secret: 4504d4faa16d75a6551ad67a011d95cc # 公众号的appsecret
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVcw03qZy6Wllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+  # 开放平台app微信授权配置
+  open:
+    app-id: wx9746858bdb5e0643
+    secret: 32dfaa2b2dcad9229935ff089c65d372
+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.14:8010
+  h5CommonApi: http://172.27.0.14:8010
+  jwt:
+    # 加密秘钥
+    secret: f4e2e52034348f86s67xdj581z0f9eb5
+    # token有效时长,7天,单位秒
+    expire: 31536000
+    header: AppToken
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+
+# 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: sxjz-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: sxjz
+cloud_host:
+  company_name: 挑宝易购
+  projectCode: SXTB
+  spaceName: sxjz-2114522511
+  volcengineUrl: https://sxjzvolcengine.ylrztop.com
+#看课授权时显示的头像
+headerImg:
+  imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
+  #下载海报地址
+  download_poster_url: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
+ipad:
+  ipadUrl: http://ipad.xianhetaihuij.cn
+  aiApi: http://49.232.181.28:3000/api
+  wxIpadUrl:
+  voiceApi:
+  commonApi:
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+weizou:
+  baseUrl: https://api.tiaobaoliansuo.com
+  appId: 598372344571410ab2598a05ba914178
+  appSecret: c3e51122dbf749b6aef170c4b3a712c7
+  createName: wz_7f35d1f365e448f6a60a6fc39d5613a1s

+ 7 - 3
fs-service/src/main/resources/application-druid-bjzm-test.yml

@@ -137,13 +137,17 @@ spring:
                         config:
                             multi-statement-allow: true
 rocketmq:
-    name-server: localhost:8080
+    name-server: rmq-1gawpw9p3.rocketmq.gz.public.tencenttdmq.com:8080
     producer:
-        group: my-producer-group
+        group: course-finish-group
         access-key: ak1gawpw9p33db21b4aaaf2 # 替换为实际的 accessKey
         secret-key: sk90be66c23f39ad85 # 替换为实际的 secretKey
     consumer:
-        group: common-group
+        #        group: common-group #这里有两个group 打标签的mq是course-finish-group 直播的是common-group
+        #        access-key: ak1gawpw9p33db21b4aaaf2 # 替换为实际的 accessKey
+        #        secret-key: sk90be66c23f39ad85 # 替换为实际的 secretKey
+        group: course-finish-group #这里有两个group 打标签的mq是course-finish-group 直播的是common-group
+        TOPIC: course-finish-note
         access-key: ak1gawpw9p33db21b4aaaf2 # 替换为实际的 accessKey
         secret-key: sk90be66c23f39ad85 # 替换为实际的 secretKey
 openIM:

+ 5 - 2
fs-service/src/main/resources/application-druid-bjzm.yml

@@ -217,11 +217,14 @@ spring:
 rocketmq:
     name-server: rmq-1gawpw9p3.rocketmq.gz.qcloud.tencenttdmq.com:8080
     producer:
-        group: my-producer-group
+        group: course-finish-group
         access-key: ak1gawpw9p33db21b4aaaf2 # 替换为实际的 accessKey
         secret-key: sk90be66c23f39ad85 # 替换为实际的 secretKey
     consumer:
-        group: common-group
+#        group: common-group #这里有两个group 打标签的mq是course-finish-group 直播的是common-group
+#        access-key: ak1gawpw9p33db21b4aaaf2 # 替换为实际的 accessKey
+#        secret-key: sk90be66c23f39ad85 # 替换为实际的 secretKey
+        group: course-finish-group #这里有两个group 打标签的mq是course-finish-group 直播的是common-group
         access-key: ak1gawpw9p33db21b4aaaf2 # 替换为实际的 accessKey
         secret-key: sk90be66c23f39ad85 # 替换为实际的 secretKey
 openIM:

+ 48 - 0
fs-service/src/main/resources/application-druid-sxjz.yml

@@ -134,6 +134,54 @@ spring:
                     wall:
                         config:
                             multi-statement-allow: true
+        easycall:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://129.28.164.235:3306/easycallcenter365?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: easycallcenter365
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                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-16pknjrda5.rocketmq.cd.qcloud.tencenttdmq.com:8080 # RocketMQ NameServer 地址
     producer:

+ 221 - 0
fs-service/src/main/resources/application-druid-sxtb.yml

@@ -0,0 +1,221 @@
+# 数据源配置
+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:
+                    url: jdbc:mysql://139.155.247.58:2345/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Sxdtcbm@#+!2025
+                # 初始连接数
+                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
+        easycall:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://129.28.164.235:3306/easycallcenter365?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: easycallcenter365
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                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-16pknjrda5.rocketmq.cd.qcloud.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak16pknjrda5f27fdaa338ab # 替换为实际的 accessKey
+        secret-key: sk7d7d9b8d8d44d405 # 替换为实际的 secretKey
+    consumer:
+        group: voice-group
+        access-key: ak16pknjrda5f27fdaa338ab # 替换为实际的 accessKey
+        secret-key: sk7d7d9b8d8d44d405 # 替换为实际的 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: 86400
+openIM:
+    secret: openIM123
+    userID: imAdmin
+    url: https://web.im.xianhthj.cn/api
+    pushUrl: https://fc-mp-d0421385-3496-42e7-b67f-59161a36a0e4.next.bspapp.com/push
+#是否使用新im
+im:
+    type: OPENIM
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: false
+
+enableRedPackAccount: 0

+ 177 - 0
fs-service/src/main/resources/mapper/company/CompanyWithdrawDetailMapper.xml

@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.company.mapper.CompanyWithdrawDetailMapper">
+
+    <sql id="withdrawDetailSelectBody">
+        SELECT
+            l.logs_id AS logsId,
+            l.logs_type AS logsType,
+            c.company_name AS companyName,
+            CASE
+                WHEN IFNULL(l.type, 0) = 0 THEN cu.nick_name
+                WHEN IFNULL(l.type, 0) = 1 THEN cul.nick_name
+                ELSE NULL
+            END AS salesName,
+            CASE
+                WHEN IFNULL(l.type, 0) = 0 THEN o.order_code
+                WHEN IFNULL(l.type, 0) = 1 THEN lo.order_code
+                ELSE NULL
+            END AS orderCode,
+            CASE
+                WHEN IFNULL(l.type, 0) = 0 THEN p.bank_transaction_id
+                WHEN IFNULL(l.type, 0) = 1 THEN lop.bank_transaction_id
+                ELSE NULL
+            END AS tradeNo,
+            CASE
+                WHEN IFNULL(l.type, 0) = 0 AND o.id IS NOT NULL THEN
+                    CASE o.status
+                        WHEN -3 THEN '已取消'
+                        WHEN -2 THEN '已退款'
+                        WHEN -1 THEN '退款中'
+                        WHEN 0 THEN '待支付'
+                        WHEN 1 THEN '待发货'
+                        WHEN 2 THEN '待收货'
+                        WHEN 3 THEN '交易完成'
+                        ELSE CAST(o.status AS CHAR)
+                    END
+                WHEN IFNULL(l.type, 0) = 1 AND lo.order_id IS NOT NULL THEN
+                    CASE lo.status
+                        WHEN -1 THEN '退款中'
+                        WHEN -2 THEN '已退款'
+                        WHEN 0 THEN '已取消'
+                        WHEN 1 THEN '待支付'
+                        WHEN 2 THEN '待发货'
+                        WHEN 3 THEN '待收货'
+                        WHEN 4 THEN '交易完成'
+                        WHEN 5 THEN '交易完成'
+                        WHEN 6 THEN '被拆分'
+                        ELSE CAST(lo.status AS CHAR)
+                    END
+                ELSE '-'
+            END AS orderStatusText,
+            CASE
+                WHEN IFNULL(l.type, 0) = 0 AND o.id IS NOT NULL THEN o.status
+                WHEN IFNULL(l.type, 0) = 1 AND lo.order_id IS NOT NULL THEN
+                    CASE lo.status
+                        WHEN -1 THEN -1
+                        WHEN -2 THEN -2
+                        WHEN 0 THEN -3
+                        WHEN 1 THEN 0
+                        WHEN 2 THEN 1
+                        WHEN 3 THEN 2
+                        WHEN 4 THEN 3
+                        WHEN 5 THEN 3
+                        ELSE lo.status
+                    END
+                ELSE NULL
+            END AS orderStatus,
+            CASE
+                WHEN a.id IS NOT NULL
+                    AND (
+                        l.logs_type IN (4, 6)
+                        OR (l.logs_type = 5 AND IFNULL(l.remark, '') LIKE '%退款%')
+                        OR (l.logs_type = 4 AND l.money &lt; 0)
+                    )
+                THEN
+                    CASE a.service_type
+                        WHEN 0 THEN '仅退款'
+                        WHEN 1 THEN '退货退款'
+                        ELSE '-'
+                    END
+                ELSE '-'
+            END AS afterSalesStatusText,
+            l.create_time AS recordTime,
+            CASE l.logs_type
+                WHEN 1 THEN '总公司充值'
+                WHEN 2 THEN '总公司扣款'
+                WHEN 7 THEN '分公司提现'
+                WHEN 8 THEN '总公司驳回提现'
+                WHEN 3 THEN '订单金额入账'
+                WHEN 6 THEN '订单金额扣减'
+                WHEN 4 THEN CASE WHEN l.money &gt;= 0 THEN '订单金额入账' ELSE '订单金额扣减' END
+                WHEN 5 THEN CASE
+                    WHEN IFNULL(l.remark, '') LIKE '%退款%' OR l.money &lt; 0 THEN '订单金额扣减'
+                    ELSE '订单金额入账'
+                END
+                ELSE '其它'
+            END AS detailTypeText,
+            l.money AS amount
+        FROM company_money_logs l
+        INNER JOIN company c ON c.company_id = l.company_id
+        LEFT JOIN fs_store_order_scrm o ON (
+            IFNULL(l.type, 0) = 0
+            AND l.logs_type IN (3, 4, 5, 6)
+            AND o.id = CAST(NULLIF(l.business_id, '') AS UNSIGNED)
+            AND o.company_id = l.company_id
+        )
+        LEFT JOIN live_order lo ON (
+            IFNULL(l.type, 0) = 1
+            AND l.logs_type IN (3, 4, 5, 6)
+            AND lo.order_id = CAST(NULLIF(l.business_id, '') AS UNSIGNED)
+            AND lo.company_id = l.company_id
+        )
+        LEFT JOIN company_user cu ON cu.user_id = o.company_user_id
+        LEFT JOIN company_user cul ON cul.user_id = lo.company_user_id
+        LEFT JOIN fs_store_payment_scrm p ON (
+            p.business_code = o.order_code AND p.status = 1 AND IFNULL(l.type, 0) = 0
+        )
+        LEFT JOIN live_order_payment lop ON (
+            lop.business_code = lo.order_code AND lop.status = 1 AND IFNULL(l.type, 0) = 1
+        )
+        LEFT JOIN (
+            SELECT a1.*
+            FROM fs_store_after_sales_scrm a1
+            INNER JOIN (
+                SELECT order_code AS oc, MAX(id) AS mid
+                FROM fs_store_after_sales_scrm
+                WHERE IFNULL(is_del, 0) = 0 AND status = 3
+                GROUP BY order_code
+            ) am ON a1.id = am.mid
+        ) a ON a.order_code = COALESCE(o.order_code, lo.order_code)
+    </sql>
+
+    <sql id="withdrawDetailBaseWhere">
+        WHERE l.create_time &gt;= '2026-03-27 00:00:00'
+          AND l.logs_type IN (1, 2, 3, 4, 5, 6, 7, 8)
+          AND NOT (l.logs_type = 5 AND IFNULL(l.remark, '') = '订单佣金冻结')
+    </sql>
+
+    <select id="selectWithdrawDetailList" resultType="com.fs.company.vo.CompanyWithdrawDetailVO">
+        <include refid="withdrawDetailSelectBody"/>
+        <include refid="withdrawDetailBaseWhere"/>
+          AND l.company_id = #{companyId}
+        ORDER BY l.create_time DESC, l.logs_id DESC
+    </select>
+
+    <select id="selectWithdrawDetailListAdmin" resultType="com.fs.company.vo.CompanyWithdrawDetailVO">
+        <include refid="withdrawDetailSelectBody"/>
+        <include refid="withdrawDetailBaseWhere"/>
+        <if test="p.companyIds != null and p.companyIds.size() &gt; 0">
+            AND l.company_id IN
+            <foreach collection="p.companyIds" item="cid" open="(" separator="," close=")">
+                #{cid}
+            </foreach>
+        </if>
+        <if test="p.detailTypes != null and p.detailTypes.size() &gt; 0">
+            AND (
+            <foreach collection="p.detailTypes" item="dt" separator=" OR ">
+                <choose>
+                    <when test="dt == 1">
+                        (l.logs_type = 3 OR (l.logs_type = 4 AND l.money &gt;= 0)
+                        OR (l.logs_type = 5 AND IFNULL(l.remark, '') NOT LIKE '%退款%' AND l.money &gt;= 0))
+                    </when>
+                    <when test="dt == 2">
+                        (l.logs_type = 6 OR (l.logs_type = 4 AND l.money &lt; 0)
+                        OR (l.logs_type = 5 AND (IFNULL(l.remark, '') LIKE '%退款%' OR l.money &lt; 0)))
+                    </when>
+                    <when test="dt == 3">l.logs_type = 1</when>
+                    <when test="dt == 4">l.logs_type = 2</when>
+                    <when test="dt == 5">l.logs_type = 7</when>
+                    <when test="dt == 6">l.logs_type = 8</when>
+                </choose>
+            </foreach>
+            )
+        </if>
+        ORDER BY l.create_time DESC, l.logs_id DESC
+    </select>
+</mapper>

+ 102 - 0
fs-service/src/main/resources/mapper/course/FsPublicCourseTrafficLogMapper.xml

@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.course.mapper.FsPublicCourseTrafficLogMapper">
+
+    <resultMap type="com.fs.course.domain.FsPublicCourseTrafficLog" id="FsPublicCourseTrafficLogResult">
+        <result property="logId" column="log_id"/>
+        <result property="uuId" column="uu_id"/>
+        <result property="userId" column="user_id"/>
+        <result property="courseId" column="course_id"/>
+        <result property="videoId" column="video_id"/>
+        <result property="internetTraffic" column="internet_traffic"/>
+        <result property="status" column="status"/>
+        <result property="createTime" column="create_time"/>
+        <result property="project_id" column="projectId"/>
+    </resultMap>
+
+    <sql id="selectFsPublicCourseTrafficLogVo">
+        select log_id,
+               uu_id,
+               user_id,
+               course_id,
+               video_id,
+               company_id,
+               internet_traffic,
+               status,
+               create_time,
+               project_id
+        from fs_public_course_traffic_log
+    </sql>
+
+    <select id="selectFsPublicCourseTrafficLogByLogId" parameterType="Long" resultMap="FsPublicCourseTrafficLogResult">
+        <include refid="selectFsPublicCourseTrafficLogVo"/>
+        where log_id = #{logId}
+    </select>
+
+    <insert id="insertFsPublicCourseTrafficLog" parameterType="com.fs.course.domain.FsPublicCourseTrafficLog"
+            useGeneratedKeys="true" keyProperty="logId">
+        insert into fs_public_course_traffic_log
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="uuId != null">uu_id,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="courseId != null">course_id,</if>
+            <if test="videoId != null">video_id,</if>
+            <if test="internetTraffic != null">internet_traffic,</if>
+            <if test="status != null">status,</if>
+            create_time,
+            <if test="projectId != null">project_id,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="uuId != null">#{uuId},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="courseId != null">#{courseId},</if>
+            <if test="videoId != null">#{videoId},</if>
+            <if test="internetTraffic != null">#{internetTraffic},</if>
+            <if test="status != null">#{status},</if>
+            sysdate(),
+            <if test="projectId != null">#{projectId},</if>
+        </trim>
+    </insert>
+
+    <update id="updateFsPublicCourseTrafficLog" parameterType="com.fs.course.domain.FsPublicCourseTrafficLog">
+        update fs_public_course_traffic_log
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="uuId != null">uu_id = #{uuId},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="courseId != null">course_id = #{courseId},</if>
+            <if test="videoId != null">video_id = #{videoId},</if>
+            <if test="internetTraffic != null">internet_traffic = #{internetTraffic},</if>
+            <if test="status != null">status = #{status},</if>
+        </trim>
+        where log_id = #{logId}
+    </update>
+
+    <insert id="insertOrUpdateTrafficLog" parameterType="com.fs.course.domain.FsPublicCourseTrafficLog">
+        insert into fs_public_course_traffic_log (uu_id, user_id, course_id, video_id,
+                                                  internet_traffic, status, create_time, project_id)
+        values (#{uuId}, #{userId}, #{courseId}, #{videoId}, #{internetTraffic}, #{status}, sysdate(),
+                #{projectId}) ON DUPLICATE KEY
+        UPDATE
+            internet_traffic = internet_traffic + #{internetTraffic}
+    </insert>
+
+    <select id="selectTrafficNew" resultType="com.fs.course.vo.FsCourseTrafficLogListVO">
+        select
+        log.course_id,
+        SUM(log.internet_traffic) AS total_internet_traffic,
+        DATE_FORMAT(log.create_time, '%Y-%m-%d') AS `month`
+        FROM fs_public_course_traffic_log log
+        <where>
+            <if test="startDate != null and endDate != null">
+                and DATE_FORMAT(log.create_time, '%Y-%m-%d') between #{startDate} AND #{endDate}
+            </if>
+            <if test="courseId != null">
+                and log.course_id = ${courseId}
+            </if>
+        </where>
+        group by log.course_id,`month`
+    </select>
+
+</mapper>

+ 12 - 0
fs-user-app/src/main/java/com/fs/app/controller/course/CourseFsUserController.java

@@ -236,6 +236,18 @@ public class CourseFsUserController extends AppBaseController {
         return courseVideoService.getInternetTraffic(param);
     }
 
+    /**
+     * 获取公开课流量
+     * @return
+     */
+    @ApiOperation("获取公开课缓冲流量")
+    @PostMapping("/getPublicCourseInternetTraffic")
+    @Login
+    public R getPublicCourseInternetTraffic(@RequestBody FsUserCourseVideoFinishUParam param ){
+        param.setUserId(Long.parseLong(getUserId()));
+        return courseVideoService.getPublicCourseInternetTraffic(param);
+    }
+
 
     @ApiOperation("答题")
     @PostMapping("/courseAnswer")

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java

@@ -340,7 +340,7 @@ public class LiveOrderController extends AppBaseController
         String userId= getUserId();
         log.info("开始创建订单,登录用户id:{}", userId);
         param.setUserId(userId);
-        if(CloudHostUtils.hasCloudHostName("济世百康")){
+        if(CloudHostUtils.hasCloudHostName("济世百康","蒙牛")){
             return  orderService.createLiveOrder(param);
         }else{
             return orderService.createStoreOrder(param);