三七 4 дней назад
Родитель
Сommit
b9549d2d94

+ 11 - 0
fs-admin/src/main/java/com/fs/qw/qwTask/qwTask.java

@@ -44,6 +44,9 @@ public class qwTask {
     @Autowired
     private IQwUserService qwUserService;
 
+    @Autowired
+    private IQwAcquisitionAssistantService qwAcquisitionAssistantService;
+
 
     @Autowired
     private FsStatisSalerWatchService fsStatisSalerWatchService;
@@ -278,4 +281,12 @@ public class qwTask {
         Integer companyServerNum=1;
         iFsUserCourseService.processQwSopPhoneRedPacketMaterialTimer(companyServerNum);
     }
+    /**
+    * 每天重置 获客链接里的 员工账号可添加次数
+    */
+    public void resetAcquisitionLinkUserLimit() {
+        qwAcquisitionAssistantService.resetAcquisitionLinkUserLimit();
+
+    }
+
 }

+ 4 - 3
fs-company/src/main/java/com/fs/company/controller/qw/QwAcquisitionAssistantController.java

@@ -107,8 +107,9 @@ public class QwAcquisitionAssistantController extends BaseController {
         try {
             LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
             qwAcquisitionAssistant.setCreateBy(String.valueOf(loginUser.getUser().getUserId()));
+            Long companyId = loginUser.getUser().getCompanyId();
             QwCompany qwCompany = getQwCompany(qwAcquisitionAssistant.getCorpId());
-            QwAcquisitionAssistant result = qwAcquisitionAssistantService.createWithQw(qwCompany.getCorpId(), qwCompany.getOpenSecret(), qwAcquisitionAssistant);
+            QwAcquisitionAssistant result = qwAcquisitionAssistantService.createWithQw(qwCompany.getCorpId(), qwCompany.getOpenSecret(), qwAcquisitionAssistant,companyId);
             return AjaxResult.success("创建成功", result);
         } catch (CustomException e) {
             return AjaxResult.error(e.getMessage());
@@ -183,7 +184,7 @@ public class QwAcquisitionAssistantController extends BaseController {
             qwAcquisitionAssistant.setUpdateBy(String.valueOf(loginUser.getUser().getUserId()));
             QwCompany qwCompany = getQwCompany(qwAcquisitionAssistant.getCorpId());
             QwAcquisitionAssistant result = qwAcquisitionAssistantService.updateWithQw(
-                    qwCompany.getCorpId(), qwCompany.getOpenSecret(), qwAcquisitionAssistant);
+                    qwCompany.getCorpId(), qwCompany.getOpenSecret(), qwAcquisitionAssistant,loginUser.getUser().getCompanyId());
 
             return AjaxResult.success("修改成功", result);
         } catch (CustomException e) {
@@ -244,4 +245,4 @@ public class QwAcquisitionAssistantController extends BaseController {
             throw new CustomException("电话号码格式不正确,请输入正确的手机号或固定电话", 400);
         }
     }
-}
+}

+ 14 - 4
fs-qwhook/src/main/java/com/fs/app/controller/ApisCommonController.java

@@ -13,6 +13,7 @@ import com.fs.qw.mapper.QwCompanyMapper;
 import com.fs.qw.mapper.QwExternalContactCrmMapper;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.param.QwConfigSignatureParam;
+import com.fs.qw.service.IQwExternalContactService;
 import com.fs.qw.service.IQwJsApiService;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qw.service.IQwUserVideoService;
@@ -27,6 +28,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.text.ParseException;
+
 
 @Api("公共接口")
 @RestController
@@ -66,15 +69,22 @@ public class ApisCommonController {
     @Autowired
     RedisCache redisCache;
 
+    @Autowired
+    IQwExternalContactService qwExternalContactService;
+
 
     @Autowired
     private IQwUserVideoService qwUserVideoService;
 
 
-    @PostMapping("/qwHookSendMsg")
-    public R qwHookSendMsg(@RequestBody QwHookSendMsgParam param ) {
-        param.setClientId(2);
-        return qwHookApiService.sendMsg(param);
+    @GetMapping("/qwHookSendMsg")
+    public R qwHookSendMsg() throws ParseException {
+
+        qwExternalContactService.insertQwExternalContactByExternalUserId("wmGqY6UAAAbR4q7V9-_3NcY631xYj95g"
+                ,"ShiGuoWei"
+                ,null,"wwe1d17c4f00599bea","link:32","CDATA[CyFyIvU44nYM_j6Vk3DLKnW3UiRKXz2_iCCIypSqR_o");
+
+        return R.ok();
     }
 
     @GetMapping("/qwHookAuth")

+ 13 - 4
fs-service/src/main/java/com/fs/qw/domain/QwAcquisitionAssistant.java

@@ -1,5 +1,6 @@
 package com.fs.qw.domain;
 
+import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import com.alibaba.fastjson.JSON;
 import lombok.Data;
@@ -9,7 +10,7 @@ import java.util.List;
 
 /**
  * 企微-获客链接管理对象 qw_acquisition_assistant
- * 
+ *
  * @author fs
  * @date 2026-03-16
  */
@@ -95,7 +96,7 @@ public class QwAcquisitionAssistant extends BaseEntity
     /**
      * 将参数列表转换为JSON字符串
      */
-    public void buildJsonFields() 
+    public void buildJsonFields()
     {
         if (userListParam != null) {
             this.userList = JSON.toJSONString(userListParam);
@@ -111,7 +112,7 @@ public class QwAcquisitionAssistant extends BaseEntity
     /**
      * 解析JSON字段到参数列表
      */
-    public void parseJsonFields() 
+    public void parseJsonFields()
     {
         if (StringUtils.isNotBlank(this.userList)) {
             this.userListParam = JSON.parseArray(this.userList, String.class);
@@ -133,4 +134,12 @@ public class QwAcquisitionAssistant extends BaseEntity
                 ", status=" + status +
                 '}';
     }
-}
+
+    /** 员工添加上限 */
+    @Excel(name = "员工添加上限")
+    private String userLimitJson;
+
+    /** 备用员工 */
+    @Excel(name = "备用员工")
+    private String spareUserIds;
+}

+ 50 - 0
fs-service/src/main/java/com/fs/qw/domain/QwContactAcquisitionUser.java

@@ -0,0 +1,50 @@
+package com.fs.qw.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 获客链接限制对象 qw_contact_acquisition_user
+ *
+ * @author fs
+ * @date 2026-04-20
+ */
+@Data
+public class QwContactAcquisitionUser{
+
+    /** id */
+    private Long id;
+
+    /** 获客链接的id */
+    @Excel(name = "获客链接的id")
+    private String linkId;
+
+    /** 企微员工id */
+    @Excel(name = "企微员工id")
+    private Long qwUserId;
+
+    /** 企微员工id */
+    @Excel(name = "企微员工id")
+    private String userId;
+
+    /** 添加总数 */
+    @Excel(name = "添加总数")
+    private Long limitCount;
+
+    /** 剩余可添加数 */
+    @Excel(name = "剩余可添加数")
+    private Long dayCount;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 企业CorpID */
+    @Excel(name = "企业CorpID")
+    private String corpId;
+
+
+}

+ 61 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwContactAcquisitionUserMapper.java

@@ -0,0 +1,61 @@
+package com.fs.qw.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.qw.domain.QwContactAcquisitionUser;
+
+/**
+ * 获客链接限制Mapper接口
+ *
+ * @author fs
+ * @date 2026-04-20
+ */
+public interface QwContactAcquisitionUserMapper extends BaseMapper<QwContactAcquisitionUser>{
+    /**
+     * 查询获客链接限制
+     *
+     * @param id 获客链接限制主键
+     * @return 获客链接限制
+     */
+    QwContactAcquisitionUser selectQwContactAcquisitionUserById(Long id);
+
+    /**
+     * 查询获客链接限制列表
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 获客链接限制集合
+     */
+    List<QwContactAcquisitionUser> selectQwContactAcquisitionUserList(QwContactAcquisitionUser qwContactAcquisitionUser);
+
+    /**
+     * 新增获客链接限制
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 结果
+     */
+    int insertQwContactAcquisitionUser(QwContactAcquisitionUser qwContactAcquisitionUser);
+
+    /**
+     * 修改获客链接限制
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 结果
+     */
+    int updateQwContactAcquisitionUser(QwContactAcquisitionUser qwContactAcquisitionUser);
+
+    /**
+     * 删除获客链接限制
+     *
+     * @param id 获客链接限制主键
+     * @return 结果
+     */
+    int deleteQwContactAcquisitionUserById(Long id);
+
+    /**
+     * 批量删除获客链接限制
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteQwContactAcquisitionUserByIds(Long[] ids);
+}

+ 6 - 5
fs-service/src/main/java/com/fs/qw/service/IQwAcquisitionAssistantService.java

@@ -10,11 +10,11 @@ import java.util.List;
 
 /**
  * 企微-获客链接管理Service接口
- * 
+ *
  * @author fs
  * @date 2026-03-16
  */
-public interface IQwAcquisitionAssistantService 
+public interface IQwAcquisitionAssistantService
 {
     /**
      * 查询企微-获客链接管理列表
@@ -49,7 +49,7 @@ public interface IQwAcquisitionAssistantService
      * @param assistant 获客链接信息
      * @return 创建成功的完整对象(包含企微返回的link_id、url等)
      */
-    public QwAcquisitionAssistant createWithQw(String corpid,String corpsecret,QwAcquisitionAssistant assistant);
+    public QwAcquisitionAssistant createWithQw(String corpid,String corpsecret,QwAcquisitionAssistant assistant, Long companyId);
 
     /**
      * 修改企微-获客链接管理
@@ -57,7 +57,7 @@ public interface IQwAcquisitionAssistantService
      * @param qwAcquisitionAssistant 企微-获客链接管理
      * @return 结果
      */
-    public QwAcquisitionAssistant updateWithQw(String corpId, String secret, QwAcquisitionAssistant qwAcquisitionAssistant);
+    public QwAcquisitionAssistant updateWithQw(String corpId, String secret, QwAcquisitionAssistant qwAcquisitionAssistant,Long companyId);
 
     /**
      * 删除获客链接
@@ -80,5 +80,6 @@ public interface IQwAcquisitionAssistantService
      * 根据页面参数查询获客链接url
      * */
     public String selectQwAcquisitionUrlByPageParam(String pageParam);
+    public void resetAcquisitionLinkUserLimit();
 
-}
+}

+ 61 - 0
fs-service/src/main/java/com/fs/qw/service/IQwContactAcquisitionUserService.java

@@ -0,0 +1,61 @@
+package com.fs.qw.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.qw.domain.QwContactAcquisitionUser;
+
+/**
+ * 获客链接限制Service接口
+ *
+ * @author fs
+ * @date 2026-04-20
+ */
+public interface IQwContactAcquisitionUserService extends IService<QwContactAcquisitionUser>{
+    /**
+     * 查询获客链接限制
+     *
+     * @param id 获客链接限制主键
+     * @return 获客链接限制
+     */
+    QwContactAcquisitionUser selectQwContactAcquisitionUserById(Long id);
+
+    /**
+     * 查询获客链接限制列表
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 获客链接限制集合
+     */
+    List<QwContactAcquisitionUser> selectQwContactAcquisitionUserList(QwContactAcquisitionUser qwContactAcquisitionUser);
+
+    /**
+     * 新增获客链接限制
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 结果
+     */
+    int insertQwContactAcquisitionUser(QwContactAcquisitionUser qwContactAcquisitionUser);
+
+    /**
+     * 修改获客链接限制
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 结果
+     */
+    int updateQwContactAcquisitionUser(QwContactAcquisitionUser qwContactAcquisitionUser);
+
+    /**
+     * 批量删除获客链接限制
+     *
+     * @param ids 需要删除的获客链接限制主键集合
+     * @return 结果
+     */
+    int deleteQwContactAcquisitionUserByIds(Long[] ids);
+
+    /**
+     * 删除获客链接限制信息
+     *
+     * @param id 获客链接限制主键
+     * @return 结果
+     */
+    int deleteQwContactAcquisitionUserById(Long id);
+}

+ 131 - 7
fs-service/src/main/java/com/fs/qw/service/impl/QwAcquisitionAssistantServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.qw.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.CustomException;
@@ -17,12 +18,15 @@ import com.fs.his.dto.SendResultDetailDTO;
 import com.fs.qw.bo.SendMsgLogBo;
 import com.fs.qw.domain.QwAcquisitionAssistant;
 import com.fs.qw.domain.QwCompany;
+import com.fs.qw.domain.QwContactAcquisitionUser;
+import com.fs.qw.domain.QwContactWayUser;
 import com.fs.qw.dto.acquisition.*;
 import com.fs.qw.enums.SmsLogType;
 import com.fs.qw.mapper.QwAcquisitionAssistantMapper;
 import com.fs.qw.service.IQwAcquisitionAssistantService;
 import com.fs.qw.service.IQwAcquisitionLinkInfoService;
 import com.fs.qw.service.IQwCompanyService;
+import com.fs.qw.service.IQwContactAcquisitionUserService;
 import com.fs.qw.utils.UniqueStringUtil;
 import com.fs.qw.vo.AcquisitionAssistantDetailVO;
 import com.fs.qwApi.config.QwApiConfig;
@@ -30,12 +34,14 @@ import com.fs.wx.kf.service.IWeixinKfService;
 import com.fs.wx.kf.vo.WeixinKfTokenVO;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
 import java.util.*;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * 企微-获客链接管理Service业务层处理
@@ -61,13 +67,19 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
 
     @Autowired
     private ICompanySmsTempService smsTempService;
-    
+
     @Autowired
     private IQwAcquisitionLinkInfoService linkInfoService;
 
     @Autowired
     private ICompanySmsService companySmsService;
 
+    @Autowired
+    private IQwContactAcquisitionUserService insertQwContactWayUser;
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
     // 获客链接管理-企微的ACCESS_TOKEN的key
     private static final String QW_ACQUISITION_KEY_PREFIX = "qw:acquisition:key:";
 
@@ -266,7 +278,7 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public QwAcquisitionAssistant createWithQw(String corpid, String corpsecret, QwAcquisitionAssistant assistant) {
+    public QwAcquisitionAssistant createWithQw(String corpid, String corpsecret, QwAcquisitionAssistant assistant, Long companyId) {
         // 参数校验
         if (StringUtils.isEmpty(assistant.getLinkName())) {
             throw new CustomException("链接名称不能为空");
@@ -328,8 +340,9 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
         if (response.getLink().getCreateTime() != null) {
             assistant.setQwCreateTime(new Date(response.getLink().getCreateTime() * 1000));
         }
-
-
+//        assistant.setQwCreateTime(new Date());
+//        assistant.setUrl("6666666666");
+//        assistant.setLinkId("123121");
         //如果这个随机参数已存在,则重新生成
         String randomParam =generateUniquePageParam();
 
@@ -342,6 +355,17 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
         setLocalFields(assistant, true);
         acquisitionAssistantMapper.insertQwAcquisitionAssistant(assistant);
 
+        String userLimitJson = assistant.getUserLimitJson();
+        List<QwContactAcquisitionUser> acquisitionUserList = JSON.parseArray(userLimitJson, QwContactAcquisitionUser.class);
+        for (QwContactAcquisitionUser acquisitionUser : acquisitionUserList) {
+            acquisitionUser.setDayCount(acquisitionUser.getLimitCount());
+            acquisitionUser.setLinkId(assistant.getLinkId());
+            acquisitionUser.setCompanyId(companyId);
+            acquisitionUser.setCorpId(corpid);
+            insertQwContactWayUser.insertQwContactAcquisitionUser(acquisitionUser);
+        }
+
+
         // ========== 缓存URL,便于后续通过pageParam访问 ==========
         try {
             String cacheKey = QW_ACQUISITION_URL_KEY_PREFIX + randomParam;
@@ -359,7 +383,7 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public QwAcquisitionAssistant updateWithQw(String corpid, String corpsecret, QwAcquisitionAssistant assistant) {
+    public QwAcquisitionAssistant updateWithQw(String corpid, String corpsecret, QwAcquisitionAssistant assistant,Long companyId) {
         // 参数校验
         if (assistant.getId() == null) {
             throw new CustomException("ID不能为空");
@@ -382,9 +406,12 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
         }
         request.setSkipVerify(Boolean.parseBoolean(assistant.getSkipVerify()));
 
+        AcquisitionRange range=new AcquisitionRange();
+        range.setUserList(assistant.getUserListParam());
+        request.setRange(range);
         //request.setMarkSource(assistant.getMarkSource());
 
-        // 调用企微API
+//         调用企微API
         String qwApiUrl = buildApiUrl(corpid, corpsecret, QwApiConfig.updateAcquisition);
         AcquisitionUpdateResponse response = callQwApi(qwApiUrl, request, AcquisitionUpdateResponse.class, "更新获客链接");
 
@@ -406,6 +433,33 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
             throw new CustomException("本地数据更新失败");
         }
 
+        //先根据linkId查询出所有ID,再删除
+        List<QwContactAcquisitionUser> userList = insertQwContactWayUser.list(
+                new LambdaQueryWrapper<QwContactAcquisitionUser>()
+                        .eq(QwContactAcquisitionUser::getLinkId, existAssistant.getLinkId()));
+
+        if (!CollectionUtils.isEmpty(userList)) {
+            List<Long> ids = userList.stream()
+                    .map(QwContactAcquisitionUser::getId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+
+            if (!ids.isEmpty()) {
+                insertQwContactWayUser.removeByIds(ids);
+            }
+        }
+
+        String userLimitJson = assistant.getUserLimitJson();
+        List<QwContactAcquisitionUser> acquisitionUserList = JSON.parseArray(userLimitJson, QwContactAcquisitionUser.class);
+        for (QwContactAcquisitionUser acquisitionUser : acquisitionUserList) {
+            acquisitionUser.setDayCount(acquisitionUser.getLimitCount());
+            acquisitionUser.setLinkId(existAssistant.getLinkId());
+            acquisitionUser.setCompanyId(companyId);
+            acquisitionUser.setCorpId(corpid);
+            insertQwContactWayUser.insertQwContactAcquisitionUser(acquisitionUser);
+        }
+
+
         return assistant;
     }
 
@@ -518,6 +572,7 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
         return friendUrl;
     }
 
+
     /**
      * 获取access_token并返回完整URL
      */
@@ -742,6 +797,8 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
             vo.setRemark(localData.getRemark());
             vo.setCorpId(localData.getCorpId());
             vo.setScheme(localData.getScheme());
+            vo.setUserLimitJson(localData.getUserLimitJson());
+            vo.setSpareUserIds(localData.getSpareUserIds());
         } else {
             // 纯企微数据,设置默认值
             vo.setStatus(1);
@@ -826,4 +883,71 @@ public class QwAcquisitionAssistantServiceImpl implements IQwAcquisitionAssistan
         }
         return counts;
     }
-}
+
+    @Override
+    public void resetAcquisitionLinkUserLimit() {
+        long startTimeMillis = System.currentTimeMillis();
+        log.info("====== 开始重置获客链接用户每日添加额度 ======");
+
+        try {
+            QwAcquisitionAssistant queryParam = new QwAcquisitionAssistant();
+            queryParam.setDelFlag("0");
+            List<QwAcquisitionAssistant> assistants = acquisitionAssistantMapper.selectQwAcquisitionAssistantList(queryParam);
+
+            if (assistants == null || assistants.isEmpty()) {
+                log.info("没有需要处理的获客链接");
+                return;
+            }
+
+            int processedCount = 0;
+            int restoredUserCount = 0;
+
+            for (QwAcquisitionAssistant assistant : assistants) {
+                try {
+                    if (assistant.getUserLimitJson() != null && !assistant.getUserLimitJson().isEmpty()) {
+                        com.alibaba.fastjson.JSONArray userLimitArray = com.alibaba.fastjson.JSON.parseArray(assistant.getUserLimitJson());
+
+                        List<String> restoredUserList = new java.util.ArrayList<>();
+                        List<Long> restoredQwUserTableIdList = new java.util.ArrayList<>();
+
+                        for (int i = 0; i < userLimitArray.size(); i++) {
+                            com.alibaba.fastjson.JSONObject userLimit = userLimitArray.getJSONObject(i);
+                            String userId = userLimit.getString("userId");
+                            Long qwUserId = userLimit.getLong("qwUserId");
+
+                            restoredUserList.add(userId);
+                            if (qwUserId != null) {
+                                restoredQwUserTableIdList.add(qwUserId);
+                            }
+                        }
+
+                        assistant.setUserList(com.alibaba.fastjson.JSON.toJSONString(restoredUserList));
+                        assistant.setQwUserTableIdList(com.alibaba.fastjson.JSON.toJSONString(restoredQwUserTableIdList));
+
+                        acquisitionAssistantMapper.updateQwAcquisitionAssistant(assistant);
+
+                        Set<String> keys = redisTemplate.keys("qwAcquisition:" + assistant.getCorpId() + ":" + assistant.getLinkId() + ":*");
+                        if (keys != null && !keys.isEmpty()) {
+                            redisTemplate.delete(keys);
+                            log.info("已清除获客链接{}的Redis计数缓存,共{}个键", assistant.getLinkId(), keys.size());
+                        }
+
+                        restoredUserCount += restoredUserList.size();
+                        processedCount++;
+
+                        log.info("获客链接{}已恢复{}个用户的添加额度", assistant.getLinkId(), restoredUserList.size());
+                    }
+                } catch (Exception e) {
+                    log.error("处理获客链接{}时出错", assistant.getId(), e);
+                }
+            }
+
+            long endTimeMillis = System.currentTimeMillis();
+            log.info("====== 获客链接用户额度重置完成,处理{}个链接,恢复{}个用户,耗时 {} 毫秒 ======",
+                    processedCount, restoredUserCount, (endTimeMillis - startTimeMillis));
+        } catch (Exception e) {
+            log.error("重置获客链接用户额度任务执行失败", e);
+        }
+    }
+
+}

+ 91 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwContactAcquisitionUserServiceImpl.java

@@ -0,0 +1,91 @@
+package com.fs.qw.service.impl;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.qw.mapper.QwContactAcquisitionUserMapper;
+import com.fs.qw.domain.QwContactAcquisitionUser;
+import com.fs.qw.service.IQwContactAcquisitionUserService;
+
+/**
+ * 获客链接限制Service业务层处理
+ *
+ * @author fs
+ * @date 2026-04-20
+ */
+@Service
+public class QwContactAcquisitionUserServiceImpl extends ServiceImpl<QwContactAcquisitionUserMapper, QwContactAcquisitionUser> implements IQwContactAcquisitionUserService {
+
+    /**
+     * 查询获客链接限制
+     *
+     * @param id 获客链接限制主键
+     * @return 获客链接限制
+     */
+    @Override
+    public QwContactAcquisitionUser selectQwContactAcquisitionUserById(Long id)
+    {
+        return baseMapper.selectQwContactAcquisitionUserById(id);
+    }
+
+    /**
+     * 查询获客链接限制列表
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 获客链接限制
+     */
+    @Override
+    public List<QwContactAcquisitionUser> selectQwContactAcquisitionUserList(QwContactAcquisitionUser qwContactAcquisitionUser)
+    {
+        return baseMapper.selectQwContactAcquisitionUserList(qwContactAcquisitionUser);
+    }
+
+    /**
+     * 新增获客链接限制
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 结果
+     */
+    @Override
+    public int insertQwContactAcquisitionUser(QwContactAcquisitionUser qwContactAcquisitionUser)
+    {
+        return baseMapper.insertQwContactAcquisitionUser(qwContactAcquisitionUser);
+    }
+
+    /**
+     * 修改获客链接限制
+     *
+     * @param qwContactAcquisitionUser 获客链接限制
+     * @return 结果
+     */
+    @Override
+    public int updateQwContactAcquisitionUser(QwContactAcquisitionUser qwContactAcquisitionUser)
+    {
+        return baseMapper.updateQwContactAcquisitionUser(qwContactAcquisitionUser);
+    }
+
+    /**
+     * 批量删除获客链接限制
+     *
+     * @param ids 需要删除的获客链接限制主键
+     * @return 结果
+     */
+    @Override
+    public int deleteQwContactAcquisitionUserByIds(Long[] ids)
+    {
+        return baseMapper.deleteQwContactAcquisitionUserByIds(ids);
+    }
+
+    /**
+     * 删除获客链接限制信息
+     *
+     * @param id 获客链接限制主键
+     * @return 结果
+     */
+    @Override
+    public int deleteQwContactAcquisitionUserById(Long id)
+    {
+        return baseMapper.deleteQwContactAcquisitionUserById(id);
+    }
+}

+ 183 - 63
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -11,6 +11,7 @@ import com.fs.ad.enums.AdUploadType;
 import com.fs.ad.service.IAdHtmlClickLogService;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.exception.CustomException;
 import com.fs.common.utils.PubFun;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.Company;
@@ -36,6 +37,9 @@ import com.fs.his.utils.PhoneUtil;
 import com.fs.hisStore.domain.FsUserInformationCollection;
 import com.fs.hisStore.mapper.FsUserInformationCollectionMapper;
 import com.fs.qw.domain.*;
+import com.fs.qw.dto.acquisition.AcquisitionBaseRequest;
+import com.fs.qw.dto.acquisition.AcquisitionRange;
+import com.fs.qw.dto.acquisition.AcquisitionUpdateResponse;
 import com.fs.qw.mapper.*;
 import com.fs.qw.param.*;
 import com.fs.qw.param.newparam.ExternalContactPageListParam;
@@ -52,6 +56,7 @@ import com.fs.qw.vo.sidebar.ExternalContactInfoVO;
 import com.fs.qw.vo.sidebar.ExternalContactQwUserVO;
 import com.fs.qw.vo.sidebar.ExternalContactTagVO;
 import com.fs.qwApi.Result.QwOpenidResult;
+import com.fs.qwApi.config.QwApiConfig;
 import com.fs.qwApi.domain.*;
 import com.fs.qwApi.domain.inner.*;
 import com.fs.qwApi.param.*;
@@ -70,6 +75,7 @@ import com.fs.sop.service.ISopUserLogsService;
 import com.fs.system.service.ISysConfigService;
 import com.fs.system.service.ISysDictTypeService;
 import com.fs.voice.utils.StringUtil;
+import com.fs.wx.kf.vo.WeixinKfTokenVO;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.gson.Gson;
@@ -145,6 +151,9 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
     @Autowired
     QwFriendWelcomeMapper qwFriendWelcomeMapper;
 
+    @Autowired
+    QwAcquisitionAssistantMapper acquisitionAssistantMapper;
+
     @Autowired
     ISopUserLogsInfoService iSopUserLogsInfoService;
 
@@ -2279,69 +2288,6 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
         QwExternalContact contact=qwExternalContact;
         QwUser qwUser = qwUserMapper.selectQwUserByCorpIdAndUserId(corpId, userID);
-
-        if (state != null && state != "") {
-            String s = "way:" + corpId + ":";
-            String userPhone = "up:";
-            if (state.contains(s)) {
-                if (welcomeCode != null && welcomeCode != "") {
-                    String substring = state.substring(state.indexOf(s) + s.length());
-                    QwContactWay qwContactWay = qwContactWayMapper.selectQwContactWayById(Long.parseLong(substring));
-                    logger.info("qwContactWay:"+qwContactWay);
-                    if (qwContactWay != null) {
-                        isWay = true;
-                        wayId = qwContactWay;
-                        if (qwContactWay.getIsWelcome() != null && qwContactWay.getIsWelcome() == 1) {
-                            Boolean isClose = true;
-                            if (wayId.getIsSpanWelcome() == 1) {
-                                ExternalContact externalContact = externalContactResult.getExternal_contact();
-                                String name = externalContact.getName();
-                                String closeWelcomeWord = wayId.getCloseWelcomeWord();
-                                if (closeWelcomeWord != null && closeWelcomeWord.length() > 0) {
-                                    List<String> strings = JSON.parseArray(closeWelcomeWord, String.class);
-                                    for (String string : strings) {
-                                        if (name.contains(string)) {
-                                            isClose = false;
-                                            break;
-                                        }
-                                    }
-                                }
-                            }
-                            if (qwContactWay.getIsSpanWelcome() == 1 && isClose) {
-                                isSend = qwContactWayService.sendWelcomeMsg(qwContactWay, corpId, welcomeCode,qwUser,contact.getId());
-                            }
-                        }
-                        if (qwContactWay.getUserType() == 1 && qwContactWay.getIsUserLimit() == 1) {
-                            QwContactWayUser qwContactWayUser = qwContactWayUserMapper.selectQwContactWayUserByUserIdAndCompanyId(userID, corpId);
-                            if (qwContactWayUser != null) {
-                                qwContactWayUser.setDayCount(qwContactWayUser.getDayCount() - 1);
-                                qwContactWayUserMapper.updateQwContactWayUser(qwContactWayUser);
-                                if (qwContactWayUser.getDayCount() <= 0) {
-                                    //超过限制
-                                    qwContactWayService.updateQwContactWayBYLimit(qwContactWayUser.getWayId());
-                                }
-
-                            }
-                        }
-                    }
-                }
-            }
-
-            if (state.contains(userPhone)) {
-                log.error("获客链接添加外部联系人小程序用户手机号");
-                try {
-                    //获取手机号数据
-                    String phone = state.substring(state.indexOf(userPhone) + userPhone.length());
-                    //更新外部联系人小程序用户手机号数据
-                    QwExternalContact updateContact = new QwExternalContact();
-                    updateContact.setId(contact.getId());
-                    updateContact.setFsUserPhone(phone);
-                    qwExternalContactMapper.updateQwExternalContact(updateContact);
-                } catch (Exception e) {
-                    log.error("获客链接添加外部联系人小程序用户手机号失败,错误信息:{}",e.getMessage());
-                }
-            }
-        }
         log.error("欢迎语====>isSend:{},welcomeCode:{}",isSend,welcomeCode);
         if (isSend && welcomeCode != null && welcomeCode != "") {
             if (qwUser != null) {
@@ -2440,6 +2386,172 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
             }
         }
 
+
+        logger.info("渠道活码的参数---:"+state);
+
+        if (state != null && state != "") {
+            String s = "way:" + corpId + ":";
+            String userPhone = "up:";
+            String linkState = "link:";
+            if (state.contains(s)) {
+                if (welcomeCode != null && welcomeCode != "") {
+                    String substring = state.substring(state.indexOf(s) + s.length());
+                    QwContactWay qwContactWay = qwContactWayMapper.selectQwContactWayById(Long.parseLong(substring));
+                    logger.info("qwContactWay:"+qwContactWay);
+                    if (qwContactWay != null) {
+                        isWay = true;
+                        wayId = qwContactWay;
+                        if (qwContactWay.getIsWelcome() != null && qwContactWay.getIsWelcome() == 1) {
+                            Boolean isClose = true;
+                            if (wayId.getIsSpanWelcome() == 1) {
+                                ExternalContact externalContact = externalContactResult.getExternal_contact();
+                                String name = externalContact.getName();
+                                String closeWelcomeWord = wayId.getCloseWelcomeWord();
+                                if (closeWelcomeWord != null && closeWelcomeWord.length() > 0) {
+                                    List<String> strings = JSON.parseArray(closeWelcomeWord, String.class);
+                                    for (String string : strings) {
+                                        if (name.contains(string)) {
+                                            isClose = false;
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                            if (qwContactWay.getIsSpanWelcome() == 1 && isClose) {
+                                isSend = qwContactWayService.sendWelcomeMsg(qwContactWay, corpId, welcomeCode,qwUser,contact.getId());
+                            }
+                        }
+                        if (qwContactWay.getUserType() == 1 && qwContactWay.getIsUserLimit() == 1) {
+                            QwContactWayUser qwContactWayUser = qwContactWayUserMapper.selectQwContactWayUserByUserIdAndCompanyId(userID, corpId);
+                            if (qwContactWayUser != null) {
+                                qwContactWayUser.setDayCount(qwContactWayUser.getDayCount() - 1);
+                                qwContactWayUserMapper.updateQwContactWayUser(qwContactWayUser);
+                                if (qwContactWayUser.getDayCount() <= 0) {
+                                    //超过限制
+                                    qwContactWayService.updateQwContactWayBYLimit(qwContactWayUser.getWayId());
+                                }
+
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (state.contains(userPhone)) {
+                log.error("获客链接添加外部联系人小程序用户手机号");
+                try {
+                    //获取手机号数据
+                    String phone = state.substring(state.indexOf(userPhone) + userPhone.length());
+                    //更新外部联系人小程序用户手机号数据
+                    QwExternalContact updateContact = new QwExternalContact();
+                    updateContact.setId(contact.getId());
+                    updateContact.setFsUserPhone(phone);
+                    qwExternalContactMapper.updateQwExternalContact(updateContact);
+                } catch (Exception e) {
+                    log.error("获客链接添加外部联系人小程序用户手机号失败,错误信息:{}",e.getMessage());
+                }
+            }
+
+            if (state.contains(linkState)){
+                try {
+                    log.info("获客链接添加外部联系人");
+                    String linkId = state.substring(state.indexOf(linkState) + linkState.length());
+                    QwAcquisitionAssistant qwAcquisitionAssistant = acquisitionAssistantMapper.selectQwAcquisitionAssistantById(Long.valueOf(linkId));
+
+                    if (qwAcquisitionAssistant != null && StringUtils.isNotBlank(qwAcquisitionAssistant.getUserLimitJson())) {
+                        try {
+                            String cacheKey = "qwAcquisition:" + corpId + ":" + linkId + ":" + userID;
+
+                            com.alibaba.fastjson.JSONArray userLimitArray = com.alibaba.fastjson.JSON.parseArray(qwAcquisitionAssistant.getUserLimitJson());
+                            for (int i = 0; i < userLimitArray.size(); i++) {
+                                com.alibaba.fastjson.JSONObject userLimit = userLimitArray.getJSONObject(i);
+                                String limitUserId = userLimit.getString("userId");
+                                Integer limitCount = userLimit.getInteger("limitCount");
+                                Integer qwUserId = userLimit.getInteger("qwUserId");
+
+                                if (userID.equals(limitUserId)) {
+                                    Long currentCount = redisTemplate.opsForValue().increment(cacheKey, 1);
+
+                                    if (currentCount == null) {
+                                        currentCount = 1L;
+                                    }
+
+                                    long expireSeconds = getSecondsUntilMidnight();
+                                    redisTemplate.expire(cacheKey, expireSeconds, java.util.concurrent.TimeUnit.SECONDS);
+
+                                    if (currentCount >= limitCount) {
+                                        log.error("用户{}已达到每日添加上限{}/{}", userID, currentCount, limitCount);
+
+//                                    redisTemplate.delete(cacheKey);
+
+                                        List<String> currentUserList = com.alibaba.fastjson.JSON.parseArray(qwAcquisitionAssistant.getUserList(), String.class);
+                                        if (currentUserList == null && StringUtils.isNotBlank(qwAcquisitionAssistant.getUserList())) {
+                                            currentUserList = com.alibaba.fastjson.JSON.parseArray(qwAcquisitionAssistant.getUserList(), String.class);
+                                        }
+
+                                        List<Long> currentQwUserTableIdList = null;
+                                        if (StringUtils.isNotBlank(qwAcquisitionAssistant.getQwUserTableIdList())) {
+                                            currentQwUserTableIdList = com.alibaba.fastjson.JSON.parseArray(qwAcquisitionAssistant.getQwUserTableIdList(), Long.class);
+                                        }
+
+                                        boolean needUpdate = false;
+
+                                        if (currentUserList != null && currentUserList.contains(userID)) {
+                                            currentUserList.remove(userID);
+                                            qwAcquisitionAssistant.setUserList(com.alibaba.fastjson.JSON.toJSONString(currentUserList));
+                                            needUpdate = true;
+                                        }
+
+                                        if (currentQwUserTableIdList != null && currentQwUserTableIdList.contains(Long.valueOf(qwUserId))) {
+                                            currentQwUserTableIdList.remove(Long.valueOf(qwUserId));
+                                            qwAcquisitionAssistant.setQwUserTableIdList(com.alibaba.fastjson.JSON.toJSONString(currentQwUserTableIdList));
+                                            needUpdate = true;
+                                        }
+
+
+                                        // 构建请求
+                                        QwLinkCreateParam linkCreateParam=new QwLinkCreateParam();
+                                        linkCreateParam.setLink_id(qwAcquisitionAssistant.getLinkId());
+
+                                        QwLinkCreateParam.Range range=new QwLinkCreateParam.Range();
+//                                        range.setUser_list(currentUserList);
+                                        range.setUser_list(JSON.parseArray(qwAcquisitionAssistant.getUserList(), String.class));
+                                        linkCreateParam.setRange(range);
+
+                                        //调用企微API
+                                        QwResult qwResult = qwApiService.linkUpdate(linkCreateParam, corpId);
+                                        if (qwResult.getErrcode() == 0) {
+                                            if (needUpdate) {
+                                                acquisitionAssistantMapper.updateQwAcquisitionAssistant(qwAcquisitionAssistant);
+                                                log.info("已从获客链接{}的可用列表中移除用户{}", linkId, userID);
+                                            }
+                                        }else {
+                                            logger.error("修改渠道活码 失败!"+linkCreateParam+":"+qwResult.getErrmsg());
+                                        }
+
+
+
+                                    } else {
+                                        log.info("用户{}今日已添加客户数:{}/{}", userID, currentCount, limitCount);
+                                    }
+                                    break;
+                                }
+                            }
+                        } catch (Exception e) {
+                            log.error("处理获客链接用户限额失败", e);
+                        }
+                    }
+                }catch (Exception e){
+                    log.error("处理获客链接用户限额失败", e);
+                }
+
+
+
+            }
+
+
+        }
+
         ExternalContact externalContact = externalContactResult.getExternal_contact();
         List<FollowUser> followUsers = externalContactResult.getFollow_user();
         logger.info("外部联系人的情况里面0:"+userID+":"+externalUserID+":"+followUsers+":"+externalContactResult.getErrmsg());
@@ -2813,6 +2925,14 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
             }
         }
     }
+
+    private long getSecondsUntilMidnight() {
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay();
+        return java.time.Duration.between(now, midnight).getSeconds();
+    }
+
+
     public void checkHaveQwSop(Set<String> combinedTagsSet,QwUser qwUser,String corpId,List<String> combinedTagsList,
                                String userID,String externalUserID,ExternalContact externalContact,QwExternalContact contact,
                                LocalDate currentDate, LocalTime localTime){

+ 24 - 15
fs-service/src/main/java/com/fs/qw/vo/AcquisitionAssistantDetailVO.java

@@ -1,6 +1,7 @@
 package com.fs.qw.vo;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
 import lombok.Data;
 import java.util.Date;
 
@@ -9,31 +10,31 @@ import java.util.Date;
  */
 @Data
 public class AcquisitionAssistantDetailVO {
-    
+
     // 本地记录ID
     private Long id;
-    
+
     // 企业ID
     private String corpId;
-    
+
     // 企微链接ID
     private String linkId;
-    
+
     // 链接名称
     private String linkName;
-    
+
     // 链接URL
     private String url;
-    
+
     // 链接Scheme
     private String scheme;
-    
+
     // 是否无需验证
     private String skipVerify;
-    
+
     // 优先分配类型(0:不启用,1:全企业,2:指定范围内)
     private Integer priorityType;
-    
+
     // 关联成员列表(JSON字符串:{"userList":[]})
     private String userList;
 
@@ -45,20 +46,28 @@ public class AcquisitionAssistantDetailVO {
 
     // 优先分配成员列表(JSON字符串:{"priority_userid_list":["tom","lisi"]})
     private String priorityUserList;
-    
+
     // 使用范围描述
     private String rangeDesc;
-    
+
     // 状态(1:正常,2:已失效)
     private Integer status;
-    
+
     // 企微创建时间
     private Long qwCreateTime;
-    
+
     // 最后同步时间
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date syncTime;
-    
+
     // 备注
     private String remark;
-}
+
+    /** 员工添加上限 */
+    @Excel(name = "员工添加上限")
+    private String userLimitJson;
+
+    /** 备用员工 */
+    @Excel(name = "备用员工")
+    private String spareUserIds;
+}

+ 11 - 2
fs-service/src/main/resources/mapper/qw/QwAcquisitionAssistantMapper.xml

@@ -27,13 +27,16 @@
         <result property="corpId"            column="corp_id"          />
         <result property="syncTime"            column="sync_time"          />
         <result property="pageParam"            column="page_param"          />
+        <result property="spareUserIds"            column="spare_user_ids"          />
+        <result property="userLimitJson"            column="user_limit_json"          />
     </resultMap>
 
     <sql id="selectQwAcquisitionAssistantVo">
         select id, link_id, link_name, url, scheme, qw_create_time, skip_verify,
                mark_source, priority_type, user_list, department_list, priority_user_list,
                qw_user_table_id_list,range_desc, status, remark,
-               create_by, create_time, update_by, update_time, del_flag,corp_id,sync_time,page_param
+               create_by, create_time, update_by, update_time, del_flag,corp_id,sync_time,page_param,
+               spare_user_ids,user_limit_json
         from qw_acquisition_assistant
     </sql>
 
@@ -130,6 +133,8 @@
             <if test="corpId != null">corp_id,</if>
             <if test="syncTime != null">sync_time,</if>
             <if test="pageParam != null">page_param,</if>
+            <if test="spareUserIds != null">spare_user_ids,</if>
+            <if test="userLimitJson != null">user_limit_json,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="linkId != null">#{linkId},</if>
@@ -154,6 +159,8 @@
             <if test="corpId != null">#{corpId},</if>
             <if test="syncTime != null">#{syncTime},</if>
             <if test="pageParam != null">#{pageParam},</if>
+            <if test="spareUserIds != null">#{spareUserIds},</if>
+            <if test="userLimitJson != null">#{userLimitJson},</if>
         </trim>
     </insert>
 
@@ -179,6 +186,8 @@
             <if test="corpId != null">corp_id = #{corpId},</if>
             <if test="syncTime != null">sync_time = #{syncTime},</if>
             <if test="pageParam != null">page_param = #{pageParam},</if>
+            <if test="spareUserIds != null">spare_user_ids=#{spareUserIds},</if>
+            <if test="userLimitJson != null">user_limit_json=#{userLimitJson},</if>
         </trim>
         where id = #{id}
     </update>
@@ -208,4 +217,4 @@
         </foreach>
     </delete>
 
-</mapper>
+</mapper>

+ 86 - 0
fs-service/src/main/resources/mapper/qw/QwContactAcquisitionUserMapper.xml

@@ -0,0 +1,86 @@
+<?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.qw.mapper.QwContactAcquisitionUserMapper">
+
+    <resultMap type="QwContactAcquisitionUser" id="QwContactAcquisitionUserResult">
+        <result property="id"    column="id"    />
+        <result property="linkId"    column="link_id"    />
+        <result property="qwUserId"    column="qw_user_id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="limitCount"    column="limit_count"    />
+        <result property="dayCount"    column="day_count"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="corpId"    column="corp_id"    />
+    </resultMap>
+
+    <sql id="selectQwContactAcquisitionUserVo">
+        select id, link_id, qw_user_id, user_id, limit_count, day_count, company_id, corp_id from qw_contact_acquisition_user
+    </sql>
+
+    <select id="selectQwContactAcquisitionUserList" parameterType="QwContactAcquisitionUser" resultMap="QwContactAcquisitionUserResult">
+        <include refid="selectQwContactAcquisitionUserVo"/>
+        <where>
+            <if test="linkId != null "> and link_id = #{linkId}</if>
+            <if test="qwUserId != null "> and qw_user_id = #{qwUserId}</if>
+            <if test="userId != null  and userId != ''"> and user_id = #{userId}</if>
+            <if test="limitCount != null "> and limit_count = #{limitCount}</if>
+            <if test="dayCount != null "> and day_count = #{dayCount}</if>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="corpId != null  and corpId != ''"> and corp_id = #{corpId}</if>
+        </where>
+    </select>
+
+    <select id="selectQwContactAcquisitionUserById" parameterType="Long" resultMap="QwContactAcquisitionUserResult">
+        <include refid="selectQwContactAcquisitionUserVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertQwContactAcquisitionUser" parameterType="QwContactAcquisitionUser" useGeneratedKeys="true" keyProperty="id">
+        insert into qw_contact_acquisition_user
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="linkId != null">link_id,</if>
+            <if test="qwUserId != null">qw_user_id,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="limitCount != null">limit_count,</if>
+            <if test="dayCount != null">day_count,</if>
+            <if test="companyId != null">company_id,</if>
+            <if test="corpId != null">corp_id,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="linkId != null">#{linkId},</if>
+            <if test="qwUserId != null">#{qwUserId},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="limitCount != null">#{limitCount},</if>
+            <if test="dayCount != null">#{dayCount},</if>
+            <if test="companyId != null">#{companyId},</if>
+            <if test="corpId != null">#{corpId},</if>
+         </trim>
+    </insert>
+
+    <update id="updateQwContactAcquisitionUser" parameterType="QwContactAcquisitionUser">
+        update qw_contact_acquisition_user
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="linkId != null">link_id = #{linkId},</if>
+            <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="limitCount != null">limit_count = #{limitCount},</if>
+            <if test="dayCount != null">day_count = #{dayCount},</if>
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="corpId != null">corp_id = #{corpId},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteQwContactAcquisitionUserById" parameterType="Long">
+        delete from qw_contact_acquisition_user where id = #{id}
+    </delete>
+
+    <delete id="deleteQwContactAcquisitionUserByIds" parameterType="String">
+        delete from qw_contact_acquisition_user where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>