浏览代码

95:红德堂APP调试 会员关联项目代码同步

Long 2 天之前
父节点
当前提交
1fc1c6d7b0
共有 56 个文件被更改,包括 1636 次插入510 次删除
  1. 3 2
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java
  2. 12 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  3. 33 2
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  4. 6 0
      fs-company-app/src/main/java/com/fs/app/controller/AppBaseController.java
  5. 29 12
      fs-company-app/src/main/java/com/fs/app/controller/CompanyTagController.java
  6. 100 17
      fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java
  7. 39 13
      fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java
  8. 153 124
      fs-company-app/src/main/java/com/fs/app/controller/WxCompanyUserController.java
  9. 14 1
      fs-company-app/src/main/java/com/fs/app/param/CompanyUserChangeApplyParam.java
  10. 5 3
      fs-company-app/src/main/java/com/fs/app/param/CompanyUserParam.java
  11. 17 0
      fs-company-app/src/main/java/com/fs/app/param/FsUserProjectUpdateParam.java
  12. 3 3
      fs-company-app/src/main/java/com/fs/app/param/FsUserTagUpdateParam.java
  13. 22 0
      fs-company-app/src/main/java/com/fs/app/param/LoginMaWxParam.java
  14. 23 0
      fs-company-app/src/main/java/com/fs/app/param/TagProjectParam.java
  15. 10 2
      fs-company/src/main/java/com/fs/company/controller/store/FsUserController.java
  16. 21 0
      fs-service/src/main/java/com/fs/company/domain/CompanyUser.java
  17. 4 0
      fs-service/src/main/java/com/fs/company/domain/CompanyUserChangeApplyUser.java
  18. 2 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyTagMapper.java
  19. 2 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyTagUserMapper.java
  20. 2 0
      fs-service/src/main/java/com/fs/company/service/ICompanyTagService.java
  21. 5 0
      fs-service/src/main/java/com/fs/company/service/ICompanyTagUserService.java
  22. 2 1
      fs-service/src/main/java/com/fs/company/service/ICompanyUserChangeApplyService.java
  23. 3 2
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  24. 11 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyTagServiceImpl.java
  25. 23 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyTagUserServiceImpl.java
  26. 14 9
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserChangeApplyServiceImpl.java
  27. 9 2
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  28. 4 0
      fs-service/src/main/java/com/fs/company/vo/CompanyTagUserVO.java
  29. 18 4
      fs-service/src/main/java/com/fs/course/domain/FsUserCompanyUser.java
  30. 6 0
      fs-service/src/main/java/com/fs/course/domain/FsUserCourseVideo.java
  31. 1 1
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  32. 14 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCompanyUserMapper.java
  33. 3 0
      fs-service/src/main/java/com/fs/course/param/BatchVideoSvae.java
  34. 1 3
      fs-service/src/main/java/com/fs/course/param/newfs/FsUserCourseBeMemberParam.java
  35. 35 7
      fs-service/src/main/java/com/fs/course/service/IFsUserCompanyUserService.java
  36. 58 9
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCompanyUserServiceImpl.java
  37. 22 13
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  38. 30 0
      fs-service/src/main/java/com/fs/his/domain/FsUserProjectTag.java
  39. 2 1
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  40. 19 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserProjectTagMapper.java
  41. 33 0
      fs-service/src/main/java/com/fs/his/service/IFsUserProjectTagService.java
  42. 8 0
      fs-service/src/main/java/com/fs/his/service/IFsUserService.java
  43. 105 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserProjectTagServiceImpl.java
  44. 60 83
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  45. 134 8
      fs-service/src/main/java/com/fs/his/vo/FsUserVO.java
  46. 1 1
      fs-service/src/main/java/com/fs/qw/dto/FsUserTransferParamDTO.java
  47. 39 28
      fs-service/src/main/java/com/fs/qw/service/impl/CustomerTransferApprovalServiceImpl.java
  48. 7 0
      fs-service/src/main/java/com/fs/store/param/h5/FsUserPageListParam.java
  49. 4 0
      fs-service/src/main/java/com/fs/store/vo/h5/CompanyUserTagListVO.java
  50. 5 0
      fs-service/src/main/java/com/fs/store/vo/h5/FsUserPageListVO.java
  51. 30 0
      fs-service/src/main/resources/mapper/company/CompanyTagMapper.xml
  52. 34 8
      fs-service/src/main/resources/mapper/company/CompanyTagUserMapper.xml
  53. 62 9
      fs-service/src/main/resources/mapper/course/FsUserCompanyUserMapper.xml
  54. 24 4
      fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  55. 281 138
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  56. 29 0
      fs-service/src/main/resources/mapper/his/FsUserProjectTagMapper.xml

+ 3 - 2
fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java

@@ -11,6 +11,7 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyUserService;
+import com.fs.qw.dto.UserProjectDTO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -145,9 +146,9 @@ public class CompanyUserController extends BaseController
     @PreAuthorize("@ss.hasPermi('company:companyUser:change')")
     @Log(title = "更换会员归属", businessType = BusinessType.OTHER)
     @PostMapping("/changeCompanyUser")
-    public AjaxResult changeCompanyUser(@RequestBody List<Long> userIds, @RequestParam Long companyUserId, @RequestParam Long companyId)
+    public AjaxResult changeCompanyUser(@RequestBody List<UserProjectDTO> users, @RequestParam Long companyUserId, @RequestParam Long companyId)
     {
-        return toAjax(companyUserService.changeCompanyUser(userIds, companyUserId, companyId));
+        return toAjax(companyUserService.changeCompanyUser(users, companyUserId, companyId));
     }
     /**
      * 根据登录的用户公司获取所有的销售

+ 12 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java

@@ -7,11 +7,13 @@ 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.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.BatchRedUpdate;
 import com.fs.course.param.BatchVideoSvae;
 import com.fs.course.param.CourseVideoUpdates;
+import com.fs.course.service.IFsUserCourseService;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.his.vo.OptionsVO;
 import com.github.pagehelper.PageHelper;
@@ -39,6 +41,8 @@ public class FsUserCourseVideoController extends BaseController
 
     @Autowired
     private FsUserCourseVideoMapper fsUserCourseVideoMapper;
+    @Autowired
+    private IFsUserCourseService fsUserCourseService;
 
     /**
      * 查询课堂视频列表
@@ -87,6 +91,10 @@ public class FsUserCourseVideoController extends BaseController
         if (count>0){
             return AjaxResult.error("课程排序重复");
         }
+
+        // 设置项目ID
+        FsUserCourse fsUserCourse = fsUserCourseService.selectFsUserCourseByCourseId(fsUserCourseVideo.getCourseId());
+        fsUserCourseVideo.setProjectId(fsUserCourse.getProject());
         return toAjax(fsUserCourseVideoService.insertFsUserCourseVideo(fsUserCourseVideo));
     }
 
@@ -134,6 +142,10 @@ public class FsUserCourseVideoController extends BaseController
     }
     @PostMapping("/batchSaveVideo")
     public R batchSaveVideo(@RequestBody BatchVideoSvae vo){
+        // 设置项目ID
+        FsUserCourse fsUserCourse = fsUserCourseService.selectFsUserCourseByCourseId(vo.getCourseId());
+        vo.setProjectId(fsUserCourse.getProject());
+
         fsUserCourseVideoService.batchSaveVideo(vo);
         return R.ok();
     }

+ 33 - 2
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -5,6 +5,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
@@ -12,6 +13,7 @@ import com.fs.common.exception.CustomException;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.his.domain.FsUserAddress;
 import com.fs.his.enums.FsUserIntegralLogTypeEnum;
 import com.fs.his.param.FsUserAddIntegralTemplateParam;
@@ -22,11 +24,13 @@ import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.FsUserExportListVO;
 import com.fs.his.vo.FsUserVO;
 import com.fs.his.vo.UserVo;
+import com.fs.qw.dto.UserProjectDTO;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.vo.h5.FsUserPageListVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -55,6 +59,7 @@ import static com.fs.his.utils.PhoneUtil.*;
  * @author fs
  * @date 2023-06-07
  */
+@Slf4j
 @RestController
 @RequestMapping("/his/user")
 public class FsUserController extends BaseController
@@ -63,6 +68,8 @@ public class FsUserController extends BaseController
     private IFsUserService fsUserService;
     @Autowired
     private IFsUserIntegralLogsService userIntegralLogsService;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
 
     /**
      * 查询用户列表
@@ -90,6 +97,18 @@ public class FsUserController extends BaseController
         return getDataTable(list);
     }
 
+    @PreAuthorize("@ss.hasPermi('his:user:list')")
+    @GetMapping("/listProject")
+    public TableDataInfo listProject(FsUser fsUser)
+    {
+        startPage();
+        List<FsUserVO> list = fsUserService.selectFsUserVOListByProject(fsUser);
+        for (FsUserVO vo : list){
+            vo.setPhone(ParseUtils.parsePhone(vo.getPhone()));
+        }
+        return getDataTable(list);
+    }
+
     /**
      * 导出用户列表
      */
@@ -181,6 +200,17 @@ public class FsUserController extends BaseController
         return toAjax(fsUserService.deleteFsUserByUserIds(userIds));
     }
 
+    /**
+     * 删除微信用户和销售关系信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:userCompanyUser:remove')")
+    @Log(title = "微信用户和销售关系", businessType = BusinessType.DELETE)
+    @DeleteMapping("/delete/{id}")
+    public AjaxResult delete(@PathVariable Long id)
+    {
+        return toAjax(userCompanyUserService.deleteFsUserCompanyUserById(id));
+    }
+
     /**
      * 查询用户
      */
@@ -224,8 +254,9 @@ public class FsUserController extends BaseController
     @PreAuthorize("@ss.hasPermi('his:user:enabledUsers')")
     @PostMapping("/enabledUsers")
     @ApiOperation("批量启用会员")
-    public ResponseResult<Boolean> enabledUsers(@RequestBody String[] ids) {
-        Boolean r = fsUserService.disabledUser(ids, true);
+    public ResponseResult<Boolean> enabledUsers(@RequestBody List<UserProjectDTO> ids) {
+        log.debug("批量启用会员 ids: {}", JSON.toJSONString(ids));
+        Boolean r = userCompanyUserService.batchUpdateUserProjectStatus(ids, 1);
         return ResponseResult.ok(r);
     }
 

+ 6 - 0
fs-company-app/src/main/java/com/fs/app/controller/AppBaseController.java

@@ -37,6 +37,12 @@ public class AppBaseController {
 		String userId = claims.getSubject().toString();
 		return userId;
 	}
+	public Long getCompanyUserId() {
+		String headValue =  ServletUtils.getRequest().getHeader("APPToken");
+		Claims claims=jwtUtils.getClaimByToken(headValue);
+		String userId = claims.getSubject();
+		return Long.parseLong(userId);
+	}
 	//获取商城手机号
 	public Long getUserId(Long companyUserId)
 	{

+ 29 - 12
fs-company-app/src/main/java/com/fs/app/controller/CompanyTagController.java

@@ -1,7 +1,9 @@
 package com.fs.app.controller;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.app.annotation.Login;
+import com.fs.app.param.TagProjectParam;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.StringUtils;
@@ -17,6 +19,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
@@ -41,8 +44,9 @@ public class CompanyTagController extends AppBaseController {
     @ApiOperation("查询公司标签列表")
     public R list(@RequestParam(required = false) String keyword,
                   @RequestParam(required = false, defaultValue = "1") Integer pageNum,
-                  @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
-        log.debug("查询公司标签列表 keyword: {}, pageNum: {}, pageSize: {}", keyword, pageNum, pageSize);
+                  @RequestParam(required = false, defaultValue = "10") Integer pageSize,
+                  @RequestParam(required = false) Long companyUserId) {
+        log.debug("查询公司标签列表 keyword: {}, pageNum: {}, pageSize: {}", keyword, pageNum, pageSize, companyUserId);
 
         Map<String, Object> params = new HashMap<>();
         params.put("companyId", getCompanyId());
@@ -51,13 +55,19 @@ public class CompanyTagController extends AppBaseController {
         }
 
         PageHelper.startPage(pageNum, pageSize);
-        List<CompanyTag> list = companyTagService.selectCompanyTagListByMap(params);
-        return R.ok().put("data", new PageInfo<>(list));
+        if (ObjectUtil.isNotEmpty(companyUserId)) {
+            params.put("companyUserId", companyUserId);
+            List<CompanyTag> list = companyTagService.selectCompanyTagByList(params);
+            return R.ok().put("data", new PageInfo<>(list));
+        } else {
+            List<CompanyTag> list = companyTagService.selectCompanyTagListByMap(params);
+            return R.ok().put("data", new PageInfo<>(list));
+        }
     }
 
-    /**
-     * 新增公司标签
-     */
+        /**
+         * 新增公司标签
+         */
     @Login
     @PostMapping("/add")
     @ApiOperation("新增公司标签")
@@ -81,13 +91,20 @@ public class CompanyTagController extends AppBaseController {
     }
 
     @Login
-    @GetMapping("/tagSubUsers")
+    @PostMapping("/tagSubUsers")
     @ApiOperation("标签下会员列表")
-    public R tagSubUsers(@RequestParam List<Long> tagId) {
+    public R tagSubUsers(@RequestBody TagProjectParam tagProjectParam) {
         Map<String, Object> params = new HashMap<>();
-        params.put("tagIds", tagId);
-        params.put("companyId", getCompanyId());
-        return R.ok().put("data", companyTagUserService.selectUserListByMap(params));
+        params.put("tagIds", tagProjectParam.getTagIds());
+        if (CollectionUtils.isNotEmpty(tagProjectParam.getProjectIds())){
+            params.put("projectIds", tagProjectParam.getProjectIds());
+        }
+        if (ObjectUtil.isEmpty(tagProjectParam.getCompanyUserId())){
+            params.put("companyUserId", getCompanyUserId());
+        }else {
+            params.put("companyUserId", tagProjectParam.getCompanyUserId());
+        }
+        return R.ok().put("data", companyTagUserService.selectUserByMap(params));
     }
 
     @Login

+ 100 - 17
fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java

@@ -1,13 +1,11 @@
 package com.fs.app.controller;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.app.annotation.Login;
-import com.fs.app.param.ChangeUserDeptAndPostParam;
-import com.fs.app.param.CompanyUserChangeApplyParam;
-import com.fs.app.param.CompanyUserParam;
-import com.fs.app.param.CompanyUserUpdateParam;
+import com.fs.app.param.*;
 import com.fs.app.service.IAppService;
 import com.fs.app.vo.CompanySubUserVO;
 import com.fs.common.annotation.RepeatSubmit;
@@ -18,14 +16,16 @@ import com.fs.common.utils.PatternUtils;
 import com.fs.common.utils.bean.BeanUtils;
 import com.fs.company.domain.*;
 import com.fs.company.mapper.CompanyRoleMapper;
-import com.fs.company.service.ICompanyDeptService;
-import com.fs.company.service.ICompanyService;
-import com.fs.company.service.ICompanyUserChangeApplyService;
-import com.fs.company.service.ICompanyUserService;
+import com.fs.company.service.*;
+import com.fs.company.vo.CompanyTagUserVO;
 import com.fs.company.vo.CompanyUserChangeApplyVO;
 import com.fs.core.security.SecurityUtils;
 import com.fs.course.service.IFsCourseRedPacketLogService;
 import com.fs.course.service.IFsCourseWatchLogService;
+import com.fs.course.service.IFsUserCompanyUserService;
+import com.fs.qw.dto.UserProjectDTO;
+import com.fs.system.service.ISysDictDataService;
+import com.fs.system.vo.DictVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
@@ -33,6 +33,8 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
@@ -57,6 +59,12 @@ public class CompanyUserController extends AppBaseController {
     private final ICompanyUserChangeApplyService companyUserChangeApplyService;
     private final CompanyRoleMapper companyRoleMapper;
     private final IAppService appService;
+    @Autowired
+    private ISysDictDataService dictDataService;
+    @Autowired
+    private IFsUserCompanyUserService fsUserCompanyUserService;
+    @Autowired
+    private ICompanyTagUserService companyTagUserService;
 
     @Login
     @ApiOperation("查询用户列表")
@@ -165,13 +173,18 @@ public class CompanyUserController extends AppBaseController {
     @ApiOperation("注册")
     @PostMapping("/resisterCompanyUser")
     public R resisterCompanyUser(@Valid @RequestBody CompanyUserParam param) {
-        Company company = companyService.selectCompanyById(param.getCompanyId());
+        CompanyUser upCompanyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());
+        if (Objects.isNull(upCompanyUser)) {
+            return R.error("邀请销售不存在");
+        }
+
+        Company company = companyService.selectCompanyById(upCompanyUser.getCompanyId());
         if (Objects.isNull(company)) {
             return R.error("公司不存在");
         }
 
         // 判断用户数量是否已达到上线
-        Integer count = companyUserService.selectCompanyUserCountByCompanyId(param.getCompanyId());
+        Integer count = companyUserService.selectCompanyUserCountByCompanyId(upCompanyUser.getCompanyId());
         if(count > company.getLimitUserCount()) {
             return R.error("用户数量已达到上限");
         }
@@ -195,9 +208,10 @@ public class CompanyUserController extends AppBaseController {
         companyUser.setPassword(SecurityUtils.encryptPassword(companyUser.getPassword()));
         companyUser.setCreateTime(new Date());
         companyUser.setIsAudit(0);
+        companyUser.setParentId(upCompanyUser.getUserId());
 
         // 部门
-        CompanyDept dept = companyDeptService.getDefaultCompanyDeptByCompanyId(param.getCompanyId());
+        CompanyDept dept = companyDeptService.getDefaultCompanyDeptByCompanyId(upCompanyUser.getCompanyId());
         if (Objects.nonNull(dept)) {
             companyUser.setDeptId(dept.getDeptId());
         }
@@ -221,7 +235,7 @@ public class CompanyUserController extends AppBaseController {
     @RepeatSubmit
     @ApiOperation("更换会员归属申请")
     @PostMapping("/changeUserParentApply")
-    public R changeVipUser(@Valid @RequestBody CompanyUserChangeApplyParam param) {
+    public R changeVipUser(@RequestBody CompanyUserChangeApplyParam param) {
         // 参数校验
         CompanyUser fromUser = companyUserService.selectCompanyUserById(param.getFrom());
         if (Objects.isNull(fromUser)) {
@@ -233,12 +247,18 @@ public class CompanyUserController extends AppBaseController {
             throw new ServiceException("申请更换归属销售不存在");
         }
 
+        if (Objects.equals(fromUser.getUserId(), toUser.getUserId())) {
+            throw new ServiceException("申请更换归属销售不能与原归属销售相同");
+        }
+
         if (param.getType() != 0 && param.getType() != 1) {
             throw new ServiceException("类型不正确");
         }
 
-        if (param.getType() == 1 && (Objects.isNull(param.getIds()) || param.getIds().isEmpty())) {
-            throw new ServiceException("请先选择会员");
+        if (param.getType() == 1 && (CollectionUtils.isEmpty(param.getIds()))
+                &&(CollectionUtils.isEmpty(param.getProject()))
+                &&(CollectionUtils.isEmpty(param.getTagList()))) {
+            throw new ServiceException("请先选择会员!");
         }
 
         // 存在待审核的申请不能再次申请
@@ -248,14 +268,58 @@ public class CompanyUserController extends AppBaseController {
         if (companyUserChangeApplyService.count(applyWrapper) > 0) {
             throw new ServiceException("存在待审核申请");
         }
-
         CompanyUser companyUser = companyUserService.selectCompanyUserById(Long.parseLong(getUserId()));
-
+        List<UserProjectDTO> list = param.getIds();
+        if(CollectionUtils.isEmpty(list)){
+            List<UserProjectDTO> userProjectDTOS = addUserId(param.getProject(),param.getTagList(),param.getFrom());
+            if (CollectionUtils.isNotEmpty(userProjectDTOS)){
+                list.addAll(userProjectDTOS);
+            }
+        }
         // 添加申请
-        companyUserChangeApplyService.apply(param.getFrom(), param.getTo(), param.getType(), param.getIds(), companyUser.getCompanyId(), companyUser.getUserName());
+        companyUserChangeApplyService.apply(param.getFrom(), param.getTo(), param.getType(),list, companyUser.getCompanyId(), companyUser.getUserName());
         return R.ok();
     }
 
+    /**
+     * 查询标签和项目中的会员添加
+     * @param tagList
+     * @param companyUserId
+     * @return
+     */
+    private List<UserProjectDTO> addUserId(List<Long> projects, List<Long> tagList, Long companyUserId) {
+        // Prepare parameters map
+        Map<String, Object> params = new HashMap<>();
+
+        if (CollectionUtils.isNotEmpty(projects)) {
+            params.put("projectIds", projects);
+        } else {
+            params.put("tagIds", tagList);
+        }
+
+        // Set company user ID
+        Long effectiveCompanyUserId = ObjectUtil.isNotEmpty(companyUserId)
+                ? companyUserId
+                : getCompanyUserId();
+        params.put("companyUserId", effectiveCompanyUserId);
+
+        // Get data from service
+        List<CompanyTagUserVO> voList = companyTagUserService.selectUserByMap(params);
+        if (CollectionUtils.isEmpty(voList)) {
+            return Collections.emptyList();
+        }
+
+        // Transform data
+        return voList.stream()
+                .map(vo -> {
+                    UserProjectDTO dto = new UserProjectDTO();
+                    dto.setUserId(vo.getUserId());
+                    dto.setProjectId(vo.getProjectId());
+                    return dto;
+                })
+                .collect(Collectors.toList());
+    }
+
     @Login
     @ApiOperation("申请列表")
     @GetMapping("/applyList")
@@ -309,4 +373,23 @@ public class CompanyUserController extends AppBaseController {
         appService.changeUserDeptAndPost(param);
         return R.ok();
     }
+
+    @ApiOperation("查询指定公司中存在会员的项目")
+    @PostMapping("/getDictByKeyByProject")
+    public R getDictByKey(
+            @RequestBody TagProjectParam tagProjectParam){
+        List<DictVO> dictVOS=dictDataService.selectDictDataListByType("sys_course_project");
+        Map<String,Object> param = new HashMap<>();
+        param.put("tagIds",tagProjectParam.getTagIds());
+        param.put("companyUserId",tagProjectParam.getCompanyUserId());
+        List<Long> projectIds =fsUserCompanyUserService.selectFsUserCompanyUserList(param);
+        if (CollectionUtils.isEmpty(projectIds)){
+            return R.ok().put("data",new ArrayList<DictVO>());
+        }
+
+        List<DictVO> filteredDictVOS = dictVOS.stream()
+                .filter(dictVO -> projectIds.contains(Long.parseLong(dictVO.getDictValue())))
+                .collect(Collectors.toList());
+        return R.ok().put("data",filteredDictVOS);
+    }
 }

+ 39 - 13
fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.app.annotation.Login;
 import com.fs.app.config.ImageStorageConfig;
+import com.fs.app.param.FsUserProjectUpdateParam;
 import com.fs.app.param.FsUserTagUpdateParam;
 import com.fs.app.param.FsUserUpdateParam;
 import com.fs.common.core.domain.R;
@@ -14,12 +15,15 @@ import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyTagUserService;
 import com.fs.company.service.ICompanyUserService;
+import com.fs.course.domain.FsUserCompanyUser;
 import com.fs.course.param.CourseAnalysisParam;
 import com.fs.course.param.newfs.FsUserCourseBeMemberImageParam;
 import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
+import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.course.vo.newfs.FsCourseAnalysisVO;
 import com.fs.his.domain.FsUser;
+import com.fs.his.service.IFsUserProjectTagService;
 import com.fs.his.service.IFsUserService;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.param.h5.TagListParam;
@@ -72,11 +76,16 @@ public class FsUserController extends AppBaseController {
 
     @Autowired
     private ISysConfigService configService;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
+    @Autowired
+    private IFsUserProjectTagService userProjectTagService;
 
     @Login
     @PostMapping("/pageList")
     @ApiOperation("用户会员分页列表")
     public ResponseResult<PageInfo<FsUserPageListVO>> pageList(@RequestBody FsUserPageListParam param) {
+        log.debug("用户会员分页列表 param: {}", JSON.toJSONString(param));
         param.setUserId(Long.parseLong(getUserId()));
 //        PageHelper.startPage(param.getPageNum(), param.getPageSize());
         PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
@@ -113,9 +122,14 @@ public class FsUserController extends AppBaseController {
     @GetMapping("/tagList")
     @ApiOperation("用户会员标签列表")
     public ResponseResult<PageInfo<CompanyUserTagListVO>> getTagList(TagListParam param) {
+        log.debug("用户会员标签列表 param: {}", JSON.toJSONString(param));
         param.setUserId(Long.parseLong(getUserId()));
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
-        List<CompanyUserTagListVO> tagList = companyTagUserService.getTagList(param);
+        List<CompanyUserTagListVO> tagList = userProjectTagService.getTagList(param);
+        CompanyUserTagListVO noTag = new CompanyUserTagListVO();
+        noTag.setTagId(0L);
+        noTag.setTagName("无标签");
+        tagList.add(0, noTag);
         PageInfo<CompanyUserTagListVO> pageInfo = new PageInfo<>(tagList);
         return ResponseResult.ok(pageInfo);
     }
@@ -123,22 +137,18 @@ public class FsUserController extends AppBaseController {
     @Login
     @PostMapping("/disabled")
     @ApiOperation("批量禁用会员")
-    public ResponseResult<Boolean> disabledUser(@ApiParam(value = "联系人id集合", required = true) @RequestBody String[] ids) {
-        Boolean r = fsUserService.disabledUser(ids, false);
+    public ResponseResult<Boolean> disabledUser(@ApiParam(value = "联系人id集合", required = true) @RequestBody List<Long> userCompanyUserIds) {
+        log.debug("批量禁用会员 ids: {}", JSON.toJSONString(userCompanyUserIds));
+        Boolean r = userCompanyUserService.batchUpdateStatus(userCompanyUserIds, 2);
         return ResponseResult.ok(r);
     }
 
     @Login
     @PostMapping("/enabled")
     @ApiOperation("批量启用会员")
-    public ResponseResult<Boolean> enabledUser(@ApiParam(value = "联系人id集合", required = true) @RequestBody String[] ids) {
-        // 如果存在重粉的数据,则禁止启用,需要提示
-        long companyUserId = Long.parseLong(getUserId());
-        Integer count = fsUserService.selectFsUserByUserIds(ids, companyUserId);
-        if(count > 0){
-            return ResponseResult.fail(400, "重粉会员不能移除小黑屋");
-        }
-        Boolean r = fsUserService.disabledUser(ids, true);
+    public ResponseResult<Boolean> enabledUser(@ApiParam(value = "联系人id集合", required = true) @RequestBody List<Long> userCompanyUserIds) {
+        log.debug("批量启用会员 ids: {}", JSON.toJSONString(userCompanyUserIds));
+        Boolean r = userCompanyUserService.batchUpdateStatus(userCompanyUserIds, 1);
         return ResponseResult.ok(r);
     }
 
@@ -260,11 +270,27 @@ public class FsUserController extends AppBaseController {
         return ResponseResult.ok();
     }
 
+    @Login
+    @ApiOperation("修改用户项目备注")
+    @PostMapping("/changeUserRemark")
+    public ResponseResult<Object> changeUserProjectRemark(@Valid @RequestBody FsUserProjectUpdateParam param) {
+        log.debug("修改用户备注 param:{}", JSON.toJSONString(param));
+        FsUserCompanyUser userCompanyUser = userCompanyUserService.selectFsUserCompanyUserById(param.getUserCompanyUserId());
+        if (Objects.isNull(userCompanyUser)) {
+            throw new ServiceException("用户不存在");
+        }
+
+        userCompanyUser.setRemark(param.getRemark());
+        userCompanyUserService.updateFsUserCompanyUser(userCompanyUser);
+        return ResponseResult.ok();
+    }
+
     @Login
     @ApiOperation("修改用户标签")
     @PostMapping("/changeUserTags")
     public ResponseResult<Object> changeUserTags(@Valid @RequestBody FsUserTagUpdateParam param) {
-        companyTagUserService.changeUserTags(param.getFsUserIds(), param.getTagIds());
+        log.debug("修改用户标签 param:{}", JSON.toJSONString(param));
+        userProjectTagService.addUserProjectTag(param.getUserCompanyUserIds(), param.getTagIds());
         return ResponseResult.ok();
     }
 
@@ -302,10 +328,10 @@ public class FsUserController extends AppBaseController {
         return ResponseResult.ok(fsUserService.companyUserSummaryCount(userId, companyUserId));
     }
 
-//    @Login
     @ApiOperation("会员关联绑定销售")
     @PostMapping("/beMember")
     public ResponseResult<Boolean> becomeMember(@Valid @RequestBody FsUserCourseBeMemberParam param) {
+        log.debug("会员关联绑定销售 param:{}", JSON.toJSONString(param));
         return fsUserService.becomeMember(param);
     }
 

+ 153 - 124
fs-company-app/src/main/java/com/fs/app/controller/WxCompanyUserController.java

@@ -11,14 +11,21 @@ import com.fs.app.param.LoginMaWxParam;
 import com.fs.app.utils.JwtUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.IpUtil;
 import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyDeptService;
+import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.core.config.WxMaConfiguration;
 import com.fs.course.config.CourseMaConfig;
+import com.fs.course.domain.FsUserCompanyUser;
+import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserWx;
 import com.fs.his.service.IFsUserService;
+import com.fs.his.service.IFsUserWxService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.wx.miniapp.config.WxMaProperties;
@@ -35,6 +42,9 @@ import org.springframework.web.bind.annotation.*;
 
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
+
+import static com.fs.his.utils.PhoneUtil.encryptPhone;
 
 @Api("微信小程序相关接口(暂废弃,后面再删除)")
 @RestController
@@ -43,164 +53,183 @@ import java.util.List;
 public class WxCompanyUserController extends AppBaseController {
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
-    @Autowired
-    private WxMaProperties maProperties;
-
     @Autowired
     JwtUtils jwtUtils;
-
-    @Autowired
-    RedisCache redisCache;
-
     @Autowired
     private ICompanyUserService companyUserService;
-
-    @Autowired
-    private ICompanyDeptService companyDeptService;
-
     @Autowired
     private IFsUserService userService;
-
     @Autowired
-    private SysConfigMapper sysConfigMapper;
+    private ICompanyService companyService;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
+    @Autowired
+    private IFsUserWxService fsUserWxService;
 
     @ApiOperation("小程序-授权登录")
     @PostMapping("/loginByMa")
     public R login(@RequestBody LoginMaWxParam param) {
+        log.info("=====================进入小程序授权登录, 入参: {}", param);
         if (StringUtils.isBlank(param.getCode())) {
             return R.error("code不存在");
         }
-        SysConfig sysConfig3 = sysConfigMapper.selectConfigByConfigKey("courseMa.config");
-        List<CourseMaConfig> courseMaConfigs = JSON.parseArray(sysConfig3.getConfigValue(), CourseMaConfig.class);
-        if (courseMaConfigs.isEmpty()){
-            return R.error("小程序配置为空");
+
+        // 特殊(需求设计:需要根据公司是否开启黑名单来设置会员初始化的状态)
+        Company company = companyService.selectCompanyById(param.getCompanyId());
+        if (company==null || company.getStatus()==0){
+            return R.error("注册失败团队已停用,或不存在!");
+        }
+
+        // 根据销售后台设置的  是否需要单独注册会员 来判断是否需要设置销售的值
+        CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());;
+        if(companyUser == null || companyUser.getStatus().equals("1")){
+            return R.error("注册失败客服已停用,或不存在!");
         }
-        CourseMaConfig courseMaConfig = courseMaConfigs.get(0);
-        //获取第二个小程序配置,序号从0开始
-        final WxMaService wxService = WxMaConfiguration.getMaService(courseMaConfig.getAppid());
+//        if (company.getCourseMiniAppId() == null) {
+//            return R.error("小程序参数错误!");
+//        }
+//        if (!param.getAppId().equals(company.getCourseMiniAppId())){
+//            return R.error("无权限,");
+//        }
+
+        final WxMaService wxService = WxMaConfiguration.getMaService(param.getAppId());
         try {
             WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
             this.logger.info(session.getSessionKey());
             this.logger.info(session.getOpenid());
-            // 解密
-            WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
-            WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
-
-            //以下暂时注释,不需要往销售表添加数据
-//            CompanyUser companyUser = companyUserService.getCompanyUserByOpenId(session.getOpenid());
-//            String ip = IpUtil.getRequestIp();
-//
-////            // 如果公司id为空(表示可能是该公司的第一位销售管理员),则需要根据电话号码判断是否存在销售,如果不存在则提示
-////            if (param.getCompanyId() == null) {
-////                if (checkPhone == null) {
-////                    throw new CustomException("由于不是管理员,不能直接登录", 401);
-////                }
-////            }
-//            if (companyUser == null) {
-//                CompanyUser checkPhone = companyUserService.getCompanyUserByPhone(phoneNoInfo.getPhoneNumber());
-//                if (checkPhone != null) {
-//                    if (checkPhone.getMaOpenId() == null) {
-//                        companyUser = checkPhone;
-//                        companyUser.setMaOpenId(session.getOpenid());
-//                        companyUser.setUserId(companyUser.getUserId());
-//                        companyUser.setUpdateTime(new DateTime());
-//                        companyUser.setLoginIp(ip);
-//                        companyUserService.updateUserProfile(companyUser);
-//                    } else {
-//                        throw new CustomException("此手机号用户已存在");
-//                    }
-//                } else {
-//                    //新增
-//                    companyUser = new CompanyUser();
-//                    companyUser.setUserName(phoneNoInfo.getPhoneNumber());
-//                    companyUser.setNickName(userInfo.getNickName() == null ? "微信用户" : userInfo.getNickName());
-//                    companyUser.setPhonenumber(phoneNoInfo.getPhoneNumber());
-//                    companyUser.setSex(userInfo.getGender());
-//                    //密码初始化为123456
-//                    String pw = "123456";
-//                    companyUser.setPassword(SecurityUtils.encryptPassword(param.getPassword() == null ? pw : param.getPassword()));
-//                    companyUser.setCreateTime(new Date());
-//                    companyUser.setCompanyId(param.getCompanyId());
-//                    companyUser.setParentId(param.getParentCompanyUseId());
-//                    companyUser.setMaOpenId(session.getOpenid());
-//
-//                    //部门信息
-//                    CompanyDept dept = companyDeptService.getDefaultCompanyDeptByCompanyId(param.getCompanyId());
-//                    if (Objects.nonNull(dept)) {
-//                        companyUser.setDeptId(dept.getDeptId());
-//                    }
-//                    companyUserService.insertUser(companyUser);
-//                }
-//            } else {
-//                CompanyUser companyUserMp = new CompanyUser();
-//                companyUserMp.setPhonenumber(phoneNoInfo.getPhoneNumber());
-//                companyUserMp.setUserId(companyUser.getUserId());
-//                companyUserMp.setUpdateTime(new DateTime());
-//                companyUserMp.setLoginIp(ip);
-//                companyUserService.updateUserProfile(companyUser);
-//            }
-
-            // 添加会员表数据
-            FsUser user = userService.selectFsUserByMpOpenId(session.getOpenid());
-            if (user != null) {
-                //修改
-                FsUser userMap = new FsUser();
-                userMap.setUserId(user.getUserId());
-                userMap.setMpOpenId(session.getOpenid());
-                userMap.setUnionId(session.getUnionid());
-                userMap.setUpdateTime(new DateTime());
-                userMap.setNickName(userInfo.getNickName() != null ? userInfo.getNickName() : "微信用户");
-                userMap.setAvatar(userInfo.getAvatarUrl() != null ? userInfo.getAvatarUrl() : null);
-                userMap.setPhone(phoneNoInfo.getPhoneNumber());
-                userService.updateFsUser(userMap);
-            } else {
-                //新增
-                user = new FsUser();
-                user.setNickName(userInfo.getNickName() != null ? userInfo.getNickName() : "微信用户");
-                user.setAvatar(userInfo.getAvatarUrl() != null ? userInfo.getAvatarUrl() : null);
-                user.setStatus(1);
-                user.setMpOpenId(session.getOpenid());
-                user.setUnionId(session.getUnionid());
-                user.setCreateTime(new Date());
-                user.setPhone(phoneNoInfo.getPhoneNumber());
-                userService.insertFsUser(user);
+            this.logger.info(session.getUnionid());
+            if (StringUtils.isEmpty(session.getOpenid())){
+                return R.error("登陆失败,openid未授权,请稍后再试!");
+            }
+
+            if (param.getAuthType() == 2 && StringUtils.isEmpty(session.getUnionid())){
+                return R.error("未绑定开发平台,请联系管理员!");
+            }
+
+            // 手机号信息
+            WxMaPhoneNumberInfo phoneNoInfo = new WxMaPhoneNumberInfo();;
+            if (param.getAuthType()==1){
+                phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
+                if (StringUtils.isEmpty(phoneNoInfo.getPhoneNumber())){
+                    return R.error("授权失败,请联系客服!");
+                }
+            }
+
+            FsUser user = getUserByAuthType(param, wxService, session, phoneNoInfo);
+
+            // 3. 处理用户注册或更新
+            String ip = IpUtil.getRequestIp();
+            user = handleUserRegisterOrUpdate(user, param, session, phoneNoInfo, company, companyUser, ip);
+
+            FsUserCompanyUser userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(user.getUserId(), param.getProjectId());
+            if (Objects.nonNull(userCompanyUser) && !param.getCompanyUserId().equals(userCompanyUser.getCompanyUserId())){
+                return R.error(500, "该用户("+user.getUserId() + ")已成为其他销售会员");
             }
-            log.info("保存成功的用户信息user: {}, 用户id: {}", user, user.getUserId());
+
+            // 4. 处理用户与小程序的绑定
+            handleFsUserWx(user, param, session);
+
+            log.info("保存成功的用户信息user: {}, 用户id: {},小程序AppId:{}", user, user.getUserId(), param.getAppId());
             String token = jwtUtils.generateToken(user.getUserId());
-            // 返回一个写死的数据到前端
-            return R.ok("登录成功").put("token", token).put("phoneNumber", phoneNoInfo.getPhoneNumber()).put("nickName", "微信用户").put("user", user);
+            // 返回TOKEN和user
+            return R.ok("登录成功").put("token", token).put("user", user);
         } catch (WxErrorException e) {
             this.logger.error(e.getMessage(), e);
             return R.error("授权失败," + e.getMessage());
         }
     }
 
-    @Login(isMiniLogin = true)
-    @ApiOperation("获取销售通过小程序登录后的用户信息")
-    @GetMapping("/getMaUser")
-    public R getUserInfo() {
-        try {
-            CompanyUser companyUser = companyUserService.selectCompanyUserById(Long.parseLong(getUserId()));
-            if (companyUser == null) {
-                return R.error(401, "用户信息不存在");
+    /**
+     * 根据authType获取用户信息
+     */
+    private FsUser getUserByAuthType(LoginMaWxParam param, WxMaService wxService, WxMaJscode2SessionResult session, WxMaPhoneNumberInfo phoneNoInfo) throws WxErrorException {
+        FsUser user = null;
+        if (param.getAuthType() == 1) {
+            user = userService.selectFsUserByPhone(encryptPhone(phoneNoInfo.getPhoneNumber()));
+        } else {
+            // unionid判定唯一
+            if (StringUtils.isNotEmpty(session.getUnionid())) {
+                user = userService.selectFsUserByUnionId(session.getUnionid());
             }
-            return R.ok().put("user", companyUser);
-        } catch (Exception e) {
-            return R.error("操作异常");
         }
+        return user;
     }
 
     /**
-     * 特殊要求:销售小程序临时登录,登录后页面中还有一个之前常用的登录,所以为了区分,token名称不能跟之前的一样
-     *
-     * @return 用户id
+     * 处理用户注册或更新
      */
-    public String getUserId() {
-        String headValue = ServletUtils.getRequest().getHeader("UserToken");
-        Claims claims = jwtUtils.getClaimByToken(headValue);
-        String userId = claims.getSubject().toString();
-        return userId;
+    private FsUser handleUserRegisterOrUpdate(FsUser user, LoginMaWxParam param, WxMaJscode2SessionResult session, WxMaPhoneNumberInfo phoneNoInfo, Company company, CompanyUser companyUser, String ip) {
+        if (user == null) {
+            return createUser(param, session, phoneNoInfo, company, companyUser);
+        } else {
+            return updateUser(user, param, session, phoneNoInfo, company, companyUser);
+        }
+    }
+
+    /**
+     * 新增用户
+     */
+    private FsUser createUser(LoginMaWxParam param, WxMaJscode2SessionResult session, WxMaPhoneNumberInfo phoneNoInfo, Company company, CompanyUser companyUser) {
+        FsUser user = new FsUser();
+        user.setStatus((company != null ? company.getFsUserIsDefaultBlack() : 0) == 1 ? 0 : 1);
+        user.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
+        user.setCreateTime(new Date());
+        if (param.getAuthType() == 1 && phoneNoInfo != null) {
+            user.setPhone(phoneNoInfo.getPhoneNumber());
+        }
+        userService.insertFsUser(user);
+
+        if((companyUser.getIsAllowedAllRegister() == null || companyUser.getIsAllowedAllRegister() == 1)
+                && companyUser.getIsNeedRegisterMember() != null && companyUser.getIsNeedRegisterMember() != 1){
+            int defaultStatus = (company != null ? company.getFsUserIsDefaultBlack() : 0) == 1 ? 0 : 1;
+            userCompanyUserService.bindRelationship(user.getUserId(), param.getProjectId(), companyUser.getCompanyId(), companyUser.getUserId(), defaultStatus);
+        }
+        return user;
     }
 
+    /**
+     * 修改用户
+     */
+    private FsUser updateUser(FsUser user, LoginMaWxParam param, WxMaJscode2SessionResult session, WxMaPhoneNumberInfo phoneNoInfo, Company company, CompanyUser companyUser) {
+        FsUser userMap = new FsUser();
+        userMap.setUserId(user.getUserId());
+        userMap.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
+        userMap.setUpdateTime(new DateTime());
+        if (param.getAuthType() == 1 && phoneNoInfo != null) {
+            userMap.setPhone(phoneNoInfo.getPhoneNumber());
+        }
 
+        userService.updateFsUser(userMap);
+        return userMap;
+    }
+
+    /**
+     * 处理用户与小程序的绑定
+     */
+    private void handleFsUserWx(FsUser user, LoginMaWxParam param, WxMaJscode2SessionResult session) {
+        if (user == null) return;
+        // 尝试更新
+        boolean updated = fsUserWxService.lambdaUpdate()
+                .eq(FsUserWx::getFsUserId, user.getUserId())
+                .eq(FsUserWx::getAppId, param.getAppId())
+                .eq(FsUserWx::getOpenId, session.getOpenid())
+                .set(FsUserWx::getCompanyId, param.getCompanyId())
+                .set(FsUserWx::getUnionId, session.getUnionid() == null ? "" : session.getUnionid())
+                .set(FsUserWx::getUpdateTime, new Date())
+                .update();
+
+        // 如果更新失败(记录不存在),则插入
+        if (!updated) {
+            FsUserWx fsUserWx = new FsUserWx();
+            fsUserWx.setType(1);
+            fsUserWx.setFsUserId(user.getUserId());
+            fsUserWx.setCompanyId(param.getCompanyId());
+            fsUserWx.setAppId(param.getAppId());
+            fsUserWx.setOpenId(session.getOpenid());
+            fsUserWx.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
+            fsUserWx.setCreateTime(new Date());
+            fsUserWx.setUpdateTime(new Date());
+            fsUserWxService.save(fsUserWx);
+        }
+    }
 }

+ 14 - 1
fs-company-app/src/main/java/com/fs/app/param/CompanyUserChangeApplyParam.java

@@ -1,5 +1,6 @@
 package com.fs.app.param;
 
+import com.fs.qw.dto.UserProjectDTO;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;
@@ -22,8 +23,20 @@ public class CompanyUserChangeApplyParam {
      */
     @NotNull(message = "类型不能为空")
     private Integer type;
+
+    /**
+     * 项目id
+     */
+    private List<Long> project;
+
+
+    /**
+     * 标签id
+     */
+    private List<Long> tagList;
+
     /**
      * 需更换归属会员id集合
      */
-    private List<Long> ids;
+    private List<UserProjectDTO> ids;
 }

+ 5 - 3
fs-company-app/src/main/java/com/fs/app/param/CompanyUserParam.java

@@ -1,5 +1,6 @@
 package com.fs.app.param;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import javax.validation.constraints.NotBlank;
@@ -9,10 +10,11 @@ import javax.validation.constraints.NotNull;
 public class CompanyUserParam {
 
     /**
-     * 公司ID
+     * 上级销售
      */
-    @NotNull(message = "公司ID不能为空")
-    private Long companyId;
+    @NotNull(message = "上级销售不能为空")
+    @ApiModelProperty("上级销售不能为空")
+    private Long companyUserId;
     /**
      * 手机号码
      */

+ 17 - 0
fs-company-app/src/main/java/com/fs/app/param/FsUserProjectUpdateParam.java

@@ -0,0 +1,17 @@
+package com.fs.app.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+public class FsUserProjectUpdateParam {
+
+    @ApiModelProperty("用户项目ID")
+    @NotNull(message = "用户项目ID不能为空")
+    private Long userCompanyUserId;
+
+    @ApiModelProperty("备注")
+    private String remark;
+}

+ 3 - 3
fs-company-app/src/main/java/com/fs/app/param/FsUserTagUpdateParam.java

@@ -11,9 +11,9 @@ public class FsUserTagUpdateParam {
     /**
      * 用户ID
      */
-    @ApiModelProperty("用户ID集合")
-    @NotEmpty(message = "用户ID不能为空")
-    private List<Long> fsUserIds;
+    @ApiModelProperty("用户项目ID集合")
+    @NotEmpty(message = "用户项目ID不能为空")
+    private List<Long> userCompanyUserIds;
     /**
      * 标签ID
      */

+ 22 - 0
fs-company-app/src/main/java/com/fs/app/param/LoginMaWxParam.java

@@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
 import java.io.Serializable;
 
 @Data
@@ -19,6 +20,18 @@ public class LoginMaWxParam implements Serializable {
     @ApiModelProperty(value = "小程序加密算法的初始向量")
     private String iv;
 
+    @NotNull(message = "公司id不能为空")
+    @ApiModelProperty(value = "公司id")
+    private Long companyId;
+
+    @NotNull(message = "销售id不能为空")
+    @ApiModelProperty(value = "销售id")
+    private Long companyUserId;
+
+    @NotNull(message = "项目id不能为空")
+    @ApiModelProperty(value = "课程归属项目id")
+    private Long projectId;
+
 //    @ApiModelProperty(value = "公司id,如果不是第一位销售,都需要传")
 //    private Long companyId;
 
@@ -31,4 +44,13 @@ public class LoginMaWxParam implements Serializable {
 //    @ApiModelProperty(value = "用户密码")
 //    private String password;
 
+    /**
+     * 0:静默授权  1:手机号授权
+     */
+    @NotNull(message = "授权类型缺失")
+    @ApiModelProperty(value = "小程序授权类型")
+    private Integer authType;
+
+    private String appId;
+
 }

+ 23 - 0
fs-company-app/src/main/java/com/fs/app/param/TagProjectParam.java

@@ -0,0 +1,23 @@
+package com.fs.app.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class TagProjectParam {
+    /**
+     * 销售id
+     */
+    private Long companyUserId;
+
+    /**
+     * 标签id
+     */
+    private List<Long> tagIds;
+
+    /**
+     * 项目id
+     */
+    private List<Long> projectIds;
+}

+ 10 - 2
fs-company/src/main/java/com/fs/company/controller/store/FsUserController.java

@@ -1,5 +1,6 @@
 package com.fs.company.controller.store;
 
+import com.alibaba.fastjson.JSON;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -9,6 +10,7 @@ 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.course.service.IFsUserCompanyUserService;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.security.SecurityUtils;
 import com.fs.framework.service.TokenService;
@@ -19,11 +21,13 @@ import com.fs.his.service.IFsUserService;
 import com.fs.his.vo.FsUserExportListVO;
 import com.fs.his.vo.FsUserVO;
 import com.fs.his.vo.UserVo;
+import com.fs.qw.dto.UserProjectDTO;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.vo.h5.FsUserPageListVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -41,6 +45,7 @@ import static com.fs.his.utils.PhoneUtil.encryptPhone;
  * @author fs
  * @date 2023-06-07
  */
+@Slf4j
 @RestController
 @RequestMapping("/store/user")
 public class FsUserController extends BaseController
@@ -49,6 +54,8 @@ public class FsUserController extends BaseController
     private IFsUserService fsUserService;
     @Autowired
     private TokenService tokenService;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
 
     /**
      * 查询用户列表
@@ -247,8 +254,9 @@ public class FsUserController extends BaseController
     @PreAuthorize("@ss.hasPermi('users:user:enabledUsers')")
     @PostMapping("/enabledUsers")
     @ApiOperation("批量启用会员")
-    public ResponseResult<Boolean> enabledUsers(@RequestBody String[] ids) {
-        Boolean r = fsUserService.disabledUser(ids, true);
+    public ResponseResult<Boolean> enabledUsers(@RequestBody List<UserProjectDTO> ids) {
+        log.debug("批量启用会员 ids: {}", JSON.toJSONString(ids));
+        Boolean r = userCompanyUserService.batchUpdateUserProjectStatus(ids, 1);
         return ResponseResult.ok(r);
     }
 

+ 21 - 0
fs-service/src/main/java/com/fs/company/domain/CompanyUser.java

@@ -151,9 +151,30 @@ public class CompanyUser extends BaseEntity
     /** 用户上级id */
     private Long parentId;
 
+    /** 微信小程序OPENID(如果有小程序授权) */
+    private String  maOpenId;
+
     /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
     private Integer isNeedRegisterMember;
 
+    /** 是否允许所有方式注册会员,1-是,0-否,默认1(用于个微注册会员) */
+    private Integer isAllowedAllRegister;
+
+    public String getMaOpenId() {
+        return maOpenId;
+    }
+
+    public void setMaOpenId(String maOpenId) {
+        this.maOpenId = maOpenId;
+    }
+
+    public Integer getIsAllowedAllRegister() {
+        return isAllowedAllRegister;
+    }
+
+    public void setIsAllowedAllRegister(Integer isAllowedAllRegister) {
+        this.isAllowedAllRegister = isAllowedAllRegister;
+    }
 
     public Long getParentId() {
         return parentId;

+ 4 - 0
fs-service/src/main/java/com/fs/company/domain/CompanyUserChangeApplyUser.java

@@ -21,4 +21,8 @@ public class CompanyUserChangeApplyUser {
      * 用户ID
      */
     private Long userId;
+    /**
+     * 项目ID
+     */
+    private Long projectId;
 }

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

@@ -80,4 +80,6 @@ public interface CompanyTagMapper
     String findUserTagByUserId(@Param("userId") Long userId,@Param("companyUserId") Long companyUserId);
     @MapKey("tagId")
     Map<Long,CompanyTag> queryAllTagMap();
+
+    List<CompanyTag> selectCompanyTagByList(@Param("params") Map<String, Object> params);
 }

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

@@ -81,4 +81,6 @@ public interface CompanyTagUserMapper
     void deleteCompanyTagUserByMap(@Param("params") Map<String, Object> params);
 
     List<CompanyUserTagListVO> getTagByUser(@Param("params")CompanyTagUser param);
+
+    List<CompanyTagUserVO> selectUserByMap(@Param("params") Map<String, Object> params);
 }

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

@@ -77,4 +77,6 @@ public interface ICompanyTagService
     Map<Long,CompanyTag> queryAllTagMap();
 
     String findUserTagByUserId(Long userId,Long companyUserId);
+
+    List<CompanyTag> selectCompanyTagByList(Map<String, Object> params);
 }

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

@@ -91,4 +91,9 @@ public interface ICompanyTagUserService
      * @return
      */
     List<CompanyUserTagListVO> getTagByUser(CompanyTagUser param);
+
+    /**
+     * 根据条件查询标签下用户
+     */
+    List<CompanyTagUserVO> selectUserByMap(Map<String, Object> params);
 }

+ 2 - 1
fs-service/src/main/java/com/fs/company/service/ICompanyUserChangeApplyService.java

@@ -3,6 +3,7 @@ package com.fs.company.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.company.domain.CompanyUserChangeApply;
 import com.fs.company.vo.CompanyUserChangeApplyVO;
+import com.fs.qw.dto.UserProjectDTO;
 
 import java.util.List;
 import java.util.Map;
@@ -19,7 +20,7 @@ public interface ICompanyUserChangeApplyService extends IService<CompanyUserChan
      * @param companyId 公司ID
      * @param userName  操作用户
      */
-    void apply(Long from, Long to, Integer type, List<Long> ids, Long companyId, String userName);
+    void apply(Long from, Long to, Integer type, List<UserProjectDTO> ids, Long companyId, String userName);
 
     /**
      * 查询申请列表

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

@@ -10,6 +10,7 @@ import com.fs.company.vo.CompanyUserVO;
 import com.fs.company.vo.DocCompanyUserVO;
 import com.fs.his.vo.CitysAreaVO;
 import com.fs.his.vo.OptionsVO;
+import com.fs.qw.dto.UserProjectDTO;
 import com.fs.qw.vo.CompanyUserQwVO;
 import com.fs.qw.vo.QwOptionsVO;
 import com.fs.qw.vo.QwUserVO;
@@ -174,10 +175,10 @@ public interface ICompanyUserService {
 
     /**
      * 更改会员归属
-     * @param userIds
+     * @param users 需更换归属会员
      * @return
      */
-    int changeCompanyUser(List<Long> userIds, Long companyUserId, Long companyId);
+    int changeCompanyUser(List<UserProjectDTO> users, Long companyUserId, Long companyId);
 
     /**
      * 查询销售选项列表

+ 11 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyTagServiceImpl.java

@@ -7,6 +7,7 @@ import com.fs.company.service.ICompanyTagService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -126,4 +127,14 @@ public class CompanyTagServiceImpl implements ICompanyTagService
     public String findUserTagByUserId(Long key,Long companyUserId) {
         return companyTagMapper.findUserTagByUserId(key,companyUserId);
     }
+
+    /**
+     * 查询标签列表
+     * @param params 条件
+     * @return list
+     */
+    @Override
+    public List<CompanyTag> selectCompanyTagByList(Map<String, Object> params) {
+        return companyTagMapper.selectCompanyTagByList(params);
+    }
 }

+ 23 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyTagUserServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.company.service.impl;
 
+import com.fs.common.core.domain.entity.SysDictData;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyTagUser;
@@ -12,6 +13,7 @@ import com.fs.his.domain.FsUser;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.store.param.h5.TagListParam;
 import com.fs.store.vo.h5.CompanyUserTagListVO;
+import com.fs.system.mapper.SysDictDataMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -35,6 +37,8 @@ public class CompanyTagUserServiceImpl implements ICompanyTagUserService
     private CompanyUserMapper  companyUserMapper;
     @Autowired
     private FsUserMapper fsUserMapper;
+    @Autowired
+    private SysDictDataMapper dictDataMapper;
 
     /**
      * 查询company
@@ -187,4 +191,23 @@ public class CompanyTagUserServiceImpl implements ICompanyTagUserService
 
         return companyTagUserMapper.getTagByUser(param);
     }
+
+    /**
+     * 根据条件查询标签下用户
+     * @param params    条件
+     * @return  list
+     */
+    @Override
+    public List<CompanyTagUserVO> selectUserByMap(Map<String, Object> params) {
+        List<CompanyTagUserVO> companyTagUserVOS = companyTagUserMapper.selectUserByMap(params);
+
+        // 项目
+        List<SysDictData> courseProject = dictDataMapper.selectDictDataByType("sys_course_project");
+        companyTagUserVOS.forEach(vo -> courseProject.stream()
+                .filter(c -> c.getDictValue().equals(vo.getProjectId().toString()))
+                .findFirst()
+                .ifPresent(c -> vo.setUserName(vo.getUserName() + "-" + (c.getDictLabel()))));
+
+        return companyTagUserVOS;
+    }
 }

+ 14 - 9
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserChangeApplyServiceImpl.java

@@ -8,8 +8,11 @@ import com.fs.company.mapper.CompanyUserChangeApplyMapper;
 import com.fs.company.service.ICompanyUserChangeApplyService;
 import com.fs.company.service.ICompanyUserChangeApplyUserService;
 import com.fs.company.vo.CompanyUserChangeApplyVO;
+import com.fs.course.domain.FsUserCompanyUser;
+import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.his.domain.FsUser;
 import com.fs.his.mapper.FsUserMapper;
+import com.fs.qw.dto.UserProjectDTO;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -25,7 +28,7 @@ import java.util.Objects;
 public class CompanyUserChangeApplyServiceImpl extends ServiceImpl<CompanyUserChangeApplyMapper, CompanyUserChangeApply> implements ICompanyUserChangeApplyService {
 
     private final ICompanyUserChangeApplyUserService companyUserChangeApplyUserService;
-    private final FsUserMapper userMapper;
+    private final IFsUserCompanyUserService userCompanyUserService;
 
     /**
      * 申请更换会员归属
@@ -39,30 +42,32 @@ public class CompanyUserChangeApplyServiceImpl extends ServiceImpl<CompanyUserCh
      */
     @Transactional(rollbackFor = Exception.class)
     @Override
-    public void apply(Long from, Long to, Integer type, List<Long> ids, Long companyId, String userName) {
+    public void apply(Long from, Long to, Integer type, List<UserProjectDTO> ids, Long companyId, String userName) {
         List<CompanyUserChangeApplyUser> users = new ArrayList<>();
 
         // 全部
         if (type == 0) {
-            FsUser param = new FsUser();
-            param.setCompanyUserId(from);
-            List<FsUser> userList = userMapper.selectFsUserList(param);
-            for (FsUser user : userList) {
+            FsUserCompanyUser params = new FsUserCompanyUser();
+            params.setCompanyUserId(from);
+            List<FsUserCompanyUser> userList = userCompanyUserService.selectFsUserCompanyUserList(params);
+            for (FsUserCompanyUser user : userList) {
                 CompanyUserChangeApplyUser uu = new CompanyUserChangeApplyUser();
                 uu.setUserId(user.getUserId());
+                uu.setProjectId(user.getProjectId());
                 users.add(uu);
             }
         }
         // 部分
         else {
-            for (Long id : ids) {
-                FsUser user = userMapper.selectFsUserById(id);
+            for (UserProjectDTO id : ids) {
+                FsUserCompanyUser user = userCompanyUserService.selectByUserIdAndProjectId(id.getUserId(), id.getProjectId());
                 if (Objects.isNull(user)) {
-                    throw new ServiceException("会员不存在");
+                    throw new ServiceException("会员关系不存在");
                 }
 
                 CompanyUserChangeApplyUser uu = new CompanyUserChangeApplyUser();
                 uu.setUserId(user.getUserId());
+                uu.setProjectId(user.getProjectId());
                 users.add(uu);
             }
         }

+ 9 - 2
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -17,10 +17,12 @@ import com.fs.company.vo.CompanyQwUserByIdsVo;
 import com.fs.company.vo.CompanyUserQwListVO;
 import com.fs.company.vo.CompanyUserVO;
 import com.fs.company.vo.DocCompanyUserVO;
+import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.service.IFsCityService;
 import com.fs.his.vo.CitysAreaVO;
 import com.fs.his.vo.OptionsVO;
+import com.fs.qw.dto.UserProjectDTO;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.vo.CompanyUserQwVO;
 import com.fs.qw.vo.QwOptionsVO;
@@ -75,6 +77,8 @@ public class CompanyUserServiceImpl implements ICompanyUserService
 
     @Autowired
     private FsUserMapper fsUserMapper;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
 
     /**
      * 查询物业公司管理员信息
@@ -491,13 +495,16 @@ public class CompanyUserServiceImpl implements ICompanyUserService
     }
 
     @Override
-    public int changeCompanyUser(List<Long> userIds, Long companyUserId, Long companyId) {
+    public int changeCompanyUser(List<UserProjectDTO> users, Long companyUserId, Long companyId) {
 
         CompanyUser toUser = companyUserMapper.selectCompanyUserById(companyUserId);
         if (Objects.isNull(toUser)) {
             throw new ServiceException("需要更换归属的销售不存在");
         }
-        return fsUserMapper.batchUpdateUserCompanyUser(userIds, companyUserId, companyId);
+        for (UserProjectDTO u : users) {
+            userCompanyUserService.changeRelationship(u.getUserId(), u.getProjectId(), toUser.getCompanyId(), toUser.getUserId());
+        }
+        return 1;
     }
 
     /**

+ 4 - 0
fs-service/src/main/java/com/fs/company/vo/CompanyTagUserVO.java

@@ -12,4 +12,8 @@ public class CompanyTagUserVO {
      * 用户昵称
      */
     private String userName;
+    /**
+     * 项目ID
+     */
+    private Long projectId;
 }

+ 18 - 4
fs-service/src/main/java/com/fs/course/domain/FsUserCompanyUser.java

@@ -1,11 +1,13 @@
 package com.fs.course.domain;
 
+import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.fs.common.annotation.Excel;
-import com.fs.common.core.domain.BaseEntity;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
 
 /**
  * 微信用户和销售关系对象 fs_user_company_user
@@ -14,10 +16,10 @@ import lombok.EqualsAndHashCode;
  * @date 2025-05-09
  */
 @Data
-@EqualsAndHashCode(callSuper = true)
-public class FsUserCompanyUser extends BaseEntity{
+public class FsUserCompanyUser {
 
     /** id */
+    @TableId(type = IdType.AUTO)
     private Long id;
 
     /** 用户id(关联fs_user表user_id) */
@@ -56,6 +58,18 @@ public class FsUserCompanyUser extends BaseEntity{
      * 企微主体ID
      */
     private Long qwCompanyId;
+    /**
+     * 状态 0小黑屋 1正常 2拉黑
+     */
+    private Integer status;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
 
 
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCourseVideo.java

@@ -98,4 +98,10 @@ public class FsUserCourseVideo extends BaseEntity
     @JsonFormat(pattern = "HH:mm:ss")
     private LocalTime lastJoinTime;
 
+    private Long userId;
+
+    /**
+     * 项目ID
+     */
+    private Long projectId;
 }

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

@@ -398,7 +398,7 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
 
     void batchUpdateFsUserWatchLog(@Param("list") List<FsCourseWatchLog> list);
 
-    @Select("select * from fs_course_watch_log where user_id = #{userId} and video_id = #{videoId} and send_type = 1")
+    @Select("select * from fs_course_watch_log where user_id = #{userId} and video_id = #{videoId} and send_type = 1 order by log_id desc limit 1")
     FsCourseWatchLog getCourseWatchLogByUser(@Param("userId") Long userId, @Param("videoId") Long videoId);
 
     /**

+ 14 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCompanyUserMapper.java

@@ -3,10 +3,12 @@ package com.fs.course.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.course.domain.FsUserCompanyUser;
 import com.fs.qw.dto.FsUserTransferParamDTO;
+import com.fs.qw.dto.UserProjectDTO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 微信用户和销售关系Mapper接口
@@ -79,4 +81,16 @@ public interface FsUserCompanyUserMapper extends BaseMapper<FsUserCompanyUser>{
     List<FsUserCompanyUser> selectRepeatCompanyUserName(@Param("userIds") List<Long> userIds);
 
     void transfer(@Param("param") FsUserTransferParamDTO transferParam);
+
+    /**
+     * 批量修改用户-项目状态
+     * @param ids       参数
+     * @param status    状态
+     * @return  count
+     */
+    int changeUserProjectStatus(@Param("ids") List<UserProjectDTO> ids, @Param("status") int status);
+
+    int batchUpdateStatus(@Param("ids") List<Long> ids, @Param("status") int status);
+
+    List<Long> selectFsUserCompanyUserListByMap(@Param("param") Map<String, Object> param);
 }

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

@@ -8,4 +8,7 @@ import java.util.List;
 public class BatchVideoSvae {
     private Long courseId;
     private List<Long> ids;
+
+    // 项目ID
+    private Long projectId;
 }

+ 1 - 3
fs-service/src/main/java/com/fs/course/param/newfs/FsUserCourseBeMemberParam.java

@@ -24,9 +24,7 @@ public class FsUserCourseBeMemberParam implements Serializable {
     @ApiModelProperty(value = "标签ids,数组格式")
     private String[] tagIds;
 
-//    @NotNull(message = "项目id不能为空")
+    @NotNull(message = "项目id不能为空")
     @ApiModelProperty(value = "课程归属项目id")
     private Long projectId;
-
-
 }

+ 35 - 7
fs-service/src/main/java/com/fs/course/service/IFsUserCompanyUserService.java

@@ -2,8 +2,10 @@ package com.fs.course.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.course.domain.FsUserCompanyUser;
+import com.fs.qw.dto.UserProjectDTO;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 微信用户和销售关系Service接口
@@ -14,7 +16,7 @@ import java.util.List;
 public interface IFsUserCompanyUserService extends IService<FsUserCompanyUser>{
     /**
      * 查询微信用户和销售关系
-     * 
+     *
      * @param id 微信用户和销售关系主键
      * @return 微信用户和销售关系
      */
@@ -22,15 +24,22 @@ public interface IFsUserCompanyUserService extends IService<FsUserCompanyUser>{
 
     /**
      * 查询微信用户和销售关系列表
-     * 
+     *
      * @param fsUserCompanyUser 微信用户和销售关系
      * @return 微信用户和销售关系集合
      */
     List<FsUserCompanyUser> selectFsUserCompanyUserList(FsUserCompanyUser fsUserCompanyUser);
 
+    /**
+     * 根据销售id查询出项目id
+     * @param param
+     * @return
+     */
+    List<Long> selectFsUserCompanyUserList(Map<String,Object> param );
+
     /**
      * 新增微信用户和销售关系
-     * 
+     *
      * @param fsUserCompanyUser 微信用户和销售关系
      * @return 结果
      */
@@ -38,7 +47,7 @@ public interface IFsUserCompanyUserService extends IService<FsUserCompanyUser>{
 
     /**
      * 修改微信用户和销售关系
-     * 
+     *
      * @param fsUserCompanyUser 微信用户和销售关系
      * @return 结果
      */
@@ -46,7 +55,7 @@ public interface IFsUserCompanyUserService extends IService<FsUserCompanyUser>{
 
     /**
      * 批量删除微信用户和销售关系
-     * 
+     *
      * @param ids 需要删除的微信用户和销售关系主键集合
      * @return 结果
      */
@@ -54,11 +63,12 @@ public interface IFsUserCompanyUserService extends IService<FsUserCompanyUser>{
 
     /**
      * 删除微信用户和销售关系信息
-     * 
+     *
      * @param id 微信用户和销售关系主键
      * @return 结果
      */
     int deleteFsUserCompanyUserById(Long id);
+
     /**
      * 根据用户ID和项目ID查询微信用户与销售的关系
      * @param userId            用户ID
@@ -91,12 +101,14 @@ public interface IFsUserCompanyUserService extends IService<FsUserCompanyUser>{
 
     /**
      * 绑定会员-项目-销售关系
+     *
      * @param userId        会员ID
      * @param projectId     项目ID
      * @param companyId     公司ID
      * @param companyUserId 销售ID
+     * @param status        状态 1正常 0小黑屋
      */
-    void bindRelationship(Long userId, Long projectId, Long companyId, Long companyUserId);
+    FsUserCompanyUser bindRelationship(Long userId, Long projectId, Long companyId, Long companyUserId, int status);
 
     /**
      * 修改会员-项目-销售关系
@@ -106,4 +118,20 @@ public interface IFsUserCompanyUserService extends IService<FsUserCompanyUser>{
      * @param companyUserId 销售ID
      */
     void changeRelationship(Long userId, Long projectId, Long companyId, Long companyUserId);
+
+    /**
+     * 修改会员-项目关系 状态
+     * @param ids       参数
+     * @param status    状态 0小黑屋 1正常 2拉黑
+     * @return Boolean
+     */
+    Boolean batchUpdateUserProjectStatus(List<UserProjectDTO> ids, int status);
+
+    /**
+     * 修改会员-项目关系 状态
+     * @param ids       参数
+     * @param status    状态 0小黑屋 1正常 2拉黑
+     * @return Boolean
+     */
+    Boolean batchUpdateStatus(List<Long> ids, int status);
 }

+ 58 - 9
fs-service/src/main/java/com/fs/course/service/impl/FsUserCompanyUserServiceImpl.java

@@ -3,12 +3,16 @@ package com.fs.course.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.exception.CustomException;
 import com.fs.course.domain.FsUserCompanyUser;
 import com.fs.course.mapper.FsUserCompanyUserMapper;
 import com.fs.course.service.IFsUserCompanyUserService;
+import com.fs.qw.dto.UserProjectDTO;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -22,7 +26,7 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
 
     /**
      * 查询微信用户和销售关系
-     * 
+     *
      * @param id 微信用户和销售关系主键
      * @return 微信用户和销售关系
      */
@@ -34,7 +38,7 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
 
     /**
      * 查询微信用户和销售关系列表
-     * 
+     *
      * @param fsUserCompanyUser 微信用户和销售关系
      * @return 微信用户和销售关系
      */
@@ -44,9 +48,18 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
         return baseMapper.selectFsUserCompanyUserList(fsUserCompanyUser);
     }
 
+    /**
+     * 根据销售id查询出项目id
+     * @return 微信用户和销售关系
+     */
+    @Override
+    public List<Long> selectFsUserCompanyUserList(Map<String,Object> param) {
+
+        return baseMapper.selectFsUserCompanyUserListByMap(param);
+    }
     /**
      * 新增微信用户和销售关系
-     * 
+     *
      * @param fsUserCompanyUser 微信用户和销售关系
      * @return 结果
      */
@@ -58,7 +71,7 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
 
     /**
      * 修改微信用户和销售关系
-     * 
+     *
      * @param fsUserCompanyUser 微信用户和销售关系
      * @return 结果
      */
@@ -70,7 +83,7 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
 
     /**
      * 批量删除微信用户和销售关系
-     * 
+     *
      * @param ids 需要删除的微信用户和销售关系主键
      * @return 结果
      */
@@ -82,7 +95,7 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
 
     /**
      * 删除微信用户和销售关系信息
-     * 
+     *
      * @param id 微信用户和销售关系主键
      * @return 结果
      */
@@ -142,21 +155,27 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
 
     /**
      * 绑定会员-项目-销售关系
+     *
      * @param userId        会员ID
      * @param projectId     项目ID
      * @param companyId     公司ID
      * @param companyUserId 销售ID
+     * @param status        状态 0小黑屋 1正常
      */
     @Override
-    public void bindRelationship(Long userId, Long projectId, Long companyId, Long companyUserId) {
+    public FsUserCompanyUser bindRelationship(Long userId, Long projectId, Long companyId, Long companyUserId, int status) {
         FsUserCompanyUser userCompanyUser = new FsUserCompanyUser();
         userCompanyUser.setUserId(userId);
         userCompanyUser.setProjectId(projectId);
         userCompanyUser.setCompanyId(companyId);
         userCompanyUser.setCompanyUserId(companyUserId);
-        boolean hasBind = hasBind(userId, companyUserId);
-        userCompanyUser.setIsRepeatFans(hasBind ? 1 : 0);
+//        boolean hasBind = hasBind(userId, companyUserId);
+//        userCompanyUser.setIsRepeatFans(hasBind ? 1 : 0);
+        userCompanyUser.setIsRepeatFans(0);
+        userCompanyUser.setStatus(status);
+        userCompanyUser.setCreateTime(LocalDateTime.now());
         save(userCompanyUser);
+        return userCompanyUser;
     }
 
     /**
@@ -179,4 +198,34 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
             updateById(userCompanyUser);
         }
     }
+
+    /**
+     * 修改会员-项目关系 状态
+     * @param ids       参数
+     * @param status    状态 0小黑屋 1正常 2拉黑
+     * @return Boolean
+     */
+    @Override
+    public Boolean batchUpdateUserProjectStatus(List<UserProjectDTO> ids, int status) {
+        if (Objects.isNull(ids) || ids.isEmpty()) {
+            throw new CustomException("请先选择会员");
+        }
+        return baseMapper.changeUserProjectStatus(ids, status) > 0;
+    }
+
+
+
+    /**
+     * 修改会员-项目关系 状态
+     * @param ids       参数
+     * @param status    状态 0小黑屋 1正常 2拉黑
+     * @return Boolean
+     */
+    @Override
+    public Boolean batchUpdateStatus(List<Long> ids, int status) {
+        if (Objects.isNull(ids) || ids.isEmpty()) {
+            throw new CustomException("请先选择会员");
+        }
+        return baseMapper.batchUpdateStatus(ids, status) > 0;
+    }
 }

+ 22 - 13
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -29,6 +29,7 @@ import com.fs.course.dto.CoursePackageDTO;
 import com.fs.course.mapper.*;
 import com.fs.course.param.*;
 import com.fs.course.param.newfs.*;
+import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.service.IFsVideoResourceService;
 import com.fs.course.vo.FsCourseVideoListBySidebarVO;
@@ -199,6 +200,8 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     private CompanyMapper companyMapper;
     @Autowired
     private IFsUserWxService fsUserWxService;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
 
 
     /**
@@ -1399,7 +1402,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Override
     @Transactional
     public ResponseResult<Boolean> isAddCompanyUser(FsUserCourseAddCompanyUserParam param) {
-        logger.info("=======================进入个微-判断是否添加客服===========================,入参:{}",param);
+        logger.info("\n 【进入个微-判断是否添加客服】,入参:{}",param);
         //查询用户
         FsUser fsUser = fsUserMapper.selectFsUserById(param.getUserId());
         if (fsUser == null){
@@ -1415,19 +1418,24 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         //判断:1、如果没有绑定销售,就返回给客服的微信图片;
         //2、如果只绑定了当前销售,需要添加看课记录(正常流程);
         //3、以上都不是,则标识重粉,需要加入关系表,并打上重粉标签
-        if(fsUser.getCompanyUserId() == null) {
+        FsUserCompanyUser userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(fsUser.getUserId(), param.getProjectId());
+        if(Objects.isNull(userCompanyUser)) {
             return ResponseResult.fail(BizResponseEnum.DATA_NOT_EXIST, getCompanyUserQRCode(companyUser));
         }
 
         // 逻辑调整:如果会员已经绑定了销售,直接提示,不添加重粉数据了-2025年6月16日14点53分
-        if (!param.getCompanyUserId().equals(fsUser.getCompanyUserId())){
-            return ResponseResult.fail(406,"该用户已成为其他销售会员");
+        if (!param.getCompanyUserId().equals(userCompanyUser.getCompanyUserId())){
+            return ResponseResult.fail(500,"该用户("+fsUser.getUserId() + ")已成为其他销售会员");
         }
 
         // 如果开启了黑名单审核,需要提示
-        if(fsUser.getStatus() == 0) {
-            return ResponseResult.fail(505, "请微信联系您的群主~");
-//            return ResponseResult.fail(BizResponseEnum.WAIT_APPROVAL,getCompanyUserQRCode(companyUser));
+        if(userCompanyUser.getStatus() == 0) {
+//            return ResponseResult.fail(505, "管理开启了会员审核,请等待审核");
+            return ResponseResult.fail(BizResponseEnum.WAIT_APPROVAL,getCompanyUserQRCode(companyUser));
+        }
+
+        if (userCompanyUser.getStatus() == 2) {
+            return ResponseResult.fail(504, "已被拉黑,请联系管理员");
         }
 
         //查询看课记录
@@ -1470,12 +1478,12 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         // 添加会员销售关系表数据
         // 逻辑调整:如果会员已经绑定了销售,直接提示,不添加重粉数据了-2025年6月16日14点58分
-        FsUserCompanyUser fsUserCompanyUser = getFsUserCompanyUser(param, fsUser);
-        QueryWrapper<FsUserCompanyUser> queryWrapper = new QueryWrapper<FsUserCompanyUser>().eq("user_id", param.getUserId()).eq("company_user_id", param.getCompanyUserId());
-        Integer i = fsUserCompanyUserMapper.selectCount(queryWrapper);
-        if(i == 0) {
-            fsUserCompanyUserMapper.insertFsUserCompanyUser(fsUserCompanyUser);
-        }
+//        FsUserCompanyUser fsUserCompanyUser = getFsUserCompanyUser(param, fsUser);
+//        QueryWrapper<FsUserCompanyUser> queryWrapper = new QueryWrapper<FsUserCompanyUser>().eq("user_id", param.getUserId()).eq("company_user_id", param.getCompanyUserId());
+//        Integer i = fsUserCompanyUserMapper.selectCount(queryWrapper);
+//        if(i == 0) {
+//            fsUserCompanyUserMapper.insertFsUserCompanyUser(fsUserCompanyUser);
+//        }
 
 //        // 如果重粉需要打上重粉标签
 //        if(1 == fsUserCompanyUser.getIsRepeatFans()){
@@ -1705,6 +1713,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             entity.setFileSize(e.getFileSize());
             entity.setFileKey(e.getFileKey());
             entity.setIsTranscode(0);
+            entity.setProjectId(vo.getProjectId());
             return entity;
         }).collect(Collectors.toList());
         fsUserCourseVideoMapper.insertBatchFsUserCourseVideo(collect);

+ 30 - 0
fs-service/src/main/java/com/fs/his/domain/FsUserProjectTag.java

@@ -0,0 +1,30 @@
+package com.fs.his.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("fs_user_project_tag")
+public class FsUserProjectTag {
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    /**
+     * 用户项目ID
+     */
+    private Long userCompanyUserId;
+    /**
+     * 标签ID
+     */
+    private Long tagId;
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+}

+ 2 - 1
fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java

@@ -303,7 +303,7 @@ public interface FsUserMapper
      */
     Map<String, Long> getUserVipCountByCompanyUserId(@Param("companyUserId") Long companyUserId);
 
-    @Select("select * from fs_user where union_id=#{unionId}")
+    @Select("select * from fs_user where union_id=#{unionId} order by user_id desc limit 1")
     FsUser selectFsUserByUnionId(String unionId);
 
     List<UserListCountVO> getUserNumber(@Param("userId") Long userId, @Param("companyId") Long companyId);
@@ -350,4 +350,5 @@ public interface FsUserMapper
 
     Map<String, Long> countCourseDetailsNew(UserStatisticsCommonParam param);
 
+    List<FsUserVO> selectFsUserVOListByProject(@Param("maps") FsUser fsUser);
 }

+ 19 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserProjectTagMapper.java

@@ -0,0 +1,19 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsUserProjectTag;
+import com.fs.store.vo.h5.CompanyUserTagListVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+public interface FsUserProjectTagMapper extends BaseMapper<FsUserProjectTag> {
+
+    /**
+     * 查询用户项目标签列表
+     * @param params     参数
+     * @return  list
+     */
+    List<CompanyUserTagListVO> getTagList(@Param("params") Map<String, Object> params);
+}

+ 33 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserProjectTagService.java

@@ -0,0 +1,33 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsUserProjectTag;
+import com.fs.store.param.h5.TagListParam;
+import com.fs.store.vo.h5.CompanyUserTagListVO;
+
+import java.util.List;
+
+public interface IFsUserProjectTagService extends IService<FsUserProjectTag> {
+
+    /**
+     * 添加用户项目标签
+     * @param id        用户项目ID
+     * @param tagIds    标签ID集合
+     */
+    void addUserProjectTag(Long id, List<Long> tagIds);
+
+    /**
+     * 添加用户项目标签
+     * @param ids       用户项目ID集合
+     * @param tagIds    标签ID集合
+     */
+    void addUserProjectTag(List<Long> ids, List<Long> tagIds);
+
+    /**
+     * 查询用户项目标签列表
+     * @param param     参数
+     * @return  list
+     */
+    List<CompanyUserTagListVO> getTagList(TagListParam param);
+
+}

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

@@ -172,4 +172,12 @@ public interface IFsUserService
     ResponseResult<Boolean> becomeMember(@Valid FsUserCourseBeMemberParam param);
 
     FsUserPageListVO selectFsUserPageListVOByUserId(Long userId);
+
+    /**
+     * 查询项目会员数据
+     *
+     * @param fsUser
+     * @return
+     */
+    List<FsUserVO> selectFsUserVOListByProject(FsUser fsUser);
 }

+ 105 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserProjectTagServiceImpl.java

@@ -0,0 +1,105 @@
+package com.fs.his.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.his.domain.FsUserProjectTag;
+import com.fs.his.mapper.FsUserProjectTagMapper;
+import com.fs.his.service.IFsUserProjectTagService;
+import com.fs.store.param.h5.TagListParam;
+import com.fs.store.vo.h5.CompanyUserTagListVO;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class FsUserProjectTagServiceImpl extends ServiceImpl<FsUserProjectTagMapper, FsUserProjectTag> implements IFsUserProjectTagService {
+
+    @Resource
+    private CompanyUserMapper companyUserMapper;
+
+    /**
+     * 添加用户项目标签
+     * @param id        用户项目ID
+     * @param tagIds    标签ID集合
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void addUserProjectTag(Long id, List<Long> tagIds) {
+        // 删除原有标签
+        LambdaUpdateWrapper<FsUserProjectTag> deleteWrapper = Wrappers.<FsUserProjectTag>lambdaUpdate()
+                .eq(FsUserProjectTag::getUserCompanyUserId, id);
+        baseMapper.delete(deleteWrapper);
+
+        // 添加新标签
+        List<FsUserProjectTag> tagList = tagIds.stream().distinct().map(tagId -> {
+            FsUserProjectTag userProjectTag = new FsUserProjectTag();
+            userProjectTag.setUserCompanyUserId(id);
+            userProjectTag.setTagId(tagId);
+            userProjectTag.setCreateTime(LocalDateTime.now());
+            return userProjectTag;
+        }).collect(Collectors.toList());
+
+        if (!tagList.isEmpty()) {
+            saveBatch(tagList);
+        }
+    }
+
+    /**
+     * 添加用户项目标签
+     * @param ids       用户项目ID集合
+     * @param tagIds    标签ID集合
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void addUserProjectTag(List<Long> ids, List<Long> tagIds) {
+        // 删除原有标签
+        LambdaUpdateWrapper<FsUserProjectTag> deleteWrapper = Wrappers.<FsUserProjectTag>lambdaUpdate()
+                .in(FsUserProjectTag::getUserCompanyUserId, ids);
+        baseMapper.delete(deleteWrapper);
+
+        if (tagIds.isEmpty()) {
+            return;
+        }
+
+        // 添加新标签
+        List<FsUserProjectTag> tagList = ids.stream().map(id ->
+                tagIds.stream().distinct().map(tagId -> {
+            FsUserProjectTag userProjectTag = new FsUserProjectTag();
+            userProjectTag.setUserCompanyUserId(id);
+            userProjectTag.setTagId(tagId);
+            userProjectTag.setCreateTime(LocalDateTime.now());
+            return userProjectTag;
+        }).collect(Collectors.toList())).flatMap(List::stream).collect(Collectors.toList());
+
+        if (!tagList.isEmpty()) {
+            saveBatch(tagList);
+        }
+    }
+
+    /**
+     * 查询用户项目标签列表
+     * @param param     参数
+     * @return  list
+     */
+    @Override
+    public List<CompanyUserTagListVO> getTagList(TagListParam param) {
+        Map<String, Object> params = new HashMap<>();
+        params.put("keywords", Optional.ofNullable(param.getKeyword()).map(keyword -> keyword.split(",")).orElse(null));
+
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getUserId());
+        if (Objects.nonNull(companyUser) && companyUser.isAdmin()) {
+            params.put("companyId", companyUser.getCompanyId());
+        } else {
+            params.put("companyUserId", param.getUserId());
+        }
+
+        return baseMapper.getTagList(params);
+    }
+}

+ 60 - 83
fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java

@@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.constant.HttpStatus;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.core.domain.entity.SysDictData;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.DictUtils;
@@ -31,6 +32,7 @@ import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.CourseAnalysisParam;
 import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
+import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
 import com.fs.course.vo.newfs.FsCourseAnalysisVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
@@ -42,6 +44,7 @@ import com.fs.his.mapper.*;
 import com.fs.his.param.FsUserAddIntegralTemplateParam;
 import com.fs.his.param.FsUserParam;
 import com.fs.his.service.IFsUserIntegralLogsService;
+import com.fs.his.service.IFsUserProjectTagService;
 import com.fs.his.vo.FsUserExportListVO;
 import com.fs.his.vo.FsUserFollowDoctorVO;
 import com.fs.his.vo.FsUserVO;
@@ -55,6 +58,7 @@ import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.param.h5.UserStatisticsCommonParam;
 import com.fs.store.service.cache.IFsUserCourseCountCacheService;
 import com.fs.store.vo.h5.*;
+import com.fs.system.mapper.SysDictDataMapper;
 import com.fs.system.service.ISysConfigService;
 import com.fs.watch.domain.WatchUser;
 import com.fs.watch.service.WatchUserService;
@@ -122,6 +126,12 @@ public class FsUserServiceImpl implements IFsUserService
     private ICompanyTagCacheService companyTagCacheService;
     @Autowired
     private IFsUserIntegralLogsService userIntegralLogsService;
+    @Autowired
+    private SysDictDataMapper dictDataMapper;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
+    @Autowired
+    private IFsUserProjectTagService userProjectTagService;
 
 
     /**
@@ -473,60 +483,41 @@ public class FsUserServiceImpl implements IFsUserService
 
     @Override
     public PageInfo<FsUserPageListVO> selectFsUserPageList(FsUserPageListParam param) {
-
-
-//        List<CompanyRole> companyRoles = companyRoleMapper.selectRolePermissionByUserId(param.getUserId());
-//        List<CompanyUser> companyUsers;
-//        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getUserId());
-//        // 判断是否管理员 或者包含 1:全部数据权限
-//        if (companyUser.isAdmin() || companyRoles.stream().anyMatch(r -> "1".equals(r.getDataScope()))) {
-//            companyUsers = companyUserService.getCompanyUserListByCompanyIdAndDeptId(companyUser.getCompanyId(), null);
-//        }
-//        // 判断是否包含 3:本部门数据权限 4:本部门及以下数据权限
-//        else if (companyRoles.stream().anyMatch(r -> "3".equals(r.getDataScope()) || "4".equals(r.getDataScope()))) {
-//            companyUsers = companyUserService.getCompanyUserListByCompanyIdAndDeptId(companyUser.getCompanyId(), companyUser.getDeptId());
-//        }
-//        // 默认空 -- 判断是否包含 5:仅可查看本人
-//        else {
-//            companyUsers = new ArrayList<>();
-//        }
-
-        if (param.getUserId() != null) {
-            CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getUserId());
-                if (companyUser.isAdmin()){
-                    param.setUserId(0L);
-                    param.setCompanyId(companyUser.getCompanyId());
-                }
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getUserId());
+        if (companyUser!=null && companyUser.isAdmin()){
+            param.setUserId(0L);
+            param.setCompanyId(companyUser.getCompanyId());
+        }
+        //筛选问题
+        if (StringUtils.isNotBlank(param.getCompanyUserId())){
+            param.setUserId(Long.valueOf(param.getCompanyUserId()));
         }
 
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
-
-        List<FsUserPageListVO> fsUserPageListVOS = fsUserMapper.selectFsUserPageList(param);
-        // 获取当前销售所有重粉会员
-        List<FsUserCompanyUser> fsUserCompanyUsers = fsUserCompanyUserMapper.selectRepeatUser(param.getUserId());
-
-        if(!fsUserCompanyUsers.isEmpty()){
-            List<Long> userIds = fsUserCompanyUsers.stream().map(FsUserCompanyUser::getUserId).collect(Collectors.toList());
-            // 获取会员所属的重粉销售
-            List<FsUserCompanyUser> repeatCompanyUserNames = fsUserCompanyUserMapper.selectRepeatCompanyUserName(userIds);
-            Map<Long, String> map = repeatCompanyUserNames.stream().collect(Collectors.toMap(FsUserCompanyUser::getUserId, FsUserCompanyUser::getRepeatCompanyUserName));
-
-            for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOS) {
-                fsUserPageListVO.setRepeatCompanyUserName(map.get(fsUserPageListVO.getUserId()));
-                if ("微信用户".equals(fsUserPageListVO.getNickname()) && StringUtils.isNotEmpty(fsUserPageListVO.getPhone())) {
-                    fsUserPageListVO.setNickname(fsUserPageListVO.getPhone());
-                }
-                if(StringUtils.isNotEmpty(fsUserPageListVO.getTag()) && fsUserPageListVO.getIsRepeatFans() == 0){
-                    StringBuilder newTag = removeRepeatFansTag(fsUserPageListVO);
-                    fsUserPageListVO.setTag(newTag.toString());
-                }
+        if (param.getTagIds() != null && param.getTagIds().length > 0) {
+            boolean containsZero = Arrays.asList(param.getTagIds()).contains("0");
+            // 如果包含 "0",则设置 isNullTag 为 true
+            System.out.println("是否包含 0:" + containsZero + ",参数:" + Arrays.toString(param.getTagIds()));
+            if (containsZero) {
+                param.setIsNullTag(true);
             }
-            return new PageInfo<>(fsUserPageListVOS);
-        } else {
-            return new PageInfo<>(fsUserPageListVOS);
         }
+        List<FsUserPageListVO> fsUserPageListVOS = fsUserMapper.selectFsUserPageList(param);
+
 
+        List<SysDictData> courseProject = dictDataMapper.selectDictDataByType("sys_course_project");
+        for (FsUserPageListVO fsUserPageListVO : fsUserPageListVOS) {
+            // 项目
+            courseProject.stream()
+                    .filter(c -> c.getDictValue().equals(fsUserPageListVO.getProjectId().toString()))
+                    .findFirst()
+                    .ifPresent(c -> fsUserPageListVO.setProjectName(c.getDictLabel()));
+            if (StringUtils.isEmpty(fsUserPageListVO.getNickname())){
+                fsUserPageListVO.setNickname("用户暂未授权昵称");
+            }
+        }
 
+        return new PageInfo<>(fsUserPageListVOS);
     }
 
     private static StringBuilder removeRepeatFansTag(FsUserPageListVO fsUserPageListVO) {
@@ -937,56 +928,37 @@ public class FsUserServiceImpl implements IFsUserService
             return ResponseResult.fail(404,"当前用户信息不存在");
         }
 
-        // 逻辑调整:如果会员已经绑定了销售,直接提示,不添加重粉数据了-2025年6月16日14点53分
-        if (fsUser.getCompanyUserId() != null && !param.getCompanyUserId().equals(fsUser.getCompanyUserId())){
-            return ResponseResult.fail(406,"该用户已成为其他销售会员");
-        }
-
         //判断该销售是否存在
         CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
         if (Objects.isNull(companyUser)){
             return ResponseResult.fail(405,"销售不存在");
         }
-
-        // 添加关系表数据
-        FsUserCompanyUser fsUserCompanyUser = getFsUserCompanyUser(param, fsUser);
-        QueryWrapper<FsUserCompanyUser> queryWrapper = new QueryWrapper<FsUserCompanyUser>().eq("user_id", param.getUserId()).eq("company_user_id", param.getCompanyUserId());
-        Integer i = fsUserCompanyUserMapper.selectCount(queryWrapper);
-        if(i == 0) {
-            fsUserCompanyUserMapper.insertFsUserCompanyUser(fsUserCompanyUser);
+        // 通过字段值判断该销售是否允许注册会员
+        if(companyUser.getIsAllowedAllRegister() != null && companyUser.getIsAllowedAllRegister() == 0){
+            return ResponseResult.fail(407,"不允许注册会员,请联系管理员");
         }
 
-        // 关联销售
-        if(fsUser.getCompanyUserId() == null) {
-            fsUser.setCompanyId(param.getCompanyId());
-            fsUser.setCompanyUserId(param.getCompanyUserId());
+        // 逻辑调整:如果会员已经绑定了销售,直接提示,不添加重粉数据了-2025年6月16日14点53分
+        // 逻辑调整:会员与销售的绑定关系通过中间表关联 /20250625 17:13
+        FsUserCompanyUser userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(fsUser.getUserId(), param.getProjectId());
+        if (Objects.nonNull(userCompanyUser) && !userCompanyUser.getCompanyUserId().equals(param.getCompanyUserId())){
+            return ResponseResult.fail(500,"该用户("+fsUser.getUserId() + ")已成为其他销售会员");
         }
+
         // 特殊(需求设计:需要根据公司是否开启黑名单来设置会员初始化的状态)
-        Company company = null;
-        if(param.getCompanyId() != null) {
-            company = companyMapper.selectCompanyById(param.getCompanyId());
-        }
+        Company company = companyMapper.selectCompanyById(param.getCompanyId());
         // isDefaultBlack 值为1 ,表示需要加入小黑屋,否则不加
         int isDefaultBlack = company != null ? company.getFsUserIsDefaultBlack() : 0;
-        fsUser.setStatus(isDefaultBlack == 1 ? 0 : 1);
-        fsUserMapper.updateFsUser(fsUser);
+
+        // 添加关系表数据
+        if (Objects.isNull(userCompanyUser)){
+            int defaultStatus = isDefaultBlack == 1 ? 0 : 1;
+            userCompanyUser = userCompanyUserService.bindRelationship(param.getUserId(), param.getProjectId(), companyUser.getCompanyId(), companyUser.getUserId(), defaultStatus);
+        }
 
         // 不为空则添加新标签
         if (Objects.nonNull(param.getTagIds()) && param.getTagIds().length > 0) {
-            //关联会员标签,先删除再新增
-            Map<String, Object> map = new HashMap<>();
-            map.put("userId", param.getUserId());
-            map.put("companyId", fsUser.getCompanyId());
-            map.put("companyUserId", fsUser.getCompanyUserId());
-            companyTagUserMapper.deleteCompanyTagUserByMap(map);
-
-            CompanyTagUser companyTagUser = new CompanyTagUser();
-            companyTagUser.setUserId(param.getUserId());
-            companyTagUser.setCompanyId(fsUser.getCompanyId());
-            companyTagUser.setCompanyUserId(fsUser.getCompanyUserId());
-            companyTagUser.setTagIds(String.join(",", param.getTagIds()));
-            companyTagUser.setCreateTime(new Date());
-            companyTagUserMapper.insertCompanyTagUser(companyTagUser);
+            userProjectTagService.addUserProjectTag(userCompanyUser.getId(), Arrays.stream(param.getTagIds()).map(Long::valueOf).collect(Collectors.toList()));
         }
 
 //        // 如果是重粉,直接打上重粉的标签
@@ -1034,6 +1006,11 @@ public class FsUserServiceImpl implements IFsUserService
         return item;
     }
 
+    @Override
+    public List<FsUserVO> selectFsUserVOListByProject(FsUser fsUser) {
+        return fsUserMapper.selectFsUserVOListByProject(fsUser);
+    }
+
 
     private FsUserStatisticsVO getUserStatistics(UserStatisticsCommonParam param) {
         FsUserStatisticsVO fsUserStatisticsVO = new FsUserStatisticsVO();

+ 134 - 8
fs-service/src/main/java/com/fs/his/vo/FsUserVO.java

@@ -1,5 +1,6 @@
 package com.fs.his.vo;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import io.swagger.annotations.ApiModelProperty;
@@ -109,13 +110,138 @@ public class FsUserVO implements Serializable {
     @Excel(name = "所属公司", sort = 9)
     private String companyName;
 
-    public void setPhone(String phone)
-    {
-       this.phone = phone;
-    }
+    private String username;
+    /** 用户密码(跟pwd) */
+    private String password;
 
-    public String getPhone()
-    {
-        return phone;
-    }
+    /** 真实姓名 */
+    private String realName;
+
+    /** 生日 */
+    private Long birthday;
+
+    /** 身份证号码 */
+    private String idCard;
+
+    /** 用户昵称 */
+    @Excel(name = "会员昵称", sort = 1)
+    private String nickname;
+
+    /** 用户备注 */
+    @Excel(name = "用户备注", sort = 12)
+    private String remark;
+
+    /** 用户余额 */
+    @Excel(name = "用户余额", sort = 4)
+    private BigDecimal nowMoney;
+
+    /** 佣金金额 */
+    private BigDecimal brokeragePrice;
+
+    /** 连续签到天数 */
+    private Long signNum;
+
+    private String statusText;
+
+    /** 等级 */
+    private Integer level;
+
+    /** 推广上级用户ID */
+    private Long spreadUserId;
+
+    /** 推广员关联时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date spreadTime;
+
+    /** 用户类型 */
+    private String userType;
+
+    /** 是否为推广员 */
+    private Integer isPromoter;
+
+    /** 用户购买次数 */
+    private Long payCount;
+
+    /** 下级人数 */
+    private Long spreadCount;
+
+    /** 详细地址 */
+    private String addres;
+
+    private Integer isWeixinAuth;
+
+    private Long companyId;
+
+    private String companyUserName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date registerDate;
+    private String registerCode;
+
+    private Integer isVip;
+    private Date  vipStartDate;
+    private Date  vipEndDate;
+    private Integer vipLevel;
+    private Integer vipStatus;
+
+    private String jpushId;
+
+    private Integer sex;
+    private Integer isAddQw;
+    private Long qwExtId;
+    private Integer isShow;//是否展示购买以及订单状态
+
+
+
+    private String courseMaOpenId;//看课小程序openId
+
+    // 企微重粉
+    private Integer qwRepeat;
+    // 小程序(看课)重粉
+    private Integer userRepeat;
+    // 是否已购0 否 1程序内下单 2程序外下单
+    private Integer payOrder;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(exist = false)
+    private Date startCreateTime;
+
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date endCreateTime;
+
+    /** 消费总金额 */
+    private BigDecimal totalAmount;
+
+    /** 最后一次消费时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date lastBuyTime;
+
+    /** 最后一次消费金额 */
+    private Double number;
+
+    /** 关联id */
+    private String businessId;
+
+    @ApiModelProperty(value = "看课数量")
+    @Excel(name = "看课数量", sort = 8)
+    private Long watchCourseCount;
+
+    @ApiModelProperty(value = "参与营期数量")
+    @Excel(name = "参与营期数量", sort = 9)
+    private Long partCourseCount;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "最后看课时间")
+    @Excel(name = "最后看课时间", dateFormat = "yyyy-MM-dd HH:mm:ss", sort = 11)
+    private Date lastWatchDate;
+
+    @Excel(name = "状态", sort = 7)
+    private String statusName;
+
+    @ApiModelProperty(value = "项目ID")
+    private Long projectId;
+
+    @ApiModelProperty(value = "销售用户关联id")
+    private Long companyUserId;
 }

+ 1 - 1
fs-service/src/main/java/com/fs/qw/dto/FsUserTransferParamDTO.java

@@ -22,7 +22,7 @@ public class FsUserTransferParamDTO implements Serializable {
     /**
      * 客户id
      */
-    private List<Long> userIds;
+    private List<UserProjectDTO> userIds;
 
     /**
      * 转移提示内容/原因

+ 39 - 28
fs-service/src/main/java/com/fs/qw/service/impl/CustomerTransferApprovalServiceImpl.java

@@ -8,18 +8,21 @@ import com.fs.company.cache.ICompanyCacheService;
 import com.fs.company.cache.ICompanyUserCacheService;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
+import com.fs.course.domain.FsUserCompanyUser;
 import com.fs.course.mapper.FsUserCompanyUserMapper;
+import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.qw.domain.CustomerTransferApproval;
 import com.fs.qw.dto.FsUserTransferParamDTO;
+import com.fs.qw.dto.UserProjectDTO;
 import com.fs.qw.mapper.CustomerTransferApprovalMapper;
 import com.fs.qw.service.ICustomerTransferApprovalService;
 import com.fs.qw.vo.TransferCustomDTO;
 import com.fs.store.service.cache.IFsUserCacheService;
 import com.hc.openapi.tool.util.StringUtils;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.http.util.Asserts;
+import org.apache.hc.core5.util.Asserts;
 import org.springframework.aop.framework.AopContext;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
@@ -30,6 +33,7 @@ import org.springframework.transaction.annotation.Transactional;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * 客户转移审批Service业务层处理
@@ -57,6 +61,9 @@ public class CustomerTransferApprovalServiceImpl implements ICustomerTransferApp
     private IFsUserService fsUserService;
     @Autowired
     private FsUserCompanyUserMapper fsUserCompanyUserMapper;
+    @Autowired
+    private IFsUserCompanyUserService userCompanyUserService;
+
     /**
      * 查询客户转移审批
      *
@@ -111,7 +118,7 @@ public class CustomerTransferApprovalServiceImpl implements ICustomerTransferApp
         }
 
         if(StringUtils.isBlank(item.getTransferBefore()) && StringUtils.isNotBlank(item.getCustomerIds())){
-            List<Long> customerIds = JSON.parseArray(item.getCustomerIds(), Long.class);
+            List<UserProjectDTO> customerIds = JSON.parseArray(item.getCustomerIds(), UserProjectDTO.class);
             List<TransferCustomDTO> customerList = getCustomerList(customerIds, item);
             item.setCustomerList(customerList);
         } else {
@@ -121,27 +128,31 @@ public class CustomerTransferApprovalServiceImpl implements ICustomerTransferApp
         return item;
     }
 
-    private List<TransferCustomDTO> getCustomerList(List<Long> customerIds, CustomerTransferApproval item) {
+    private List<TransferCustomDTO> getCustomerList(List<UserProjectDTO> customerIds, CustomerTransferApproval item) {
         List<TransferCustomDTO> customerList = new ArrayList<>();
 
-        for (Long customerId : customerIds) {
+        for (UserProjectDTO customerId : customerIds) {
 
-            FsUser fsUser = fsUserCacheService.selectFsUserById(customerId);
+            FsUser fsUser = fsUserCacheService.selectFsUserById(customerId.getUserId());
             if(ObjectUtils.isNotNull(fsUser)){
-                String companyUserName = "无";
-                if(ObjectUtils.isNotNull(fsUser.getCompanyUserId())){
-                    CompanyUser companyUser = companyUserCacheService.selectCompanyUserById(fsUser.getCompanyUserId());
-                    companyUserName = String.format("%s_%d", companyUser.getUserName(), companyUser.getUserId());
-                }
+                FsUserCompanyUser userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(customerId.getUserId(), customerId.getProjectId());
+                if(Objects.nonNull(userCompanyUser)){
+                    CompanyUser companyUser = companyUserCacheService.selectCompanyUserById(userCompanyUser.getCompanyUserId());
+                    String companyUserName = String.format("%s_%d", companyUser.getUserName(), companyUser.getUserId());
+
+                    CompanyUser afterCompanyUser = companyUserCacheService.selectCompanyUserById(item.getTargetUserId());
+                    String afterCompanyUserName = String.format("%s_%d", afterCompanyUser.getUserName(), companyUser.getUserId());
 
-                customerList.add(TransferCustomDTO.builder()
-                        .userName(String.format("%s_%d", fsUser.getNickName(), fsUser.getUserId()))
-                        .userId(fsUser.getUserId())
-                        .beforeCompanyUserName(companyUserName)
-                        .beforeCompanyUserId(fsUser.getCompanyUserId())
-                        .afterCompanyUserName(item.getTargetUserName())
-                        .afterCompanyUserId(item.getTargetUserId())
-                        .build());
+                    customerList.add(TransferCustomDTO.builder()
+                            .userName(String.format("%s_%d", fsUser.getNickName(), fsUser.getUserId()))
+                            .userId(fsUser.getUserId())
+                            .projectId(customerId.getProjectId())
+                            .beforeCompanyUserName(companyUserName)
+                            .beforeCompanyUserId(companyUser.getUserId())
+                            .afterCompanyUserName(afterCompanyUserName)
+                            .afterCompanyUserId(item.getTargetUserId())
+                            .build());
+                }
             }
         }
         return customerList;
@@ -226,27 +237,27 @@ public class CustomerTransferApprovalServiceImpl implements ICustomerTransferApp
         item.setProcessedAt(new Date());
 //        审批状态: 0=待审批, 1=审批通过, 2=审批驳回, 3=已撤销
         // 如果审批通过 进行转移
+        List<UserProjectDTO> customerIds1 = JSON.parseArray(item.getCustomerIds(), UserProjectDTO.class);
+        List<TransferCustomDTO> customerList = getCustomerList(customerIds1, item);
+        item.setTransferBefore(JSON.toJSONString(customerList));
+
         if(ObjectUtil.equal(1,item.getApprovalStatus())){
             FsUserTransferParamDTO transferParam = new FsUserTransferParamDTO();
             transferParam.setContent(item.getContent());
             transferParam.setTargetCompanyUserId(item.getTargetUserId());
 
             Asserts.check(StringUtils.isNotBlank(item.getCustomerIds()),"转移客户不能为空!");
-            List<Long> customerIds = JSON.parseArray(item.getCustomerIds(), Long.class);
+            List<UserProjectDTO> customerIds = JSON.parseArray(item.getCustomerIds(), UserProjectDTO.class);
             transferParam.setUserIds(customerIds);
             transferParam.setSourceCompanyUserId(item.getOriginalUserId());
 
-            if(CollectionUtils.isNotEmpty(transferParam.getUserIds())) {
-                fsUserService.transfer(transferParam);
-            }
-
-            if(CollectionUtils.isNotEmpty(transferParam.getUserIds())) {
-                fsUserCompanyUserMapper.transfer(transferParam);
+            for (UserProjectDTO customerId : customerIds) {
+                CompanyUser companyUser = companyUserCacheService.selectCompanyUserById(item.getTargetUserId());
+                userCompanyUserService.changeRelationship(customerId.getUserId(), customerId.getProjectId(), companyUser.getCompanyId(), companyUser.getUserId());
             }
         }
-        List<Long> customerIds = JSON.parseArray(item.getCustomerIds(), Long.class);
-        List<TransferCustomDTO> customerList = getCustomerList(customerIds, item);
-        item.setTransferBefore(JSON.toJSONString(customerList));
+
+
         return customerTransferApprovalMapper.updateCustomerTransferApproval(item);
     }
 

+ 7 - 0
fs-service/src/main/java/com/fs/store/param/h5/FsUserPageListParam.java

@@ -76,7 +76,14 @@ public class FsUserPageListParam implements Serializable {
      */
     private Boolean isMyFsUser = Boolean.TRUE;
 
+    private Boolean isAdmin;
+    /**
+     * 判断是否选择了无标签
+     */
+    private Boolean isNullTag =false;
 
+    @ApiModelProperty(value = "状态 0小黑屋 1正常 2拉黑")
+    private Integer status;
 
 
 }

+ 4 - 0
fs-service/src/main/java/com/fs/store/vo/h5/CompanyUserTagListVO.java

@@ -15,5 +15,9 @@ public class CompanyUserTagListVO {
 
     @ApiModelProperty(value = "标签名称")
     private String tagName;
+    /**
+     * 项目ID
+     */
+    private Long projectId;
 
 }

+ 5 - 0
fs-service/src/main/java/com/fs/store/vo/h5/FsUserPageListVO.java

@@ -94,4 +94,9 @@ public class FsUserPageListVO {
     @ApiModelProperty(value = "重粉所属销售,多个用逗号隔开")
     private String repeatCompanyUserName;
 
+    @ApiModelProperty(value = "项目名称")
+    private String projectName;
+    @ApiModelProperty(value = "用户-项目-销售ID")
+    private Long userCompanyUserId;
+
 }

+ 30 - 0
fs-service/src/main/resources/mapper/company/CompanyTagMapper.xml

@@ -64,6 +64,36 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select tag_id,tag from company_tag
     </select>
 
+    <!-- 查询标签列表 -->
+    <select id="selectCompanyTagByList" resultType="com.fs.company.domain.CompanyTag">
+        select ct.*,fu.nickname from company_tag ct
+        inner join fs_user_project_tag ft on ct.tag_id =ft.tag_id
+        inner join fs_user_company_user fucu on fucu.id = ft.user_company_user_id
+        inner join fs_user fu on fu.user_id =fucu.user_id
+        <where>
+            <if test="params.keyword != null and params.keyword.length > 0">
+                and
+                <foreach collection="params.keyword" item="item"  open="(" separator="or" close=")">
+                    ct.tag like concat('%',#{item},'%')
+                </foreach>
+            </if>
+            <if test="params.companyId != null">
+                and ct.company_id = #{params.companyId}
+            </if>
+
+            <if test="params.companyUserId != null">
+                and fucu.company_user_id = #{params.companyUserId}
+            </if>
+            <if test="params.tagName != null">
+                and ct.tag = #{params.tagName}
+            </if>
+            <if test="params.tagName != null">
+                and ct.tag = #{params.tagName}
+            </if>
+        </where>
+        group by ct.tag_id
+    </select>
+
     <insert id="insertCompanyTag" parameterType="CompanyTag" useGeneratedKeys="true" keyProperty="tagId">
         insert into company_tag
         <trim prefix="(" suffix=")" suffixOverrides=",">

+ 34 - 8
fs-service/src/main/resources/mapper/company/CompanyTagUserMapper.xml

@@ -113,20 +113,46 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             find_in_set(#{tagId}, ctu.tag_ids)
         </foreach>
     </select>
+
     <select id="getTagByUser" resultType="com.fs.store.vo.h5.CompanyUserTagListVO">
         SELECT distinct
-        company_tag.tag as tagName,
-        company_tag.tag_id
-        FROM
-        company_tag_user
-        right JOIN company_tag ON FIND_IN_SET( company_tag.tag_id, company_tag_user.tag_ids ) > 0
-        where company_tag_user.user_id = #{params.userId}
+        ct.tag as tagName,
+        ct.tag_id,
+        ft.project_id
+        FROM company_tag ct
+        inner join fs_user_project_tag ft on ct.tag_id =ft.tag_id
+        inner join fs_user_company_user fucu on fucu.id = ft.user_company_user_id
+        where fucu.user_id = #{params.userId}
             <if test="params.companyId != null">
-                and company_tag_user.company_id = #{params.companyId}
+                and fucu.company_id = #{params.companyId}
             </if>
             <if test="params.companyUserId != null">
-                and company_tag_user.company_user_id = #{params.companyUserId}
+                and fucu.company_user_id = #{params.companyUserId}
             </if>
     </select>
 
+    <select id="selectUserByMap" resultType="com.fs.company.vo.CompanyTagUserVO">
+        select fu.user_id,
+        fucu.project_id,
+        fu.nickname as userName from company_tag ct
+        inner join fs_user_project_tag ft on ct.tag_id =ft.tag_id
+        inner join fs_user_company_user fucu on fucu.id = ft.user_company_user_id
+        inner join fs_user fu on fu.user_id =fucu.user_id
+        where fucu.company_user_id = #{params.companyUserId}
+        <if test="params.tagIds != null and params.tagIds.size() > 0">
+            and ft.tag_id in
+            <foreach collection="params.tagIds" item="item" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+        </if>
+
+        <if test="params.projectIds != null and params.projectIds.size() > 0">
+            and fucu.project_id in
+            <foreach collection="params.projectIds" item="item" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+        </if>
+        group by fucu.user_id
+    </select>
+
 </mapper>

+ 62 - 9
fs-service/src/main/resources/mapper/course/FsUserCompanyUserMapper.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper
-PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.course.mapper.FsUserCompanyUserMapper">
 
     <resultMap type="FsUserCompanyUser" id="FsUserCompanyUserResult">
@@ -14,10 +14,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="qwUserId"    column="qw_user_id"    />
         <result property="qwExternalContactId"    column="qw_external_contact_id"    />
         <result property="qwCompanyId"    column="qw_company_id"    />
+        <result property="status"    column="status"    />
+        <result property="remark"    column="remark"    />
+        <result property="createTime"    column="create_time"    />
     </resultMap>
 
     <sql id="selectFsUserCompanyUserVo">
-        select * from fs_user_company_user
+        select id, user_id, company_user_id, company_id, is_repeat_fans, project_id, qw_user_id, qw_external_contact_id, qw_company_id, `status`, remark, create_time from fs_user_company_user
     </sql>
 
     <select id="selectFsUserCompanyUserList" parameterType="FsUserCompanyUser" resultMap="FsUserCompanyUserResult">
@@ -31,6 +34,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="qwUserId != null "> and qw_user_id = #{qwUserId}</if>
             <if test="qwExternalContactId != null "> and qw_external_contact_id = #{qwExternalContactId}</if>
             <if test="qwCompanyId != null "> and qw_company_id = #{qwCompanyId}</if>
+            <if test="status != null "> and `status` = #{status}</if>
+            <if test="remark != null "> and remark = #{remark}</if>
+            <if test="createTime != null "> and create_time = #{createTime}</if>
         </where>
     </select>
 
@@ -51,6 +57,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="qwUserId != null">qw_user_id,</if>
             <if test="qwExternalContactId != null">qw_external_contact_id,</if>
             <if test="qwCompanyId != null">qw_company_id,</if>
+            <if test="status != null">`status`,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createTime != null">create_time,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
@@ -62,6 +71,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="qwUserId != null">#{qwUserId},</if>
             <if test="qwExternalContactId != null">#{qwExternalContactId},</if>
             <if test="qwCompanyId != null">#{qwCompanyId},</if>
+            <if test="status != null">#{status},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createTime != null">#{createTime},</if>
         </trim>
     </insert>
 
@@ -76,9 +88,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
             <if test="qwExternalContactId != null">qw_external_contaact_id = #{qwExternalContactId},</if>
             <if test="qwCompanyId != null">qw_company_id = #{qwCompanyId},</if>
+            <if test="status != null">`status` = #{status},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
         </trim>
         where id = #{id}
     </update>
+    <update id="transfer">
+        update fs_user_company_user set company_user_id=#{param.targetCompanyUserId}
+        <where>
+            <if test="param.userIds != null and param.userIds.size() > 0">
+                user_id in
+                <foreach collection="param.userIds" item="item" separator="," open="(" close=")">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+    </update>
+
+    <update id="changeUserProjectStatus">
+        update fs_user_company_user ucu
+        set ucu.`status` = #{status}
+        where (ucu.user_id, ucu.project_id) in
+        <foreach collection="ids" item="item" separator="," open="(" close=")">
+            (#{item.userId}, #{item.projectId})
+        </foreach>
+    </update>
+
+    <update id="batchUpdateStatus">
+        update fs_user_company_user ucu
+        set ucu.`status` = #{status}
+        where id in
+        <foreach collection="ids" item="item" separator="," open="(" close=")">
+            (#{item})
+        </foreach>
+    </update>
+
 
     <delete id="deleteFsUserCompanyUserById" parameterType="Long">
         delete from fs_user_company_user where id = #{id}
@@ -108,15 +153,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         fs_user_company_user.user_id
     </select>
 
-    <update id="transfer">
-        update fs_user_company_user set company_user_id=#{targetCompanyUserId}
+    <select id="selectFsUserCompanyUserListByMap" resultType="java.lang.Long">
+        select fucu.project_id from company_tag ct
+        inner join fs_user_project_tag ft on ct.tag_id =ft.tag_id
+        inner join fs_user_company_user fucu on fucu.id = ft.user_company_user_id
         <where>
-            <if test="param.userIds != null and param.userIds.size() > 0">
-                user_id in
-                <foreach collection="param.userIds" item="item" separator="," open="(" close=")">
+            <if test="param.tagIds != null and param.tagIds.size() > 0">
+                and ct.tag_id in
+                <foreach collection="param.tagIds" item="item" separator="," open="(" close=")">
                     #{item}
                 </foreach>
             </if>
+            <if test="param.companyUserId != null">
+                and fucu.company_user_id = #{param.companyUserId}
+            </if>
         </where>
-    </update>
+        group by fucu.project_id
+    </select>
+
+
 </mapper>

+ 24 - 4
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -35,6 +35,8 @@
         <result property="viewStartTime"    column="view_start_time"    />
         <result property="viewEndTime"    column="view_end_time"    />
         <result property="lastJoinTime"    column="last_join_time"    />
+        <result property="userId" column="user_id" />
+        <result property="projectId"    column="project_id"    />
     </resultMap>
 
     <sql id="selectFsUserCourseVideoVo">
@@ -55,6 +57,8 @@
             <if test="status != null "> and status = #{status}</if>
             <if test="courseSort != null "> and course_sort = #{courseSort}</if>
             <if test="questionBankId != null "> and question_bank_id = #{questionBankId}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="projectId != null "> and project_id = #{projectId}</if>
         </where>
     </select>
 
@@ -95,6 +99,8 @@
             <if test="viewStartTime != null">view_start_time,</if>
             <if test="viewEndTime != null">view_end_time,</if>
             <if test="lastJoinTime != null">last_join_time,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="projectId != null">project_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="fileId != null">#{fileId},</if>
@@ -126,6 +132,8 @@
             <if test="viewStartTime != null">#{viewStartTime},</if>
             <if test="viewEndTime != null">#{viewEndTime},</if>
             <if test="lastJoinTime != null">#{lastJoinTime},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="projectId != null">#{projectId},</if>
         </trim>
     </insert>
     <insert id="insertBatchFsUserCourseVideo" parameterType="FsUserCourseVideo" useGeneratedKeys="true" keyProperty="videoId">
@@ -146,7 +154,9 @@
         red_packet_money,
         file_size,
         file_key,
-        is_transcode
+        is_transcode,
+        user_id,
+        project_id
         )
         values
         <foreach collection="collect" item="item" separator=",">
@@ -166,7 +176,9 @@
             #{item.redPacketMoney},
             #{item.fileSize},
             #{item.fileKey},
-            #{item.isTranscode}
+            #{item.isTranscode},
+            #{item.userId},
+            #{item.projectId}
             )
         </foreach>
     </insert>
@@ -203,6 +215,8 @@
             <if test="viewStartTime != null">view_start_time = #{viewStartTime},</if>
             <if test="viewEndTime != null">view_end_time = #{viewEndTime},</if>
             <if test="lastJoinTime != null">last_join_time = #{lastJoinTime},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="projectId != null">project_id = #{projectId},</if>
         </trim>
         where video_id = #{videoId}
     </update>
@@ -239,7 +253,8 @@
         fcpd.period_id,
         fcpd.id,
         if(ccut.start_date_time is null, fcpd.start_date_time, ccut.start_date_time) as startDateTime,
-        if(ccut.end_date_time is null, fcpd.end_date_time, ccut.end_date_time) as endDateTime
+        if(ccut.end_date_time is null, fcpd.end_date_time, ccut.end_date_time) as endDateTime,
+        course.project as projectId
         FROM `fs_user_course_video` video
         left join fs_user_course_period_days fcpd on fcpd.video_id = video.video_id
         left join fs_user_course_period fcp on fcp.period_id = fcpd.period_id
@@ -292,7 +307,8 @@
         fcpd.last_join_time,
         fcpd.id,
         if(ccut.start_date_time is null, fcpd.start_date_time, ccut.start_date_time) as startDateTime,
-        if(ccut.end_date_time is null, fcpd.end_date_time, ccut.end_date_time) as endDateTime
+        if(ccut.end_date_time is null, fcpd.end_date_time, ccut.end_date_time) as endDateTime,
+        course.project as projectId
         from `fs_user_course_video` video
         left join fs_user_course_period_days fcpd on fcpd.video_id = video.video_id
         left join fs_user_course_period fcp on fcp.period_id = fcpd.period_id
@@ -308,6 +324,10 @@
         <if test="params.dayDate != null">
             and fcpd.day_date = #{params.dayDate}
         </if>
+        and (
+        (fcpd.start_date_time &lt;=  CONCAT( CURDATE(), ' 23:59:59' ) and fcpd.end_date_time >= CONCAT( CURDATE(), ' 00:00:00' ))
+        or (ccut.start_date_time &lt;=  CONCAT( CURDATE(), ' 23:59:59' ) and ccut.end_date_time >= CONCAT( CURDATE(), ' 00:00:00' ))
+        )
         order by video.course_sort
     </select>
     <select id="selectFsUserCourseVideoVoByVideoId" resultType="com.fs.course.vo.FsUserCourseVO">

+ 281 - 138
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -57,6 +57,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectFsUserList" parameterType="FsUser" resultMap="FsUserResult">
         <include refid="selectFsUserVo"/>
         <where>
+            <if test="userId != null">and user_id = #{userId}</if>
             <if test="nickName != null  and nickName != ''"> and nick_name like concat( #{nickName}, '%')</if>
             <if test="avatar != null  and avatar != ''"> and avatar = #{avatar}</if>
             <if test="phone != null  and phone != ''"> and phone = #{phone}</if>
@@ -110,6 +111,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     #{videoId}
                 </foreach>
             </if>
+            <if test="companyId != null">
+                AND fwl.company_id = #{companyId}
+            </if>
         </where>
         GROUP BY
         fwl.video_id
@@ -125,10 +129,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
         <where>
             <if test="companyUserId != null and companyUserId != 0 ">
-                AND fs_user.company_user_id = #{companyUserId}
+                AND flog.company_user_id = #{companyUserId}
             </if>
             <if test="companyUserId != null and companyUserId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and flog.company_id = #{companyId}
             </if>
             <if test="periodId != null and periodId != ''">
                 AND flog.period_id =  #{periodId}
@@ -142,6 +146,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     #{videoId}
                 </foreach>
             </if>
+            <if test="companyId != null">
+                AND flog.company_id = #{companyId}
+            </if>
         </where>
         GROUP BY
         flog.video_id
@@ -167,10 +174,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
         <where>
             <if test="companyUserId != null and companyUserId != 0 ">
-                AND fs_user.company_user_id = #{companyUserId}
+                AND fs_course_answer_logs.company_user_id = #{companyUserId}
             </if>
             <if test="companyUserId != null and companyUserId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and fs_course_answer_logs.company_id = #{companyId}
             </if>
             <if test="periodId != null and periodId != ''">
                 AND fs_course_answer_logs.period_id =  #{periodId}
@@ -184,7 +191,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     #{videoId}
                 </foreach>
             </if>
-
+            <if test="companyId != null">
+                AND fs_course_answer_logs.company_id = #{companyId}
+            </if>
         </where>
         GROUP BY
         fs_course_answer_logs.video_id
@@ -196,7 +205,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectFsUserPageList" resultType="com.fs.store.vo.h5.FsUserPageListVO">
         SELECT
-        fs_user.*,
+        fs_user.user_id,
+        fs_user.avatar,
+        fs_user.nickname,
+        fs_user.phone,
         fs_user_course_count.id,
         fs_user_course_count.watch_course_count,
         fs_user_course_count.miss_course_count,
@@ -210,53 +222,64 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         GROUP_CONCAT(DISTINCT company_tag.tag) AS tag,
         GROUP_CONCAT(DISTINCT company_tag.tag_id) AS tagIds,
         company_user.nick_name as companyUserNickName,
-        fs_user_company_user.is_repeat_fans
+        fs_user_company_user.is_repeat_fans,
+        fs_user_company_user.project_id,
+        fs_user_company_user.`status`,
+        fs_user_company_user.remark,
+        fs_user_company_user.id as userCompanyUserId,
+        fs_user_company_user.create_time
         FROM
         fs_user
-        LEFT JOIN fs_user_course_count ON fs_user.user_id = fs_user_course_count.user_id
-        LEFT JOIN company_tag_user ON fs_user.user_id = company_tag_user.user_id
-        LEFT JOIN company_tag ON FIND_IN_SET(company_tag.tag_id, company_tag_user.tag_ids) > 0
-        LEFT JOIN fs_user_company_user ON fs_user_company_user.user_id = fs_user.user_id
+        INNER JOIN fs_user_company_user ON fs_user_company_user.user_id = fs_user.user_id
+        LEFT JOIN fs_user_course_count ON fs_user_company_user.user_id = fs_user_course_count.user_id and fs_user_company_user.project_id = fs_user_course_count.project_id
+        left join fs_user_project_tag upt ON upt.user_company_user_id = fs_user_company_user.id
+        LEFT JOIN company_tag ON company_tag.tag_id = upt.tag_id
         LEFT JOIN company_user ON company_user.user_id = fs_user_company_user.company_user_id
         where fs_user.is_del = 0
         <if test="userId != null and userId!= 0 ">
-            and fs_user.company_user_id = #{userId}
+            and fs_user_company_user.company_user_id = #{userId}
         </if>
         <if test="companyId != null ">
-            and fs_user.company_id = #{companyId}
+            and fs_user_company_user.company_id = #{companyId}
         </if>
-        <if test="companyUserId != null and companyUserId!= '' ">
-            and fs_user.company_user_id = #{companyUserId}
+        <if test="status != null">
+            AND fs_user_company_user.status = #{status}
+        </if>
+        <if test="projectId != null">
+            AND fs_user_company_user.project_id = #{projectId}
         </if>
-        <choose>
-            <when test = "isBlack">
-                AND (fs_user.status = 0 or fs_user_company_user.is_repeat_fans = 1)
-            </when>
-            <otherwise>
-                AND (fs_user.status = 1 and fs_user_company_user.is_repeat_fans = 0)
-            </otherwise>
-        </choose>
         <if test="keyword != null and keyword !='' ">
-            AND (fs_user.nick_name LIKE concat('%',#{keyword},'%')
+            AND (fs_user.nickname LIKE concat('%',#{keyword},'%')
             or  fs_user.phone LIKE concat('%',#{keyword},'%')
             )
         </if>
         <if test="registerStartTime != null and registerStartTime !='' ">
-            AND fs_user.create_time &gt;= #{registerStartTime}
+            AND fs_user_company_user.create_time &gt;= #{registerStartTime}
         </if>
         <if test="registerEndTime != null and registerEndTime !='' ">
-            AND fs_user.create_time &lt;= #{registerEndTime}
+            AND fs_user_company_user.create_time &lt;= #{registerEndTime}
+        </if>
+        <if test="isNullTag">
+            and (upt.tag_id is null
+            <if test="tagIds != null and tagIds.length > 0">
+                or upt.tag_id in
+                <foreach collection="tagIds" item="item" index="index" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            )
         </if>
-        <if test="tagIds != null and tagIds.length > 0">
-            AND
-            <foreach collection="tagIds" item="item" index="index" open="(" separator="or" close=")">
-                CONCAT(',', company_tag_user.tag_ids, ',') LIKE CONCAT('%,', #{item}, ',%')
+
+        <if test="!isNullTag and tagIds != null and tagIds.length > 0">
+            AND upt.tag_id in
+            <foreach collection="tagIds" item="item" index="index" open="(" separator="," close=")">
+                #{item}
             </foreach>
         </if>
         <if test="tabValue != null and tabValue !='' ">
             <choose>
                 <when test = "tabValue == 1">
-                    AND DAY(fs_user.create_time) = DAY(NOW())
+                    AND DAY(fs_user_company_user.create_time) = DAY(NOW())
                 </when>
                 <when test = "tabValue == 2">
                     AND DAY(fs_user_course_count.complete_watch_date) = DAY(NOW())
@@ -290,16 +313,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             </choose>
         </if>
 
-        group by fs_user.user_id
+        group by fs_user.user_id, fs_user_company_user.project_id
 
         <if test="continueMissCourseSort != null and continueMissCourseSort !='' ">
             order by
             <choose>
                 <when test = "continueMissCourseSort == 0">
-                    fs_user.create_time desc
+                    fs_user_company_user.create_time desc
                 </when>
                 <when test = "continueMissCourseSort == 1">
-                    fs_user.nick_name asc
+                    fs_user.nickname asc
                 </when>
             </choose>
         </if>
@@ -314,17 +337,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         fs_user.status,
         fs_user.create_time,
         fs_user.remark,
-        fs_user.company_user_id,
-        fs_user.company_id
+        ucu.company_user_id,
+        ucu.company_id,
+        ucu.project_id
         FROM
         fs_user
         <where>
             fs_user.is_del = 0
+            <if test="userId != null">
+                AND fs_user.user_id = #{userId}
+            </if>
             <if test="companyId != null">
-                AND fs_user.company_id = #{companyId}
+                AND ucu.company_id = #{companyId}
             </if>
             <if test="companyUserId != null and companyUserId != '' ">
-                AND fs_user.company_user_id = #{companyUserId}
+                AND ucu.company_user_id = #{companyUserId}
             </if>
             <if test="registerStartTime != null and registerStartTime !='' ">
                 AND fs_user.create_time &gt;= #{registerStartTime}
@@ -333,7 +360,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 AND fs_user.create_time &lt;= #{registerEndTime}
             </if>
             <if test="companyUserIds != null and companyUserIds.size > 0">
-                AND fs_user.company_user_id in
+                AND ucu.company_user_id in
                 <foreach collection="companyUserIds" item="item" index="index" open="(" separator="," close=")">
                     ${item}
                 </foreach>
@@ -344,6 +371,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="phone != null and phone != ''">
                 AND fs_user.phone like concat('%', #{phone},'%')
             </if>
+            <if test="projectId != null">
+                AND ucu.project_id = #{projectId}
+            </if>
         </where>
         limit ${(pageNum-1)*pageSize},${pageSize}
     </select>
@@ -353,8 +383,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         count(1)
         FROM
         fs_user
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
         <where>
             fs_user.is_del = 0
+            <if test="companyId != null">
+                AND ucu.company_id = #{companyId}
+            </if>
+            <if test="companyUserId != null and companyUserId != '' ">
+                AND ucu.company_user_id = #{companyUserId}
+            </if>
             <if test="registerStartTime != null and registerStartTime !='' ">
                 AND fs_user.create_time &gt;= #{registerStartTime}
             </if>
@@ -362,7 +399,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 AND fs_user.create_time &lt;= #{registerEndTime}
             </if>
             <if test="companyUserIds != null and companyUserIds.size > 0">
-                AND fs_user.company_user_id in
+                AND ucu.company_user_id in
                 <foreach collection="companyUserIds" item="item" index="index" open="(" separator="," close=")">
                     ${item}
                 </foreach>
@@ -373,8 +410,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="phone != null and phone!=''">
                 AND fs_user.phone = #{phone}
             </if>
-            <if test="companyId != null">
-                AND fs_user.company_id = #{companyId}
+            <if test="projectId != null">
+                AND ucu.project_id = #{projectId}
             </if>
         </where>
     </select>
@@ -596,10 +633,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN company_user ON company_user.user_id = fs_user_company_user.company_user_id
         WHERE fs_user.is_del = 0
         <if test="userId != null and userId != 0 ">
-            and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+            and (fs_user_company_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
         </if>
         <if test="companyId != null ">
-            and fs_user.company_id = #{companyId}
+            and fs_user_company_user.company_id = #{companyId}
         </if>
         GROUP BY
             fs_user.`status`
@@ -632,7 +669,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_user_course_count
         LEFT JOIN fs_user ON fs_user.user_id = fs_user_course_count.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        inner JOIN fs_user_company_user cu ON cu.user_id = fs_user.user_id and cu.project_id = fs_user_course_count.project_id
         <where>
             <if test="dateTag != null and dateTag !='' ">
                 <choose>
@@ -650,6 +687,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     </when>
                 </choose>
             </if>
+            <if test="userCompanyId!=null">
+                and cu.id = #{userCompanyId}
+            </if>
             and fs_user.user_id = #{fsUserId}
         </where>
         GROUP BY
@@ -664,7 +704,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        left join fs_course_watch_log fcwl on fs_course_answer_logs.watch_log_id =fcwl.log_id
+        left join fs_user_company_user fucu on fucu.user_id =fs_user.user_id and fcwl.project = fucu.project_id
         <where>
 
             <if test="dateTag != null and dateTag !='' ">
@@ -683,18 +724,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     </when>
                 </choose>
             </if>
-            and fs_user.user_id = #{fsUserId}
+            and fs_user.user_id = #{fsUserId} and fucu.company_user_id =#{userId}
         </where>
         GROUP BY
         fs_user.user_id
         ) AS answerTime,
         (
         SELECT
-        ifnull(count( DISTINCT log_id ), 0) AS answerRightTime
+        ifnull(count( DISTINCT fs_course_answer_logs.log_id ), 0) AS answerRightTime
         FROM
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        left join fs_course_watch_log fcwl on fs_course_answer_logs.watch_log_id =fcwl.log_id
+        left join fs_user_company_user fucu on fucu.user_id =fs_user.user_id and fcwl.project = fucu.project_id
         <where>
             fs_course_answer_logs.is_right = 1
             <if test="dateTag != null and dateTag !='' ">
@@ -713,7 +755,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     </when>
                 </choose>
             </if>
-            and fs_user.user_id = #{fsUserId}
+            and fs_user.user_id = #{fsUserId} and fucu.company_user_id =#{userId}
         </where>
         GROUP BY
         fs_user.user_id
@@ -722,13 +764,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="getCountRedPacket" resultType="com.fs.store.vo.h5.UserDetailsVO">
         SELECT
-        ifnull( count( DISTINCT log_id ), 0 ) AS answerRedPacketTime,
+        ifnull( count( DISTINCT fs_course_red_packet_log.log_id ), 0 ) AS answerRedPacketTime,
         ifnull( sum( amount ), 0 ) AS answerRedPacketAmount,
         fs_user.user_id
         FROM
         fs_course_red_packet_log
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_red_packet_log.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        left join fs_course_watch_log fcwl on fs_course_red_packet_log.watch_log_id =fcwl.log_id
+        left join fs_user_company_user fucu on fucu.user_id =fs_user.user_id and fcwl.project = fucu.project_id
         <where>
             fs_course_red_packet_log.status = 1
             <if test="dateTag != null and dateTag !='' ">
@@ -747,7 +790,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     </when>
                 </choose>
             </if>
-            and  fs_user.user_id = #{fsUserId}
+            and  fs_user.user_id = #{fsUserId} and fucu.company_user_id =#{userId}
         </where>
         GROUP BY
         fs_user.user_id
@@ -756,45 +799,46 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="countUserSummary" resultType="com.fs.store.vo.h5.FsUserSummaryCountVO">
         SELECT (SELECT count(fs_user.user_id)
         FROM fs_user
-        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
+        LEFT JOIN company_user ON ucu.company_user_id = company_user.user_id
         WHERE fs_user.is_del = 0
         <if test="userId != null and userId != 0 ">
-            and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+            and (ucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
         </if>
         <if test="companyId != null ">
-            and fs_user.company_id = #{companyId}
+            and ucu.company_id = #{companyId}
         </if>
         ) as userTotal,
         (SELECT count(fs_user.user_id)
         FROM fs_user
-        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
+        LEFT JOIN company_user ON ucu.company_user_id = company_user.user_id
         WHERE fs_user.is_del = 0
         <if test="userId != null and userId != 0 ">
-            and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+            and (ucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
         </if>
         <if test="companyId != null ">
-            and fs_user.company_id = #{companyId}
+            and ucu.company_id = #{companyId}
         </if>
-        AND to_days(fs_user.create_time) = to_days(now())) as todayNewUser
+        AND to_days(ucu.create_time) = to_days(now())) as todayNewUser
     </select>
 
     <select id="countTag" resultType="com.fs.store.vo.h5.FsUserSummaryCountTagVO">
         SELECT
         company_tag.tag AS tagName,
-        count( fs_user.user_id ) AS number
+        count( ucu.user_id ) AS number
         FROM
-        company_tag_user
-        LEFT JOIN fs_user ON fs_user.user_id = company_tag_user.user_id
-        LEFT JOIN company_tag ON FIND_IN_SET( company_tag.tag_id, company_tag_user.tag_ids ) > 0
-        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        fs_user_project_tag upt
+        inner join fs_user_company_user ucu on ucu.id = upt.user_company_user_id
+        inner join company_tag ON upt.tag_id = company_tag.tag_id
+        left join company_user on company_user.user_id = ucu.company_user_id
         <where>
             <if test="userId != null and userId != 0 ">
-                and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                and (ucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="companyId != null ">
-                and fs_user.company_id = #{companyId}
+                and ucu.company_id = #{companyId}
             </if>
-            and company_tag.tag_id is not null
         </where>
         GROUP BY
         company_tag.tag_id
@@ -802,20 +846,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="countUserCourse" resultType="Map">
         SELECT
-        (
-        SELECT
-        count(distinct fcc.user_id )
-        FROM
-        fs_user_course_count fcc
-        LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
-        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        (SELECT COUNT(*) FROM (
+        SELECT 1
+        FROM fs_user_course_count fcc
+        JOIN fs_user ON fs_user.user_id = fcc.user_id
+        JOIN fs_user_company_user ucu ON ucu.user_id = fs_user.user_id
+        JOIN company_user ON ucu.company_user_id = company_user.user_id
         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET(fcpd.period_id, fcc.course_ids) > 0
         <where>
+            fcc.project_id = ucu.project_id
             <if test="userId != null and userId != 0 ">
-                and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                and (ucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and ucu.company_id = #{companyId}
             </if>
             <if test="startTime != null and startTime !='' ">
                 and fcc.create_time &gt;= #{startTime}
@@ -835,20 +879,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             </if>
         </where>
         ) as courseWatchNum,
-        (
-        SELECT
-        count(distinct fcc.user_id )
-        FROM
-        fs_user_course_count fcc
-        LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
-        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        (SELECT COUNT(*) FROM (
+        SELECT 1
+        FROM fs_user_course_count fcc
+        JOIN fs_user ON fs_user.user_id = fcc.user_id
+        JOIN fs_user_company_user ucu ON ucu.user_id = fs_user.user_id
+        JOIN company_user ON ucu.company_user_id = company_user.user_id
         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET(fcpd.period_id, fcc.course_ids) > 0
         <where>
+            fcc.project_id = ucu.project_id
             <if test="userId != null and userId != 0 ">
-                and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                and (ucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and ucu.company_id = #{companyId}
             </if>
             AND fcc.complete_watch_count > 0
             <if test="startTime != null and startTime !='' ">
@@ -868,24 +912,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 AND company_user.user_id = #{companyUserId}
             </if>
         </where>
-        ) as courseCompleteNum
+        GROUP BY fcc.user_id, ucu.project_id
+        ) AS complete_counts ) as courseCompleteNum
     </select>
 
     <select id="countUserAnswer" resultType="Map">
         SELECT
         (
         SELECT
-        count(distinct fs_user.user_id )
+        count(fs_user.user_id )
         FROM
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        LEFT JOIN company_user ON company_user.user_id = fs_course_answer_logs.company_user_id
+        left join fs_course_watch_log fcwl on fs_course_answer_logs.watch_log_id=fcwl.log_id
+        left join fs_user_company_user fucu on fucu.user_id =fs_user.user_id and fcwl.project = fucu.project_id
         <where>
             <if test="userId != null and userId != 0 ">
-                and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                and (fucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and fs_course_answer_logs.company_id = #{companyId}
             </if>
             <if test="startTime != null and startTime !='' ">
                 AND fs_course_answer_logs.create_time &gt;= #{startTime}
@@ -907,17 +954,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         ) AS answerNum,
         (
         SELECT
-        count(distinct fs_user.user_id )
+        count(fs_user.user_id )
         FROM
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        LEFT JOIN company_user ON company_user.user_id = fs_course_answer_logs.company_user_id
+        left join fs_course_watch_log fcwl on fs_course_answer_logs.watch_log_id=fcwl.log_id
+        left join fs_user_company_user fucu on fucu.user_id =fs_user.user_id and fcwl.project = fucu.project_id
         <where>
             <if test="userId != null and userId != 0 ">
-                and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                and (fucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and fs_course_answer_logs.company_id = #{companyId}
             </if>
             AND fs_course_answer_logs.is_right = 1
             <if test="startTime != null and startTime !='' ">
@@ -948,20 +997,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_user_course_period fpd on fpd.period_id = fcpd.period_id
         LEFT JOIN fs_user_course_count fcc ON FIND_IN_SET( fcpd.period_id, fcc.course_ids ) > 0
         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
-        WHERE 1=1
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
+        WHERE 1=1 and fcpd.del_flag =0 and fpd.del_flag =0
         AND FIND_IN_SET(#{companyId}, fpd.company_id)
         <if test="userId != null and userId != 0 ">
-            AND fs_user.company_user_id = #{userId}
+            AND ucu.company_user_id = #{userId}
         </if>
         <if test="userId != null and userId == 0 ">
-            and fs_user.company_id = #{companyId}
+            and ucu.company_id = #{companyId}
         </if>
         <if test="periodId != null and periodId != ''">
             AND fcpd.period_id =  #{periodId}
         </if>
         -- 单独通过销售id查询
         <if test="companyUserId != null and companyUserId != ''">
-            AND fs_user.company_user_id = #{companyUserId}
+            AND ucu.company_user_id = #{companyUserId}
         </if>
         ) as courseNum,
 
@@ -970,13 +1020,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_user_course_period fpd on fpd.period_id = fcpd.period_id
         LEFT JOIN fs_user_course_count fcc ON FIND_IN_SET( fcpd.period_id, fcc.course_ids ) > 0
         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
-        WHERE 1=1
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
+        WHERE 1=1 and fcpd.del_flag =0 and fpd.del_flag =0
         AND FIND_IN_SET(#{companyId}, fpd.company_id)
         <if test="userId != null and userId != 0 ">
-            AND fs_user.company_user_id = #{userId}
+            AND ucu.company_user_id = #{userId}
         </if>
         <if test="userId != null and userId == 0 ">
-            and fs_user.company_id = #{companyId}
+            and ucu.company_id = #{companyId}
         </if>
         <if test="periodId != null and periodId != ''">
             AND fcpd.period_id =  #{periodId}
@@ -986,13 +1037,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
         -- 单独通过销售id查询
         <if test="companyUserId != null and companyUserId != ''">
-            AND fs_user.company_user_id = #{companyUserId}
+            AND ucu.company_user_id = #{companyUserId}
         </if>
         ) as videoNum,
 
         ( SELECT count(DISTINCT fs_user.user_id ) FROM fs_user_course_count fcc
         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET( fcpd.period_id, fcc.course_ids ) > 0
         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
         <if test="periodId != null and periodId != ''">
             AND fcpd.period_id =  #{periodId}
         </if>
@@ -1001,14 +1053,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
         -- 单独通过销售id查询
         <if test="companyUserId != null and companyUserId != ''">
-            AND fs_user.company_user_id = #{companyUserId}
+            AND ucu.company_user_id = #{companyUserId}
         </if>
         <where>
             <if test="userId != null and userId != 0 ">
-                AND fs_user.company_user_id = #{userId}
+                AND ucu.company_user_id = #{userId}
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and ucu.company_id = #{companyId}
             </if>
         </where>
         ) as courseUserNum
@@ -1023,14 +1075,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_user_course_count fcc
         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
-        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
+        LEFT JOIN company_user ON ucu.company_user_id = company_user.user_id
         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET( fcpd.period_id, fcc.course_ids ) > 0
         <where>
             <if test="userId != null and userId != 0 ">
-                AND  ( fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                AND  ( ucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and ucu.company_id = #{companyId}
             </if>
             <if test="startTime != null and startTime !='' ">
                 AND fcc.create_time &gt;= #{startTime}
@@ -1070,13 +1123,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        LEFT JOIN company_user ON company_user.user_id = fs_course_answer_logs.company_user_id
         <where>
             <if test="userId != null and userId != 0 ">
-                AND  ( fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                AND  ( fs_course_answer_logs.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and fs_course_answer_logs.company_id = #{companyId}
             </if>
             <if test="startTime != null and startTime !='' ">
                 AND fs_course_answer_logs.create_time &gt;= #{startTime}
@@ -1127,10 +1180,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_user_course_video fcv ON fcv.video_id = fwl.video_id
         <where>
             <if test="userId != null and userId != 0 ">
-                AND ( fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                AND ( fs_user_company_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and fs_user_company_user.company_id = #{companyId}
             </if>
             <if test="startTime != null and startTime !='' ">
                 AND fwl.create_time &gt;= #{startTime}
@@ -1176,14 +1229,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         fs_course_answer_logs
         LEFT JOIN fs_user ON fs_user.user_id = fs_course_answer_logs.user_id
         LEFT JOIN fs_user_company_user ON fs_user_company_user.user_id = fs_user.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user_company_user.company_user_id
+        LEFT JOIN company_user ON company_user.user_id = fs_course_answer_logs.company_user_id
         LEFT JOIN fs_user_course_video fcv ON fcv.video_id = fs_course_answer_logs.video_id
         <where>
             <if test="userId != null and userId != 0 ">
-                AND ( fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                AND ( fs_course_answer_logs.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and fs_course_answer_logs.company_id = #{companyId}
             </if>
             <if test="startTime != null and startTime !='' ">
                 AND fs_course_answer_logs.create_time &gt;= #{startTime}
@@ -1222,13 +1275,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_course_red_packet_log flog
         LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        LEFT JOIN company_user ON company_user.user_id = flog.company_user_id
+        left join fs_course_watch_log fcwl on flog.watch_log_id =fcwl.log_id
+        left join fs_user_company_user fucu on fucu.user_id =fs_user.user_id and fcwl.project = fucu.project_id
         where flog.status = 1
             <if test="userId != null and userId != 0 ">
-                and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                and (fucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and flog.company_id = #{companyId}
             </if>
             <if test="startTime != null and startTime !='' ">
                 AND flog.create_time &gt;= #{startTime}
@@ -1253,13 +1308,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_course_red_packet_log flog
         LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
-        LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        LEFT JOIN company_user ON company_user.user_id = flog.company_user_id
+        left join fs_course_watch_log fcwl on flog.watch_log_id =fcwl.log_id
+        left join fs_user_company_user fucu on fucu.user_id =fs_user.user_id and fcwl.project = fucu.project_id
         where flog.status = 1
             <if test="userId != null and userId != 0 ">
-                and (fs_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+                and (fucu.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
             </if>
             <if test="userId != null and userId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and flog.company_id = #{companyId}
             </if>
             <if test="startTime != null and startTime !='' ">
                 AND flog.create_time &gt;= #{startTime}
@@ -1296,14 +1353,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         FROM
         fs_user_course_count fcc
         LEFT JOIN fs_user ON fs_user.user_id = fcc.user_id
-        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
+        LEFT JOIN company_user ON ucu.company_user_id = company_user.user_id
         LEFT JOIN fs_user_course_period_days fcpd ON FIND_IN_SET( fcpd.period_id, fcc.course_ids ) > 0
         <where>
             <if test="companyUserId != null and companyUserId != 0 ">
-                AND fs_user.company_user_id = #{companyUserId}
+                AND ucu.company_user_id = #{companyUserId}
             </if>
             <if test="companyUserId != null and companyUserId == 0 ">
-                and fs_user.company_id = #{companyId}
+                and ucu.company_id = #{companyId}
             </if>
             <if test="periodId != null and periodId != ''">
                 AND fcpd.period_id =  #{periodId}
@@ -1319,13 +1377,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="companyUserCount" resultType="com.fs.store.vo.h5.CompanyUserSummaryCountVO">
         SELECT
         (
-        SELECT count( fs_user.user_id ) FROM fs_user LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        SELECT count( fs_user.user_id ) FROM fs_user left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id LEFT JOIN company_user ON ucu.company_user_id = company_user.user_id
         <where>
             <if test="companyUserId != null and companyUserId != '' and companyUserId != '0' ">
-                AND fs_user.company_user_id = #{companyUserId}
+                AND ucu.company_user_id = #{companyUserId}
             </if>
             <if test="companyUserId != null and companyUserId != '' and companyUserId == '0' ">
-                and fs_user.company_id = #{companyId}
+                and ucu.company_id = #{companyId}
             </if>
         </where>
         ) AS userTotal,
@@ -1334,13 +1392,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         count( fs_user.user_id )
         FROM
         fs_user
-        LEFT JOIN company_user ON fs_user.company_user_id = company_user.user_id
+        left join fs_user_company_user ucu on ucu.user_id = fs_user.user_id
+        LEFT JOIN company_user ON ucu.company_user_id = company_user.user_id
         <where>
             <if test="companyUserId != null and companyUserId != '' and companyUserId != '0' ">
-                AND fs_user.company_user_id = #{companyUserId}
+                AND ucu.company_user_id = #{companyUserId}
             </if>
             <if test="companyUserId != null and companyUserId != '' and companyUserId == '0' ">
-                and fs_user.company_id = #{companyId}
+                and ucu.company_id = #{companyId}
             </if>
             and fs_user.is_del = 0
             AND to_days( fs_user.create_time ) = to_days(
@@ -1358,10 +1417,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
         <where>
             <if test="companyUserId != null and companyUserId != '' and companyUserId != '0' ">
-                AND fs_user.company_user_id = #{companyUserId}
+                AND flog.company_user_id = #{companyUserId}
             </if>
             <if test="companyUserId != null and companyUserId != '' and companyUserId == '0' ">
-                and fs_user.company_id = #{companyId}
+                and flog.company_id = #{companyId}
             </if>
         </where>
     </select>
@@ -1375,10 +1434,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         fs_course_watch_log l
         LEFT JOIN fs_user on fs_user.user_id = l.user_id
         LEFT JOIN company_user ON l.company_user_id = company_user.user_id
+        LEFT JOIN fs_user_company_user ON fs_user_company_user.user_id = fs_user.user_id and l.project =fs_user_company_user.project_id
         where
         l.log_type != 3 and send_type = 1
         <if test="userId != null and userId != 0 ">
-            and (l.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+            and (fs_user_company_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
         </if>
         <if test="userId != null and userId == 0 ">
             and l.company_id = #{companyId}
@@ -1394,7 +1454,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
         <if test="endTime != null and endTime != ''">
             and l.create_time &lt;= #{endTime}
-        </if>
+        </if> <if test="companyUserId != null and companyUserId != ''">
+        AND l.user_id = #{companyUserId}
+    </if>
         -- 单独通过销售id查询
         <if test="companyUserId != null and companyUserId != ''">
             AND l.company_user_id = #{companyUserId}
@@ -1405,12 +1467,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         count(DISTINCT l.user_id)
         FROM
         fs_course_watch_log l
-        LEFT JOIN fs_user on fs_user.user_id = l.user_id
         LEFT JOIN company_user ON l.company_user_id = company_user.user_id
+        LEFT JOIN fs_user ON fs_user.user_id = l.user_id
+        LEFT JOIN fs_user_company_user ON fs_user_company_user.user_id = fs_user.user_id and l.project =fs_user_company_user.project_id
         where
         l.log_type = 2 and send_type = 1
         <if test="userId != null and userId != 0 ">
-            and (l.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
+            and (fs_user_company_user.company_user_id = #{userId} OR company_user.parent_id = #{userId} )
         </if>
         <if test="userId != null and userId == 0 ">
             and l.company_id = #{companyId}
@@ -1463,4 +1526,84 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             AND l.company_user_id = #{companyUserId}
         </if>
     </select>
+
+    <select id="selectFsUserVOListByProject" resultType="com.fs.his.vo.FsUserVO">
+        SELECT distinct
+        b.total_amount,b.last_buy_time,p.pay_money as number,p.payment_id,p.pay_time,
+        u.*,
+        fcc.watch_course_count, fcc.part_course_count, company_user.nick_name AS companyUserNickName, fcc.last_watch_date
+        ,company.company_name,
+        ucu.project_id,
+        ucu.id as companyUserId
+        FROM
+        fs_user u
+        LEFT JOIN (
+        SELECT max( payment_id ) AS payment_id, max( pay_time ) AS last_buy_time, SUM( pay_money ) AS total_amount,
+        user_id
+        FROM
+        fs_store_payment
+        WHERE
+        STATUS = 1
+        AND user_id IS NOT NULL
+        GROUP BY
+        user_id
+        ) b ON u.user_id = b.user_id
+        LEFT JOIN fs_store_payment p ON u.user_id = p.user_id
+        AND b.last_buy_time = p.pay_time
+        AND b.payment_id = p.payment_id
+        LEFT JOIN (
+        SELECT
+        fs_user_course_count.user_id,Max( fs_user_course_count.last_watch_date ) AS last_watch_date,fs_user_course_count.watch_course_count,
+        fs_user_course_count.part_course_count
+        FROM
+        fs_user_course_count
+        GROUP BY fs_user_course_count.user_id
+        ) fcc ON fcc.user_id = u.user_id
+        left join fs_user_company_user ucu on ucu.user_id = u.user_id
+        LEFT JOIN company_user ON company_user.user_id = ucu.company_user_id
+        LEFT JOIN company on company.company_id = company_user.company_id
+        <where>
+            1 = 1 and u.nickname is not null
+            <if test = "maps.nickname != null and  maps.nickname !='' " >
+                AND u.nickname LIKE CONCAT("%",#{maps.nickname},"%")
+            </if >
+            <if test = "maps.userId != null and  maps.userId !='' " >
+                AND u.user_id = #{maps.userId}
+            </if >
+            <if test = "maps.phone != null   and  maps.phone !='' " >
+                AND u.phone LIKE CONCAT("%",#{maps.phone},"%")
+            </if >
+            <if test = "maps.startCreateTime != null and maps.endCreateTime != null" >
+                AND (DATE_FORMAT( u.create_time, "%Y-%m-%d" ) &gt;= DATE_FORMAT(#{maps.startCreateTime}, "%Y-%m-%d")
+                and DATE_FORMAT( u.create_time, "%Y-%m-%d" ) &lt;= DATE_FORMAT(#{maps.endCreateTime}, "%Y-%m-%d")
+                )
+            </if >
+            <if test = "maps.registerCode != null  and  maps.registerCode !=''  " >
+                AND u.register_code = #{maps.registerCode}
+            </if >
+            <if test = "maps.status != null" >
+                AND u.STATUS = #{maps.status}
+            </if >
+            <if test = "maps.companyUserNickName != null and maps.companyUserNickName != '' " >
+                AND company_user.nick_name like CONCAT ("%",#{maps.companyUserNickName},"%")
+            </if >
+            <if test = "maps.companyName != null and maps.companyName != '' " >
+                AND company.company_name like CONCAT ("%",#{maps.companyName},"%")
+            </if >
+            <if test = "maps.companyId != null and maps.companyId != '' " >
+                AND company.company_id = #{maps.companyId}
+            </if >
+            <if test = "maps.level != null  and  maps.level !=''" >
+                AND u.LEVEL = #{maps.level}
+            </if >
+            <if test = "maps.isPromoter != null  and  maps.isPromoter !=''" >
+                AND u.is_promoter = #{maps.isPromoter}
+            </if >
+            <if test = "maps.projectId != null" >
+                AND ucu.project_id = #{maps.projectId}
+            </if >
+        </where>
+        ORDER BY
+        user_id DESC
+    </select>
 </mapper>

+ 29 - 0
fs-service/src/main/resources/mapper/his/FsUserProjectTagMapper.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsUserProjectTagMapper">
+
+    <select id="getTagList" resultType="com.fs.store.vo.h5.CompanyUserTagListVO">
+        select distinct
+            tag.tag_id,
+            tag.tag tagName
+        from company_tag tag
+        inner join fs_user_project_tag upt on tag.tag_id = upt.tag_id
+        inner join fs_user_company_user ucu on ucu.id = upt.user_company_user_id
+        <where>
+            <if test="params.companyId != null">
+                and ucu.company_id = #{params.companyId}
+            </if>
+            <if test="params.companyUserId != null">
+                and ucu.company_user_id = #{params.companyUserId}
+            </if>
+            <if test="params.keywords != null and params.keywords.length > 0 ">
+                and
+                <foreach item="item" collection="params.keywords" open="(" separator="or" close=")">
+                    tag.tag like concat('%',#{item},'%')
+                </foreach>
+            </if>
+        </where>
+    </select>
+</mapper>