Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master'

yfh 5 giorni fa
parent
commit
0ef7a952c0

+ 1 - 0
fs-company/src/main/java/com/fs/company/controller/course/FsCourseFinishTempController.java

@@ -82,6 +82,7 @@ public class FsCourseFinishTempController extends BaseController
     {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         fsCourseFinishTemp.setCompanyId(loginUser.getCompany().getCompanyId());
+        fsCourseFinishTemp.setCreateBy(String.valueOf(loginUser.getUser().getUserId()));
         return toAjax(fsCourseFinishTempService.insertFsCourseFinishTemp(fsCourseFinishTemp));
     }
 

+ 118 - 5
fs-company/src/main/java/com/fs/company/controller/course/FsCourseFinishTempParentController.java

@@ -1,7 +1,11 @@
 package com.fs.company.controller.course;
 
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
+import com.fs.company.service.impl.CompanyDeptServiceImpl;
+import com.fs.company.service.impl.CompanyUserServiceImpl;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.security.SecurityUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -25,7 +29,7 @@ import com.fs.common.core.page.TableDataInfo;
 
 /**
  * 完课模板Controller
- * 
+ *
  * @author 吴树波
  * @date 2025-05-22
  */
@@ -36,6 +40,12 @@ public class FsCourseFinishTempParentController extends BaseController
     @Autowired
     private IFsCourseFinishTempParentService fsCourseFinishTempParentService;
 
+    @Autowired
+    private CompanyDeptServiceImpl companyDeptService;
+
+    @Autowired
+    private CompanyUserServiceImpl companyUserService;
+
     /**
      * 查询完课模板列表
      */
@@ -50,6 +60,55 @@ public class FsCourseFinishTempParentController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 查询我创建的完课模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:myList')")
+    @GetMapping("/myList")
+    public TableDataInfo myList(FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        startPage();
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsCourseFinishTempParent.setCompanyId(loginUser.getCompany().getCompanyId());
+        fsCourseFinishTempParent.setCreateBy(String.valueOf(loginUser.getUser().getUserId()));
+        List<FsCourseFinishTempParent> list = fsCourseFinishTempParentService.selectFsCourseFinishTempParentList(fsCourseFinishTempParent);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询部门的创建的完课模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:deptList')")
+    @GetMapping("/deptList")
+    public TableDataInfo deptList(FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsCourseFinishTempParent.setCompanyId(loginUser.getCompany().getCompanyId());
+
+        List<Long> combinedList = new ArrayList<>();
+        //本部门
+        Long deptId = loginUser.getUser().getDeptId();
+        if (deptId!=null){
+            combinedList.add(deptId);
+        }
+        //本部门的下级部门
+        List<Long> deptList = companyDeptService.selectCompanyDeptByParentId(deptId);
+        if (!deptList.isEmpty()){
+            combinedList.addAll(deptList);
+        }
+
+        List<Long> userIds = companyUserService.selectCompanyQwUserByDept(deptList, loginUser.getUser().getUserType());
+        if (userIds.isEmpty()){
+            return getDataTable(new ArrayList<>());
+        }
+
+        fsCourseFinishTempParent.setUserIds(userIds);
+
+        startPage();
+        List<FsCourseFinishTempParent> list = fsCourseFinishTempParentService.selectFsCourseFinishTempParentList(fsCourseFinishTempParent);
+        return getDataTable(list);
+    }
+
     /**
      * 导出完课模板列表
      */
@@ -58,15 +117,67 @@ public class FsCourseFinishTempParentController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsCourseFinishTempParent fsCourseFinishTempParent)
     {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsCourseFinishTempParent.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<FsCourseFinishTempParent> list = fsCourseFinishTempParentService.selectFsCourseFinishTempParentList(fsCourseFinishTempParent);
+        ExcelUtil<FsCourseFinishTempParent> util = new ExcelUtil<FsCourseFinishTempParent>(FsCourseFinishTempParent.class);
+        return util.exportExcel(list, "完课模板数据");
+    }
+
+    /**
+     * 导出我的完课模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:myExport')")
+    @Log(title = "完课模板", businessType = BusinessType.EXPORT)
+    @GetMapping("/myExport")
+    public AjaxResult myExport(FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsCourseFinishTempParent.setCompanyId(loginUser.getCompany().getCompanyId());
+        fsCourseFinishTempParent.setCreateBy(String.valueOf(loginUser.getUser().getUserId()));
         List<FsCourseFinishTempParent> list = fsCourseFinishTempParentService.selectFsCourseFinishTempParentList(fsCourseFinishTempParent);
         ExcelUtil<FsCourseFinishTempParent> util = new ExcelUtil<FsCourseFinishTempParent>(FsCourseFinishTempParent.class);
         return util.exportExcel(list, "完课模板数据");
     }
 
+    /**
+     * 导出部门完课模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:myExport')")
+    @Log(title = "完课模板", businessType = BusinessType.EXPORT)
+    @GetMapping("/deptExport")
+    public AjaxResult deptExport(FsCourseFinishTempParent fsCourseFinishTempParent)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+
+        List<Long> combinedList = new ArrayList<>();
+        //本部门
+        Long deptId = loginUser.getUser().getDeptId();
+        if (deptId!=null){
+            combinedList.add(deptId);
+        }
+        //本部门的下级部门
+        List<Long> deptList = companyDeptService.selectCompanyDeptByParentId(deptId);
+        if (!deptList.isEmpty()){
+            combinedList.addAll(deptList);
+        }
+
+        List<Long> userIds = companyUserService.selectCompanyQwUserByDept(deptList, loginUser.getUser().getUserType());
+        if (userIds.isEmpty()){
+            return AjaxResult.error();
+        }
+
+        fsCourseFinishTempParent.setUserIds(userIds);
+        List<FsCourseFinishTempParent> list = fsCourseFinishTempParentService.selectFsCourseFinishTempParentList(fsCourseFinishTempParent);
+        ExcelUtil<FsCourseFinishTempParent> util = new ExcelUtil<FsCourseFinishTempParent>(FsCourseFinishTempParent.class);
+        return util.exportExcel(list, "完课模板数据");
+    }
+
+
     /**
      * 获取完课模板详细信息
      */
-    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:query')")
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:query') || @ss.hasPermi('course:courseFinishTempParent:myQuery') || @ss.hasPermi('course:courseFinishTempParent:deptQuery')")
     @GetMapping(value = "/{id}")
     public AjaxResult getInfo(@PathVariable("id") Long id)
     {
@@ -76,20 +187,22 @@ public class FsCourseFinishTempParentController extends BaseController
     /**
      * 新增完课模板
      */
-    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:add')")
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:add') || @ss.hasPermi('course:courseFinishTempParent:myAdd') || @ss.hasPermi('course:courseFinishTempParent:deptAdd')")
     @Log(title = "完课模板", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@RequestBody FsCourseFinishTempParent fsCourseFinishTempParent){
 
         LoginUser loginUser = SecurityUtils.getLoginUser();
         fsCourseFinishTempParent.setCompanyId(loginUser.getCompany().getCompanyId());
+        fsCourseFinishTempParent.setCreateTime(new Date());
+        fsCourseFinishTempParent.setCreateBy(String.valueOf(loginUser.getUser().getUserId()));
         return toAjax(fsCourseFinishTempParentService.insertFsCourseFinishTempParent(fsCourseFinishTempParent));
     }
 
     /**
      * 修改完课模板
      */
-    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:edit')")
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:edit') || @ss.hasPermi('course:courseFinishTempParent:myEdit') || @ss.hasPermi('course:courseFinishTempParent:deptEdit')")
     @Log(title = "完课模板", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody FsCourseFinishTempParent fsCourseFinishTempParent)
@@ -102,7 +215,7 @@ public class FsCourseFinishTempParentController extends BaseController
     /**
      * 删除完课模板
      */
-    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:remove')")
+    @PreAuthorize("@ss.hasPermi('course:courseFinishTempParent:remove') || @ss.hasPermi('course:courseFinishTempParent:myRemove') || @ss.hasPermi('course:courseFinishTempParent:deptRemove')")
     @Log(title = "完课模板", businessType = BusinessType.DELETE)
 	@DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)

+ 15 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java

@@ -136,6 +136,21 @@ public class QwUserController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 查询我的企微员工列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:myStaffList')")
+    @GetMapping("/myStaffList")
+    public TableDataInfo myStaffList(QwUserListParam qwUser) {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
+        qwUser.setCompanyUserId(loginUser.getUser().getUserId());
+        List<QwUserVO> list = qwUserService.selectQwUserListStaffVO(qwUser);
+        return getDataTable(list);
+    }
+
+
     /**
      * 导出企微员工列表
      * @param qwUser

+ 39 - 6
fs-qw-api/src/main/java/com/fs/app/service/QwDataCallbackService.java

@@ -26,6 +26,8 @@ import com.google.gson.JsonParser;
 import com.tencent.wework.Finance;
 import lombok.extern.slf4j.Slf4j;
 import org.json.JSONObject;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
@@ -73,6 +75,9 @@ public class QwDataCallbackService {
     @Autowired
     IQwAutoTagsService qwAutoTagsService;
 
+    @Autowired
+    private RedissonClient redissonClient;
+
     @Autowired
     IQwAutoTagsLogsService qwAutoTagsLogsService;
 
@@ -202,13 +207,41 @@ public class QwDataCallbackService {
                             if(WelcomeCodeList.getLength() > 0) {
                                 WelcomeCode = WelcomeCodeList.item(0).getTextContent();
                             }
-
-                            String qwApiExternal=redisCache.getCacheObject("qwApiExternal:"+root.getElementsByTagName("UserID").item(0).getTextContent()+":"+corpId+":"+root.getElementsByTagName("ExternalUserID").item(0).getTextContent());
-                            if (StringUtil.strIsNullOrEmpty(qwApiExternal)){
-                                redisCache.setCacheObject("qwApiExternal:"+root.getElementsByTagName("UserID").item(0).getTextContent()+":"+corpId+":"+root.getElementsByTagName("ExternalUserID").item(0).getTextContent() ,"1",10, TimeUnit.MINUTES);
-                                qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
-
+                            String userId = root.getElementsByTagName("UserID").item(0).getTextContent();
+                            String externalUserId = root.getElementsByTagName("ExternalUserID").item(0).getTextContent();
+                            String cacheKey = "qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId;
+                            String lockKey = "lock:qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId; // 锁Key(Hash类型,加前缀lock:)
+
+                            // 2. 获取 Redisson 分布式锁
+                            RLock lock = redissonClient.getLock(lockKey);
+                            boolean isLocked = false;
+                            try {
+                                // 3. 尝试加锁:最多等待 5 秒,锁自动释放时间 15 分钟
+                                isLocked = lock.tryLock(5, 15, TimeUnit.MINUTES);
+                                if (isLocked) {
+                                    // 4. 加锁成功后,再次检查缓存(避免多线程竞争时重复执行业务)
+                                    String qwApiExternal = redisCache.getCacheObject(cacheKey);
+                                    if (StringUtil.strIsNullOrEmpty(qwApiExternal)) {
+                                        try {
+                                            // 5. 新增用户
+                                            qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
+                                            // 6. 业务逻辑执行成功后,写入 Redis 缓存(有效期 10 分钟)
+                                            redisCache.setCacheObject(cacheKey, "1", 10, TimeUnit.MINUTES);
+                                        } catch (Exception e) {
+                                            // 7. 业务逻辑失败时,删除缓存
+                                            redisCache.deleteObject(cacheKey);
+                                        }
+                                    }
+                                }
+                            } catch (InterruptedException e) {
+                                logger.error("中断异常");
+                            } finally {
+                                // 4. 确保锁最终被释放(只有加锁成功的线程才需要释放)
+                                if (isLocked && lock.isHeldByCurrentThread()) {
+                                    lock.unlock();
+                                }
                             }
+
                             break;
                         case "edit_external_contact":
                             qwExternalContactService.updateQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);

+ 12 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java

@@ -284,4 +284,16 @@ public interface CompanyUserMapper
 
 
     List<String> selectCompanyUserNameByIdsList(@Param("companyUserIDs")List<Long> companyUserID);
+
+    @Select("<script>" +
+            "SELECT user_id FROM company_user WHERE 1=1 " +
+            "<if test=\"companyUserIDs != null and companyUserIDs.size() > 0 and userType != '00'\">" +
+            "   AND dept_id IN " +
+            "   <foreach collection='companyUserIDs' item='item' open='(' separator=',' close=')'>" +
+            "       #{item}" +
+            "   </foreach>" +
+            "</if>" +
+            "</script>")
+    List<Long> selectCompanyQwUserByDept(@Param("companyUserIDs") List<Long> companyUserIDs, @Param("userType") String userType);
+
 }

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

@@ -244,4 +244,6 @@ public interface ICompanyUserService {
      * @param batchUserRolesVO 批量修改角色参数
      */
     R updateBatchUserRoles(BatchUserRolesVO batchUserRolesVO);
+
+    List<Long> selectCompanyQwUserByDept(List<Long> deptList,String userType);
 }

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

@@ -1061,4 +1061,9 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         }
         return R.ok("修改成功");
     }
+
+    @Override
+    public List<Long> selectCompanyQwUserByDept(List<Long> deptList,String userType) {
+        return companyUserMapper.selectCompanyQwUserByDept(deptList,userType);
+    }
 }

+ 5 - 0
fs-service/src/main/java/com/fs/course/domain/FsCourseFinishTempParent.java

@@ -8,6 +8,8 @@ import lombok.Data;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.EqualsAndHashCode;
 
+import java.util.List;
+
 /**
  * 完课模板对象 fs_course_finish_temp_parent
  *
@@ -45,4 +47,7 @@ public class FsCourseFinishTempParent extends BaseEntity{
     private String companyUserIds;
     @TableField(exist = false)
     private Integer isAllCompanyUser;
+
+    @TableField(exist = false)
+    private List<Long> userIds;
 }

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

@@ -1,5 +1,6 @@
 package com.fs.course.service.impl;
 
+import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -79,6 +80,8 @@ public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFin
             temp.setCompanyId(fsCourseFinishTempParent.getCompanyId());
             temp.setCourseId(e.getCourseId());
             temp.setVideoId(e.getVideoId());
+            temp.setCreateBy(fsCourseFinishTempParent.getCreateBy());
+            temp.setCreateTime(new Date());
             temp.setCompanyUserIds(fsCourseFinishTempParent.getCompanyUserIds());
             temp.setIsAllCompanyUser(fsCourseFinishTempParent.getIsAllCompanyUser());
             temp.setParentId(fsCourseFinishTempParent.getId());

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

@@ -1542,14 +1542,11 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         FsStorePayment queryParam = new FsStorePayment();
         queryParam.setStatus(0);//未支付
         queryParam.setBeginTime(DateUtils.addDateDays(-1));
-        queryParam.setEndTime(DateUtils.getNowDate().toString());
+        queryParam.setEndTime(DateUtils.getDate());
         List<FsStorePayment> list = selectFsStorePaymentList(queryParam);
         if (list != null && !list.isEmpty()) {
             List<CompletableFuture<Void>> futures = new ArrayList<>();
             for (FsStorePayment fsStorePayment : list) {
-                if (fsStorePayment.getPayCode().equals("1974233163920048128")){
-                    System.out.println(fsStorePayment.getPayCode());
-                }
                 CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                     updateFsStorePaymentByDecryptForm(fsStorePayment.getPaymentId());
                     logger.info("定时任务:同步支付状态,payment_id:{}",fsStorePayment.getPaymentId());

+ 13 - 6
fs-service/src/main/resources/mapper/course/FsCourseFinishTempParentMapper.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.course.mapper.FsCourseFinishTempParentMapper">
-    
+
     <resultMap type="FsCourseFinishTempParent" id="FsCourseFinishTempParentResult">
         <result property="id"    column="id"    />
         <result property="name"    column="name"    />
@@ -22,18 +22,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectFsCourseFinishTempParentList" parameterType="FsCourseFinishTempParent" resultMap="FsCourseFinishTempParentResult">
         <include refid="selectFsCourseFinishTempParentVo"/>
-        <where>  
+        <where>
             <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
             <if test="courseId != null "> and course_id = #{courseId}</if>
             <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="createBy != null "> and create_by = #{createBy}</if>
+            <if test="userIds != null and !userIds.isEmpty() ">
+                AND create_by IN
+                 <foreach collection='userIds' item='item' open='(' separator=',' close=')'>
+                 #{item}
+                </foreach>
+             </if>
         </where>
     </select>
-    
+
     <select id="selectFsCourseFinishTempParentById" parameterType="Long" resultMap="FsCourseFinishTempParentResult">
         <include refid="selectFsCourseFinishTempParentVo"/>
         where id = #{id}
     </select>
-        
+
     <insert id="insertFsCourseFinishTempParent" parameterType="FsCourseFinishTempParent" useGeneratedKeys="true" keyProperty="id">
         insert into fs_course_finish_temp_parent
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -75,9 +82,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </delete>
 
     <delete id="deleteFsCourseFinishTempParentByIds" parameterType="String">
-        delete from fs_course_finish_temp_parent where id in 
+        delete from fs_course_finish_temp_parent where id in
         <foreach item="id" collection="array" open="(" separator="," close=")">
             #{id}
         </foreach>
     </delete>
-</mapper>
+</mapper>

+ 1 - 1
fs-service/src/main/resources/mapper/his/FsStorePaymentMapper.xml

@@ -59,7 +59,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="businessCode != null "> and business_code = #{businessCode}</if>
             <if test="appId != null and appId !=''"> and app_id = #{appId}</if>
             <if test="beginTime != null and beginTime !=''"> and create_time >= #{beginTime}</if>
-            <if test="endTime != null and endTime !=''"> and create_time &lt;= #{endTime}</if>
+            <if test="endTime != null and endTime !=''"> and create_time &lt; #{endTime}</if>
         </where>
     </select>
 

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/param/FsUserEditParam.java

@@ -14,7 +14,7 @@ import java.io.Serializable;
 public class FsUserEditParam implements Serializable {
 
     @NotNull(message = "用户昵称不能为空!")
-    @JsonAlias({"nickname", "nickName"})
+    @JsonAlias({ "nickName","nickname"})
     private String nickname;
 
     //    @NotBlank(message = "用户头像不能为空!")