正式环境代码提交

master
yqy 1 year ago
parent 5f44b093cd
commit c45d7d2d2f

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ad-distribute-common</artifactId>
<groupId>com.baiye</groupId>
<version>1.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common-i18n</artifactId>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<!-- slf4j日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

@ -1,32 +0,0 @@
package com.baiye;
import lombok.RequiredArgsConstructor;
import org.springframework.context.support.AbstractMessageSource;
import org.springframework.lang.Nullable;
import java.text.MessageFormat;
import java.util.Locale;
/**
* MessageSource redis message
*
* @author hccake
*/
@RequiredArgsConstructor
public class DynamicMessageSource extends AbstractMessageSource {
public static final String DYNAMIC_MESSAGE_SOURCE_BEAN_NAME = "dynamicMessageSource";
private final I18nMessageProvider i18nMessageProvider;
@Override
@Nullable
protected MessageFormat resolveCode(String code, Locale locale) {
I18nMessage i18nMessage = i18nMessageProvider.getI18nMessage(code, locale);
if (i18nMessage != null) {
return createMessageFormat(i18nMessage.getMessage(), locale);
}
return null;
}
}

@ -1,16 +0,0 @@
package com.baiye;
import java.lang.annotation.*;
/**
* , {@link I18nField} 使
*
* @see I18nResponseAdvice
* @author hccake
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface I18nClass {
}

@ -1,41 +0,0 @@
package com.baiye;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
/**
* String {@link I18nClass}
*
* @author hccake
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface I18nField {
/**
* <p>
* This is an alias for {@link #code}
* </p>
* @return String
*/
@AliasFor("code")
String value() default "";
/**
* 使SpEL code 1, 使 code 2, ,
* code ,使 code () : String & Number(String) :
* "title" 3,code prefix() : "'prefix'+ "title"
* @return String
*/
@AliasFor("value")
String code() default "";
/**
* SpEL
* @return boolean SpEL
*/
String condition() default "";
}

@ -1,15 +0,0 @@
package com.baiye;
import java.lang.annotation.*;
/**
*
*
* @author hccake
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface I18nIgnore {
}

@ -1,38 +0,0 @@
package com.baiye;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
/**
* message bundle
*
* @author hccake
*/
@Data
@Schema(title = "国际化信息")
public class I18nMessage {
/**
*
*/
@NotEmpty(message = "{i18nMessage.code}{}")
@Schema(title = "国际化标识")
private String code;
/**
*
*/
@NotEmpty(message = "{i18nMessage.message}{}")
@Schema(title = "文本值,可以使用 { } 加角标,作为占位符")
private String message;
/**
*
*/
@NotEmpty(message = "{i18nMessage.languageTag}{}")
@Schema(title = "语言标签")
private String languageTag;
}

@ -1,23 +0,0 @@
package com.baiye;
import org.springframework.context.ApplicationEvent;
import java.util.List;
/**
* I18nMessage Listener I18nMessage
*
* @author hccake
*/
public class I18nMessageCreateEvent extends ApplicationEvent {
public I18nMessageCreateEvent(List<I18nMessage> i18nMessages) {
super(i18nMessages);
}
@SuppressWarnings("unchecked")
public List<I18nMessage> getI18nMessages() {
return (List<I18nMessage>) super.getSource();
}
}

@ -1,20 +0,0 @@
package com.baiye;
import java.util.Locale;
/**
* 使
*
* @author hccake
*/
public interface I18nMessageProvider {
/**
* I18nMessage
* @param code
* @param locale
* @return
*/
I18nMessage getI18nMessage(String code, Locale locale);
}

@ -1,23 +0,0 @@
package com.baiye;
import lombok.Data;
import org.springframework.stereotype.Component;
/**
* @author hccake
*/
@Data
@Component
public class I18nOptions {
/**
* languageTag 退 languageTag退
*/
private String fallbackLanguageTag = "zh-CN";
/**
* 使NoSuchMessageException
*/
private boolean useCodeAsDefaultMessage = true;
}

@ -1,237 +0,0 @@
package com.baiye;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* ResponseBodyAdvice
*
* @author Yakir
* @author hccake
*/
@Slf4j
@RestControllerAdvice
public class I18nResponseAdvice implements ResponseBodyAdvice<Object> {
private final MessageSource messageSource;
private final boolean useCodeAsDefaultMessage;
private Locale fallbackLocale = null;
/**
* SpEL
*/
private static final ExpressionParser PARSER = new SpelExpressionParser();
/**
*
*/
private static final Map<String, Expression> EXPRESSION_CACHE = new HashMap<>();
public I18nResponseAdvice(MessageSource messageSource, I18nOptions i18nOptions) {
this.messageSource = messageSource;
String fallbackLanguageTag = i18nOptions.getFallbackLanguageTag();
if (fallbackLanguageTag != null) {
String[] arr = fallbackLanguageTag.split("-");
Assert.isTrue(arr.length == 2, "error fallbackLanguageTag!");
fallbackLocale = new Locale(arr[0], arr[1]);
}
this.useCodeAsDefaultMessage = i18nOptions.isUseCodeAsDefaultMessage();
}
/**
* 使 @I18nIgnore
* @param returnType MethodParameter
* @param converterType
* @return boolean: true is support, false is ignored
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
AnnotatedElement annotatedElement = returnType.getAnnotatedElement();
I18nIgnore i18nIgnore = AnnotationUtils.findAnnotation(annotatedElement, I18nIgnore.class);
return i18nIgnore == null;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
try {
switchLanguage(body);
}
catch (Exception ex) {
log.error("[国际化]响应体国际化处理异常:{}", body);
}
return body;
}
/**
* <p>
* {@link I18nClass}
* </p>
* ps: String {@link I18nField}
* @param source
*/
public void switchLanguage(Object source) {
if (source == null) {
return;
}
Class<?> sourceClass = source.getClass();
// 只对添加了 I18nClass 注解的类进行处理
I18nClass i18nClass = sourceClass.getAnnotation(I18nClass.class);
if (i18nClass == null) {
return;
}
for (Field field : ReflectUtil.getFields(sourceClass)) {
Class<?> fieldType = field.getType();
Object fieldValue = ReflectUtil.getFieldValue(source, field);
if (fieldValue instanceof String) {
// 若不存在国际化注解 直接跳过
I18nField i18nField = field.getAnnotation(I18nField.class);
if (i18nField == null) {
continue;
}
// 国际化条件判断
String conditionExpression = i18nField.condition();
if (CharSequenceUtil.isNotEmpty(conditionExpression)) {
Expression expression = EXPRESSION_CACHE.computeIfAbsent(conditionExpression,
PARSER::parseExpression);
Boolean needI18n = expression.getValue(source, Boolean.class);
if (needI18n != null && !needI18n) {
continue;
}
}
// 获取国际化标识
String code = parseMessageCode(source, (String) fieldValue, i18nField);
if (CharSequenceUtil.isEmpty(code)) {
continue;
}
// 把当前 field 的值更新为国际化后的属性
Locale locale = LocaleContextHolder.getLocale();
String message = codeToMessage(code, locale, (String) fieldValue, fallbackLocale);
ReflectUtil.setFieldValue(source, field, message);
}
else if (fieldValue instanceof Collection) {
@SuppressWarnings("unchecked")
Collection<Object> elements = (Collection<Object>) fieldValue;
if (CollUtil.isEmpty(elements)) {
continue;
}
// 集合属性 递归处理
for (Object element : elements) {
switchLanguage(element);
}
}
else if (fieldType.isArray()) {
Object[] elements = (Object[]) fieldValue;
if (elements == null || elements.length == 0) {
continue;
}
// 数组 递归处理
for (Object element : elements) {
switchLanguage(element);
}
}
else {
// 其他类型的属性,递归判断处理
switchLanguage(fieldValue);
}
}
}
/**
* code
* <ul>
* <li> @I18nField code SpEL 使 code
* <li>使 code
* </ul>
* @param source
* @param fieldValue
* @param i18nField
* @return String code
*/
private String parseMessageCode(Object source, String fieldValue, I18nField i18nField) {
// 如果没有指定 spel则直接返回属性值
String codeExpression = i18nField.code();
if (CharSequenceUtil.isEmpty(codeExpression)) {
return fieldValue;
}
// 否则解析 spel
Expression expression = EXPRESSION_CACHE.computeIfAbsent(codeExpression, PARSER::parseExpression);
return expression.getValue(source, String.class);
}
/**
* code
* @param code
* @param locale
* @param fallbackLocale 退
* @return text code
*/
private String codeToMessage(String code, Locale locale, String defaultMessage, Locale fallbackLocale) {
String message;
try {
message = messageSource.getMessage(code, null, locale);
return message;
}
catch (NoSuchMessageException e) {
log.warn("[codeToMessage]未找到对应的国际化配置code: {}, local: {}", code, locale);
}
// 当配置了回退语言时,尝试回退
if (fallbackLocale != null && locale != fallbackLocale) {
try {
message = messageSource.getMessage(code, null, fallbackLocale);
return message;
}
catch (NoSuchMessageException e) {
log.warn("[codeToMessage]期望语言和回退语言中皆未找到对应的国际化配置code: {}, local: {}, fallbackLocale{}", code, locale,
fallbackLocale);
}
}
if (useCodeAsDefaultMessage) {
return code;
}
else {
return defaultMessage;
}
}
}

@ -1,41 +0,0 @@
package com.baiye;
import org.springframework.context.HierarchicalMessageSource;
import org.springframework.context.MessageSource;
import org.springframework.context.support.AbstractApplicationContext;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* MessageSource DynamicMessageSource
*
* @author hccake
*/
public class MessageSourceHierarchicalChanger {
@Resource(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME)
private MessageSource messageSource;
@Resource(name = DynamicMessageSource.DYNAMIC_MESSAGE_SOURCE_BEAN_NAME)
private DynamicMessageSource dynamicMessageSource;
/**
* dynamicMessageSource messageSource <br/>
* messageSource messageSource dynamicMessageSource
*/
@PostConstruct
public void changeMessageSourceParent() {
// 优先走 messageSource从资源文件中查找
if (messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hierarchicalMessageSource = (HierarchicalMessageSource) messageSource;
MessageSource parentMessageSource = hierarchicalMessageSource.getParentMessageSource();
dynamicMessageSource.setParentMessageSource(parentMessageSource);
hierarchicalMessageSource.setParentMessageSource(dynamicMessageSource);
}
else {
dynamicMessageSource.setParentMessageSource(messageSource);
}
}
}

@ -1,76 +0,0 @@
package com.baiye;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* ResourceBundleMessageSource便 jar .
*
* ReloadableResourceBundleMessageSource
*
* @see <a href=
* "https://stackoverflow.com/questions/3888832/does-spring-messagesource-support-multiple-class-path">Does
* Spring MessageSource Support Multiple Class Path?</a>
* @author Nicolás Miranda
* @author hccake
*/
@Slf4j
public class WildcardReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {
private static final String PROPERTIES_SUFFIX = ".properties";
private final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
/**
* Calculate all filenames for the given bundle basename and Locale. Will calculate
* filenames for the given Locale, the system Locale (if applicable), and the default
* file.
* @param basename the basename of the bundle
* @param locale the locale
* @return the List of filenames to check
* @see #setFallbackToSystemLocale
* @see #calculateFilenamesForLocale
*/
@Override
protected List<String> calculateAllFilenames(String basename, Locale locale) {
// 父类默认的方法会将 basename 也放入 filenames 列表
List<String> filenames = super.calculateAllFilenames(basename, locale);
// 当 basename 有匹配符时,从 filenames 中移除,否则扫描文件将抛出 Illegal char <*> 的异常
if (basename.contains("*")) {
filenames.remove(basename);
}
return filenames;
}
@Override
protected List<String> calculateFilenamesForLocale(String basename, Locale locale) {
// 支持 basename 用 . 表示文件层级
basename = basename.replace(".", "/");
// 资源文件名
List<String> fileNames = new ArrayList<>();
// 获取到待匹配的国际化信息文件名集合
List<String> matchFilenames = super.calculateFilenamesForLocale(basename, locale);
for (String matchFilename : matchFilenames) {
try {
Resource[] resources = resolver.getResources("classpath*:" + matchFilename + PROPERTIES_SUFFIX);
for (Resource resource : resources) {
String sourcePath = resource.getURI().toString().replace(PROPERTIES_SUFFIX, "");
fileNames.add(sourcePath);
}
}
catch (IOException ex) {
log.error("读取国际化信息文件异常", ex);
}
}
return fileNames;
}
}

@ -1,3 +0,0 @@
i18nMessage.languageTag=Language Tag
i18nMessage.code=Code
i18nMessage.message=Message

@ -1,3 +0,0 @@
i18nMessage.languageTag=Language Tag
i18nMessage.code=Code
i18nMessage.message=Message

@ -1,3 +0,0 @@
i18nMessage.languageTag=\u8BED\u8A00\u6807\u7B7E
i18nMessage.code=\u56FD\u9645\u5316\u6807\u8BC6
i18nMessage.message=\u6587\u672C\u503C

@ -1,34 +0,0 @@
package com.baiye;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 使
*
* @author hccake
*/
public class DefautlI18nMessageProvider {
private static final Map<String, I18nMessage> map = new ConcurrentHashMap<>();
static {
I18nMessage i18nMessage = new I18nMessage();
i18nMessage.setMessage("你好啊");
i18nMessage.setCode("test");
i18nMessage.setLanguageTag("zh-CN");
map.put("test:zh-CN", i18nMessage);
I18nMessage i18nMessage2 = new I18nMessage();
i18nMessage2.setMessage("Hello");
i18nMessage2.setCode("test");
i18nMessage2.setLanguageTag("en-US");
map.put("test:en-US", i18nMessage2);
}
public I18nMessage getI18nMessage(String code, Locale locale) {
String languageTag = locale.toLanguageTag();
return map.get(code + ":" + languageTag);
}
}

@ -13,7 +13,7 @@ import java.io.Serializable;
* @param <T>
* @author Hccake
*/
@I18nClass
// @I18nClass
@Getter
@Setter
@ToString

@ -13,7 +13,6 @@
<modules>
<module>common-core</module>
<module>common-desensitize</module>
<module>common-i18n</module>
<module>common-idempotent</module>
<module>common-log</module>
<module>common-model</module>

@ -68,7 +68,6 @@ public final class PasswordUtils {
byte[] secretKeyBytes = secretKey.getBytes();
AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, secretKeyBytes, secretKeyBytes);
byte[] result = aes.decrypt(Base64.decode(aesPass.getBytes(StandardCharsets.UTF_8)));
System.out.println(new String(result, StandardCharsets.UTF_8));
return new String(result, StandardCharsets.UTF_8);
}

@ -10,7 +10,6 @@ import com.example.entity.Job;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@ -31,30 +30,28 @@ public class JobApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
// log.info("==============项目启动,自动添加业务中定时任务==============");
// List<DistributeTaskEntity> distributeTaskEntities =
// distributeTaskMapper.selectList(
// new
// LambdaQueryWrapper<DistributeTaskEntity>().eq(DistributeTaskEntity::getDistributeTaskType,
// 1)
// .eq(DistributeTaskEntity::getTimeStatus, 1)
// .ne(DistributeTaskEntity::getExecuteStatus, 0));
//
// if (CollUtil.isNotEmpty(distributeTaskEntities)) {
// for (DistributeTaskEntity distributeTaskEntity : distributeTaskEntities) {
// Job job = new Job();
// job.setJobName(PrefixKeyConstant.JOB_KEY +
// distributeTaskEntity.getDistributeTaskId());
// String cron = DateTimeToCronUtils.getCron(distributeTaskEntity.getStartTime(),
// DateTimeToCronUtils.EVERYDAY);
// job.setCron(cron);
// job.setJobClass("com.baiye.job.LinkWatchJob");
// jobService.addJob(job);
// // 暂停
// if (distributeTaskEntity.getExecuteStatus() == 3)
// jobService.pauseJob(job.getJobName());
// }
// }
log.info("==============项目启动,自动添加业务中定时任务==============");
List<DistributeTaskEntity> distributeTaskEntities = distributeTaskMapper.selectList(
new LambdaQueryWrapper<DistributeTaskEntity>().eq(DistributeTaskEntity::getDistributeTaskType, 1)
.eq(DistributeTaskEntity::getTimeStatus, 1)
.ne(DistributeTaskEntity::getExecuteStatus, 0));
if (CollUtil.isNotEmpty(distributeTaskEntities)) {
for (DistributeTaskEntity distributeTaskEntity : distributeTaskEntities) {
if (distributeTaskEntity != null && distributeTaskEntity.getStartTime() != null) {
Job job = new Job();
job.setJobName(PrefixKeyConstant.JOB_KEY + distributeTaskEntity.getDistributeTaskId());
String cron = DateTimeToCronUtils.getCron(distributeTaskEntity.getStartTime(),
DateTimeToCronUtils.EVERYDAY);
job.setCron(cron);
job.setJobClass("com.baiye.job.LinkWatchJob");
jobService.addJob(job);
// 暂停
if (distributeTaskEntity.getExecuteStatus() == 3)
jobService.pauseJob(job.getJobName());
}
}
}
}
}

@ -26,7 +26,10 @@ public class LinkWatchJob implements SimpleJob {
String str = jobName.substring(jobName.lastIndexOf("_") + 1);
log.info("==============定时任务开始ID{}================", str);
DistributeTaskEntity entity = distributeTaskService.getById(Long.parseLong(str));
distributeTaskService.execute(entity);
if (entity != null) {
distributeTaskService.execute(entity);
}
}
}

@ -1,7 +1,6 @@
package com.baiye.modules.distribute.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.baiye.exception.BadRequestException;
import com.baiye.modules.distribute.service.ClueFileService;
import com.baiye.result.R;
@ -10,15 +9,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Map;
@ -31,12 +24,17 @@ public class ClueFileController {
private final ClueFileService clueFileService;
private final ResourceLoader resourceLoader;
@PostMapping("/detection")
@Operation(summary = "校验表头信息")
public R<Map<String, Object>> detection(@RequestParam("file") MultipartFile file) {
return R.ok(clueFileService.detection(file));
}
@PostMapping("/fileUpload")
@Operation(summary = "文件上传资源")
public R<Object> clueFileUpload(@RequestParam("file") MultipartFile file) {
return R.ok(clueFileService.clueFileUpload(file));
@GetMapping("/readFile")
@Operation(summary = "读取文件信息")
public R<Object> readFile(@RequestParam("recordId") Long recordId) {
clueFileService.readFile(recordId);
return R.ok();
}
@GetMapping("/export")
@ -47,8 +45,7 @@ public class ClueFileController {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
// EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).sheet().doWrite(null);
final ExcelWriter write = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).build();
EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).sheet().doWrite(new ArrayList<>());
}
catch (IOException e) {
throw new BadRequestException("导出失败,请联系管理员");

@ -0,0 +1,38 @@
package com.baiye.modules.distribute.controller;
import com.baiye.modules.distribute.entity.ClueFollowRecordEntity;
import com.baiye.modules.distribute.service.ClueFollowRecordService;
import com.baiye.result.BaseResultCode;
import com.baiye.result.R;
import com.baiye.validation.group.CreateGroup;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequiredArgsConstructor
@RestController
@Tag(name = "资源跟进记录API")
@RequestMapping("/clueFollow")
public class ClueFollowRecordController {
private final ClueFollowRecordService clueFollowRecordService;
@PostMapping("/add")
@Operation(summary = "新增线索跟进记录", description = "新增线索跟进记录")
public R<Object> add(@Validated({ CreateGroup.class }) @RequestBody ClueFollowRecordEntity clueStageEntity) {
return clueFollowRecordService.add(clueStageEntity) ? R.ok()
: R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "添加失败");
}
@DeleteMapping("/delAll")
@Operation(summary = "ID删除线索阶段")
public R<Void> deleteByUserId(@RequestBody List<Long> ids) {
return clueFollowRecordService.removeBatchByIds(ids) ? R.ok()
: R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "删除失败");
}
}

@ -1,31 +1,28 @@
package com.baiye.modules.distribute.dto;
import cn.hutool.json.JSONArray;
import lombok.Data;
/**
* @Author YQY
* @Date 2023/8/7
*/
@Data
public class DBPushClueDTO {
private String app_id;
private String startTime;
private Long startTime;
private String endTime;
private Long endTime;
private String recId;
private String ringTime;
private Long ringTime;
private String talkTime;
private Long talkTime;
private String wordId;
private String notConnectStatus;
private Integer notConnectStatus;
private String actId;
private Long actId;
private String actType;
@ -45,11 +42,9 @@ public class DBPushClueDTO {
private String empClientTypeName;
private String clientVariables;
private JSONArray audioText;
private String audioText;
private String sender;
private Integer sender;
private String context;
@ -57,7 +52,7 @@ public class DBPushClueDTO {
private String sms_content;
private String sms_status;
private Integer sms_status;
private String remark;

@ -0,0 +1,46 @@
package com.baiye.modules.distribute.entity;
import com.baiye.entity.BaseEntity;
import com.baiye.validation.group.CreateGroup;
import com.baiye.validation.group.UpdateGroup;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Getter
@Setter
@ToString
@TableName("tb_clue_follow_record")
@Schema(title = "线索跟进记录表")
public class ClueFollowRecordEntity extends BaseEntity {
@TableId
@Schema(title = "ID")
@NotNull(message = "ID不能为空", groups = { UpdateGroup.class })
private Long id;
@Schema(title = "线索ID")
@NotNull(message = "线索ID不能为空", groups = { CreateGroup.class })
private Long clueId;
@Schema(title = "线索阶段ID")
@NotNull(message = "线索阶段ID不能为空", groups = { CreateGroup.class })
private Long clueStageId;
@Schema(title = "跟进信息")
private String recordInfo;
@Schema(title = "跟进信息集合")
@TableField(exist = false)
@NotEmpty(message = "跟进信息不能为空", groups = { CreateGroup.class })
private List<String> recordInfoList;
}

@ -3,6 +3,7 @@ package com.baiye.modules.distribute.entity;
import com.baiye.entity.BaseEntity;
import com.baiye.validation.group.CreateGroup;
import com.baiye.validation.group.UpdateGroup;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
@ -12,6 +13,7 @@ import lombok.ToString;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @Author YQY
@ -40,4 +42,8 @@ public class ClueStageEntity extends BaseEntity {
@NotNull(message = "线索阶段排序不能为空", groups = { CreateGroup.class })
private Integer sort;
@Schema(title = "线索阶段记录")
@TableField(exist = false)
private List<ClueFollowRecordEntity> clueFollowRecordList;
}

@ -36,10 +36,10 @@ public class DistributeTaskEntity extends BaseEntity {
private String taskName;
@Schema(title = "分发规则 0:平均 1:权重")
private Integer ruleStatus = 0;
private Integer ruleStatus;
@Schema(title = "分发时间 0:实时 1:定时")
private Integer timeStatus = 1;
private Integer timeStatus;
@Schema(title = "定时开始时间")
private LocalDateTime startTime;

@ -0,0 +1,8 @@
package com.baiye.modules.distribute.mapper;
import com.baiye.extend.mybatis.plus.mapper.ExtendMapper;
import com.baiye.modules.distribute.entity.ClueFollowRecordEntity;
public interface ClueFollowRecordMapper extends ExtendMapper<ClueFollowRecordEntity> {
}

@ -41,7 +41,8 @@ public interface ClueRecordMapper extends ExtendMapper<ClueRecordEntity> {
IPage<ClueRecordVO> selectByPage(IPage<ClueRecordVO> page,
@Param(Constants.WRAPPER) Wrapper<ClueRecordEntity> wrapper);
void updateAllocationStatus(@Param("list") List<Long> recordIdList, @Param("status") Integer status);
void updateAllocationStatusAndDistributeStatus(@Param("list") List<Long> recordIdList,
@Param("status") Integer status, @Param("distributeStatus") Integer distributeStatus);
void updateDistributeStatus(@Param("list") List<Long> recordIdList, @Param("status") Integer status);

@ -6,10 +6,15 @@ import java.util.Map;
public interface ClueFileService {
/**
*
*/
Map<String, Object> detection(MultipartFile file);
/**
*
*/
Map<String, Object> clueFileUpload(MultipartFile file);
void readFile(Long recordId);
/**
*

@ -0,0 +1,10 @@
package com.baiye.modules.distribute.service;
import com.baiye.extend.mybatis.plus.service.ExtendService;
import com.baiye.modules.distribute.entity.ClueFollowRecordEntity;
public interface ClueFollowRecordService extends ExtendService<ClueFollowRecordEntity> {
boolean add(ClueFollowRecordEntity clueStageEntity);
}

@ -1,5 +1,6 @@
package com.baiye.modules.distribute.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.ExcelReader;
import com.baiye.constant.DefaultNumberConstants;
@ -44,7 +45,7 @@ public class ClueFileServiceImpl implements ClueFileService {
private final SyncTask syncTask;
@Override
public Map<String, Object> clueFileUpload(MultipartFile multipartFile) {
public Map<String, Object> detection(MultipartFile multipartFile) {
// 检测文件的内容格式
ExcelReader excelReader = ClueFileTestingUtil.testingExcel(multipartFile);
// 保存文件
@ -62,23 +63,28 @@ public class ClueFileServiceImpl implements ClueFileService {
// 获取文件中第一行数据的来源字段 null为未知
List<Object> oneReadList = excelReader.readRow(DefaultNumberConstants.ZERO_NUMBER);
List<Object> twoReadList = excelReader.readRow(DefaultNumberConstants.ONE_NUMBER);
int index = oneReadList.indexOf(UploadTemplateHeadConstant.HEAD_ORIGIN);
String channelStr = (String) twoReadList.get(index);
if (StringUtils.isBlank(channelStr))
channelStr = "未知";
clueRecordEntity.setChannelType(SecurityUtils.getUser().getUsername() + "-" + channelStr);
clueRecordEntity.setChannelIdentifying(channelStr);
if (CollUtil.isNotEmpty(twoReadList)) {
int index = oneReadList.indexOf(UploadTemplateHeadConstant.HEAD_ORIGIN);
String channelStr = (String) twoReadList.get(index);
if (StringUtils.isBlank(channelStr))
channelStr = "未知";
clueRecordEntity.setChannelType(SecurityUtils.getUser().getUsername() + "-" + channelStr);
clueRecordEntity.setChannelIdentifying(channelStr);
}
clueRecordService.save(clueRecordEntity);
// 异步读取资源
syncTask.clueUpload(clueRecordEntity);
Map<String, Object> returnMap = new HashMap<>();
returnMap.put("excelHead", oneReadList);
returnMap.put("clueRecordId", clueRecordEntity.getClueRecordId());
return returnMap;
}
@Override
public void readFile(Long recordId) {
ClueRecordEntity clueRecordEntity = clueRecordService.getById(recordId);
// 异步读取资源
syncTask.clueUpload(clueRecordEntity);
}
@Override
public Map<String, Object> generateSecretKey() {
Map<String, Object> map = new HashMap<>();

@ -0,0 +1,35 @@
package com.baiye.modules.distribute.service.impl;
import com.baiye.extend.mybatis.plus.service.impl.ExtendServiceImpl;
import com.baiye.modules.distribute.entity.ClueFollowRecordEntity;
import com.baiye.modules.distribute.mapper.ClueFollowRecordMapper;
import com.baiye.modules.distribute.service.ClueFollowRecordService;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Service
@Slf4j
public class ClueFollowRecordServiceImpl extends ExtendServiceImpl<ClueFollowRecordMapper, ClueFollowRecordEntity>
implements ClueFollowRecordService {
@Override
@Transactional(rollbackFor = Exception.class)
public boolean add(ClueFollowRecordEntity entity) {
List<ClueFollowRecordEntity> list = new ArrayList<>();
List<String> recordInfoList = entity.getRecordInfoList();
for (String recordInfo : recordInfoList) {
ClueFollowRecordEntity clueFollowRecordEntity = new ClueFollowRecordEntity();
BeanUtils.copyProperties(entity, clueFollowRecordEntity);
clueFollowRecordEntity.setRecordInfo(recordInfo);
list.add(clueFollowRecordEntity);
}
return SqlHelper.retBool(baseMapper.insertBatchSomeColumn(list));
}
}

@ -36,7 +36,8 @@ public class ClueRecordServiceImpl extends ExtendServiceImpl<ClueRecordMapper, C
@Transactional(rollbackFor = Exception.class)
public boolean deleteByUserId(Long clueRecordId) {
ClueRecordEntity clueRecordEntity = baseMapper.selectById(clueRecordId);
FileUtil.del(clueRecordEntity.getUrl());
if (clueRecordEntity != null)
FileUtil.del(clueRecordEntity.getUrl());
return SqlHelper.retBool(baseMapper.deleteById(clueRecordId));
}

@ -8,6 +8,7 @@ import com.baiye.domain.PageResult;
import com.baiye.modules.distribute.converter.ClueConverter;
import com.baiye.modules.distribute.dto.ClueDTO;
import com.baiye.modules.distribute.entity.*;
import com.baiye.modules.distribute.mapper.ClueFollowRecordMapper;
import com.baiye.modules.distribute.mapper.ClueMapper;
import com.baiye.modules.distribute.mapper.ClueRecordMapper;
import com.baiye.modules.distribute.qo.ClueQo;
@ -19,6 +20,8 @@ import com.baiye.security.util.SecurityUtils;
import com.baiye.util.AESUtils;
import com.baiye.util.MobileUtil;
import com.baiye.extend.mybatis.plus.service.impl.ExtendServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -42,6 +45,8 @@ public class ClueServiceImpl extends ExtendServiceImpl<ClueMapper, ClueEntity> i
private final ClueStageService clueStageService;
private final ClueFollowRecordMapper clueFollowRecordMapper;
private final SecurityProperties securityProperties;
@Override
@ -95,20 +100,23 @@ public class ClueServiceImpl extends ExtendServiceImpl<ClueMapper, ClueEntity> i
if (CollUtil.isNotEmpty(recordList)) {
for (ClueVO record : recordList) {
// 手机号隐藏中间4位
// // 手机号隐藏中间4位
String decryptNid = AESUtils.decrypt(record.getNid(), securityProperties.getPasswordSecretKey());
if (StringUtils.isNotBlank(decryptNid)) {
StringBuilder stringBuilder = new StringBuilder(decryptNid);
String nid = stringBuilder.replace(3, 7, "****").toString();
record.setNid(nid);
// StringBuilder stringBuilder = new StringBuilder(decryptNid);
// String nid = stringBuilder.replace(3, 7, "****").toString();
record.setNid(decryptNid);
}
else {
record.setNid("");
}
// 转换标签
JSONArray array = JSONUtil.parseArray(record.getClueLabelName());
record.setClueLabelList(JSONUtil.toList(array, String.class));
record.setClueLabelName("");
String clueLabelName = record.getClueLabelName();
if (StringUtils.isNotBlank(clueLabelName)) {
JSONArray array = JSONUtil.parseArray(clueLabelName);
record.setClueLabelList(JSONUtil.toList(array, String.class));
record.setClueLabelName("");
}
}
}
return pageResult;
@ -129,6 +137,17 @@ public class ClueServiceImpl extends ExtendServiceImpl<ClueMapper, ClueEntity> i
List<String> nameList = clueLabelList.stream().map(LabelEntity::getLabelName).collect(Collectors.toList());
clueEntity.setClueLabelName(JSONUtil.toJsonStr(nameList));
}
else {
// 修改标签为空
LambdaUpdateWrapper<ClueEntity> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(ClueEntity::getClueId, clueDTO.getClueId());
updateWrapper.set(ClueEntity::getClueLabel, null);
updateWrapper.set(ClueEntity::getClueLabelName, null);
baseMapper.update(null, updateWrapper);
clueEntity.setClueLabelName(null);
clueEntity.setClueLabel(null);
}
return SqlHelper.retBool(baseMapper.updateById(clueEntity));
}
@ -144,7 +163,25 @@ public class ClueServiceImpl extends ExtendServiceImpl<ClueMapper, ClueEntity> i
List<LabelOrganizeEntity> organizeEntities = labelOrganizeService.queryUserList(whichUserId);
// 查询上级用户阶段
List<ClueStageEntity> clueStageEntities = clueStageService.queryUserList(whichUserId);
if (CollUtil.isNotEmpty(clueStageEntities)) {
List<Long> clueStageIds = clueStageEntities.stream()
.map(ClueStageEntity::getClueStageId)
.collect(Collectors.toList());
// 查询阶段的记录
List<ClueFollowRecordEntity> clueFollowRecordEntities = clueFollowRecordMapper.selectList(
new LambdaQueryWrapper<ClueFollowRecordEntity>().eq(ClueFollowRecordEntity::getClueId, clueId)
.in(ClueFollowRecordEntity::getClueStageId, clueStageIds));
// 记录放入阶段中
if (CollUtil.isNotEmpty(clueFollowRecordEntities)) {
Map<Long, List<ClueFollowRecordEntity>> map = clueFollowRecordEntities.stream()
.collect(Collectors.groupingBy(ClueFollowRecordEntity::getClueStageId));
for (ClueStageEntity clueStageEntity : clueStageEntities) {
if (map.containsKey(clueStageEntity.getClueStageId())) {
clueStageEntity.setClueFollowRecordList(map.get(clueStageEntity.getClueStageId()));
}
}
}
}
clueVO.setOrganizeEntities(organizeEntities);
clueVO.setClueStageEntities(clueStageEntities);

@ -29,7 +29,6 @@ import com.baiye.system.service.SysUserService;
import com.baiye.utils.AssignDataUtil;
import com.baiye.utils.DateTimeToCronUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.example.entity.Job;
import lombok.RequiredArgsConstructor;
@ -125,26 +124,16 @@ public class DistributeTaskServiceImpl extends ExtendServiceImpl<DistributeTaskM
}
}
// 2、修改自动任务信息
if (distributeTaskType != null && distributeTaskType == 1) {
if (!distributeTaskType.equals(taskEntity.getDistributeTaskType())) {
// 添加定时任务
this.addJob(taskId, taskEntity.getStartTime(), true);
if (distributeTaskType != null && distributeTaskType == 1 && taskEntity.getDistributeTaskType() == 1) {
Integer timeStatus = taskEntity.getTimeStatus();
LocalDateTime time = taskEntity.getStartTime();
if (timeStatus == 1 && status == 0) {
// 删除定时任务
jobService.removeJob(PrefixKeyConstant.JOB_KEY + taskId);
}
else {
Integer timeStatus = taskEntity.getTimeStatus();
LocalDateTime time = taskEntity.getStartTime();
if (status == 1 && timeStatus == 0) {
// 添加定时任务
this.addJob(taskId, taskEntity.getStartTime(), true);
}
if (timeStatus == 1 && status == 0) {
// 删除定时任务
jobService.removeJob(PrefixKeyConstant.JOB_KEY + taskId);
}
if (timeStatus == 1 && startTime != null && time != null && !startTime.isEqual(time)) {
// 修改定时任务
this.addJob(taskId, time, false);
}
if (timeStatus == 1 && status == 1 && startTime != null && time != null && !startTime.isEqual(time)) {
// 修改定时任务
this.addJob(taskId, startTime, false);
}
}
if (executeStatus != null && executeStatus == 3 && !executeStatus.equals(taskEntity.getExecuteStatus())) {
@ -193,21 +182,20 @@ public class DistributeTaskServiceImpl extends ExtendServiceImpl<DistributeTaskM
updateEntity.setDistributeTaskId(taskId);
if (taskEntity != null) {
// 执行手动任务
// 执行手动任务(立即执行分发)
Integer timeStatus = taskEntity.getTimeStatus();
if (taskEntity.getDistributeTaskType() == 0 || (timeStatus != null && timeStatus == 0)) {
this.execute(taskEntity);
updateEntity.setExecuteStatus(2);
}
// 执行自动任务
// 执行自动任务(对定时任务进行修改)
if (taskEntity.getDistributeTaskType() == 1 && timeStatus != null && timeStatus == 1) {
// 添加定时任务
if (taskEntity.getExecuteStatus() == 0) {
this.addJob(taskId, taskEntity.getStartTime(), true);
Job jobDetail = jobService.getJobDetail(PrefixKeyConstant.JOB_KEY + taskId);
if (jobDetail != null && jobDetail.getJobName() != null) {
jobService.resumeJob(PrefixKeyConstant.JOB_KEY + taskId);// 开启定时任务
}
// 开启定时任务
if (taskEntity.getExecuteStatus() == 3) {
jobService.start(PrefixKeyConstant.JOB_KEY + taskId);
else {
this.addJob(taskId, taskEntity.getStartTime(), true);// 添加定时任务
}
updateEntity.setExecuteStatus(1);
}
@ -302,91 +290,89 @@ public class DistributeTaskServiceImpl extends ExtendServiceImpl<DistributeTaskM
.collect(Collectors.toList());
}
}
// 查询分配人用户信息
List<SysUser> updateSysUserList = new ArrayList<>();
List<SysUser> sysUsers = sysUserService.listByUserIds(userIdList);
Map<Long, List<SysUser>> userIdMap = sysUsers.stream().collect(Collectors.groupingBy(SysUser::getUserId));
// 获取文件中未分配的资源ID
List<Long> clueIds = clueService.findUndistributedClueIds(recordIdList);
// 分配
DistributeDTO distributeDTO = new DistributeDTO();
distributeDTO.setDeptIds(userIdList);
distributeDTO.setResourceList(clueIds);
if (taskEntity.getRuleStatus() == DefaultNumberConstants.ONE_NUMBER) {
distributeDTO.setIsWeight(true);
List<Integer> weightList = userEntities.stream()
.map(DistributeTaskUserEntity::getWeight)
.collect(Collectors.toList());
List<Double> weights = weightList.stream().map(i -> i * 10.0).collect(Collectors.toList());
distributeDTO.setWeights(weights);
}
// 查询业务管理员用户的默认文件记录
Map<Long, List<ClueRecordEntity>> map = null;
if (createBy == 1) {
List<ClueRecordEntity> recordEntities = clueRecordMapper
.selectList(new LambdaQueryWrapper<ClueRecordEntity>().in(ClueRecordEntity::getCreateBy, userIdList)
.eq(ClueRecordEntity::getRecordType, DefaultNumberConstants.ONE_NUMBER));
map = recordEntities.stream().collect(Collectors.groupingBy(ClueRecordEntity::getCreateBy));
}
// 分配数据
List<ClueEntity> clueEntityList = new ArrayList<>();
List<DistributeResponseDTO> responseDTOS = AssignDataUtil.assignData(distributeDTO);
// 更新分配信息
for (DistributeResponseDTO responseDTO : responseDTOS) {
// 用户分发量修改
if (userIdMap.containsKey(responseDTO.getDeptId())) {
SysUser sysUser = userIdMap.get(responseDTO.getDeptId()).get(0);
sysUser.setDistributeNum(sysUser.getDistributeNum() + responseDTO.getResponseList().size());
updateSysUserList.add(sysUser);
}
Long assignedBy = responseDTO.getDeptId();
for (Long clueId : responseDTO.getResponseList()) {
ClueEntity clueEntity = new ClueEntity();
clueEntity.setClueId(clueId);
// 业务员更新的是分配人,否则是admin给业务管理员分配(分配到默认创建的记录中)
if (createBy != 1) {
clueEntity.setAssignedBy(assignedBy);
if (userIdMap.containsKey(assignedBy)) {
SysUser sysUser = userIdMap.get(assignedBy).get(0);
clueEntity.setAssignedName(sysUser.getUsername());
}
if (CollUtil.isNotEmpty(recordIdList)) {
// 查询分配人用户信息
List<SysUser> updateSysUserList = new ArrayList<>();
List<SysUser> sysUsers = sysUserService.listByUserIds(userIdList);
Map<Long, List<SysUser>> userIdMap = sysUsers.stream()
.collect(Collectors.groupingBy(SysUser::getUserId));
// 获取文件中未分配的资源
List<Long> clueIds = clueService.findUndistributedClueIds(recordIdList);
// 分配
if (CollUtil.isNotEmpty(clueIds)) {
DistributeDTO distributeDTO = new DistributeDTO();
distributeDTO.setDeptIds(userIdList);
distributeDTO.setResourceList(clueIds);
if (taskEntity.getRuleStatus() == DefaultNumberConstants.ONE_NUMBER) {
distributeDTO.setIsWeight(true);
List<Integer> weightList = userEntities.stream()
.map(DistributeTaskUserEntity::getWeight)
.collect(Collectors.toList());
List<Double> weights = weightList.stream().map(i -> i * 10.0).collect(Collectors.toList());
distributeDTO.setWeights(weights);
}
List<DistributeResponseDTO> responseDTOS = AssignDataUtil.assignData(distributeDTO);
// 查询业务管理员用户的默认文件记录
Map<Long, List<ClueRecordEntity>> map = null;
if (createBy == 1) {
List<ClueRecordEntity> recordEntities = clueRecordMapper.selectList(
new LambdaQueryWrapper<ClueRecordEntity>().in(ClueRecordEntity::getCreateBy, userIdList)
.eq(ClueRecordEntity::getRecordType, DefaultNumberConstants.ONE_NUMBER));
map = recordEntities.stream().collect(Collectors.groupingBy(ClueRecordEntity::getCreateBy));
}
// admin给业务管理员分配 改变线索的记录ID即可
else {
if (CollUtil.isNotEmpty(map) && map.containsKey(assignedBy)) {
ClueRecordEntity clueRecordEntity = map.get(assignedBy).get(0);
clueEntity.setClueRecordId(clueRecordEntity.getClueRecordId());
List<ClueEntity> clueEntityList = new ArrayList<>();
// 更新分配信息
for (DistributeResponseDTO responseDTO : responseDTOS) {
// 用户分发量修改
if (userIdMap.containsKey(responseDTO.getDeptId())) {
SysUser sysUser = userIdMap.get(responseDTO.getDeptId()).get(0);
sysUser.setDistributeNum(sysUser.getDistributeNum() + responseDTO.getResponseList().size());
updateSysUserList.add(sysUser);
}
Long assignedBy = responseDTO.getDeptId();
for (Long clueId : responseDTO.getResponseList()) {
ClueEntity clueEntity = new ClueEntity();
clueEntity.setClueId(clueId);
// 业务员更新的是分配人,否则是admin给业务管理员分配(分配到默认创建的记录中)
if (createBy != 1) {
clueEntity.setAssignedBy(assignedBy);
if (userIdMap.containsKey(assignedBy)) {
SysUser sysUser = userIdMap.get(assignedBy).get(0);
clueEntity.setAssignedName(sysUser.getUsername());
}
}
// admin给业务管理员分配 改变线索的记录ID即可
else {
if (CollUtil.isNotEmpty(map) && map.containsKey(assignedBy)) {
ClueRecordEntity clueRecordEntity = map.get(assignedBy).get(0);
clueEntity.setClueRecordId(clueRecordEntity.getClueRecordId());
}
}
// 批量修改数据
clueEntityList.add(clueEntity);
if (clueEntityList.size() >= 3000) {
clueService.updateBatchById(clueEntityList);
clueEntityList.clear();
}
}
}
// 批量修改数据
clueEntityList.add(clueEntity);
if (clueEntityList.size() >= 3000) {
if (CollUtil.isNotEmpty(clueEntityList)) {
clueService.updateBatchById(clueEntityList);
clueEntityList.clear();
}
}
}
// 批量修改数据
if (CollUtil.isNotEmpty(clueEntityList)) {
clueService.updateBatchById(clueEntityList);
}
// 用户分发量修改
sysUserService.updateDistributeNum(updateSysUserList);
// 修改任务执行次数+1
baseMapper.updateByExecuteNumAddOne(taskEntity.getDistributeTaskId());
// 修改记录分配状态
if (CollUtil.isNotEmpty(recordIdList))
clueRecordMapper.updateAllocationStatus(recordIdList, 1);
// 异步分发下级任务
if (taskEntity.getCreateBy() == 1) {
List<DistributeTaskEntity> taskEntities = baseMapper.selectList(
new LambdaQueryWrapper<DistributeTaskEntity>().eq(DistributeTaskEntity::getDefaultType, 0)
.in(DistributeTaskEntity::getCreateBy, userIdList));
if (CollUtil.isNotEmpty(taskEntities)) {
List<Long> list = taskEntities.stream()
.map(DistributeTaskEntity::getDistributeTaskId)
.collect(Collectors.toList());
this.syncExecuteTask(list);
// 用户分发量修改
sysUserService.updateDistributeNum(updateSysUserList);
// 修改任务执行次数+1
baseMapper.updateByExecuteNumAddOne(taskEntity.getDistributeTaskId());
// 修改记录分配状态
if (CollUtil.isNotEmpty(recordIdList)) {
clueRecordMapper.updateAllocationStatusAndDistributeStatus(recordIdList, 1, 1);
}
// 分发下级任务
if (taskEntity.getCreateBy() == 1) {
this.syncExecuteTask(userIdList);
}
}
}
}
@ -556,10 +542,19 @@ public class DistributeTaskServiceImpl extends ExtendServiceImpl<DistributeTaskM
/**
*
*/
private void syncExecuteTask(List<Long> taskIds) {
List<DistributeTaskEntity> distributeTaskEntities = baseMapper.selectBatchIds(taskIds);
for (DistributeTaskEntity distributeTaskEntity : distributeTaskEntities) {
this.execute(distributeTaskEntity);
private void syncExecuteTask(List<Long> userIdList) {
List<DistributeTaskEntity> taskEntities = baseMapper
.selectList(new LambdaQueryWrapper<DistributeTaskEntity>().eq(DistributeTaskEntity::getDefaultType, 0)
.in(DistributeTaskEntity::getCreateBy, userIdList));
if (CollUtil.isNotEmpty(taskEntities)) {
for (DistributeTaskEntity distributeTaskEntity : taskEntities) {
Integer executeStatus = distributeTaskEntity.getExecuteStatus();
Integer distributeTaskType = distributeTaskEntity.getDistributeTaskType();
Integer timeStatus = distributeTaskEntity.getTimeStatus();
if ((distributeTaskType == 1 && timeStatus == 0) && executeStatus != 0 && executeStatus != 3) {
this.execute(distributeTaskEntity);
}
}
}
}

@ -75,7 +75,7 @@ public class OutsideReqServiceImpl implements OutsideReqService {
new LambdaQueryWrapper<DistributeTaskEntity>().eq(DistributeTaskEntity::getDefaultType, 0)
.eq(DistributeTaskEntity::getCreateBy, linkEntity.getCreateBy())
.eq(DistributeTaskEntity::getFileRecordId, linkEntity.getClueRecordId()));
if (entity.getExecuteStatus() != 1 && entity.getExecuteStatus() != 3)
if (entity.getExecuteStatus() != 0 && entity.getExecuteStatus() != 3)
distributeTaskService.execute(entity);
}

@ -39,7 +39,7 @@ public class PushLinkServiceImpl extends ExtendServiceImpl<PushLinkMapper, PushL
PushLinkEntity pushLinkEntity = baseMapper
.selectOne(new LambdaQueryWrapper<PushLinkEntity>().eq(PushLinkEntity::getUserId, userId));
if (pushLinkEntity != null) {
dbPushUrl = dbPushUrl.concat(pushLinkEntity.getAppKey());
dbPushUrl = dbPushUrl.concat(pushLinkEntity.getAppKey()).concat("?dataType=detail&encrypt=1");
}
else {
// 生成的appKey标识重复,重新生成
@ -51,7 +51,7 @@ public class PushLinkServiceImpl extends ExtendServiceImpl<PushLinkMapper, PushL
break;
appKey = AppUtils.getAppId();
}
dbPushUrl = dbPushUrl.concat(appKey);
dbPushUrl = dbPushUrl.concat(appKey).concat("?dataType=detail&encrypt=1");
// 创建记录(任务)
ClueRecordEntity clueRecordEntity = clueRecordService
.addDefaultRecordService(SecurityUtils.getCurrentUserId(), dtoName, dtoName);

@ -4,7 +4,6 @@ import com.alibaba.excel.EasyExcelFactory;
import com.baiye.easyexcel.listener.ClueListener;
import com.baiye.modules.distribute.entity.ClueRecordEntity;
import com.baiye.modules.distribute.service.ClueService;
import com.baiye.modules.distribute.service.DistributeTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@ -1,5 +1,6 @@
package com.baiye.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
@ -55,8 +56,14 @@ public class ClueFileTestingUtil {
}
// 检测excel数量
int rowCount = reader.getRowCount() - 1;
if (rowCount < 1)
if (rowCount < 1) {
throw new BadRequestException("空文件,请检查文件内容");
}
// 如果第二行就是空行 判断为空文件
List<Object> rowData = reader.readRow(1);
if (CollUtil.isEmpty(rowData)) {
throw new BadRequestException("空文件,请检查文件内容");
}
if (rowCount > 1000000)
throw new BadRequestException("文件行数不得超过100w行,请处理");
return reader;

@ -19,7 +19,7 @@ business:
urls:
dbPushUrl: https://aidrop.z48.cn/outside/pushClue/
dbPushUrl: http://cs.tuoz.net:8100/outside/pushClue/
springdoc:
swagger-ui:

@ -1,25 +1,25 @@
spring:
datasource:
url: jdbc:mysql://localhost:3306/ballcat?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
url: jdbc:mysql://localhost:3306/ad_distribute?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 7f2vvawx
redis:
host: ballcat-redis
host: localhost
password: ''
port: 6379
# 日志文件地址,配置此属性以便 SBA 在线查看日志
logging:
file:
path: logs/@artifactId@
name: ${logging.file.path}/output.log
business:
roleCodes:
# admin超级管理员
- ROLE_ADMIN
# 业务管理员
- ROLE_SALES_EXECUTIVE
urls:
dbPushUrl: https://baiyea.net/api/outside/pushClue/
# 生产环境关闭文档
ballcat:
openapi:
enabled: false
oss:
bucket: your-bucket-here
endpoint: http://oss-cn-shanghai.aliyuncs.com
access-key: your key here
access-secret: your secret here
enabled: false

@ -18,7 +18,7 @@ business:
- ROLE_SALES_EXECUTIVE
urls:
dbPushUrl: https://aidrop.z48.cn/outside/pushClue/
dbPushUrl: http://cs.tuoz.net:8100/outside/pushClue/
springdoc:
swagger-ui:

@ -5,11 +5,7 @@ spring:
application:
name: @artifactId@
profiles:
active: dev # 当前激活配置默认dev
messages:
# basename 中的 . 和 / 都可以用来表示文件层级,默认的 basename 是 messages
# 必须注册此 basename, 否则 security 错误信息将一直都是英文
basename: 'ballcat-*, org.springframework.security.messages'
active: dev
# 天爱图形验证码
captcha:
@ -58,38 +54,6 @@ ballcat:
# 项目 redis 缓存的 key 前缀
redis:
key-prefix: 'ballcat:'
# actuator 加解密密钥
actuator:
auth: true
secret-id: 'ballcat-monitor'
secret-key: '=BallCat-Monitor'
openapi:
info:
title: BallCat-Admin Docs
description: BallCat 后台管理服务Api文档
version: ${project.version}
terms-of-service: http://www.ballcat.cn/
license:
name: Powered By BallCat
url: http://www.ballcat.cn/
contact:
name: Hccake
email: chengbohua@foxmail.com
url: https://github.com/Hccake
components:
security-schemes:
apiKey:
type: APIKEY
in: HEADER
name: 'api-key'
oauth2:
type: OAUTH2
flows:
password:
token-url: /oauth/token
security:
- oauth2: [ ]
- apiKey: [ ]
springdoc:
# 开启 oauth2 端点显示

@ -11,7 +11,7 @@
<!--<withJansi>true</withJansi> &lt;!&ndash; 如果是UTF-8的环境这句要注释掉 &ndash;&gt;-->
<encoder>
<!-- <pattern>%highlight([%-5level]) %cyan(%d{yyyy-MM-dd#HH:mm:ss.SSS}) %yellow([Thread:%thread]) %magenta([Logger:%logger]) -> %msg%n</pattern>-->
<pattern>%highlight([%-5level]) %cyan(%d{yyyy-MM-dd#HH:mm:ss.SSS} [userId-%X{userId}] [reqUrl-%X{reqUrl}]) %yellow([Thread:%thread]) %magenta([Logger:%logger]) -> %msg%n</pattern>
<pattern>%highlight([%-5level]) %cyan(%d{yyyy-MM-dd#HH:mm:ss.SSS}) %yellow([Thread:%thread]) %magenta([Logger:%logger]) -> %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
</appender>

@ -49,11 +49,12 @@
</if>
</select>
<update id="updateAllocationStatus">
<update id="updateAllocationStatusAndDistributeStatus">
UPDATE
tb_clue_record
SET
allocation_status = #{status}
allocation_status = #{status},
distribute_status = #{distributeStatus}
where
<if test="list != null and list.size() == 1">
clue_record_id = #{list[0]}

Loading…
Cancel
Save