diff --git a/ad-platform-pojo/pom.xml b/ad-platform-pojo/pom.xml
index 51b2bdc0..0fec244f 100644
--- a/ad-platform-pojo/pom.xml
+++ b/ad-platform-pojo/pom.xml
@@ -55,7 +55,39 @@
spring-cloud-starter-alibaba-nacos-discovery
+
+ com.querydsl
+ querydsl-jpa
+
+
+
+ com.querydsl
+ querydsl-apt
+ provided
+
+
+
+
+
+ com.mysema.maven
+ apt-maven-plugin
+ 1.1.3
+
+
+
+ process
+
+
+ target/generated-sources/java
+ com.querydsl.apt.jpa.JPAAnnotationProcessor
+
+
+
+
+
+
+
diff --git a/ad-platform-services/ad-platform-source/pom.xml b/ad-platform-services/ad-platform-source/pom.xml
index 32292f41..85953a7f 100644
--- a/ad-platform-services/ad-platform-source/pom.xml
+++ b/ad-platform-services/ad-platform-source/pom.xml
@@ -98,6 +98,17 @@
poi-ooxml-schemas
+
+ com.querydsl
+ querydsl-jpa
+
+
+
+ com.querydsl
+ querydsl-apt
+ provided
+
+
@@ -119,6 +130,25 @@
+
+
+
+ com.mysema.maven
+ apt-maven-plugin
+ 1.1.3
+
+
+
+ process
+
+
+ target/generated-sources/java
+ com.querydsl.apt.jpa.JPAAnnotationProcessor
+
+
+
+
+
diff --git a/ad-platform-services/ad-platform-source/src/main/java/com/baiye/config/JPAQueryFactoryConfiguration.java b/ad-platform-services/ad-platform-source/src/main/java/com/baiye/config/JPAQueryFactoryConfiguration.java
new file mode 100644
index 00000000..f0133ac4
--- /dev/null
+++ b/ad-platform-services/ad-platform-source/src/main/java/com/baiye/config/JPAQueryFactoryConfiguration.java
@@ -0,0 +1,20 @@
+package com.baiye.config;
+
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @Author YQY
+ * @Date 2023/7/4
+ */
+@Configuration
+public class JPAQueryFactoryConfiguration {
+
+ @Bean
+ public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
+ return new JPAQueryFactory(entityManager);
+ }
+}
\ No newline at end of file
diff --git a/ad-platform-services/ad-platform-source/src/main/java/com/baiye/module/dao/ClueQueryDSL.java b/ad-platform-services/ad-platform-source/src/main/java/com/baiye/module/dao/ClueQueryDSL.java
new file mode 100644
index 00000000..57655a8d
--- /dev/null
+++ b/ad-platform-services/ad-platform-source/src/main/java/com/baiye/module/dao/ClueQueryDSL.java
@@ -0,0 +1,308 @@
+package com.baiye.module.dao;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baiye.constant.DefaultNumberConstants;
+import com.baiye.constant.KeyFieldConstants;
+import com.baiye.exception.BadRequestException;
+import com.baiye.feign.TaskClient;
+import com.baiye.model.dto.ClueDto;
+import com.baiye.model.dto.ClueQueryCriteria;
+import com.baiye.model.entity.QBaseClueMiddle;
+import com.baiye.model.vo.ResSourceLabel;
+import com.baiye.module.entity.QClue;
+import com.baiye.module.entity.QClueMiddle;
+import com.baiye.module.entity.QClueTalk;
+import com.baiye.util.RedisUtils;
+import com.baiye.util.ValidationUtil;
+import com.querydsl.core.BooleanBuilder;
+import com.querydsl.core.types.Expression;
+import com.querydsl.core.types.Projections;
+import com.querydsl.core.types.dsl.Expressions;
+import com.querydsl.jpa.impl.JPAQuery;
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.sql.Timestamp;
+import java.util.*;
+
+/**
+ * @Author YQY
+ * @Date 2023/7/4
+ */
+@Component
+public class ClueQueryDSL {
+
+ @Resource
+ private JPAQueryFactory jpaQueryFactory;
+ @Resource
+ private RedisUtils redisUtils;
+ @Resource
+ private TaskClient taskClient;
+
+ private final QClue qClue = QClue.clue;
+ private final QClueMiddle qClueMiddle = QClueMiddle.clueMiddle;
+ private final QClueTalk qClueTalk = QClueTalk.clueTalk;
+
+ /**
+ * 联合查询"crm"线索
+ */
+ public List getCRMClueList(ClueQueryCriteria clueQueryCriteria, Pageable pageable) {
+ JPAQuery query =
+ jpaQueryFactory.select(
+ Projections.bean(
+ ClueDto.class,
+ cluePojo(DefaultNumberConstants.ONE_NUMBER)
+ )).from(qClue)
+ .innerJoin(qClueMiddle)
+ .on(qClue.id.eq(qClueMiddle.clueId))
+ .where(this.builder(clueQueryCriteria, DefaultNumberConstants.ONE_NUMBER))
+ .orderBy(qClue.createTime.desc(), qClue.id.desc());
+ if (pageable != null) {
+ query.offset((long) pageable.getPageNumber() * pageable.getPageSize()).limit(pageable.getPageSize());
+ }
+ return this.dataHandle(query.fetch(), clueQueryCriteria.getIsAdmin());
+ }
+
+ /**
+ * 联合分页查询"crm"线索的"总条数"
+ */
+ public Long getCRMCount(ClueQueryCriteria clueQueryCriteria) {
+ return jpaQueryFactory.select(
+ QClue.clue.count()
+ ).from(QClue.clue)
+ .innerJoin(QClueMiddle.clueMiddle)
+ .on(QClue.clue.id.eq(QClueMiddle.clueMiddle.clueId))
+ .where(this.builder(clueQueryCriteria, DefaultNumberConstants.ONE_NUMBER))
+ .fetchOne();
+ }
+
+ /**
+ * 联合查询"拓客"线索
+ */
+ public List getTalkClueList(ClueQueryCriteria clueQueryCriteria, Pageable pageable) {
+ JPAQuery query =
+ jpaQueryFactory.select(
+ Projections.bean(
+ ClueDto.class,
+ cluePojo(DefaultNumberConstants.TWO_NUMBER)
+ )).from(qClue)
+ .innerJoin(qClueTalk)
+ .on(qClue.id.eq(qClueTalk.clueId))
+ .where(this.builder(clueQueryCriteria, DefaultNumberConstants.TWO_NUMBER))
+ .orderBy(qClue.createTime.desc(), qClue.id.desc());
+ if (pageable != null) {
+ query.offset((long) pageable.getPageNumber() * pageable.getPageSize()).limit(pageable.getPageSize());
+ }
+ return this.dataHandle(query.fetch(), clueQueryCriteria.getIsAdmin());
+ }
+
+ /**
+ * 联合分页查询"拓客"线索的"总条数"
+ */
+ public Long getTalkCount(ClueQueryCriteria clueQueryCriteria) {
+ return jpaQueryFactory.select(
+ QClue.clue.count()
+ ).from(QClue.clue)
+ .innerJoin(QClueTalk.clueTalk)
+ .on(QClue.clue.id.eq(QClueTalk.clueTalk.clueId))
+ .where(this.builder(clueQueryCriteria, DefaultNumberConstants.TWO_NUMBER))
+ .fetchOne();
+ }
+
+ /**
+ * 表字段映射
+ *
+ * @param type 1:crm中间表映射 2:拓客线索中间表映射
+ */
+ public Expression>[] cluePojo(Integer type) {
+ QBaseClueMiddle qBaseClueMiddle;
+ if (type == DefaultNumberConstants.ONE_NUMBER) qBaseClueMiddle = qClueMiddle._super;
+ else qBaseClueMiddle = qClueTalk._super;
+
+ Expression>[] expressions = new Expression[]{
+ qBaseClueMiddle.clueStage, qBaseClueMiddle.clueStageTime, qBaseClueMiddle.clueCallStatus, qBaseClueMiddle.organizeId,
+ qBaseClueMiddle.memberId, qBaseClueMiddle.taskId, qBaseClueMiddle.memberStatus, qBaseClueMiddle.sourceLabel, qBaseClueMiddle.labelTime,
+ qBaseClueMiddle.newestCallTime, qBaseClueMiddle.remark, qBaseClueMiddle.publicPoolStatus, qBaseClueMiddle.turnoverAmount, qBaseClueMiddle.clueType
+ };
+ Expression>[] clueExpressions = new Expression[]{
+ qClue.id, qClue.audioUrl, qClue.gender, qClue.name, qClue.nid, qClue.wx, qClue.routeId,
+ qClue.amount, qClue.collectTime, qClue.address, qClue.platform, qClue.recordId, qClue.createBy,
+ qClue.createTime, qClue.updateTime, qClue.isEncryption, qClue.tag
+ };
+ Expression>[] allData = ArrayUtil.addAll(expressions, clueExpressions);
+ if (type == DefaultNumberConstants.TWO_NUMBER) {
+ Expression>[] talkArr = new Expression[]{qClueTalk.isFreeze};
+ allData = ArrayUtil.addAll(allData, talkArr);
+ }
+ return allData;
+ }
+
+ /**
+ * 构建查询条件
+ *
+ * @param type 1:crm中间表 2:拓客线索中间表
+ */
+ private BooleanBuilder builder(ClueQueryCriteria clueQuery, Integer type) {
+ Integer memberStatus = clueQuery.getMemberStatus();
+ Boolean isAdmin = clueQuery.getIsAdmin();
+ List newestCallTimeList = clueQuery.getNewestCallTime();
+ List createTime = clueQuery.getCreateTime();
+
+ QBaseClueMiddle qBaseClueMiddle;
+ if (type == DefaultNumberConstants.ONE_NUMBER)
+ qBaseClueMiddle = qClueMiddle._super;
+ else
+ qBaseClueMiddle = qClueTalk._super;
+
+ BooleanBuilder builder = new BooleanBuilder();
+ if (clueQuery.getId() != null) {
+ builder.and(qClue.id.eq(clueQuery.getId()));
+ }
+ if (StrUtil.isNotBlank(clueQuery.getNid())) {
+ builder.and(qClue.nid.eq(clueQuery.getNid()));
+ }
+ if (StringUtils.isNotBlank(clueQuery.getName())) {
+ builder.and(qClue.name.like("%".concat(clueQuery.getName()).concat("%")));
+ }
+ if (clueQuery.getRouteId() != null) {
+ builder.and(qClue.routeId.eq(clueQuery.getRouteId()));
+ }
+ if (CollUtil.isNotEmpty(clueQuery.getRouteIdList())) {
+ builder.and(qClue.routeId.in(clueQuery.getRouteIdList()));
+ }
+ if (clueQuery.getUserId() != null) {
+ builder.and(qClue.createBy.eq(clueQuery.getUserId()));
+ }
+ if (clueQuery.getMemberId() != null && !isAdmin) {
+ builder.and(qBaseClueMiddle.memberId.eq(clueQuery.getMemberId()));
+ }
+ if (clueQuery.getUserIdList() != null) {
+ builder.and(qBaseClueMiddle.memberId.in(clueQuery.getUserIdList()));
+ }
+ if (clueQuery.getOrganizeId() != null) {
+ builder.and(qBaseClueMiddle.organizeId.eq(clueQuery.getOrganizeId()));
+ }
+ if (memberStatus != null) {
+ if (isAdmin) {
+ if (memberStatus == 0) {
+ builder.and(qBaseClueMiddle.memberId.isNull());
+ }
+ if (memberStatus > 0) {
+ builder.and(qBaseClueMiddle.memberId.isNotNull());
+ }
+ } else {
+ builder.and(qBaseClueMiddle.memberStatus.eq(memberStatus));
+ }
+ }
+ if (StrUtil.isNotEmpty(clueQuery.getLabel())) {
+ builder.and(Expressions.booleanTemplate("LOWER({0}) LIKE LOWER({1})", qBaseClueMiddle.sourceLabel, "%" + clueQuery.getLabel() + "%"));
+ }
+ if (clueQuery.getClueCallStatus() != null) {
+ builder.and(qBaseClueMiddle.clueCallStatus.eq(clueQuery.getClueCallStatus()));
+ }
+ if (clueQuery.getClueStage() != null) {
+ builder.and(qBaseClueMiddle.clueStage.eq(clueQuery.getClueStage()));
+ }
+ if (createTime != null && createTime.size() == 2) {
+ Date createTimeBegin = new Date(createTime.get(0).getTime());
+ Date createTimeEnd = new Date(createTime.get(1).getTime());
+ builder.and(qBaseClueMiddle.createTime.between(createTimeBegin, createTimeEnd));
+ }
+ if (newestCallTimeList != null && newestCallTimeList.size() == 2) {
+ Date beginTime = new Date(newestCallTimeList.get(0).getTime());
+ Date endTime = new Date(newestCallTimeList.get(1).getTime());
+ builder.and(qBaseClueMiddle.newestCallTime.between(beginTime, endTime));
+ }
+ if (clueQuery.getClueType() != null) {
+ builder.and(qBaseClueMiddle.clueType.eq(clueQuery.getClueType()));
+ }
+ if (CollUtil.isNotEmpty(clueQuery.getClueTypes())) {
+ builder.and(qBaseClueMiddle.clueType.in(clueQuery.getClueTypes()));
+ }
+ if (CollUtil.isNotEmpty(clueQuery.getTaskIds())) {
+ builder.and(qBaseClueMiddle.taskId.in(clueQuery.getTaskIds()));
+ }
+ if (clueQuery.getPublicPoolStatus() != null) {
+ builder.and(qBaseClueMiddle.publicPoolStatus.eq(clueQuery.getPublicPoolStatus()));
+ }
+ if (clueQuery.getIsFreeze() != null) {
+ builder.and(qClueTalk.isFreeze.eq(clueQuery.getIsFreeze()));
+ }
+ return builder;
+ }
+
+ /**
+ * 查询结果 数据处理(手机号解密...)
+ */
+ private List dataHandle(List result, boolean isAdmin) {
+ for (ClueDto clueDto : result) {
+ //查看任务是否需要加密显示资源
+ String taskEncryption = String.valueOf(redisUtils.get(KeyFieldConstants.TASK_ENCRYPTION_KEY + clueDto.getTaskId()));
+ if (StringUtils.isBlank(taskEncryption) || taskEncryption.equals("null")) {
+ ResponseEntity