Prechádzať zdrojové kódy

红德堂-销售端项目会员新增导出

Long 18 hodín pred
rodič
commit
7421b8145d

+ 41 - 0
fs-company/src/main/java/com/fs/user/FsUserAdminController.java

@@ -17,7 +17,9 @@ import com.fs.course.service.IFsUserCourseService;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 
+import com.fs.his.domain.FsExportTask;
 import com.fs.his.domain.FsUser;
+import com.fs.his.service.IFsExportTaskService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.im.dto.OpenImResponseDTO;
@@ -25,6 +27,7 @@ import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.CustomerTransferApproval;
 import com.fs.qw.dto.FsUserTransferParamDTO;
 import com.fs.qw.service.ICustomerTransferApprovalService;
+import com.fs.store.param.h5.FsUserPageListExportParam;
 import com.fs.store.param.h5.FsUserPageListParam;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -63,6 +66,8 @@ public class FsUserAdminController extends BaseController {
 
     @Autowired
     private OpenIMService openIMService;
+    @Autowired
+    private IFsExportTaskService exportTaskService;
 
     @PreAuthorize("@ss.hasPermi('user:fsUser:list')")
     @PostMapping("/list")
@@ -87,6 +92,42 @@ public class FsUserAdminController extends BaseController {
         return fsUserService.selectFsUserPageListNew(param);
     }
 
+    @PreAuthorize("@ss.hasPermi('user:fsUser:export')")
+    @PostMapping("/export")
+    @Log(title = "项目会员列表", businessType = BusinessType.EXPORT)
+    @ApiOperation("项目会员列表导出(与移动端使用的相同查询)")
+    public AjaxResult projectUserExport(FsUserPageListExportParam param) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        if(param.getPhone()!=null && !"".equals(param.getPhone())){
+            param.setPhone(PhoneUtil.encryptPhone(param.getPhone()));
+        }
+
+        Long userId = loginUser.getUser().getUserId();
+        Integer exportType1 = exportTaskService.isExportType2(userId);
+        if (exportType1 > 0){
+            return AjaxResult.error("你已经有正在导出的任务");
+        }
+
+        Long count = fsUserService.selectProjectUserExportCount(param);
+        if (count > 30000){
+            return AjaxResult.error("导出数据不可超过3w条");
+        }
+
+        FsExportTask task=new FsExportTask();
+        task.setTaskType(12);
+        task.setStatus(0);
+        task.setStartTime(new Date());
+        task.setRemark("项目会员导出");
+        task.setSysType(2);
+        task.setCompanyUserId(userId);
+        exportTaskService.insertFsExportTask(task);
+        param.setTaskId(task.getTaskId());
+        fsUserService.exportProjectUserData(param);
+
+        return new AjaxResult(200,"后台正在导出,请等待...任务ID:"+task.getTaskId(),task.getTaskId());
+    }
+
     @PreAuthorize("@ss.hasPermi('user:fsUser:myList')")
     @PostMapping("/myList")
     @ApiOperation("我的会员列表(与移动端使用的相同查询)")

+ 11 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java

@@ -20,6 +20,7 @@ import com.fs.hisStore.vo.FsCompanyUserListQueryVO;
 import com.fs.qw.dto.FsUserTransferParamDTO;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
+import com.fs.store.param.h5.FsUserPageListExportParam;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.param.h5.UserStatisticsCommonParam;
 import com.fs.store.vo.UserProjectPair;
@@ -476,4 +477,14 @@ public interface FsUserMapper
     void updateUserOrderCountAndAmount(@Param("userId") Long userId, @Param("amount") BigDecimal amount);
 
     List<FsUser> selectFsUserListByPhone(String phone);
+
+    /**
+     * 项目会员导出数据条数查询
+     */
+    Long selectProjectUserExportCount(FsUserPageListExportParam param);
+
+    /**
+     * 项目会员导出数据
+     */
+    List<FsUserPageListExportVO> FsUserPageListExportVO(FsUserPageListExportParam param);
 }

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

@@ -28,6 +28,7 @@ import com.fs.live.vo.HisFsUserVO;
 import com.fs.qw.dto.FsUserTransferParamDTO;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
+import com.fs.store.param.h5.FsUserPageListExportParam;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.param.h5.UserStatisticsCommonParam;
 import com.fs.store.vo.h5.*;
@@ -240,4 +241,14 @@ public interface IFsUserService
     HisFsUserVO getHisUserIntegralWithLogs(FsUser fsUser);
 
     List<FsUser> selectFsUserListByPhone(String phone);
+
+    /**
+     * 项目会员导出数据条数查询
+     */
+    Long selectProjectUserExportCount(FsUserPageListExportParam param);
+
+    /**
+     * 项目会员导出
+     */
+    void exportProjectUserData(FsUserPageListExportParam param);
 }

+ 138 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java

@@ -19,6 +19,7 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.constant.HttpStatus;
+import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.domain.entity.SysDictData;
@@ -31,6 +32,7 @@ import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.DictUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.cache.ICompanyTagCacheService;
 import com.fs.company.cache.ICompanyUserCacheService;
 import com.fs.company.domain.*;
@@ -80,6 +82,7 @@ import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
 import com.fs.store.domain.FsUserCourseCount;
 import com.fs.store.mapper.FsUserCourseCountMapper;
+import com.fs.store.param.h5.FsUserPageListExportParam;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.param.h5.UserStatisticsCommonParam;
 import com.fs.store.service.cache.IFsUserCourseCountCacheService;
@@ -196,6 +199,8 @@ public class FsUserServiceImpl implements IFsUserService {
     private FsPatientMapper fsPatientMapper;
     @Autowired
     private FsCourseWatchLogMapper courseWatchLogMapper;
+    @Autowired
+    FsExportTaskMapper fsExportTaskMapper;
 
 
     /**
@@ -1619,4 +1624,137 @@ public class FsUserServiceImpl implements IFsUserService {
         return fsUserMapper.selectFsUserListByPhone(phone);
     }
 
+    /**
+     * 项目会员导出数据条数查询
+     */
+    @Override
+    public Long selectProjectUserExportCount(FsUserPageListExportParam param) {
+        return fsUserMapper.selectProjectUserExportCount(param);
+    }
+
+    /**
+     * 项目会员导出
+     */
+    @Override
+    public void exportProjectUserData(FsUserPageListExportParam param) {
+        // 找出下级销售
+        String companyUserId = param.getCompanyUserId();
+        if (StringUtils.isNotBlank(companyUserId)) {
+            Long companyUser = Long.parseLong(companyUserId);
+            Set<Long> userIds = companyUserCacheService.selectUserAllCompanyUserId(companyUser);
+            if (userIds != null || userIds.size() <= 1) {
+                if (param.getIsAdmin() != null && param.getIsAdmin()) {
+                    List<CompanyUser> companyUsers = companyUserMapper.selectCompanyUserByCompanyId(param.getCompanyId());
+                    userIds = companyUsers.stream().map(CompanyUser::getUserId).collect(Collectors.toSet());
+                }
+            }
+            param.setCompanyUserIds(userIds);
+        }
+
+        List<FsUserPageListExportVO> fsUserPageListVOS = fsUserMapper.FsUserPageListExportVO(param);
+        Map<Long, CompanyTag> tagMap = companyTagCacheService.queryAllTagMap();
+        //获取会员的最新的看课状态和最后看课时间
+        Set<Long> userIds = fsUserPageListVOS.stream().map(FsUserPageListExportVO::getUserId).collect(Collectors.toSet());
+        List<FsUserLastCount> fsUserCourseCounts = Collections.emptyList();
+        if (!userIds.isEmpty()) {
+            fsUserCourseCounts = fsUserCourseCountMapper.selectUserLastCount(userIds);
+        }
+        Map<Long, FsUserLastCount> countMap = fsUserCourseCounts.stream().collect(Collectors.toMap(FsUserLastCount::getUserId, Function.identity()));
+
+        List<UserProjectPair> pairs = fsUserPageListVOS.stream()
+                .map(user -> new UserProjectPair(user.getUserId(), user.getProjectId()))
+                .collect(Collectors.toList());
+        Map<Object, Date> watchTimeMap = new HashMap<>();
+        if(CollectionUtils.isNotEmpty(pairs)){
+            List<Map<String, Object>> mapList = fsUserMapper.selectLastWatchTimeByUserAndProject(pairs);
+            if (!CollectionUtils.isEmpty(mapList)) {
+                watchTimeMap = mapList.stream()
+                        .collect(HashMap::new,
+                                (map, item) -> map.put(
+                                        item.get("userProjectKey"),
+                                        (Date) item.get("lastWatchTime")
+                                ),
+                                HashMap::putAll
+                        );
+            }
+        }
+        for (FsUserPageListExportVO item : fsUserPageListVOS) {
+            if (item.getCompanyUserId() != null) {
+                String companyUserName = companyUserCacheService.selectCompanyUserNameUserById(item.getCompanyUserId());
+                if (companyUserName != null) {
+                    item.setCompanyUserNickName(companyUserName);
+                }
+            }
+            if (item.getPhone() != null) {
+                item.setPhone(ParseUtils.parsePhone(item.getPhone()));
+            }
+            if (item.getStatus() != null) {
+                String userStatus = DictUtils.getDictLabel("user_status", String.valueOf(item.getStatus()));
+                if (StringUtils.isNotBlank(userStatus)) {
+                    item.setStatusText(userStatus);
+                }
+            }
+            if (item.getUserId() != null) {
+                FsUserCourseCount byUserId = fsUserCourseCountCacheService.findByUserId(item.getUserId());
+                if (byUserId != null) {
+                    item.setWatchCourseCount(byUserId.getWatchCourseCount());
+                    item.setMissCourseCount(byUserId.getMissCourseCount());
+                    item.setMissCourseStatus(byUserId.getMissCourseStatus());
+                    if (StringUtils.isNotEmpty(byUserId.getPartCourseCount())) {
+                        item.setPartCourseCount(new BigDecimal(byUserId.getPartCourseCount()).longValue());
+                    }
+//                    item.setCourseCountStatus(byUserId.getStatus());
+                    item.setStopWatchDays(byUserId.getStopWatchDays());
+                    item.setCompleteWatchDate(byUserId.getCompleteWatchDate());
+                    item.setLastWatchDate(watchTimeMap.getOrDefault(item.getUserId() + "_" + item.getProjectId(),null));
+                }
+                FsUserLastCount fsUserCourseCount = countMap.get(item.getUserId());
+                if (fsUserCourseCount != null) {
+                    item.setCourseCountStatus(fsUserCourseCount.getStatus());
+                }
+                String userTagByUserId = companyTagCacheService
+                        .findUserTagByUserId(item.getUserId(), item.getCompanyUserId());
+                if (StringUtils.isNotEmpty(userTagByUserId)) {
+                    String[] split = userTagByUserId.split(",");
+                    Set<String> tagNames = new HashSet<>();
+                    for (String tag : split) {
+                        if (StringUtils.isNotBlank(tag)) {
+                            Long tagL = Long.parseLong(tag);
+                            CompanyTag companyTag = tagMap.get(tagL);
+                            if (companyTag != null) {
+                                tagNames.add(companyTag.getTag());
+                            }
+                        }
+                    }
+                    item.setTagIds(userTagByUserId);
+                    item.setTag(String.join(",", tagNames));
+                }
+
+                // 是否宠粉
+//                Integer isRepeat = qwExternalContactCacheService.selectQwIsRepeat(item.getUserId());
+//                if(isRepeat != null) {
+//                    item.setIsRepeat(isRepeat);
+//                }
+            }
+
+            // 解密
+            if (item.getPhone() != null && item.getPhone() != "") {
+                if (item.getPhone().length() > 11) {
+                    item.setPhone(decryptPhoneMk(item.getPhone()));
+                } else {
+                    item.setPhone(item.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                }
+            }
+
+        }
+
+        ExcelUtil<FsUserPageListExportVO> util = new ExcelUtil<>(FsUserPageListExportVO.class);
+        AjaxResult result =  util.exportExcel(fsUserPageListVOS, "项目会员");
+        FsExportTask task=fsExportTaskMapper.selectFsExportTaskByTaskId(param.getTaskId());
+        task.setFinishTime(new Date());
+        task.setStatus(1);
+        task.setFileUrl(result.get("msg").toString());
+        fsExportTaskMapper.updateFsExportTask(task);
+    }
+
 }

+ 89 - 0
fs-service/src/main/java/com/fs/store/param/h5/FsUserPageListExportParam.java

@@ -0,0 +1,89 @@
+package com.fs.store.param.h5;
+
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Set;
+
+
+@Data
+public class FsUserPageListExportParam implements Serializable {
+
+    @ApiModelProperty(value = "模糊搜索,可以通过微信名称、电话来模糊匹配")
+    private String keyword;
+
+    @ApiModelProperty(value = "用户id,不用传")
+    private Long userId;
+
+    @ApiModelProperty(value = "是否是黑名单,默认是false", required = true)
+    private Boolean isBlack = false;
+
+    @ApiModelProperty(value = "销售id")
+    private String companyUserId;
+
+    @ApiModelProperty(value = "注册时间-开始")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String registerStartTime;
+
+    @ApiModelProperty(value = "注册时间-结束")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String registerEndTime;
+
+    @ApiModelProperty(value = "标签")
+    private String[] tagIds;
+
+    @ApiModelProperty(value = "tab序号,0全部;1今日新增;2今日完播;3未看过课")
+    private String tabValue;
+
+    @ApiModelProperty(value = "看课状态,0全部;1未看过课;2正常看课;3停止看课")
+    private String watchCourseType;
+
+    @ApiModelProperty(value = "缺课状态,0全部;1-已缺课;2-未缺课")
+    private String missCourseStatus;
+
+    @ApiModelProperty(value = "排序,0-按注册时间晚到早;1-会员姓名0-9-A-Z")
+    private String continueMissCourseSort;
+
+    @ApiModelProperty(value = "昵称 (PC端使用)")
+    private String nickname;
+
+    @ApiModelProperty(value = "电话 (PC端使用)")
+    private String phone;
+
+    /**
+     * 公司id
+     */
+    private Long companyId;
+
+    private Set<Long> companyUserIds;
+
+    /**
+     * 销售端登录用户id(该字段用于区分之前的登录用户)
+     */
+    private Long pcLoginUserId;
+    private Long projectId;
+    /**
+     * 是否为我的
+     */
+    private Boolean isMyFsUser = Boolean.TRUE;
+
+    private Boolean isAdmin;
+    /**
+     * 判断是否选择了无标签
+     */
+    private Boolean isNullTag =false;
+
+    @ApiModelProperty(value = "状态 0小黑屋 1正常 2拉黑")
+    private Integer status;
+    /**
+     * 电话是否隐藏中间部分
+     */
+    private Boolean isHidePhoneMiddle = Boolean.TRUE;
+
+    private Long taskId;
+
+}
+

+ 131 - 0
fs-service/src/main/java/com/fs/store/vo/h5/FsUserPageListExportVO.java

@@ -0,0 +1,131 @@
+package com.fs.store.vo.h5;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 用户分页列表返回对象
+ */
+@Data
+@ApiModel
+public class FsUserPageListExportVO {
+
+    @ApiModelProperty(value = "用户id")
+    @Excel(name = "ID")
+    private Long userId;
+
+    @ApiModelProperty(value = "项目名称")
+    @Excel(name = "项目", dictType = "sys_course_project")
+    private Integer projectId;
+
+    @ApiModelProperty(value = "用户昵称")
+    @Excel(name = "昵称")
+    private String nickname;
+
+    @ApiModelProperty(value = "手机号码")
+    @Excel(name = "手机号码")
+    private String phone;
+
+    @ApiModelProperty(value = "看课数量")
+    @Excel(name = "看课数量")
+    private Long watchCourseCount;
+
+    @ApiModelProperty(value = "缺课数量")
+    @Excel(name = "缺课数量")
+    private Long missCourseCount;
+
+    @ApiModelProperty(value = "参与营期数量")
+    @Excel(name = "参与营期数量")
+    private Long partCourseCount;
+
+    @ApiModelProperty(value = "状态:1为正常,0为禁止")
+    @Excel(name = "状态", dictType = "user_status")
+    private Integer status;
+
+    @ApiModelProperty(value = "用户状态,1-正常;2-停止;3-未看")
+    @Excel(name = "看课状态", readConverterExp = "1=正常看课,2=停止看课,3=未看课,null=未知状态")
+    private Long courseCountStatus;
+
+    @ApiModelProperty(value = "标签名称")
+    @Excel(name = "标签")
+    private String tag;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "最后一次看课时间")
+    @Excel(name = "最后看课时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date lastWatchDate;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "注册时间")
+    @Excel(name = "注册时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @ApiModelProperty(value = "备注")
+    @Excel(name = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "销售名称")
+    @Excel(name = "所属员工")
+    private String companyUserNickName;
+
+    @ApiModelProperty(value = "用户积分")
+    @Excel(name = "会员积分")
+    private BigDecimal integral;
+
+    @ApiModelProperty(value = "是否购买 1:是 0 否")
+    @Excel(name = "是否购买", readConverterExp = "0=否,1=是")
+    private BigDecimal isBuy;
+
+
+
+
+    private String statusText;
+
+    @ApiModelProperty(value = "公司id")
+    private Long companyId;
+
+    @ApiModelProperty(value = "销售id(目前的登录用户id)")
+    private Long companyUserId;
+
+    @ApiModelProperty(value = "缺课状态,1-已缺课;2-未缺课")
+    private Long missCourseStatus;
+
+    @ApiModelProperty(value = "停课天数")
+    private Long stopWatchDays;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "完播时间")
+    private Date completeWatchDate;
+
+    @ApiModelProperty(value = "标签ids,多个用逗号隔开")
+    private String tagIds;
+
+    @ApiModelProperty(value = "是否属于当前销售")
+    private int isCurrentCompanyUser;
+
+    /**
+     * 是否宠粉
+     */
+    private Integer isRepeat;
+
+    private String projectName;
+
+    @ApiModelProperty(value = "是否是重粉,1-是,0-否")
+    private int isRepeatFans;
+
+    @ApiModelProperty(value = "重粉所属销售,多个用逗号隔开")
+    private String repeatCompanyUserName;
+
+    @ApiModelProperty(value = "用户-项目-销售ID")
+    private Long userCompanyUserId;
+
+    @ApiModelProperty(value = "用户头像")
+    private String avatar;
+
+}

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

@@ -2391,4 +2391,98 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select * from fs_user where phone=#{phone}
     </select>
 
+    <select id="selectProjectUserExportCount" resultType="java.lang.Long">
+        SELECT 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="userId != null">
+                AND fs_user.user_id = #{userId}
+            </if>
+            <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 ucu.update_time >= #{registerStartTime}
+            </if>
+            <if test="registerEndTime != null and registerEndTime !='' ">
+                <![CDATA[
+                AND ucu.update_time < date_add(#{registerEndTime}, interval 1 day)
+            ]]>
+            </if>
+            <if test="companyUserIds != null and companyUserIds.size > 0">
+                AND ucu.company_user_id in
+                <foreach collection="companyUserIds" item="item" index="index" open="(" separator="," close=")">
+                    ${item}
+                </foreach>
+            </if>
+            <if test="nickname != null and nickname != ''">
+                AND fs_user.nick_name like concat('%', #{nickname},'%')
+            </if>
+            <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>
+    </select>
+
+    <select id="FsUserPageListExportVO" resultType="com.fs.store.vo.h5.FsUserPageListExportVO">
+        SELECT
+            fs_user.user_id,
+            fs_user.nick_name as nickname,
+            fs_user.avatar,
+            fs_user.phone,
+            fs_user.status,
+            ucu.update_time createTime,
+            fs_user.remark,
+            ucu.company_user_id,
+            ucu.company_id,
+            ucu.project_id,
+            fs_user.integral,
+            if(fs_user.pay_count>0,1,0) as isBuy
+        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="userId != null">
+                AND fs_user.user_id = #{userId}
+            </if>
+            <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 ucu.update_time &gt;= #{registerStartTime}
+            </if>
+            <if test="registerEndTime != null and registerEndTime !='' ">
+                <![CDATA[
+                AND ucu.update_time < date_add(#{registerEndTime}, interval 1 day)
+            ]]>
+            </if>
+            <if test="companyUserIds != null and companyUserIds.size > 0">
+                AND ucu.company_user_id in
+                <foreach collection="companyUserIds" item="item" index="index" open="(" separator="," close=")">
+                    ${item}
+                </foreach>
+            </if>
+            <if test="nickname != null and nickname != ''">
+                AND fs_user.nick_name like concat('%', #{nickname},'%')
+            </if>
+            <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>
+    </select>
+
 </mapper>