Jelajahi Sumber

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
#	fs-user-app/src/main/java/com/fs/app/controller/live/LiveCompletionPointsController.java
#	fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java
yfh 1 Minggu lalu
induk
melakukan
efbe3b48ee
36 mengubah file dengan 1565 tambahan dan 202 penghapusan
  1. 5 5
      fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
  2. 19 1
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  3. 20 0
      fs-admin/src/main/java/com/fs/fastGpt/GptRoleController.java
  4. 15 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  5. 4 4
      fs-admin/src/main/java/com/fs/qw/controller/QwCompanyController.java
  6. 688 84
      fs-admin/src/main/java/com/fs/qw/controller/QwUserController.java
  7. 18 4
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  8. 33 9
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  9. 11 4
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  10. 21 0
      fs-service/src/main/java/com/fs/course/param/BatchEditCoverParam.java
  11. 10 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  12. 16 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  13. 4 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralCartMapper.java
  14. 5 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralCartServiceImpl.java
  15. 8 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralGoodsServiceImpl.java
  16. 4 1
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java
  17. 24 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java
  18. 7 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreOrderScrm.java
  19. 5 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderItemScrmMapper.java
  20. 14 0
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java
  21. 24 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderBatchAuditParam.java
  22. 2 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderParam.java
  23. 8 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java
  24. 25 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java
  25. 93 10
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  26. 6 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderExportVO.java
  27. 6 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderItemExportVO.java
  28. 5 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderVO.java
  29. 26 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java
  30. 2 4
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  31. 95 12
      fs-service/src/main/java/com/fs/live/service/impl/LiveRedConfServiceImpl.java
  32. 15 1
      fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  33. 9 0
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  34. 19 2
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  35. 102 59
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveCompletionPointsController.java
  36. 197 0
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java

+ 5 - 5
fs-admin/src/main/java/com/fs/company/controller/CompanyController.java

@@ -134,7 +134,7 @@ public class CompanyController extends BaseController
      * 新增企业
      */
     @PreAuthorize("@ss.hasPermi('company:company:add')")
-    @Log(title = "企业", businessType = BusinessType.INSERT)
+    @Log(title = "企业", businessType = BusinessType.INSERT, isStoreLog = true)
     @PostMapping
     public R add(@RequestBody Company company)
     {
@@ -153,7 +153,7 @@ public class CompanyController extends BaseController
      * 修改企业
      */
     @PreAuthorize("@ss.hasPermi('company:company:edit')")
-    @Log(title = "企业", businessType = BusinessType.UPDATE)
+    @Log(title = "企业", businessType = BusinessType.UPDATE, isStoreLog = true)
     @PutMapping
     public AjaxResult edit(@RequestBody Company company)
     {
@@ -186,7 +186,7 @@ public class CompanyController extends BaseController
      * 删除企业
      */
     @PreAuthorize("@ss.hasPermi('company:company:remove')")
-    @Log(title = "企业", businessType = BusinessType.DELETE)
+    @Log(title = "企业", businessType = BusinessType.DELETE, isStoreLog = true)
 	@DeleteMapping("/{companyIds}")
     public AjaxResult remove(@PathVariable Long[] companyIds)
     {
@@ -244,7 +244,7 @@ public class CompanyController extends BaseController
 
 
     @PreAuthorize("@ss.hasPermi('company:company:recharge')")
-    @Log(title = "企业转账", businessType = BusinessType.INSERT)
+    @Log(title = "企业转账", businessType = BusinessType.INSERT, isStoreLog = true)
     @PostMapping(value = "/recharge")
     @Transactional
     @RepeatSubmit
@@ -270,7 +270,7 @@ public class CompanyController extends BaseController
     }
 
     @PreAuthorize("@ss.hasPermi('company:company:deduct')")
-    @Log(title = "企业扣款", businessType = BusinessType.INSERT)
+    @Log(title = "企业扣款", businessType = BusinessType.INSERT, isStoreLog = true)
     @PostMapping(value = "/deduct")
     @Transactional
     @RepeatSubmit

+ 19 - 1
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java

@@ -15,6 +15,7 @@ import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
+import com.fs.course.param.BatchEditCoverParam;
 import com.fs.course.param.BatchRedUpdate;
 import com.fs.course.param.BatchVideoSvae;
 import com.fs.course.param.CourseVideoUpdates;
@@ -23,12 +24,13 @@ import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.vo.FsUserCourseVideoChooseVO;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
-import com.fs.qw.vo.SortDayVo;
 import com.fs.system.service.ISysConfigService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
@@ -262,4 +264,20 @@ public class FsUserCourseVideoController extends BaseController
         List<FsUserCourseVideoChooseVO> list = fsUserCourseVideoService.getChooseCourseVideoListByMap(params);
         return R.ok().put("data", new PageInfo<>(list));
     }
+
+    @ApiOperation("视频下架")
+    @PreAuthorize("@ss.hasPermi('course:userCourseVideo:batchDown')")
+    @Log(title = "课堂视频", businessType = BusinessType.UPDATE)
+    @PostMapping("/batchDown/{videoIds}")
+    public AjaxResult batchDown(@PathVariable String[] videoIds) {
+        return toAjax(fsUserCourseVideoService.batchDown(videoIds));
+    }
+
+    @ApiOperation("批量修改视频封面图")
+    @PreAuthorize("@ss.hasPermi('course:userCourseVideo:batchEditCover')")
+    @Log(title = "课堂视频", businessType = BusinessType.UPDATE)
+    @PostMapping("/batchEditCover")
+    public AjaxResult batchEditCover(@Validated @RequestBody BatchEditCoverParam param) {
+        return toAjax(fsUserCourseVideoService.batchEditCover(param));
+    }
 }

+ 20 - 0
fs-admin/src/main/java/com/fs/fastGpt/GptRoleController.java

@@ -6,6 +6,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.fastGpt.domain.FastGptRole;
 import com.fs.fastGpt.service.IFastGptRoleService;
@@ -49,6 +50,25 @@ public class GptRoleController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 查询应用列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptRole:newList')")
+    @GetMapping("/newList")
+    public TableDataInfo newList(FastGptRole fastGptRole)
+    {
+        startPage();
+        fastGptRole.setCompanyId(fastGptRole.getCompanyId());
+        List<FastGptRoleVO> list = fastGptRoleService.selectFastGptRoleListVONew(fastGptRole);
+        for (FastGptRoleVO fastGptRoleVO : list) {
+            String reminderWords = fastGptRoleVO.getReminderWords();
+            if (reminderWords!=null && reminderWords.length()>110) {
+                fastGptRoleVO.setReminderWords(reminderWords.substring(0,110)+"...");
+            }
+        }
+        return getDataTable(list);
+    }
+
     /**
      * 导出应用列表
      */

+ 15 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -1122,6 +1122,21 @@ public class FsStoreOrderScrmController extends BaseController {
         return R.ok();
     }
 
+    @ApiOperation("批量审核订单")
+    @Log(title = "订单管理", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('store:storeOrder:batchAudit')")
+    @PostMapping("/batchAudit")
+    public R batchAuditOrder(@Validated @RequestBody FsStoreOrderBatchAuditParam param) {
+        if (param.getOrderIds() == null || param.getOrderIds().isEmpty()) {
+            return R.error("订单ID列表不能为空");
+        }
+        if (param.getIsAudit() == null) {
+            return R.error("审核状态不能为空");
+        }
+        int count = fsStoreOrderService.batchAuditOrder(param);
+        return R.ok("成功审核 " + count + " 条订单");
+    }
+
     private FsStoreOrderDf getDFInfo(String loginAccount) {
         //查询订单账户 判断是否存在该订单账户
         List<FsDfAccount> erpAccounts = fsDfAccountService.selectFsDfAccountList(null);

+ 4 - 4
fs-admin/src/main/java/com/fs/qw/controller/QwCompanyController.java

@@ -87,7 +87,7 @@ public class QwCompanyController extends BaseController
      * 导出企微主体列表
      */
     @PreAuthorize("@ss.hasPermi('qw:qwCompany:export')")
-    @Log(title = "企微主体", businessType = BusinessType.EXPORT)
+    @Log(title = "企微主体", businessType = BusinessType.EXPORT, isStoreLog = true)
     @GetMapping("/export")
     public AjaxResult export(QwCompany qwCompany)
     {
@@ -110,7 +110,7 @@ public class QwCompanyController extends BaseController
      * 新增企微主体
      */
     @PreAuthorize("@ss.hasPermi('qw:qwCompany:add')")
-    @Log(title = "企微主体", businessType = BusinessType.INSERT)
+    @Log(title = "企微主体", businessType = BusinessType.INSERT, isStoreLog = true)
     @PostMapping
     public AjaxResult add(@RequestBody QwCompany qwCompany)
     {
@@ -125,7 +125,7 @@ public class QwCompanyController extends BaseController
      * 修改企微主体
      */
     @PreAuthorize("@ss.hasPermi('qw:qwCompany:edit')")
-    @Log(title = "企微主体", businessType = BusinessType.UPDATE)
+    @Log(title = "企微主体", businessType = BusinessType.UPDATE, isStoreLog = true)
     @PutMapping
     public AjaxResult edit(@RequestBody QwCompany qwCompany)
     {
@@ -136,7 +136,7 @@ public class QwCompanyController extends BaseController
      * 删除企微主体
      */
     @PreAuthorize("@ss.hasPermi('qw:qwCompany:remove')")
-    @Log(title = "企微主体", businessType = BusinessType.DELETE)
+    @Log(title = "企微主体", businessType = BusinessType.DELETE, isStoreLog = true)
 	@DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     {

+ 688 - 84
fs-admin/src/main/java/com/fs/qw/controller/QwUserController.java

@@ -1,32 +1,39 @@
 package com.fs.qw.controller;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.constant.Constants;
 import com.fs.common.core.domain.R;
 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.utils.ServletUtils;
-import com.fs.company.domain.Company;
+import com.fs.common.exception.ServiceException;
+import com.fs.common.exception.user.UserPasswordNotMatchException;
+import com.fs.common.utils.MessageUtils;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.company.service.ICompanyUserService;
+import com.fs.company.service.impl.CompanyDeptServiceImpl;
+import com.fs.fastGpt.domain.FastGptRole;
+import com.fs.fastGpt.mapper.FastGptRoleMapper;
+import com.fs.framework.manager.AsyncManager;
+import com.fs.framework.manager.factory.AsyncFactory;
 import com.fs.qw.domain.QwExternalContact;
-import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwCompanyMapper;
 import com.fs.qw.mapper.QwExternalContactMapper;
-import com.fs.qw.param.QwFsUserParam;
-import com.fs.qw.param.QwUserBingParam;
-import com.fs.qw.param.QwUserListParam;
+import com.fs.qw.param.*;
 import com.fs.qw.service.IQwDeptService;
 import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qw.vo.QwOptionsVO;
 import com.fs.qw.vo.QwUserVO;
+import com.fs.qw.vo.UpdateSendTypeVo;
 import com.fs.qwApi.domain.QwExternalContactAllListResult;
 import com.fs.qwApi.domain.inner.ExternalContact;
 import com.fs.qwApi.domain.inner.ExternalContactInfo;
@@ -34,14 +41,18 @@ import com.fs.qwApi.domain.inner.FollowInfo;
 import com.fs.qwApi.param.QwExternalListParam;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.voice.utils.StringUtil;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import javax.annotation.Resource;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -77,25 +88,612 @@ public class QwUserController extends BaseController {
     @Autowired
     private QwExternalContactMapper qwExternalContactMapper;
 
-    @GetMapping("/getQwUserAll")
-    public AjaxResult getQwUserAll(){
-        return AjaxResult.success(qwUserService.getQwUserAll());
+    @Autowired
+    private CompanyDeptServiceImpl companyDeptService;
+
+    @Resource
+    private AuthenticationManager authenticationManager;
+    @Autowired
+    private FastGptRoleMapper fastGptRoleMapper;
+
+    /**
+     * 查询企微员工列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:staffList')")
+    @GetMapping("/staffList")
+    public TableDataInfo staffList(QwUserListParam qwUser) {
+
+        // 添加企微部门查询条件
+        Long deptId = qwUser.getDeptId();
+        if(deptId!=null && qwUser.getCorpId()!=null){
+            List<Long> qwDeptIdList = new ArrayList<>();
+            if (deptId!=null){
+                qwDeptIdList.add(deptId);
+            }
+            // 本部门的下级部门
+            List<Long> deptList = qwUserService.selectDeptByParentId(deptId,qwUser.getCorpId());
+            if (!deptList.isEmpty()){
+                qwDeptIdList.addAll(deptList);
+            }
+            qwUser.setQwDeptIdList(qwDeptIdList);
+        }
+        startPage();
+        List<QwUserVO> list = qwUserService.selectQwUserListStaffVO(qwUser);
+        return getDataTable(list);
     }
 
     /**
-     * 获取企微信息
-     * **/
-    @GetMapping("/getQwUserInfo")
-    public R getQwUserInfo(QwFsUserParam param){
-        return R.ok().put("data",qwUserService.getQwUserInfo(param));
+     * 查询企微员工列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:staffListPost')")
+    @PostMapping("/staffListPost")
+    public TableDataInfo staffListPost(@RequestBody QwUserListParam qwUser) {
+        // 添加企微部门查询条件
+        Long deptId = qwUser.getDeptId();
+        if(deptId!=null && qwUser.getCorpId()!=null){
+            List<Long> qwDeptIdList = new ArrayList<>();
+            qwDeptIdList.add(deptId);
+            // 本部门的下级部门
+            List<Long> deptList = qwUserService.selectDeptByParentId(deptId,qwUser.getCorpId());
+            if (!deptList.isEmpty()){
+                qwDeptIdList.addAll(deptList);
+            }
+            qwUser.setQwDeptIdList(qwDeptIdList);
+        }
+        startPage();
+        List<QwUserVO> list = qwUserService.selectQwUserListStaffVO(qwUser);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询我的企微员工列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:myStaffList')")
+    @GetMapping("/myStaffList")
+    public TableDataInfo myStaffList(QwUserListParam qwUser) {
+        startPage();
+        qwUser.setCompanyId(qwUser.getCompanyId());
+        List<QwUserVO> list = qwUserService.selectQwUserListStaffVO(qwUser);
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 导出企微员工列表
+     * @param qwUser
+     * @return AjaxResult
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:export')")
+    @Log(title = "企微员工", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportStaff")
+    public AjaxResult export(QwUserListParam qwUser) {
+        qwUser.setCompanyId(qwUser.getCompanyId());
+        List<QwUserVO> list = qwUserService.selectQwUserListStaffVO(qwUser);
+        ExcelUtil<QwUserVO> util = new ExcelUtil<QwUserVO>(QwUserVO.class);
+        return util.exportExcel(list, "企微员工数据");
+    }
+
+    /**
+     * 导出企微用户列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:export')")
+    @Log(title = "企微用户", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwUser qwUser) {
+        qwUser.setCompanyId(qwUser.getCompanyId());
+        List<QwUser> list = qwUserService.selectQwUserList(qwUser);
+        ExcelUtil<QwUser> util = new ExcelUtil<QwUser>(QwUser.class);
+        return util.exportExcel(list, "企微用户数据");
+    }
+
+
+    /**
+     * 查询我的部门 企业微信员工列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:myDepartList')")
+    @GetMapping("/myDepartList")
+    public TableDataInfo myDepartList(QwUserListParam qwUser)
+    {
+
+        qwUser.setCompanyId(qwUser.getCompanyId());
+//        qwUser.setUserType(loginUser.getUser().getUserType());
+        List<Long> combinedList = new ArrayList<>();
+        //本部门
+        Long deptId = getLoginUser().getUser().getDeptId();
+        if (deptId!=null){
+            combinedList.add(deptId);
+        }
+        //本部门的下级部门
+        List<Long> deptList = companyDeptService.selectCompanyDeptByParentId(deptId);
+        if (!deptList.isEmpty()){
+            combinedList.addAll(deptList);
+        }
+
+        // 添加企微部门查询条件
+        Long qwDeptId = qwUser.getDeptId();
+        if(qwDeptId!=null && qwUser.getCorpId()!=null){
+            List<Long> qwDeptIdList = new ArrayList<>();
+            if (qwDeptId!=null){
+                qwDeptIdList.add(qwDeptId);
+            }
+            // 本部门的下级部门
+            List<Long> qwDeptList = qwUserService.selectDeptByParentId(qwDeptId,qwUser.getCorpId());
+            if (!qwDeptList.isEmpty()){
+                qwDeptIdList.addAll(qwDeptList);
+            }
+            qwUser.setQwDeptIdList(qwDeptIdList);
+        }
+
+
+        qwUser.setCuDeptIdList(combinedList);
+//        qwUser.setUserType(loginUser.getUser().getUserType());
+
+        startPage();
+        List<QwUserVO> list = qwUserService.selectQwUserListStaffVO(qwUser);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/loginQwIpad")
+    public R loginQwIpad(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.loginQwIpad(loginParam);
+    }
+
+
+    /**
+     * 查询部门下的 企业微信账号
+     */
+    @PostMapping("/getQwUserByDept")
+    public R getQwUserByDept(@RequestBody QwUserByDeptParam deptParam){
+        deptParam.setCompanyId(deptParam.getCompanyId());
+        return R.ok().put("data",qwUserService.getQwUserByDept(deptParam)) ;
+    }
+
+
+
+
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/getQwIpad")
+    @RepeatSubmit
+    public R getQwIpad(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.getQwIpad(loginParam);
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/delQwIpad")
+    @RepeatSubmit
+    public R delQwIpad(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.delQwIpad(loginParam);
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/qrCodeStatus")
+    public R qrCodeStatus(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.qrCodeStatus(loginParam);
+    }
+    //输入验证码
+    @PostMapping("/qrCodeVerify")
+    public R qrCodeVerify(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.qrCodeVerify(loginParam);
+    }
+
+    @PostMapping("/outLoginQwIpad")
+    public R outLoginQwIpad(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.outLoginQwIpad(loginParam);
+    }
+
+    @PostMapping("/twoCode")
+    public R twoCode(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.getTwoCode(loginParam);
+    }
+    @PostMapping("/twoCodeStatus")
+    public R TwoCodeStatus(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.getTwoCodeStatus(loginParam);
+    }
+
+    @PostMapping("/getQwIpadStatus")
+    public R getQwIpadStatus(@RequestBody QwLoginHookParam loginParam){
+        return qwUserService.getLoginQwIpadStatus(loginParam);
+    }
+    /**
+     * 直接授权key
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:authAppKey')")
+    @PostMapping("/authAppKey")
+    public R authAppKey(@RequestBody QwUser param){
+        return qwUserService.authAppKey(param);
+    }
+
+    /**
+     * 输入授权key
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:authAppKey')")
+    @PostMapping("/handleInputAuthAppKey")
+    public R handleInputAuthAppKey(@RequestBody QwUser param){
+        return qwUserService.handleInputAuthAppKey(param);
     }
 
-   @GetMapping("/getMyQwCompanyList")
-    public R getMyQwCompanyList()
+
+    /**
+     * 登录企业微信(发起登录)
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/loginQwCode")
+    public R loginQwCode(@RequestBody QwLoginParam loginParam){
+        return qwUserService.loginQwCode(loginParam);
+    }
+
+    /**
+     * 登录请求-刷新获取二维码
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/loginQwCodeUrl")
+    public R loginQwCodeUrl(@RequestBody QwLoginParam loginParam){
+        return qwUserService.loginQwCodeUrl(loginParam);
+    }
+    /**
+     * 取redis里的登录二维码
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/getQwCodeUrl")
+    public R getQwCodeUrl(@RequestBody QwLoginParam loginParam) throws InterruptedException {
+        return qwUserService.getQwCodeUrl(loginParam);
+    }
+
+    /**
+     * 登录企业微信(传输验证信息)
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/loginQwCodeMsg")
+    public R loginQwCodeMsg(@RequestBody QwLoginParam loginParam){
+        return qwUserService.loginQwCodeMsg(loginParam);
+    }
+
+    /**
+     * 退出企业微信(退出插件)
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/logoutQwLogout")
+    public R logoutQwLogout(@RequestBody QwLoginParam loginParam){
+        return qwUserService.logoutQwLogout(loginParam);
+    }
+
+//    /**
+//     * 企业微信(修改登录状态)
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+//    @PostMapping("/modifyLoginQwStatus")
+//    public R modifyLoginQwStatus(@RequestBody QwLoginParam loginParam){
+//        return qwUserService.modifyLoginQwStatus(loginParam);
+//    }
+//
+    /**
+     * 查询企业微信登录状态
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:login')")
+    @PostMapping("/getLoginQwStatus")
+    public R getLoginQwStatus(@RequestBody QwLoginParam loginParam){
+        return qwUserService.getLoginQwStatus(loginParam);
+    }
+
+    @PutMapping
+    public AjaxResult updateUser(@RequestBody QwUser qwUser){
+        return toAjax(qwUserService.updateQwUser(qwUser));
+    }
+
+    /**
+     * 自动发课启用禁用
+     * @param qwUser
+     * @return
+     */
+    @PostMapping("/updateIsAuto")
+    @PreAuthorize("@ss.hasPermi('qw:user:isauto')")
+    public AjaxResult updateIsAuto(@RequestBody QwUser qwUser){
+        return toAjax(qwUserService.updateQwUser(qwUser));
+    }
+
+    /**
+     * 企业微信员工账号 绑定 云主机
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:loginIp')")
+    @Log(title = "绑定 云主机", businessType = BusinessType.INSERT)
+    @GetMapping("/qwBindCloudHost/{appKey}")
+    public R qwBindCloudHost(@PathVariable("appKey") String appKey){
+        return qwUserService.qwBindCloudHost(appKey);
+    }
+
+    /**
+     * 获取云主机的账密
+     *
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:cloudAP')")
+    @PostMapping("/selectCloudAP")
+    public R selectCloudAP(@RequestBody QwCloudAPParam param) throws Exception {
+        return qwUserService.selectCloudAP(param);
+    }
+
+    /**
+     * 根据销售账号密码 获取 他的所有企业微信账号以及云主机和账号密码
+     */
+    @PostMapping("/selectCloudByCompany")
+    public R selectCloudByCompany(@RequestBody QwCloudIPByCompanyParam param) throws Exception {
+
+        // 用户验证
+        Authentication authentication = null;
+        try
+        {
+            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
+            authentication = authenticationManager
+                    .authenticate(new UsernamePasswordAuthenticationToken(param.getCompanyAdmin(), param.getCompanyPassWord()));
+        }
+        catch (Exception e)
+        {
+            if (e instanceof BadCredentialsException)
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(param.getCompanyAdmin(), Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+                throw new UserPasswordNotMatchException();
+            }
+            else
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(param.getCompanyAdmin(), Constants.LOGIN_FAIL, e.getMessage()));
+                throw new ServiceException(e.getMessage());
+            }
+        }
+        LoginUser loginUser=(LoginUser) authentication.getPrincipal();
+
+        return qwUserService.selectCloudByCompany(loginUser.getUser().getCompanyId(),loginUser.getUser().getUserId());
+    }
+
+
+    /**
+     * 企业微信员工账号 绑定 云主机
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:bindIp')")
+    @GetMapping("/qwBindCloudHostByIp/{appKey}/{IP}")
+    public R qwBindCloudHostByIp(@PathVariable("appKey") String appKey,@PathVariable("IP") String IP){
+        return qwUserService.qwBindCloudHostByIp(appKey,IP);
+    }
+
+    /**
+     * 企业微信员工账号 解除绑定 云主机
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:loginIpOut')")
+    @Log(title = "解除绑定 云主机", businessType = BusinessType.UPDATE)
+    @GetMapping("/qwUnbindCloudHost/{appKey}")
+    public R qwUnbindCloudHost(@PathVariable("appKey") String appKey){
+        return qwUserService.qwUnbindCloudHost(appKey);
+    }
+
+    /**
+     * 根据销售名称模糊查询
+     * @param qwUserName  名称
+     * @return  list
+     */
+    @GetMapping("/getQwUserListLikeName")
+    public R getQwUserListLikeName(@RequestParam(required = false) String qwUserName,
+                                   @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                   @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String,Object> params = new HashMap<>();
+        params.put("qwUserName", qwUserName);
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<QwOptionsVO> qwUserList = companyUserService.selectQwUserListLikeName(params);
+        return R.ok().put("data", new PageInfo<>(qwUserList));
+    }
+
+    /**
+     * 查询企微用户列表
+     */
+//    @PreAuthorize("@ss.hasPermi('qw:user:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwUserListParam qwUser)
     {
-        List<QwOptionsVO> list = qwUserService.selectQwCompanyListOptionsVOAll();
+        startPage();
+        qwUser.setCompanyId(qwUser.getCompanyId());
+        if (ObjectUtil.isNotEmpty(qwUser.getIsRemark())&&qwUser.getIsRemark().equals("1")){
+            qwUser.setCompanyUserId(getLoginUser().getUser().getUserId());
+        }else if (ObjectUtil.isNotEmpty(qwUser.getIsRemark())&&qwUser.getIsRemark().equals("2")){
+            qwUser.setDeptId(getLoginUser().getDeptId());
+            qwUser.setCorpId(null);
+        }
+
+        List<QwUserVO> list = qwUserService.selectQwUserListVO(qwUser);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询企微用户列表
+     */
+
+    @GetMapping("/userList")
+    public TableDataInfo userList(QwUserListParam qwUser)
+    {
+        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
+
+        List<QwUserVO> list = qwUserService.selectAllQwUserListVO(qwUser);
+        return getDataTable(list);
+    }
+    //    /**
+//     * 查询我的企微用户列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:user:myList')")
+//    @GetMapping("/myList")
+//    public TableDataInfo myList(QwUserParam qwUser)
+//    {
+//        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
+//        qwUser.setCompanyUserId(loginUser.getCompany().getUserId());
+//        List<QwUserVO> list = qwUserService.selectQwUserListVO(qwUser);
+//        return getDataTable(list);
+//    }
+    @GetMapping("/getQwAllUserList")
+    public R getQwAllUserList(@RequestParam String corpId, @RequestParam Long companyId)
+    {
+        List<QwUserVO> list = companyUserService.selectCompanyQwUserList(corpId, companyId);
         return  R.ok().put("data",list);
     }
+    /**
+     * 查询企微用户列表-下拉框
+     */
+    @GetMapping("/qwList")
+    public TableDataInfo getQwList(QwUser qwUser)
+    {
+        startPage();
+
+        if(ObjectUtil.notEqual(qwUser.getDisableCompanyId(),1)){
+            qwUser.setCompanyId(qwUser.getCompanyId());
+        }
+        List<QwUser> list = qwUserService.selectQwUserList(qwUser);
+        return getDataTable(list);
+    }
+    /**
+     * 查询企微员工列表-用于员工管理绑定
+     */
+    @GetMapping("/getQwUserList")
+    public R getQwUserList()
+    {
+        QwUserParam qwUser = new QwUserParam();
+        List<String> strings = qwCompanyMapper.selectQwCompanyCorpIdListByCompanyId(getLoginUser().getUser().getCompanyId());
+        qwUser.setCorpId(strings);
+        if (strings==null||strings.size()==0){
+            return  R.ok().put("data",null);
+        }
+        qwUser.setIsDel(0);
+        List<QwUserVO> list = qwUserService.selectQwUserListBindVO(qwUser);
+        return  R.ok().put("data",list);
+    }
+
+    @GetMapping("/getMyQwUserList")
+    public R getMyQwUserList()
+    {
+        List<QwOptionsVO> list = qwUserService.selectQwUserListOptionsVOByCompanyUserId(getLoginUser().getUser().getUserId());
+        return  R.ok().put("data",list);
+    }
+    @GetMapping("/getMyQwCompanyList/{companyId}")
+    public R getMyQwCompanyList(@PathVariable Long companyId)
+    {
+        List<QwOptionsVO> list = qwUserService.selectQwCompanyListOptionsVOByCompanyId(companyId);
+        return  R.ok().put("data",list);
+    }
+    /**
+     * 获取企微用户详细信息
+     */
+
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(qwUserService.selectQwUserVOById(id));
+    }
+    /**
+     * 批量查询 企微用户详细信息
+     */
+    @GetMapping(value = "/getInfo/{ids}")
+    public AjaxResult getInfoByIds(@PathVariable("ids") Long[] ids)
+    {
+        return AjaxResult.success(qwUserService.selectQwUserVOByIds(ids));
+    }
+
+
+//    /**
+//     * 新增企微用户
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:user:add')")
+//    @Log(title = "企微用户", businessType = BusinessType.INSERT)
+//    @PostMapping
+//    public R add()
+//    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//
+//        return R.ok(qwUserService.syncQwUser(loginUser.getCompany().getCompanyId()));
+//    }
+
+
+
+    /**
+     * 同步企微用户
+     */
+    @RepeatSubmit
+    @PreAuthorize("@ss.hasPermi('qw:user:sync')")
+    @Log(title = "企微用户", businessType = BusinessType.INSERT)
+    @PostMapping("sync/{corpId}")
+    public R sync(@PathVariable String corpId)
+    {
+        List<String> strings = qwCompanyMapper.selectQwCompanyCorpIdListByCompanyId(getLoginUser().getUser().getCompanyId());
+        for (String string : strings) {
+
+            if (string.equals(corpId)){
+                qwUserService.syncQwUser(string);
+                qwDeptService.insertOrUpdateQwDept(string);
+                logger.info("同步完成");
+            }
+        }
+        return R.ok();
+    }
+    @RepeatSubmit
+    @PreAuthorize("@ss.hasPermi('qw:user:sync')")
+    @Log(title = "同步企微用户名称", businessType = BusinessType.INSERT)
+    @PostMapping("syncName/{corpId}")
+    public R syncName(@PathVariable String corpId)
+    {
+        List<String> strings = qwCompanyMapper.selectQwCompanyCorpIdListByCompanyId(getLoginUser().getUser().getCompanyId());
+        for (String string : strings) {
+            if (string.equals(corpId)){
+                qwUserService.syncQwUserName(string);
+            }
+        }
+        return R.ok();
+    }
+    /**
+     * 绑定AI客服
+     */
+//    @PreAuthorize("@ss.hasPermi('qw:user:bindAi')")
+    @Log(title = "企微用户", businessType = BusinessType.UPDATE)
+    @PutMapping("/bindAi")
+    @RepeatSubmit
+    public R edit(@RequestBody QwUserBindAi param)
+    {
+        QwUser qwUser=new QwUser();
+        qwUser.setId(param.getId());
+        qwUser.setFastGptRoleId(param.getFastGptRoleId());
+        FastGptRole role = fastGptRoleMapper.selectFastGptRoleByRoleId(param.getFastGptRoleId());
+
+        if (role.getBindCorpId()!=null){
+            if (role.getBindCorpId().equals(param.getCorpId())){
+                qwUserService.updateQwUser(qwUser);
+            }else {
+                return R.error("该角色已绑定其他企业");
+            }
+        }else {
+            int i = qwUserService.updateQwUser(qwUser);
+
+            FastGptRole fastGptRole=new FastGptRole();
+            fastGptRole.setRoleId(param.getFastGptRoleId());
+            fastGptRole.setBindCorpId(param.getCorpId());
+            fastGptRoleMapper.updateFastGptRole(fastGptRole);
+
+            if (i>0){
+                return R.ok();
+            }else {
+                return R.error("绑定失败");
+            }
+        }
+
+        return R.ok();
+    }
+
+    /**
+     * 解除应用绑定
+     */
+//    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptRole:relieve')")
+    @Log(title = "解除应用", businessType = BusinessType.UPDATE)
+    @GetMapping("/relieveFastGptRoleById/{id}")
+    public R relieveFastGptRoleById(@PathVariable("id") Long id)
+    {
+        return qwUserService.relieveFastGptRoleById(id);
+    }
 
     /**
      * 绑定企微用户
@@ -188,6 +786,7 @@ public class QwUserController extends BaseController {
         }
         return R.error("绑定失败");
 
+
     }
 
 
@@ -201,6 +800,52 @@ public class QwUserController extends BaseController {
         syncMyQwExternalContact(qu,null);
     }
 
+    /** 修改企微用户的欢迎语 */
+    @PostMapping("/weclomeQwUser")
+    public R weclomeQwUser(@RequestBody QwUser qwUser) throws Exception {
+
+
+        return  qwUserService.weclomeQwUser(qwUser);
+    }
+
+    /**
+     * 删除企微用户
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:remove')")
+    @Log(title = "企微用户", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(qwUserService.deleteQwUserByIds(ids));
+    }
+
+
+    /**
+     * 获取企业微信用户列表
+     */
+    @GetMapping("/qwUserList/{corpId}")
+    public TableDataInfo qwUserList(@PathVariable String corpId)
+    {
+
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        Long companyId = loginUser.getCompany().getCompanyId();
+
+        List<QwOptionsVO> list = qwUserService.selectQwUserListOptionsVO(corpId);
+        return getDataTable(list);
+    }
+    @GetMapping("/getQwUserAll")
+    public AjaxResult getQwUserAll(){
+        return AjaxResult.success(qwUserService.getQwUserAll());
+    }
+
+    /**
+     * 获取企微信息
+     * **/
+    @GetMapping("/getQwUserInfo")
+    public R getQwUserInfo(QwFsUserParam param){
+        return R.ok().put("data",qwUserService.getQwUserInfo(param));
+    }
+
     public R  syncMyQwExternalContact(QwUser qwUser,String getNextCursor )  {
 
         String qwUserId = qwUser.getQwUserId();
@@ -286,79 +931,38 @@ public class QwUserController extends BaseController {
         return R.ok();
     }
 
-
-    /**
-     * 同步企微用户
-     */
-    @RepeatSubmit
-    @PreAuthorize("@ss.hasPermi('qw:user:sync')")
-    @Log(title = "企微用户", businessType = BusinessType.INSERT)
-    @PostMapping("sync/{corpId}")
-    public R sync(@PathVariable("corpId") String corpId)
-    {
-
-        List<String> strings = qwCompanyMapper.selectQwCompanyCorpIdListByAll();
-        for (String string : strings) {
-
-            if (string.equals(corpId)){
-                qwUserService.syncQwUser(string);
-                qwDeptService.insertOrUpdateQwDept(string);
-                logger.info("同步完成");
-            }
-        }
-        return R.ok();
-    }
-
-    /**
-     * 获取企微用户详细信息
-     */
-
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(qwUserService.selectQwUserVOById(id));
-    }
-    /**
-     * 批量查询 企微用户详细信息
-     */
-    @GetMapping(value = "/getInfo/{ids}")
-    public AjaxResult getInfoByIds(@PathVariable("ids") Long[] ids)
-    {
-        return AjaxResult.success(qwUserService.selectQwUserVOByIds(ids));
+    //    /**
+//     * 重启云主机
+//     * @return
+//     */
+//    @PutMapping("/restartHost")
+//    public R restartCloudHost(@RequestParam String serverIp) {
+//        return qwUserService.restartCloudHost(serverIp);
+//    }
+    @PostMapping("/updateSendType")
+    public R updateSendType(@RequestBody UpdateSendTypeVo vo) {
+        return qwUserService.updateSendType(vo);
     }
 
-    @RepeatSubmit
-    @PreAuthorize("@ss.hasPermi('qw:user:sync')")
-    @Log(title = "同步企微用户名称", businessType = BusinessType.INSERT)
-    @PostMapping("syncName/{corpId}")
-    public R syncName(@PathVariable("corpId") String corpId)
-    {
-        List<String> strings = qwCompanyMapper.selectQwCompanyCorpIdListByAll();
-        for (String string : strings) {
-            if (string.equals(corpId)){
-                qwUserService.syncQwUserName(string);
-            }
-        }
+    @GetMapping("/changeVideoStatus")
+    public R changeVideoStatus(Long id) {
+        qwUserService.changeVideoStatus(id);
         return R.ok();
     }
 
-
-    /**
-     * 查询企微用户列表
-     */
-
-    @GetMapping("/userList")
-    public TableDataInfo userList(QwUserListParam qwUser)
+    @GetMapping("/companyQwUserlist")
+    public TableDataInfo companyQwUserlist(@RequestParam Long companyId,
+                                           @RequestParam String corpId,
+                                           @RequestParam(required = false) String nickName)
     {
         startPage();
-        List<QwUserVO> list = qwUserService.selectAllQwUserListVO(qwUser);
+        List<QwUserVO> list = qwUserService.selectQwUserListByCompanyIdAndCorpIdAndNickName(companyId, corpId, nickName);
         return getDataTable(list);
     }
 
-    @GetMapping("/getQwAllUserList")
-    public R getQwAllUserList(@RequestParam String corpId, @RequestParam Long companyId)
+    @GetMapping("/updateFastGptRoleStatusById/{id}")
+    public R updateFastGptRoleStatusById(@PathVariable Long id)
     {
-        List<QwUserVO> list = companyUserService.selectCompanyQwUserList(corpId, companyId);
-        return  R.ok().put("data",list);
+        return qwUserService.updateQwUserFastGptRoleStatusById(id);
     }
 }

+ 18 - 4
fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -30,13 +30,11 @@ import com.fs.hisStore.dto.ExpressInfoDTO;
 import com.fs.hisStore.dto.StoreOrderProductDTO;
 import com.fs.hisStore.enums.OrderLogEnum;
 import com.fs.hisStore.enums.ShipperCodeEnum;
-import com.fs.hisStore.param.FsStoreOrderBindCustomerParam;
-import com.fs.hisStore.param.FsStoreOrderCreateUserParam;
-import com.fs.hisStore.param.FsStoreOrderFinishParam;
-import com.fs.hisStore.param.FsStoreOrderParam;
+import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.*;
 import com.fs.hisStore.vo.*;
 import com.fs.system.service.ISysConfigService;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -473,4 +471,20 @@ public class FsStoreOrderScrmController extends BaseController
         Integer createSalesOrderType = config.getCreateSalesOrderType();
         return R.ok().put("createSalesOrderType",createSalesOrderType);
     }
+
+    @ApiOperation("批量审核订单")
+    @Log(title = "订单管理", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('store:storeOrder:batchAudit')")
+    @PostMapping("/batchAudit")
+    public R batchAuditOrder(@Validated @RequestBody FsStoreOrderBatchAuditParam param) {
+        if (param.getOrderIds() == null || param.getOrderIds().isEmpty()) {
+            return R.error("订单ID列表不能为空");
+        }
+        if (param.getIsAudit() == null) {
+            return R.error("审核状态不能为空");
+        }
+        int count = fsStoreOrderService.batchAuditOrder(param);
+        return R.ok("成功审核 " + count + " 条订单");
+    }
+
 }

+ 33 - 9
fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java

@@ -678,13 +678,23 @@ public class CompanyServiceImpl implements ICompanyService
                 orderMap.setTuiMoneyStatus(1);
                 storeOrderMapper.updateFsStoreOrder(orderMap);
                 // order.getPayRemain() 数据库实际没有这个字段了 直接使用 应付金额
-                BigDecimal money = order.getPayPrice();
-                company.setMoney(company.getMoney().add(money));
+                // 卓美,按照润天进行百分比进行分佣
+                String json =configService.selectConfigByKey("store.config");
+                com.fs.store.config.StoreConfig config= JSONUtil.toBean(json, com.fs.store.config.StoreConfig.class);
+                //支付金额-(订单金额*rate%)
+                BigDecimal tuiMoney = BigDecimal.ZERO;
+                if (config != null && config.getTuiMoneyRate() != null) {
+                    Double rate = config.getTuiMoneyRate() / 100d;
+                    tuiMoney = order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
+                } else {
+                    tuiMoney = order.getPayPrice();
+                }
+                company.setMoney(company.getMoney().add(tuiMoney));
                 companyMapper.updateCompany(company);
                 CompanyMoneyLogs log=new CompanyMoneyLogs();
                 log.setCompanyId(company.getCompanyId());
                 log.setRemark("佣金入账");
-                log.setMoney(money);
+                log.setMoney(tuiMoney);
                 log.setLogsType(3);
                 log.setBalance(company.getMoney());
                 log.setCreateTime(new Date());
@@ -703,20 +713,34 @@ 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()));
+                // 卓美,按照润天进行百分比进行分佣
+                String json =configService.selectConfigByKey("store.config");
+                com.fs.store.config.StoreConfig config= JSONUtil.toBean(json, com.fs.store.config.StoreConfig.class);
+                //支付金额-(订单金额*rate%)
+                BigDecimal tuiMoney = BigDecimal.ZERO;
+                if (config != null && config.getTuiMoneyRate() != null) {
+                    Double rate = config.getTuiMoneyRate() / 100d;
+                    tuiMoney = order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
+                } else {
+                    tuiMoney = order.getPayPrice();
+                }
+                company.setMoney(company.getMoney().add(tuiMoney));
                 companyMapper.updateCompany(company);
                 //写入日志
                 CompanyMoneyLogs log=new CompanyMoneyLogs();
                 log.setCompanyId(order.getCompanyId());
-                log.setRemark("订单佣金退款");
-                log.setMoney(order.getTuiMoney().multiply(new BigDecimal(-1)));
-                log.setLogsType(4);
+                log.setRemark("佣金入账");
+                log.setMoney(tuiMoney);
+                log.setLogsType(3);
                 log.setBalance(company.getMoney());
                 log.setCreateTime(new Date());
                 log.setBusinessId(order.getOrderId().toString());
                 moneyLogsMapper.insertCompanyMoneyLogs(log);
-
+                LiveOrder liveOrder = new LiveOrder();
+                liveOrder.setOrderId(order.getOrderId());
+                liveOrder.setTuiMoneyStatus(1);
+                liveOrder.setTuiMoney(tuiMoney);
+                liveOrderMapper.updateLiveOrder(liveOrder);
             }
         }
     }

+ 11 - 4
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -3,10 +3,7 @@ package com.fs.course.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.domain.FsVideoResource;
-import com.fs.course.param.CourseVideoUpdates;
-import com.fs.course.param.FsCourseListBySidebarParam;
-import com.fs.course.param.FsUserCourseVideoListUParam;
-import com.fs.course.param.FsUserCourseVideoParam;
+import com.fs.course.param.*;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
 import com.fs.course.vo.*;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
@@ -282,4 +279,14 @@ public interface FsUserCourseVideoMapper extends BaseMapper<FsUserCourseVideo> {
 
     @Select("select * from fs_video_resource where hsy_vid is not null")
     List<FsVideoResource> selectVideoByVid();
+
+    /**
+     * 下架
+     */
+    int batchDown(String[] videoIds);
+
+    /**
+     * 批量修改视频封面
+     */
+    int batchEditCover(BatchEditCoverParam param);
 }

+ 21 - 0
fs-service/src/main/java/com/fs/course/param/BatchEditCoverParam.java

@@ -0,0 +1,21 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+@Data
+public class BatchEditCoverParam {
+    /**
+     * 封面图
+     */
+    @NotBlank(message = "封面图不能为空")
+    private String thumbnail;
+    /**
+     * 视频小节
+     */
+    @NotEmpty(message = "小节ID不能为空")
+    private List<Long> videoIds;
+}

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

@@ -17,7 +17,6 @@ import com.fs.course.vo.newfs.FsUserVideoListVO;
 import com.fs.his.domain.FsUser;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.param.FsUserCourseRedPageParam;
-import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 import java.util.Map;
@@ -245,4 +244,14 @@ public interface IFsUserCourseVideoService extends IService<FsUserCourseVideo> {
     R createRoomMiniLinkByCourse(FsCourseLinkRoomNewParam param);
 
     void updateMediaPublishStatus(String vid);
+
+    /**
+     * 视频下架
+     */
+    int batchDown(String[] videoIds);
+
+    /**
+     * 批量修改视频封面
+     */
+    int batchEditCover(BatchEditCoverParam param);
 }

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

@@ -4452,5 +4452,21 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
             }
         }
     }
+
+    /**
+     * 视频下架
+     */
+    @Override
+    public int batchDown(String[] videoIds) {
+        return baseMapper.batchDown(videoIds);
+    }
+
+    /**
+     * 批量修改视频封面
+     */
+    @Override
+    public int batchEditCover(BatchEditCoverParam param) {
+        return baseMapper.batchEditCover(param);
+    }
 }
 

+ 4 - 0
fs-service/src/main/java/com/fs/his/mapper/FsIntegralCartMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.his.domain.FsIntegralCart;
 import com.fs.his.vo.FsIntegralCartVO;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
 
 import java.util.List;
 import java.util.Map;
@@ -35,4 +36,7 @@ public interface FsIntegralCartMapper extends BaseMapper<FsIntegralCart> {
      * @return  删除数量
      */
     int deleteCartByGoodsId(@Param("goodsId") Long goodsId);
+
+    @Update("update fs_integral_cart set integral = #{integral} where goods_id = #{goodsId}")
+    void updateIntegralByGoodsId(@Param("goodsId")Long goodsId,@Param("integral") Long integral);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralCartServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.his.service.impl;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.his.domain.FsIntegralCart;
 import com.fs.his.domain.FsIntegralGoods;
@@ -61,6 +62,10 @@ public class FsIntegralCartServiceImpl extends ServiceImpl<FsIntegralCartMapper,
             log.warn("addOrUpdateCart goods not enough cartNum: {}", goodsId);
             throw new CustomException("库存不足");
         }
+        if (fsIntegralGoods.getStatus() == 0) {
+            log.warn("addOrUpdateCart goods not enable cartNum: {}", goodsId);
+            throw new CustomException("商品停售");
+        }
 
         FsIntegralCart cart = new FsIntegralCart();
         cart.setUserId(userId);

+ 8 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralGoodsServiceImpl.java

@@ -90,6 +90,14 @@ public class FsIntegralGoodsServiceImpl implements IFsIntegralGoodsService
     @Override
     public int updateFsIntegralGoods(FsIntegralGoods fsIntegralGoods)
     {
+        FsIntegralGoods existGoods = fsIntegralGoodsMapper.selectFsIntegralGoodsByGoodsId(fsIntegralGoods.getGoodsId());
+        if (existGoods == null) {
+            return -1;
+        }
+        // 存在的积分和现在的积分不相等,更新积分购物车的积分
+        if(existGoods.getIntegral() != fsIntegralGoods.getIntegral()) {
+            fsIntegralCartMapper.updateIntegralByGoodsId(fsIntegralGoods.getGoodsId(), fsIntegralGoods.getIntegral());
+        }
         return fsIntegralGoodsMapper.updateFsIntegralGoods(fsIntegralGoods);
     }
 

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

@@ -312,7 +312,7 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
             return R.error("积分不足");
         }
         if (integralGoods.getStatus() == 0) {
-            return R.error("商品已经停,请联系客户进行处理!");
+            return R.error("商品已经停,请联系客户进行处理!");
         }
 
         // 减库存
@@ -473,6 +473,9 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
             if(integralGoods.getStock() < cart.getCartNum()){
                 throw new CustomException("库存不足");
             }
+            if (integralGoods.getStatus() == 0) {
+                return R.error(integralGoods.getGoodsName() + "商品已经停售,请联系客户进行处理!");
+            }
 
             // 减库存
             if (fsIntegralGoodsMapper.subStock(integralGoods.getGoodsId(), cart.getCartNum()) <= 0) {

+ 24 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java

@@ -668,6 +668,30 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
     @Override
     @Transactional
     public R applyAfterSales(long uesrId, FsStoreAfterSalesApplyParam param) {
+        // 查询配置:是否删除历史售后数据
+        try {
+            String deleteAfterSalesConfig = configService.selectConfigByKey("delete_after_sales");
+            if (StringUtils.isNotEmpty(deleteAfterSalesConfig) && "true".equalsIgnoreCase(deleteAfterSalesConfig.trim())) {
+                // 查询历史售后数据,将 is_del 设置为 1
+                FsStoreAfterSales queryAfterSales = new FsStoreAfterSales();
+                queryAfterSales.setOrderId(param.getOrderId());
+                List<FsStoreAfterSales> historyAfterSalesList = fsStoreAfterSalesMapper.selectFsStoreAfterSalesList(queryAfterSales);
+                if (historyAfterSalesList != null && !historyAfterSalesList.isEmpty()) {
+                    for (FsStoreAfterSales historyAfterSales : historyAfterSalesList) {
+                        if (historyAfterSales.getIsDel() != null && historyAfterSales.getIsDel() == 0) {
+                            FsStoreAfterSales updateAfterSales = new FsStoreAfterSales();
+                            updateAfterSales.setId(historyAfterSales.getId());
+                            updateAfterSales.setIsDel(1);
+                            fsStoreAfterSalesMapper.updateFsStoreAfterSales(updateAfterSales);
+                            logger.info("删除历史售后数据,售后ID:{},订单ID:{}", historyAfterSales.getId(), param.getOrderId());
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            logger.error("查询或更新历史售后数据失败", e);
+        }
+        
         FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderByOrderId(param.getOrderId());
         if (!order.getUserId().equals(uesrId)) {
             throw new CustomException("非法操作");

+ 7 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsStoreOrderScrm.java

@@ -353,4 +353,11 @@ public class FsStoreOrderScrm extends BaseEntity
 
     @TableField(exist = false)
     private String bankTransactionId;
+
+     // 是否审核,1-是,0-否
+    private Integer isAudit;
+
+    // 订单总后台备注
+    private String orderRemark;
+
 }

+ 5 - 1
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderItemScrmMapper.java

@@ -76,7 +76,8 @@ public interface FsStoreOrderItemScrmMapper
 
     @Select({"<script> " +
             "select i.*,o.user_id,psps.cost,o.pay_postage,o.total_num,o.status,fspcs.cate_name, o.real_name,o.user_phone,o.user_address,o.create_time,o.pay_time,o.delivery_sn,o.delivery_name,o.delivery_id, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber,o.upload_time ,CASE WHEN o.certificates IS NULL OR o.certificates = '' THEN 0 ELSE 1 END AS is_upload   " +
-            " ,p.title as package_name,cts.name as scheduleName,os.pay_money, os.bank_transaction_id as bankTransactionId " +
+            " ,p.title as package_name,cts.name as scheduleName,os.pay_money, os.bank_transaction_id as bankTransactionId, o.delivery_send_time " +
+            ", CASE o.is_audit WHEN 1 THEN '是' ELSE '否' END AS isAudit " +
             " from fs_store_order_item_scrm i " +
             " left join fs_store_order_scrm o on o.id=i.order_id" +
             " left join fs_store_payment_scrm os on os.business_order_id = o.id " +
@@ -159,6 +160,9 @@ public interface FsStoreOrderItemScrmMapper
             "<if test = 'maps.scheduleId != null    '> " +
             "and o.schedule_id =#{maps.scheduleId} " +
             "</if>" +
+            "<if test = 'maps.isAudit != null'> " +
+            "and o.is_audit = #{maps.isAudit} " +
+            "</if>" +
             " order by o.id desc limit 50000"+
             "</script>"})
     List<FsStoreOrderItemExportVO> selectFsStoreOrderItemListExportVO(@Param("maps")FsStoreOrderParam fsStoreOrder);

+ 14 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java

@@ -651,6 +651,7 @@ public interface FsStoreOrderScrmMapper
 
     @Select({"<script> " +
             "select o.*,cts.name as scheduleName,u.nickname,u.phone,cc.push_code,cc.create_time as customer_create_time,cc.source,cc.customer_code, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber ,p.title as package_title ,CASE WHEN o.certificates IS NULL OR o.certificates = '' THEN 0 ELSE 1 END AS is_upload  " +
+            ", CASE o.is_audit WHEN 1 THEN '是' ELSE '否' END AS isAudit " +
             " from fs_store_order_scrm o  " +
             " left JOIN fs_store_product_package_scrm p on o.package_id=p.package_id " +
             " left join fs_user u on o.user_id=u.user_id  " +
@@ -748,6 +749,9 @@ public interface FsStoreOrderScrmMapper
             "<if test = 'maps.isUpload != null and maps.isUpload == 1    '> " +
             "and o.certificates is not null " +
             "</if>" +
+            "<if test = 'maps.isAudit != null'> " +
+            "and o.is_audit = #{maps.isAudit} " +
+            "</if>" +
             " ${maps.params.dataScope} "+
             " order by o.id desc limit 50000"+
             "</script>"})
@@ -1421,4 +1425,14 @@ public interface FsStoreOrderScrmMapper
 
     @Select("SELECT * FROM fs_store_order_scrm WHERE create_time >= DATE_SUB(NOW(), INTERVAL 30 MINUTE) and status = 0")
     List<FsStoreOrderScrm> selectBankOrder();
+
+    /**
+     * 批量更新订单审核状态
+     *
+     * @param orderIds 订单ID列表
+     * @param isAudit  审核状态 1-是,0-否
+     * @return 更新条数
+     */
+    int batchUpdateAuditStatus(@Param("orderIds") List<Long> orderIds, @Param("isAudit") Integer isAudit);
+
 }

+ 24 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderBatchAuditParam.java

@@ -0,0 +1,24 @@
+package com.fs.hisStore.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 批量审核订单参数
+ *
+ * @author fs
+ * @date 2024
+ */
+@Data
+public class FsStoreOrderBatchAuditParam {
+    /**
+     * 订单ID列表
+     */
+    private List<Long> orderIds;
+
+    /**
+     * 审核状态 1-是,0-否
+     */
+    private Integer isAudit;
+}

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderParam.java

@@ -119,4 +119,6 @@ public class FsStoreOrderParam extends BaseEntity implements Serializable
     private Integer pageNum;
     private Integer pageSize;
 
+    // 是否审核,1-是,0-否
+    private Integer isAudit;
 }

+ 8 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java

@@ -349,4 +349,12 @@ public interface IFsStoreOrderScrmService
     void cancelOrderByCode(String outerPayId);
 
     void updateFsStoreOrderDb(FsStoreOrderScrm order);
+
+    /**
+     * 批量审核订单
+     *
+     * @param param 批量审核参数
+     * @return 更新条数
+     */
+    int batchAuditOrder(FsStoreOrderBatchAuditParam param);
 }

+ 25 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java

@@ -285,6 +285,31 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
     @Transactional
     public R applyForAfterSales(long userId, FsStoreAfterSalesParam storeAfterSalesParam) {
         logger.info("申请退款请求信息:"+JSONUtil.toJsonStr(storeAfterSalesParam));
+        
+        // 查询配置:是否删除历史售后数据
+        try {
+            String deleteAfterSalesConfig = configService.selectConfigByKey("delete_after_sales");
+            if (StringUtils.isNotEmpty(deleteAfterSalesConfig) && "true".equalsIgnoreCase(deleteAfterSalesConfig.trim())) {
+                // 查询历史售后数据,将 is_del 设置为 1
+                FsStoreAfterSalesScrm queryAfterSales = new FsStoreAfterSalesScrm();
+                queryAfterSales.setOrderCode(storeAfterSalesParam.getOrderCode());
+                List<FsStoreAfterSalesScrm> historyAfterSalesList = fsStoreAfterSalesMapper.selectFsStoreAfterSalesList(queryAfterSales);
+                if (historyAfterSalesList != null && !historyAfterSalesList.isEmpty()) {
+                    for (FsStoreAfterSalesScrm historyAfterSales : historyAfterSalesList) {
+                        if (historyAfterSales.getIsDel() != null && historyAfterSales.getIsDel() == 0) {
+                            FsStoreAfterSalesScrm updateAfterSales = new FsStoreAfterSalesScrm();
+                            updateAfterSales.setId(historyAfterSales.getId());
+                            updateAfterSales.setIsDel(1);
+                            fsStoreAfterSalesMapper.updateFsStoreAfterSales(updateAfterSales);
+                            logger.info("删除历史售后数据,售后ID:{},订单号:{}", historyAfterSales.getId(), storeAfterSalesParam.getOrderCode());
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            logger.error("查询或更新历史售后数据失败", e);
+        }
+        
         FsStoreOrderScrm order=orderService.selectFsStoreOrderByOrderCode(storeAfterSalesParam.getOrderCode());
         Integer orderStatus = order.getStatus();
         if(!order.getUserId().equals(userId)){

+ 93 - 10
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -362,6 +362,12 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     @Autowired
     private FsStoreAfterSalesItemScrmMapper fsStoreAfterSalesItemMapper;
 
+    @Autowired
+    private FsStoreAfterSalesScrmMapper fsStoreAfterSalesScrmMapper;
+
+    @Autowired
+    private FsStoreAfterSalesStatusScrmMapper fsStoreAfterSalesStatusScrmMapper;
+
     @Autowired
     private FsPackageOrderMapper fsPackageOrderMapper;
 
@@ -2458,12 +2464,9 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 fsStoreAfterSalesParam.setProductList(productParams);
 
                 return fsStoreAfterSalesScrmService.applyForAfterSales(order.getUserId(),fsStoreAfterSalesParam);
-            }/* else{
-                ErpRefundOrder order1=new ErpRefundOrder();
-                order1.setOrderCode(order.getOrderCode());
-                order1.setDeliverySn(order.getDeliverySn());
-                erpOrderService.refundOrder(order1);
-            }*/
+            } else{
+                jSTOrderService.refundUpdateScrm(request);
+            }
         }
         order.setStatus(-2);
         order.setRefundPrice(order.getPayMoney());
@@ -2589,6 +2592,71 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         if (order.getTuiUserId() != null && order.getTuiUserId() > 0) {
             userService.subTuiMoney(order);
         }
+        // 卓美财务要求,如果退款就必须生成售后订单
+        // 检查配置,如果delete_after_sales为true,创建退款成功的售后订单
+        String deleteAfterSalesConfig = configService.selectConfigByKey("delete_after_sales");
+        if ("true".equals(deleteAfterSalesConfig)) {
+            try {
+                // 检查是否已存在售后订单
+                FsStoreAfterSalesScrm existingAfterSales = new FsStoreAfterSalesScrm();
+                existingAfterSales.setOrderCode(order.getOrderCode());
+                List<FsStoreAfterSalesScrm> existingList = fsStoreAfterSalesScrmMapper.selectFsStoreAfterSalesList(existingAfterSales);
+
+                // 如果不存在售后订单,则创建
+                if (existingList == null || existingList.isEmpty()) {
+                    // 创建售后订单
+                    FsStoreAfterSalesScrm storeAfterSales = new FsStoreAfterSalesScrm();
+                    storeAfterSales.setOrderCode(order.getOrderCode());
+                    storeAfterSales.setRefundAmount(order.getPayMoney());
+                    storeAfterSales.setServiceType(0); // 0仅退款
+                    storeAfterSales.setReasons("退款成功自动生成售后订单");
+                    storeAfterSales.setExplains("退款成功自动生成售后订单");
+                    storeAfterSales.setExplainImg(null);
+                    storeAfterSales.setStatus(AfterSalesStatusEnum.STATUS_4.getValue()); // 4财务已审核(退款成功)
+                    storeAfterSales.setSalesStatus(3); // 3已完成
+                    storeAfterSales.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
+                    storeAfterSales.setIsDel(0);
+                    storeAfterSales.setUserId(order.getUserId());
+                    storeAfterSales.setOrderStatus(order.getStatus());
+                    storeAfterSales.setCompanyId(order.getCompanyId());
+                    storeAfterSales.setCompanyUserId(order.getCompanyUserId());
+                    if (order.getPackageJson() != null) {
+                        storeAfterSales.setPackageJson(order.getPackageJson());
+                    }
+                    if (order.getIsPackage() != null) {
+                        storeAfterSales.setIsPackage(order.getIsPackage());
+                    }
+                    fsStoreAfterSalesScrmMapper.insertFsStoreAfterSales(storeAfterSales);
+
+                    // 创建售后商品详情
+                    List<FsStoreOrderItemVO> orderItemVO = fsStoreOrderItemMapper.selectFsStoreOrderItemListByOrderId(order.getId());
+                    if (orderItemVO != null && !orderItemVO.isEmpty()) {
+                        for (FsStoreOrderItemVO item : orderItemVO) {
+                            FsStoreAfterSalesItemScrm afterSalesItem = new FsStoreAfterSalesItemScrm();
+                            afterSalesItem.setStoreAfterSalesId(storeAfterSales.getId());
+                            afterSalesItem.setProductId(item.getProductId());
+                            afterSalesItem.setNum(Math.toIntExact(item.getNum()));
+                            afterSalesItem.setJsonInfo(item.getJsonInfo());
+                            afterSalesItem.setIsDel(0);
+                            fsStoreAfterSalesItemMapper.insertFsStoreAfterSalesItem(afterSalesItem);
+                        }
+                    }
+
+                    // 创建售后状态记录
+                    FsStoreAfterSalesStatusScrm storeAfterSalesStatus = new FsStoreAfterSalesStatusScrm();
+                    storeAfterSalesStatus.setStoreAfterSalesId(storeAfterSales.getId());
+                    storeAfterSalesStatus.setChangeType(AfterSalesStatusEnum.STATUS_4.getValue());
+                    storeAfterSalesStatus.setChangeMessage(AfterSalesStatusEnum.STATUS_4.getDesc());
+                    storeAfterSalesStatus.setChangeTime(Timestamp.valueOf(LocalDateTime.now()));
+                    storeAfterSalesStatus.setOperator("系统");
+                    fsStoreAfterSalesStatusScrmMapper.insertFsStoreAfterSalesStatus(storeAfterSalesStatus);
+                }
+            } catch (Exception e) {
+                logger.error("创建售后订单失败", e);
+                // 不抛出异常,避免影响退款流程
+            }
+        }
+
         return R.ok();
 
     }
@@ -4242,6 +4310,10 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     order.setPayMoney(order.getPayPrice());
                     if(!"广州郑多燕".equals(cloudHostProper.getCompanyName())){
                         order.setPayDelivery(BigDecimal.ZERO);
+                    }else {
+                        // 郑多燕单独设置支付类型
+                        order.setPayType(order.getPayPrice().compareTo(order.getTotalPrice()) == 0 ?"1":"5");
+                        logger.info("支付------------实际支付金额和总金额:{},{},", order.getPayPrice(), order.getTotalPrice());
                     }
                 }
                 else if(param.getPayType().equals(2)){
@@ -4279,8 +4351,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 }
                 this.updateFsStoreOrder(order);
             }
-            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
-            if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
+            String payCode =  OrderCodeUtils.getOrderSn();
+            if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")||order.getPayType().equals("5")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
                 if (StringUtils.isBlank(param.getAppId())) {
                     throw new IllegalArgumentException("appId不能为空");
                 }
@@ -4431,7 +4503,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             if(!order.getIsPayRemain().equals(0)){
                 return R.error("此订单已支付");
             }
-            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
+            String payCode =  OrderCodeUtils.getOrderSn();
             if (StringUtils.isBlank(param.getAppId())) {
                 throw new IllegalArgumentException("appId不能为空");
             }
@@ -4675,7 +4747,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         }
         FsUserScrm user=userService.selectFsUserById(order.getUserId());
         if(user!=null){
-            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
+            String payCode =  OrderCodeUtils.getOrderSn();
             if (StringUtils.isBlank(param.getAppId())) {
                 throw new IllegalArgumentException("appId不能为空");
             }
@@ -4810,6 +4882,11 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     if(!"广州郑多燕".equals(cloudHostProper.getCompanyName())){
                         order.setPayDelivery(BigDecimal.ZERO);
                     }
+//                    else {
+//                        // 郑多燕单独设置支付类型
+//                        order.setPayType(order.getPayPrice().compareTo(order.getTotalPrice()) == 0 ?"1":"5");
+//                        logger.info("修改价格--------实际支付金额和总金额:{},{},", order.getPayPrice(), order.getTotalPrice());
+//                    }
                 }
                 else if(param.getPayType().equals(2)){
                     // 物流代收
@@ -5424,6 +5501,12 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         fsStoreOrderMapper.updateFsStoreOrder(order);
     }
 
+    @Override
+    @Transactional
+    public int batchAuditOrder(FsStoreOrderBatchAuditParam param) {
+        return fsStoreOrderMapper.batchUpdateAuditStatus(param.getOrderIds(), param.getIsAudit());
+    }
+
     private static final DateTimeFormatter CST_FORMATTER = DateTimeFormatter
             .ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US)
             .withZone(ZoneId.of("Asia/Shanghai"));

+ 6 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderExportVO.java

@@ -252,6 +252,9 @@ public class FsStoreOrderExportVO implements Serializable
     @Excel(name = "物流跟踪状态" , dictType = "store_order_delivery_type")
     private String deliveryType;
 
+    @Excel(name = "发货时间")
+    private String deliverySendTime;
+
     @Excel(name = "客户编码")
     private String customerCode;
 
@@ -267,4 +270,7 @@ public class FsStoreOrderExportVO implements Serializable
 
     @Excel(name = "归属档期")
     private String scheduleName;
+
+    @Excel(name = "是否审核")
+    private String isAudit;
 }

+ 6 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderItemExportVO.java

@@ -89,6 +89,9 @@ public class FsStoreOrderItemExportVO implements Serializable
     @Excel(name = "快递单号")
     private String deliveryId;
 
+    @Excel(name = "发货时间")
+    private String deliverySendTime;
+
     @Excel(name = "所属公司")
     private String companyName;
     @Excel(name = "所属销售")
@@ -114,4 +117,7 @@ public class FsStoreOrderItemExportVO implements Serializable
     @Excel(name = "银行交易流水号")
     private String bankTransactionId;
 
+    @Excel(name = "是否审核")
+    private String isAudit;
+
 }

+ 5 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderVO.java

@@ -251,6 +251,9 @@ public class FsStoreOrderVO implements Serializable
     @Excel(name = "物流代收金额")
     private BigDecimal deliveryPayMoney;
 
+    @Excel(name = "发货时间")
+    private String deliverySendTime;
+
     private String itemJson;
 
     private String orderVisit;
@@ -271,5 +274,7 @@ public class FsStoreOrderVO implements Serializable
     @Excel(name = "银行交易流水号")
     private String bankTransactionId;
 
+    // 是否审核,1-是,0-否
+    private Boolean isAudit;
 
 }

+ 26 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java

@@ -410,6 +410,32 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
             log.info("申请售后订单锁获取成功,订单号:{}", param.getOrderCode());
             
             LiveOrder order=liveOrderService.selectOrderIdByOrderCode(param.getOrderCode());
+            
+            // 查询配置:是否删除历史售后数据
+            try {
+                String deleteAfterSalesConfig = configService.selectConfigByKey("delete_after_sales");
+                if (StringUtils.isNotEmpty(deleteAfterSalesConfig) && "true".equalsIgnoreCase(deleteAfterSalesConfig.trim())) {
+                    // 查询历史售后数据,将 is_del 设置为 1
+                    if (order != null && order.getOrderId() != null) {
+                        LiveAfterSales queryAfterSales = new LiveAfterSales();
+                        queryAfterSales.setOrderId(order.getOrderId());
+                        List<LiveAfterSales> historyAfterSalesList = baseMapper.selectLiveAfterSalesList(queryAfterSales);
+                        if (historyAfterSalesList != null && !historyAfterSalesList.isEmpty()) {
+                            for (LiveAfterSales historyAfterSales : historyAfterSalesList) {
+                                if (historyAfterSales.getIsDel() != null && historyAfterSales.getIsDel() == 0) {
+                                    LiveAfterSales updateAfterSales = new LiveAfterSales();
+                                    updateAfterSales.setId(historyAfterSales.getId());
+                                    updateAfterSales.setIsDel(1);
+                                    baseMapper.updateLiveAfterSales(updateAfterSales);
+                                    log.info("删除历史售后数据,售后ID:{},订单ID:{}", historyAfterSales.getId(), order.getOrderId());
+                                }
+                            }
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                log.error("查询或更新历史售后数据失败", e);
+            }
             if(!order.getUserId().equals(userId)){
                 throw new CustomException("非法操作");
             }

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

@@ -794,10 +794,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                         List<LiveWatchLog> logs = liveWatchLogService.selectLiveWatchLogList(queryLog);
                         if (logs != null && !logs.isEmpty()) {
                             for (LiveWatchLog log : logs) {
-                                if (log.getLogType() == null || log.getLogType() != 2) {
-                                    log.setLiveBuy(1);
-                                    liveWatchLogService.updateLiveWatchLog(log);
-                                }
+                                log.setLiveBuy(1);
+                                liveWatchLogService.updateLiveWatchLog(log);
                             }
                         }
                     }

+ 95 - 12
fs-service/src/main/java/com/fs/live/service/impl/LiveRedConfServiceImpl.java

@@ -270,7 +270,8 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
             liveRedConf.setRedStatus(2L);
             baseMapper.updateLiveRedConf(liveRedConf);
             Set<String> range = CollUtil.newHashSet(String.valueOf(red.getRedId()));
-            finishRedStatusBySetIds(range);
+//            finishRedStatusBySetIds(range);
+            updateDbByRed(liveRedConf);
             return R.error("手慢了,红包已被抢完~");
         }
         // 记录用户红包
@@ -280,14 +281,44 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
         record.setUserId(red.getUserId());
         record.setIntegral(integral);
         record.setCreateTime(new Date());
-        // 更新用户余额
-        BigDecimal balanceAmount = BigDecimal.valueOf(integral);
-        int updateResult = fsUserScrmMapper.incrIntegral(red.getUserId(), balanceAmount);
-        if (updateResult <= 0) {
-            log.error("更新用户余额失败,userId: {}, balance: {}", red.getUserId(), balanceAmount);
-            return R.error("更新用户余额失败");
+        
+        // 双重检查:先检查 Redis(已有),再检查数据库(防止重复领取)
+        String redisKey = String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, red.getLiveId(), red.getRedId());
+        Object redisRecord = redisCache.hashGet(redisKey, String.valueOf(red.getUserId()));
+        if (ObjectUtil.isNotEmpty(redisRecord)) {
+            log.warn("用户 {} 在 Redis 中已存在红包记录 redId: {},跳过重复处理", red.getUserId(), red.getRedId());
+            return R.error("您已经领取过红包了!");
+        }
+        
+        LiveUserRedRecord queryRecord = new LiveUserRedRecord();
+        queryRecord.setUserId(red.getUserId());
+        queryRecord.setRedId(red.getRedId());
+        List<LiveUserRedRecord> existingRecords = userRedRecordMapper.selectLiveUserRedRecordList(queryRecord);
+        if (existingRecords != null && !existingRecords.isEmpty()) {
+            log.warn("用户 {} 在数据库中已存在红包记录 redId: {},跳过重复处理", red.getUserId(), red.getRedId());
+            // 如果数据库已有记录但 Redis 没有,同步到 Redis
+            redisCache.hashPut(redisKey, String.valueOf(red.getUserId()), JSONUtil.toJsonStr(existingRecords.get(0)));
+            return R.error("您已经领取过红包了!");
+        }
+        
+        // 先插入数据库记录(使用数据库约束防止重复)
+        int insertResult = userRedRecordMapper.insertLiveUserRedRecord(record);
+        if (insertResult <= 0) {
+            log.error("插入红包记录失败,userId: {}, redId: {}", red.getUserId(), red.getRedId());
+            return R.error("领取红包失败,请稍后重试");
+        }
+        
+        // 插入后再次验证,防止并发插入导致重复
+        List<LiveUserRedRecord> verifyRecords = userRedRecordMapper.selectLiveUserRedRecordList(queryRecord);
+        if (verifyRecords != null && verifyRecords.size() > 1) {
+            // 发现重复记录,删除刚插入的记录并回滚
+            log.error("检测到重复红包记录,userId: {}, redId: {},记录数: {}", red.getUserId(), red.getRedId(), verifyRecords.size());
+            // 删除最后插入的记录(通常是当前请求插入的)
+            userRedRecordMapper.deleteLiveUserRedRecordById(record.getId());
+            return R.error("您已经领取过红包了!");
         }
 
+
         // 查询用户当前余额
         com.fs.hisStore.domain.FsUserScrm user = fsUserScrmMapper.selectFsUserById(red.getUserId());
         Long currentIntegral = user.getIntegral() != null ? user.getIntegral() : 0L;
@@ -304,11 +335,22 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
         integralLogs.setStatus(0);
         integralLogs.setCreateTime(new Date());
         fsUserIntegralLogsMapper.insertFsUserIntegralLogs(integralLogs);
+        // 更新用户余额
+        BigDecimal balanceAmount = BigDecimal.valueOf(integral);
+        int updateResult = fsUserScrmMapper.incrIntegral(red.getUserId(), balanceAmount);
+        if (updateResult <= 0) {
+            log.error("更新用户余额失败,userId: {}, balance: {}", red.getUserId(), balanceAmount);
+            // 回滚:删除已插入的记录
+            userRedRecordMapper.deleteLiveUserRedRecordById(record.getId());
+            return R.error("更新用户余额失败");
+        }
+
+        // 最后更新 Redis 缓存(确保原子性:先插入数据库,再更新 Redis)
+        redisCache.hashPut(redisKey, String.valueOf(red.getUserId()), JSONUtil.toJsonStr(record));
 
         // WebSocket 通知
         //String msg = String.format("用户 %d 抢到了红包 %d,获得 %d 芳华币", userId, redId, integral);
         //WebSocketServer.notifyUsers(msg);
-        redisCache.hashPut(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, red.getLiveId(), red.getRedId()), String.valueOf(red.getUserId()), JSONUtil.toJsonStr(record));
         return R.ok("恭喜您成功抢到" + integral + "芳华币");
 /*        } catch (Exception e) {
             e.printStackTrace();
@@ -358,6 +400,9 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
         // 插入抽奖记录
         for (Long id : redIds) {
             LiveRedConf liveRedConf = baseMapper.selectLiveRedConfByRedId(id);
+            if (liveRedConf == null) {
+                continue;
+            }
             // 更新数据库
             updateDbByRed(liveRedConf);
             String hashKey = String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_RED, liveRedConf.getLiveId(), liveRedConf.getRedId());
@@ -367,11 +412,49 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
                 liveUserRedRecords = hashEntries.values().stream()
                         .map(value -> JSONUtil.toBean(JSONUtil.parseObj(value), LiveUserRedRecord.class))
                         .collect(Collectors.toList());
-                userRedRecordMapper.insertLiveUserRedRecordBatch(liveUserRedRecords);
+                
+                // 过滤掉已经存在于数据库中的记录(避免重复增加积分)
+                List<LiveUserRedRecord> newRecords = new ArrayList<>();
                 for (LiveUserRedRecord liveUserRedRecord : liveUserRedRecords) {
-                    userService.incrIntegral(Collections.singletonList(liveUserRedRecord.getUserId()), liveUserRedRecord.getIntegral());
-                    // 保存用户领取芳华币记录 方便统计计算
-                    saveUserRewardRecord(liveUserRedRecord);
+                    // 检查数据库中是否已存在该记录(使用 redId 和 userId 组合查询)
+                    LiveUserRedRecord queryRecord = new LiveUserRedRecord();
+                    queryRecord.setUserId(liveUserRedRecord.getUserId());
+                    queryRecord.setRedId(liveUserRedRecord.getRedId());
+                    List<LiveUserRedRecord> existingRecords = userRedRecordMapper.selectLiveUserRedRecordList(queryRecord);
+                    
+                    // 如果不存在,则添加到新记录列表
+                    if (existingRecords == null || existingRecords.isEmpty()) {
+                        newRecords.add(liveUserRedRecord);
+                    }
+                }
+                
+                // 只插入新记录(这些记录可能是从 Redis 同步过来的,但还没有插入数据库)
+                if (CollUtil.isNotEmpty(newRecords)) {
+                    try {
+                        userRedRecordMapper.insertLiveUserRedRecordBatch(newRecords);
+                        
+                        // 只为新记录增加积分(避免重复增加)
+                        // 注意:如果 claimRedPacket 已经处理过,这里不应该再增加积分
+                        // 所以这里只处理那些在 claimRedPacket 中还没有处理过的记录
+                        for (LiveUserRedRecord liveUserRedRecord : newRecords) {
+                            // 再次检查:如果 claimRedPacket 已经处理过,数据库中应该有记录
+                            // 如果这里还能插入,说明 claimRedPacket 没有处理过,需要增加积分
+                            LiveUserRedRecord verifyRecord = new LiveUserRedRecord();
+                            verifyRecord.setUserId(liveUserRedRecord.getUserId());
+                            verifyRecord.setRedId(liveUserRedRecord.getRedId());
+                            List<LiveUserRedRecord> verifyRecords = userRedRecordMapper.selectLiveUserRedRecordList(verifyRecord);
+                            // 确保只有一条记录,且积分还没有增加过
+                            if (verifyRecords != null && verifyRecords.size() == 1) {
+                                // 检查积分日志,如果已经增加过积分,则不再增加
+                                // 这里简化处理:如果记录存在且只有一条,说明是新的,需要增加积分
+                                userService.incrIntegral(Collections.singletonList(liveUserRedRecord.getUserId()), liveUserRedRecord.getIntegral());
+                                // 保存用户领取芳华币记录 方便统计计算
+                                saveUserRewardRecord(liveUserRedRecord);
+                            }
+                        }
+                    } catch (Exception e) {
+                        log.error("批量插入红包记录失败,redId: {}", id, e);
+                    }
                 }
             }
             redisCache.deleteObject(hashKey);

+ 15 - 1
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -305,7 +305,7 @@
         </if>
         <!-- 营销提前查看天数逻辑 -->
         AND DATE_SUB(fcpd.day_date, INTERVAL fcp.max_view_num DAY) &lt;= now()
-        order by video.course_sort
+        order by fcpd.start_date_time, ccut.start_date_time, video.course_sort
     </select>
 
     <select id="selectVideoListByMap" resultType="com.fs.his.vo.OptionsVO">
@@ -503,4 +503,18 @@
            and video.is_del = 0  and video.course_id= #{courseId}
             limit 1
     </select>
+
+    <update id="batchDown" parameterType="String">
+        update fs_user_course_video set is_on_put = 1 where video_id in
+        <foreach item="videoId" collection="array" open="(" separator="," close=")">
+            #{videoId}
+        </foreach>
+    </update>
+
+    <update id="batchEditCover" parameterType="com.fs.course.param.BatchEditCoverParam">
+        update fs_user_course_video set thumbnail = #{thumbnail} where video_id in
+        <foreach item="videoId" collection="videoIds" open="(" separator="," close=")">
+            #{videoId}
+        </foreach>
+    </update>
 </mapper>

+ 9 - 0
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -2433,5 +2433,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select * from fs_user where phone=#{phone}
     </select>
 
+    <!-- 批量更新用户积分(增加积分) -->
+    <update id="batchUpdateUserIntegral">
+        update fs_user
+        set integral = integral + #{addIntegral}
+        where user_id in
+        <foreach collection="userIds" item="userId" open="(" separator="," close=")">
+            #{userId}
+        </foreach>
+    </update>
 
 </mapper>

+ 19 - 2
fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml

@@ -956,8 +956,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     WHEN order_code = #{item.orderNumber} THEN #{item.deliveryPayTime}
                 </foreach>
                 ELSE delivery_pay_time
-                END
+                END,
             </if>
+            delivery_send_time = NOW()
         </set>
         WHERE order_code IN
         <foreach collection="list" item="item" open="(" separator="," close=")">
@@ -1593,7 +1594,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectFsStoreOrderListVO" resultType="com.fs.hisStore.vo.FsStoreOrderVO">
         select DISTINCT o.id,o.order_code,o.extend_order_id,o.pay_order_id,o.bank_order_id,o.user_id,o.real_name,o.user_phone,o.user_address,o.cart_id,o.freight_price,o.total_num,o.total_price,o.total_postage,o.pay_price,o.pay_postage,o.pay_delivery,o.pay_money,o.deduction_price,o.coupon_id,o.coupon_price,o.paid,o.pay_time,o.pay_type,o.create_time,o.update_time,o.status,o.refund_status,o.refund_reason_wap_img,o.refund_reason_wap_explain,o.refund_reason_time,o.refund_reason_wap,o.refund_reason,o.refund_price,o.delivery_sn,o.delivery_name,o.delivery_type,o.delivery_id,o.gain_integral,o.use_integral,o.pay_integral,o.back_integral,o.mark,o.is_del,o.remark,o.verify_code,o.store_id,o.shipping_type,o.is_channel,o.is_remind,o.is_sys_del,o.is_prescribe,o.prescribe_id,o.company_id,o.company_user_id,o.is_package,o.package_json,o.order_type,o.package_id,o.finish_time,o.delivery_status,o.delivery_pay_status,o.delivery_time,o.delivery_pay_time,o.delivery_pay_money,o.tui_money,o.tui_money_status,o.delivery_import_time,o.tui_user_id,o.tui_user_money_status,o.order_create_type,o.store_house_code,o.dept_id,o.is_edit_money,o.customer_id,o.is_pay_remain,o.delivery_send_time,o.certificates,o.upload_time,o.item_json,o.schedule_id,o.delivery_pay_type,o.order_visit,o.service_fee,o.cycle,o.prescribe_price,o.follow_doctor_id,o.follow_time,o.user_coupon_id,o.order_medium,o.erp_phone
         ,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber
-        , csc.name miniProgramName,fsp.cost, fspc.cate_name,spavs.bar_code, sp_latest.bank_transaction_id as bankTransactionId
+        , csc.name miniProgramName,fsp.cost, fspc.cate_name,spavs.bar_code, sp_latest.bank_transaction_id as bankTransactionId, o.is_audit
         from fs_store_order_scrm o
         left join fs_user u on o.user_id=u.user_id
         left join company c on c.company_id=o.company_id
@@ -1731,6 +1732,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.erpAccount == '未分拣'">
                 and ( df.login_account is null or df.login_account like '')
             </if>
+            <if test="maps.isAudit != null   ">
+                and o.is_audit = #{maps.isAudit}
+            </if>
         </where>
         ${maps.params.dataScope}
 <!--        <if test="maps.productName != null and  maps.productName !=  ''   ">-->
@@ -1915,6 +1919,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.erpAccount == '未分拣'">
                 and ( df.login_account is null or df.login_account like '')
             </if>
+            <if test="maps.isAudit != null ">
+                and o.is_audit = #{maps.isAudit}
+            </if>
         </where>
         ${maps.params.dataScope}
 <!--        <if test="maps.productName != null and  maps.productName !=  ''   ">-->
@@ -2129,4 +2136,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </update>
 
+    <!-- 批量更新订单审核状态 -->
+    <update id="batchUpdateAuditStatus">
+        UPDATE fs_store_order_scrm
+        SET is_audit = #{isAudit}
+        WHERE id IN
+        <foreach collection="orderIds" item="orderId" open="(" separator="," close=")">
+            #{orderId}
+        </foreach>
+    </update>
+
 </mapper>

+ 102 - 59
fs-user-app/src/main/java/com/fs/app/controller/live/LiveCompletionPointsController.java

@@ -16,7 +16,12 @@ import com.fs.live.domain.LiveCompletionPointsRecord;
 import com.fs.live.mapper.LiveCompletionPointsRecordMapper;
 import com.fs.live.service.ILiveCompletionPointsRecordService;
 import com.fs.live.service.ILiveService;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
@@ -27,6 +32,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 直播完课积分Controller
@@ -35,6 +41,8 @@ import java.util.Map;
 @RequestMapping("/app/live/completion")
 public class LiveCompletionPointsController extends AppBaseController {
 
+    private static final Logger logger = LoggerFactory.getLogger(LiveCompletionPointsController.class);
+
     @Autowired
     private ILiveCompletionPointsRecordService completionPointsRecordService;
 
@@ -50,6 +58,9 @@ public class LiveCompletionPointsController extends AppBaseController {
     @Autowired
     private LiveCompletionPointsRecordMapper completionPointsRecordMapper;
 
+    @Autowired
+    private RedissonClient redissonClient;
+
     /**
      * 领取完课积分
      */
@@ -181,6 +192,7 @@ public class LiveCompletionPointsController extends AppBaseController {
      * 更新用户看课completionPointsRecordService看课记录里面的时长
      */
     @PostMapping("/update-watch-duration")
+    @Transactional
     public R updateWatchDuration(@RequestParam Long liveId, @RequestParam Long watchDuration) {
         Long userId = Long.parseLong(getUserId());
 
@@ -251,6 +263,8 @@ public class LiveCompletionPointsController extends AppBaseController {
             if (record == null) {
                 // 如果没有记录,先创建记录
                 record = completionPointsRecordService.createCompletionRecord(liveId, userId);
+                record.setWatchDuration(finalWatchDuration);
+                completionPointsRecordMapper.updateRecord(record);
             } else {
                 // 更新现有记录的看课时长
                 Long currentWatchDuration = record.getWatchDuration() != null
@@ -269,7 +283,10 @@ public class LiveCompletionPointsController extends AppBaseController {
                     record.setCompletionRate(completionRate);
                 }
 
-                completionPointsRecordMapper.updateRecord(record);
+                int updateResult = completionPointsRecordMapper.updateRecord(record);
+                if (updateResult <= 0) {
+                    return R.error("更新看课时间失败");
+                }
             }
 
             UpdateWatchDurationVO vo = new UpdateWatchDurationVO();
@@ -291,81 +308,107 @@ public class LiveCompletionPointsController extends AppBaseController {
      * 没达到,返回报错
      */
     @PostMapping("/receive-points")
-    @RepeatSubmit
     public R receivePoints(@RequestParam Long liveId) {
         Long userId = Long.parseLong(getUserId());
 
-        try {
-            // 1. 查询当前用户和当前直播间的最近一次完课记录(不限制日期)
-            LiveCompletionPointsRecord record = completionPointsRecordMapper.selectLatestByUserAndLiveId(liveId, userId);
-
-            if (record == null) {
-                return R.error("您还没有看课记录,无法领取积分");
-            }
+        // 创建唯一锁,确保同一个 liveId 和 userId 只能有一个线程在执行
+        String lockKey = String.format("receivePoints:liveId:%d:userId:%d", liveId, userId);
+        RLock lock = redissonClient.getLock(lockKey);
 
-            // 2. 获取直播间信息和配置
-            Live live = liveService.selectLiveByLiveId(liveId);
-            if (live == null) {
-                return R.error("直播间不存在");
+        try {
+            // 尝试获取锁,等待时间0秒,锁持有时间15秒
+            boolean locked = lock.tryLock(0, 15, TimeUnit.SECONDS);
+            if (!locked) {
+                logger.warn("获取领取积分锁失败,liveId: {}, userId: {}", liveId, userId);
+                return R.error("系统繁忙,请稍后重试");
             }
 
-            // 3. 检查看课记录里面的时长是否达到完课标准
-            Long watchDuration = record.getWatchDuration();
-            if (watchDuration == null || watchDuration <= 0) {
-                return R.error("您的看课时长不足,无法领取积分");
-            }
+            try {
+                // 1. 查询当前用户和当前直播间的最近一次完课记录(不限制日期)
+                LiveCompletionPointsRecord record = completionPointsRecordMapper.selectLatestByUserAndLiveId(liveId, userId);
 
-            // 4. 检查完课比例是否达到标准
-            BigDecimal completionRate = record.getCompletionRate();
-            if (completionRate == null) {
-                // 重新计算完课比例
-                Long videoDuration = live.getDuration();
-                if (videoDuration == null || videoDuration <= 0) {
-                    return R.error("直播间视频时长配置错误");
+                if (record == null) {
+                    return R.error("您还没有看课记录,无法领取积分");
                 }
-                completionRate = BigDecimal.valueOf(watchDuration)
-                        .multiply(BigDecimal.valueOf(100))
-                        .divide(BigDecimal.valueOf(videoDuration), 2, java.math.RoundingMode.HALF_UP);
-                if (completionRate.compareTo(BigDecimal.valueOf(100)) > 0) {
-                    completionRate = BigDecimal.valueOf(100);
+
+                // 2. 获取直播间信息和配置
+                Live live = liveService.selectLiveByLiveId(liveId);
+                if (live == null) {
+                    return R.error("直播间不存在");
                 }
-                record.setCompletionRate(completionRate);
-            }
 
-            // 5. 从直播间配置获取完课标准
-            String configJson = live.getConfigJson();
-            Integer requiredCompletionRate = null;
-            if (configJson != null && !configJson.isEmpty()) {
-                try {
-                    com.alibaba.fastjson.JSONObject jsonConfig = com.alibaba.fastjson.JSON.parseObject(configJson);
-                    requiredCompletionRate = jsonConfig.getInteger("completionRate");
-                } catch (Exception e) {
-                    // 解析失败,忽略
+                // 3. 检查看课记录里面的时长是否达到完课标准
+                Long watchDuration = record.getWatchDuration();
+                if (watchDuration == null || watchDuration <= 0) {
+                    return R.error("您的看课时长不足,无法领取积分");
                 }
-            }
 
-            // 6. 判断是否达到完课标准
-            if (requiredCompletionRate != null && completionRate.compareTo(BigDecimal.valueOf(requiredCompletionRate)) < 0) {
-                return R.error("您的完课比例未达到标准(" + requiredCompletionRate + "%),当前完课比例:" + completionRate + "%");
-            }
+                // 4. 检查完课比例是否达到标准
+                BigDecimal completionRate = record.getCompletionRate();
+                if (completionRate == null) {
+                    // 重新计算完课比例
+                    Long videoDuration = live.getDuration();
+                    if (videoDuration == null || videoDuration <= 0) {
+                        return R.error("直播间视频时长配置错误");
+                    }
+                    completionRate = BigDecimal.valueOf(watchDuration)
+                            .multiply(BigDecimal.valueOf(100))
+                            .divide(BigDecimal.valueOf(videoDuration), 2, java.math.RoundingMode.HALF_UP);
+                    if (completionRate.compareTo(BigDecimal.valueOf(100)) > 0) {
+                        completionRate = BigDecimal.valueOf(100);
+                    }
+                    record.setCompletionRate(completionRate);
+                }
 
-            // 7. 检查是否已领取
-            if (record.getReceiveStatus() != null && record.getReceiveStatus() == 1) {
-                return R.error("该完课积分已领取");
-            }
+                // 5. 从直播间配置获取完课标准
+                String configJson = live.getConfigJson();
+                Integer requiredCompletionRate = null;
+                if (configJson != null && !configJson.isEmpty()) {
+                    try {
+                        com.alibaba.fastjson.JSONObject jsonConfig = com.alibaba.fastjson.JSON.parseObject(configJson);
+                        requiredCompletionRate = jsonConfig.getInteger("completionRate");
+                    } catch (Exception e) {
+                        // 解析失败,忽略
+                    }
+                }
 
-            // 8. 领取积分(更新看课记录的领取状态,给用户加积分)
-            LiveCompletionPointsRecord receivedRecord = completionPointsRecordService.receiveCompletionPoints(record.getId(), userId);
+                // 6. 判断是否达到完课标准
+                if (requiredCompletionRate != null && completionRate.compareTo(BigDecimal.valueOf(requiredCompletionRate)) < 0) {
+                    return R.error("您的完课比例未达到标准(" + requiredCompletionRate + "%),当前完课比例:" + completionRate + "%");
+                }
 
-            ReceivePointsVO vo = new ReceivePointsVO();
-            vo.setRecord(receivedRecord);
-            vo.setPoints(receivedRecord.getPointsAwarded());
-            vo.setContinuousDays(receivedRecord.getContinuousDays());
+                // 7. 检查是否已领取
+                if (record.getReceiveStatus() != null && record.getReceiveStatus() == 1) {
+                    return R.error("该完课积分已领取");
+                }
 
-            return R.ok().put("data", vo);
-        } catch (BaseException e) {
-            return R.error(e.getMessage());
+                // 8. 领取积分(更新看课记录的领取状态,给用户加积分)
+                LiveCompletionPointsRecord receivedRecord = completionPointsRecordService.receiveCompletionPoints(record.getId(), userId);
+
+                ReceivePointsVO vo = new ReceivePointsVO();
+                vo.setRecord(receivedRecord);
+                vo.setPoints(receivedRecord.getPointsAwarded());
+                vo.setContinuousDays(receivedRecord.getContinuousDays());
+
+                return R.ok().put("data", vo);
+            } catch (BaseException e) {
+                return R.error(e.getMessage());
+            } catch (Exception e) {
+                logger.error("领取积分失败,liveId: {}, userId: {}", liveId, userId, e);
+                return R.error("领取失败: " + e.getMessage());
+            } finally {
+                // 释放锁
+                if (lock.isHeldByCurrentThread()) {
+                    lock.unlock();
+                    logger.debug("领取积分锁已释放,liveId: {}, userId: {}", liveId, userId);
+                }
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            logger.error("获取领取积分锁被中断,liveId: {}, userId: {}", liveId, userId, e);
+            return R.error("系统繁忙,请稍后重试");
         } catch (Exception e) {
+            logger.error("领取积分异常,liveId: {}, userId: {}", liveId, userId, e);
             return R.error("领取失败: " + e.getMessage());
         }
     }

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

@@ -35,7 +35,10 @@ import com.fs.his.domain.FsPayConfig;
 import com.fs.his.domain.MerchantAppConfig;
 import com.fs.his.mapper.MerchantAppConfigMapper;
 import com.fs.hisStore.domain.FsUserScrm;
+import com.fs.hisStore.enums.AfterSalesStatusEnum;
 import com.fs.hisStore.enums.OrderInfoEnum;
+import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
+import com.fs.hisStore.service.IFsStoreAfterSalesScrmService;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import com.fs.hisStore.service.IFsUserScrmService;
@@ -44,9 +47,12 @@ import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
 import com.fs.huifuPay.service.HuiFuService;
+import com.fs.live.domain.LiveAfterSales;
 import com.fs.live.domain.LiveOrder;
 import com.fs.live.domain.LiveOrderPayment;
 import com.fs.live.dto.LiveOrderComputeDTO;
+import com.fs.live.enums.LiveAfterSalesStatusEnum;
+import com.fs.live.enums.LiveOrderCancleReason;
 import com.fs.live.mapper.LiveOrderPaymentMapper;
 import com.fs.live.param.FsMyLiveOrderQueryParam;
 import com.fs.live.param.LiveOrderComputedParam;
@@ -85,7 +91,9 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
+import java.sql.Timestamp;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
@@ -132,6 +140,12 @@ public class LiveOrderController extends AppBaseController
     IPayService ybPayService;
     @Autowired
     private HuiFuService huiFuService;
+    @Autowired
+    private IFsStoreOrderScrmService fsStoreOrderScrmService;
+    @Autowired
+    private IFsStoreAfterSalesScrmService fsStoreAfterSalesScrmService;
+    @Autowired
+    private FsStorePaymentScrmMapper fsStorePaymentScrmMapper;
 
 
 
@@ -946,5 +960,188 @@ public class LiveOrderController extends AppBaseController
     }
 
 
+    @ApiOperation("批量生成售后订单并退款")
+//    @PostMapping("/batchCreateAfterSalesAndRefund")
+    public R batchCreateAfterSalesAndRefund(@RequestBody List<String> payCodes) {
+        if (payCodes == null || payCodes.isEmpty()) {
+            return R.error("支付订单号列表不能为空");
+        }
+
+        List<Map<String, Object>> results = new ArrayList<>();
+
+        for (String payCode : payCodes) {
+            Map<String, Object> result = new HashMap<>();
+            result.put("payCode", payCode);
+
+            try {
+                // 先查询支付记录
+                // 先尝试查询商城订单支付记录
+                FsStorePaymentScrm storePayment = fsStorePaymentScrmMapper.selectFsStorePaymentByCode(payCode.split("-")[1]);
+
+                if (storePayment != null) {
+                    // 商城订单支付记录
+                    result.put("paymentType", "store");
+                    result.put("paymentId", storePayment.getPaymentId());
+
+                    // 根据支付记录查询订单
+                    FsStoreOrderScrm storeOrder = null;
+                    if (storePayment.getOrderId() != null) {
+                        storeOrder = fsStoreOrderScrmService.selectFsStoreOrderById(storePayment.getOrderId());
+                    } else if (StringUtils.isNotEmpty(storePayment.getBusinessOrderId())) {
+                        // 如果没有orderId,尝试通过businessOrderId查询
+                        storeOrder = fsStoreOrderScrmService.selectFsStoreOrderByOrderCode(storePayment.getBusinessOrderId());
+                    }
+
+                    if (storeOrder == null) {
+                        result.put("success", false);
+                        result.put("message", "根据支付记录未找到对应的订单");
+                        results.add(result);
+                        continue;
+                    }
+
+                    result.put("orderCode", storeOrder.getOrderCode());
+                    result.put("orderId", storeOrder.getId());
+
+                    // 查询售后记录
+                    FsStoreAfterSalesScrm queryAfterSales = new FsStoreAfterSalesScrm();
+                    queryAfterSales.setOrderCode(storeOrder.getOrderCode());
+                    List<FsStoreAfterSalesScrm> existingAfterSales = fsStoreAfterSalesScrmService.selectFsStoreAfterSalesList(queryAfterSales);
+
+                    FsStoreAfterSalesScrm afterSales = null;
+                    if (existingAfterSales == null || existingAfterSales.isEmpty()) {
+                        // 创建售后记录
+                        afterSales = new FsStoreAfterSalesScrm();
+                        afterSales.setOrderCode(storeOrder.getOrderCode());
+                        afterSales.setRefundAmount(storeOrder.getPayMoney());
+                        afterSales.setServiceType(0); // 0仅退款
+                        afterSales.setReasons("系统自动生成售后订单");
+                        afterSales.setExplains("系统自动生成售后订单");
+                        afterSales.setExplainImg(null);
+                        afterSales.setStatus(AfterSalesStatusEnum.STATUS_4.getValue()); // 4财务已审核(退款成功)
+                        afterSales.setSalesStatus(3); // 3已完成
+                        afterSales.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
+                        afterSales.setIsDel(0);
+                        afterSales.setUserId(storeOrder.getUserId());
+                        afterSales.setOrderStatus(storeOrder.getStatus());
+                        afterSales.setCompanyId(storeOrder.getCompanyId());
+                        afterSales.setCompanyUserId(storeOrder.getCompanyUserId());
+                        if (storeOrder.getPackageJson() != null) {
+                            afterSales.setPackageJson(storeOrder.getPackageJson());
+                        }
+                        if (storeOrder.getIsPackage() != null) {
+                            afterSales.setIsPackage(storeOrder.getIsPackage());
+                        }
+                        fsStoreAfterSalesScrmService.insertFsStoreAfterSales(afterSales);
+                        result.put("afterSalesCreated", true);
+                    } else {
+                        afterSales = existingAfterSales.get(0);
+                        result.put("afterSalesCreated", false);
+                        result.put("afterSalesId", afterSales.getId());
+                    }
+
+                    // 修改订单状态为退款成功
+                    storeOrder.setStatus(OrderInfoEnum.STATUS_NE2.getValue()); // -2退款成功
+                    storeOrder.setRefundStatus(OrderInfoEnum.REFUND_STATUS_2.getValue()); // 2已退款
+                    storeOrder.setRefundPrice(storeOrder.getPayMoney());
+                    fsStoreOrderScrmService.updateFsStoreOrder(storeOrder);
+
+                    result.put("success", true);
+                    result.put("message", "处理成功");
+                    result.put("afterSalesId", afterSales != null ? afterSales.getId() : null);
+
+                } else {
+                    // 尝试查询直播订单支付记录
+                    LiveOrderPayment livePayment = liveOrderPaymentMapper.selectLiveOrderPaymentByPaymentCode(payCode.split("-")[1]);
+
+                    if (livePayment != null) {
+                        // 直播订单支付记录
+                        result.put("paymentType", "live");
+                        result.put("paymentId", livePayment.getPaymentId());
+
+                        // 根据支付记录查询订单
+                        LiveOrder liveOrder = null;
+                        if (StringUtils.isNotEmpty(livePayment.getBusinessId())) {
+                            // businessId 是订单ID(Long类型转String)
+                            try {
+                                Long orderId = Long.parseLong(livePayment.getBusinessId());
+                                liveOrder = orderService.selectLiveOrderByOrderId(String.valueOf(orderId));
+                            } catch (NumberFormatException e) {
+                                // 如果不是数字,可能是订单号
+                                liveOrder = orderService.selectLiveOrderByOrderId(livePayment.getBusinessId());
+                            }
+                        } else if (StringUtils.isNotEmpty(livePayment.getBusinessCode())) {
+                            // 通过businessCode(订单号)查询
+                            liveOrder = orderService.selectLiveOrderByOrderId(livePayment.getBusinessCode());
+                        }
+
+                        if (liveOrder == null) {
+                            result.put("success", false);
+                            result.put("message", "根据支付记录未找到对应的订单");
+                            results.add(result);
+                            continue;
+                        }
+
+                        result.put("orderCode", liveOrder.getOrderCode());
+                        result.put("orderId", liveOrder.getOrderId());
+
+                        // 查询售后记录
+                        LiveAfterSales queryAfterSales = new LiveAfterSales();
+                        queryAfterSales.setOrderId(liveOrder.getOrderId());
+                        List<LiveAfterSales> existingAfterSales = liveAfterSalesService.selectLiveAfterSalesList(queryAfterSales);
+
+                        LiveAfterSales afterSales = null;
+                        if (existingAfterSales == null || existingAfterSales.isEmpty()) {
+                            // 创建售后记录
+                            afterSales = new LiveAfterSales();
+                            afterSales.setOrderId(liveOrder.getOrderId());
+                            afterSales.setRefundAmount(liveOrder.getPayMoney());
+                            afterSales.setRefundType(0); // 0仅退款
+                            afterSales.setReasons("系统自动生成售后订单");
+                            afterSales.setExplains("系统自动生成售后订单");
+                            afterSales.setExplainImg(null);
+                            afterSales.setStatus(LiveAfterSalesStatusEnum.STATUS_4.getValue()); // 4财务已审核(退款成功)
+                            afterSales.setSalesStatus(3); // 3已完成
+                            afterSales.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
+                            afterSales.setIsDel(0);
+                            afterSales.setUserId(Long.valueOf(liveOrder.getUserId()));
+                            afterSales.setOrderStatus(liveOrder.getStatus());
+                            afterSales.setCompanyId(liveOrder.getCompanyId());
+                            afterSales.setCompanyUserId(liveOrder.getCompanyUserId());
+                            liveAfterSalesService.insertLiveAfterSales(afterSales);
+                            result.put("afterSalesCreated", true);
+                        } else {
+                            afterSales = existingAfterSales.get(0);
+                            result.put("afterSalesCreated", false);
+                            result.put("afterSalesId", afterSales.getId());
+                        }
+
+                        // 修改订单状态为退款成功
+                        liveOrder.setStatus(OrderInfoEnum.STATUS_NE2.getValue()); // -2退款成功
+                        liveOrder.setRefundStatus(String.valueOf(OrderInfoEnum.REFUND_STATUS_2.getValue())); // 2已退款
+                        liveOrder.setRefundMoney(liveOrder.getPayMoney());
+                        liveOrder.setRefundTime(new Date());
+                        orderService.updateLiveOrder(liveOrder);
+
+                        result.put("success", true);
+                        result.put("message", "处理成功");
+                        result.put("afterSalesId", afterSales != null ? afterSales.getId() : null);
+
+                    } else {
+                        result.put("success", false);
+                        result.put("message", "未找到对应的支付记录");
+                    }
+                }
+
+            } catch (Exception e) {
+                logger.error("处理支付订单失败: " + payCode, e);
+                result.put("success", false);
+                result.put("message", "处理失败: " + e.getMessage());
+            }
+
+            results.add(result);
+        }
+
+        return R.ok().put("results", results);
+    }
 
 }