diff --git a/ad-distribute-common/common-i18n/pom.xml b/ad-distribute-common/common-i18n/pom.xml deleted file mode 100644 index 50f3fd1..0000000 --- a/ad-distribute-common/common-i18n/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - ad-distribute-common - com.baiye - 1.1.0 - - 4.0.0 - common-i18n - - - - cn.hutool - hutool-core - - - io.swagger.core.v3 - swagger-annotations - - - jakarta.annotation - jakarta.annotation-api - - - jakarta.validation - jakarta.validation-api - - - - org.slf4j - slf4j-api - - - org.springframework - spring-context - - - org.springframework - spring-web - true - - - org.springframework - spring-webmvc - true - - - diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/DynamicMessageSource.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/DynamicMessageSource.java deleted file mode 100644 index b541e2d..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/DynamicMessageSource.java +++ /dev/null @@ -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; - } - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nClass.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nClass.java deleted file mode 100644 index a104355..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nClass.java +++ /dev/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 { - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nField.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nField.java deleted file mode 100644 index df7cb0a..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nField.java +++ /dev/null @@ -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 { - - /** - *

- * This is an alias for {@link #code} - *

- * @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 ""; - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nIgnore.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nIgnore.java deleted file mode 100644 index dc95c41..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nIgnore.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baiye; - -import java.lang.annotation.*; - -/** - * 用于标注在需要国际化的 方法上,用于标记其需要国际化。 - * - * @author hccake - */ -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface I18nIgnore { - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessage.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessage.java deleted file mode 100644 index 5badbc8..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessage.java +++ /dev/null @@ -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; - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessageCreateEvent.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessageCreateEvent.java deleted file mode 100644 index 99ddd5e..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessageCreateEvent.java +++ /dev/null @@ -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 i18nMessages) { - super(i18nMessages); - } - - @SuppressWarnings("unchecked") - public List getI18nMessages() { - return (List) super.getSource(); - } - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessageProvider.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessageProvider.java deleted file mode 100644 index ee4821c..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nMessageProvider.java +++ /dev/null @@ -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); - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nOptions.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nOptions.java deleted file mode 100644 index 994d4ba..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nOptions.java +++ /dev/null @@ -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; - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nResponseAdvice.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nResponseAdvice.java deleted file mode 100644 index cc1229e..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/I18nResponseAdvice.java +++ /dev/null @@ -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 { - - private final MessageSource messageSource; - - private final boolean useCodeAsDefaultMessage; - - private Locale fallbackLocale = null; - - /** - * SpEL 解析器 - */ - private static final ExpressionParser PARSER = new SpelExpressionParser(); - - /** - * 表达式缓存 - */ - private static final Map 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> 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> selectedConverterType, ServerHttpRequest request, - ServerHttpResponse response) { - - try { - switchLanguage(body); - } - catch (Exception ex) { - log.error("[国际化]响应体国际化处理异常:{}", body); - } - - return body; - } - - /** - *

- * 对提供了 {@link I18nClass} 注解的类进行国际化处理,递归检查所有属性。 - *

- * 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 elements = (Collection) 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 - *
    - *
  • 如果 @I18nField 注解中未指定 code 的 SpEL 表达式, 则使用当前属性值作为 code。 - *
  • 否则使用该表达式解析出来的 code 值。 - *
- * @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; - } - } - -} diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/MessageSourceHierarchicalChanger.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/MessageSourceHierarchicalChanger.java deleted file mode 100644 index 5bb8177..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/MessageSourceHierarchicalChanger.java +++ /dev/null @@ -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 的父级
- * 若 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); - } - } - -} \ No newline at end of file diff --git a/ad-distribute-common/common-i18n/src/main/java/com/baiye/WildcardReloadableResourceBundleMessageSource.java b/ad-distribute-common/common-i18n/src/main/java/com/baiye/WildcardReloadableResourceBundleMessageSource.java deleted file mode 100644 index cffdb97..0000000 --- a/ad-distribute-common/common-i18n/src/main/java/com/baiye/WildcardReloadableResourceBundleMessageSource.java +++ /dev/null @@ -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 Does - * Spring MessageSource Support Multiple Class Path? - * @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 calculateAllFilenames(String basename, Locale locale) { - // 父类默认的方法会将 basename 也放入 filenames 列表 - List filenames = super.calculateAllFilenames(basename, locale); - // 当 basename 有匹配符时,从 filenames 中移除,否则扫描文件将抛出 Illegal char <*> 的异常 - if (basename.contains("*")) { - filenames.remove(basename); - } - return filenames; - } - - @Override - protected List calculateFilenamesForLocale(String basename, Locale locale) { - // 支持 basename 用 . 表示文件层级 - basename = basename.replace(".", "/"); - - // 资源文件名 - List fileNames = new ArrayList<>(); - // 获取到待匹配的国际化信息文件名集合 - List 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; - } - -} diff --git a/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage.properties b/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage.properties deleted file mode 100644 index 08d62c5..0000000 --- a/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage.properties +++ /dev/null @@ -1,3 +0,0 @@ -i18nMessage.languageTag=Language Tag -i18nMessage.code=Code -i18nMessage.message=Message \ No newline at end of file diff --git a/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage_en_US.properties b/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage_en_US.properties deleted file mode 100644 index 08d62c5..0000000 --- a/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage_en_US.properties +++ /dev/null @@ -1,3 +0,0 @@ -i18nMessage.languageTag=Language Tag -i18nMessage.code=Code -i18nMessage.message=Message \ No newline at end of file diff --git a/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage_zh_CN.properties b/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage_zh_CN.properties deleted file mode 100644 index efa9762..0000000 --- a/ad-distribute-common/common-i18n/src/main/resources/ballcat-i18nMessage_zh_CN.properties +++ /dev/null @@ -1,3 +0,0 @@ -i18nMessage.languageTag=\u8BED\u8A00\u6807\u7B7E -i18nMessage.code=\u56FD\u9645\u5316\u6807\u8BC6 -i18nMessage.message=\u6587\u672C\u503C \ No newline at end of file diff --git a/ad-distribute-common/common-i18n/src/test/java/com/baiye/DefautlI18nMessageProvider.java b/ad-distribute-common/common-i18n/src/test/java/com/baiye/DefautlI18nMessageProvider.java deleted file mode 100644 index 6b90ab7..0000000 --- a/ad-distribute-common/common-i18n/src/test/java/com/baiye/DefautlI18nMessageProvider.java +++ /dev/null @@ -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 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); - } - -} diff --git a/ad-distribute-common/common-model/src/main/java/com/baiye/result/R.java b/ad-distribute-common/common-model/src/main/java/com/baiye/result/R.java index f016321..fdfc98d 100644 --- a/ad-distribute-common/common-model/src/main/java/com/baiye/result/R.java +++ b/ad-distribute-common/common-model/src/main/java/com/baiye/result/R.java @@ -13,7 +13,7 @@ import java.io.Serializable; * @param * @author Hccake */ -@I18nClass +// @I18nClass @Getter @Setter @ToString diff --git a/ad-distribute-common/pom.xml b/ad-distribute-common/pom.xml index 49e8e64..8158aa1 100644 --- a/ad-distribute-common/pom.xml +++ b/ad-distribute-common/pom.xml @@ -13,7 +13,6 @@ common-core common-desensitize - common-i18n common-idempotent common-log common-model diff --git a/ad-distribute-security/security-oauth2-core/src/main/java/com/baiye/security/util/PasswordUtils.java b/ad-distribute-security/security-oauth2-core/src/main/java/com/baiye/security/util/PasswordUtils.java index 0be4c53..5f5df96 100644 --- a/ad-distribute-security/security-oauth2-core/src/main/java/com/baiye/security/util/PasswordUtils.java +++ b/ad-distribute-security/security-oauth2-core/src/main/java/com/baiye/security/util/PasswordUtils.java @@ -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); } diff --git a/admin/src/main/java/com/baiye/job/JobApplicationRunner.java b/admin/src/main/java/com/baiye/job/JobApplicationRunner.java index 3d37730..eec116c 100644 --- a/admin/src/main/java/com/baiye/job/JobApplicationRunner.java +++ b/admin/src/main/java/com/baiye/job/JobApplicationRunner.java @@ -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 distributeTaskEntities = - // distributeTaskMapper.selectList( - // new - // LambdaQueryWrapper().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 distributeTaskEntities = distributeTaskMapper.selectList( + new LambdaQueryWrapper().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()); + } + } + } } } diff --git a/admin/src/main/java/com/baiye/job/LinkWatchJob.java b/admin/src/main/java/com/baiye/job/LinkWatchJob.java index 4555b95..3fbf63b 100644 --- a/admin/src/main/java/com/baiye/job/LinkWatchJob.java +++ b/admin/src/main/java/com/baiye/job/LinkWatchJob.java @@ -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); + } + } } diff --git a/admin/src/main/java/com/baiye/modules/distribute/controller/ClueFileController.java b/admin/src/main/java/com/baiye/modules/distribute/controller/ClueFileController.java index 27b0f24..3092957 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/controller/ClueFileController.java +++ b/admin/src/main/java/com/baiye/modules/distribute/controller/ClueFileController.java @@ -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> detection(@RequestParam("file") MultipartFile file) { + return R.ok(clueFileService.detection(file)); + } - @PostMapping("/fileUpload") - @Operation(summary = "文件上传资源") - public R clueFileUpload(@RequestParam("file") MultipartFile file) { - return R.ok(clueFileService.clueFileUpload(file)); + @GetMapping("/readFile") + @Operation(summary = "读取文件信息") + public R 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("导出失败,请联系管理员"); diff --git a/admin/src/main/java/com/baiye/modules/distribute/controller/ClueFollowRecordController.java b/admin/src/main/java/com/baiye/modules/distribute/controller/ClueFollowRecordController.java new file mode 100644 index 0000000..9ed27af --- /dev/null +++ b/admin/src/main/java/com/baiye/modules/distribute/controller/ClueFollowRecordController.java @@ -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 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 deleteByUserId(@RequestBody List ids) { + return clueFollowRecordService.removeBatchByIds(ids) ? R.ok() + : R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "删除失败"); + } + +} diff --git a/admin/src/main/java/com/baiye/modules/distribute/dto/DBPushClueDTO.java b/admin/src/main/java/com/baiye/modules/distribute/dto/DBPushClueDTO.java index a300755..eaa2458 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/dto/DBPushClueDTO.java +++ b/admin/src/main/java/com/baiye/modules/distribute/dto/DBPushClueDTO.java @@ -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; diff --git a/admin/src/main/java/com/baiye/modules/distribute/entity/ClueFollowRecordEntity.java b/admin/src/main/java/com/baiye/modules/distribute/entity/ClueFollowRecordEntity.java new file mode 100644 index 0000000..23fef84 --- /dev/null +++ b/admin/src/main/java/com/baiye/modules/distribute/entity/ClueFollowRecordEntity.java @@ -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 recordInfoList; + +} diff --git a/admin/src/main/java/com/baiye/modules/distribute/entity/ClueStageEntity.java b/admin/src/main/java/com/baiye/modules/distribute/entity/ClueStageEntity.java index beaa41d..eed6a8d 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/entity/ClueStageEntity.java +++ b/admin/src/main/java/com/baiye/modules/distribute/entity/ClueStageEntity.java @@ -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 clueFollowRecordList; + } diff --git a/admin/src/main/java/com/baiye/modules/distribute/entity/DistributeTaskEntity.java b/admin/src/main/java/com/baiye/modules/distribute/entity/DistributeTaskEntity.java index 75912d3..8d33ebe 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/entity/DistributeTaskEntity.java +++ b/admin/src/main/java/com/baiye/modules/distribute/entity/DistributeTaskEntity.java @@ -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; diff --git a/admin/src/main/java/com/baiye/modules/distribute/mapper/ClueFollowRecordMapper.java b/admin/src/main/java/com/baiye/modules/distribute/mapper/ClueFollowRecordMapper.java new file mode 100644 index 0000000..1c0063f --- /dev/null +++ b/admin/src/main/java/com/baiye/modules/distribute/mapper/ClueFollowRecordMapper.java @@ -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 { + +} diff --git a/admin/src/main/java/com/baiye/modules/distribute/mapper/ClueRecordMapper.java b/admin/src/main/java/com/baiye/modules/distribute/mapper/ClueRecordMapper.java index 782e6a9..6777a58 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/mapper/ClueRecordMapper.java +++ b/admin/src/main/java/com/baiye/modules/distribute/mapper/ClueRecordMapper.java @@ -41,7 +41,8 @@ public interface ClueRecordMapper extends ExtendMapper { IPage selectByPage(IPage page, @Param(Constants.WRAPPER) Wrapper wrapper); - void updateAllocationStatus(@Param("list") List recordIdList, @Param("status") Integer status); + void updateAllocationStatusAndDistributeStatus(@Param("list") List recordIdList, + @Param("status") Integer status, @Param("distributeStatus") Integer distributeStatus); void updateDistributeStatus(@Param("list") List recordIdList, @Param("status") Integer status); diff --git a/admin/src/main/java/com/baiye/modules/distribute/service/ClueFileService.java b/admin/src/main/java/com/baiye/modules/distribute/service/ClueFileService.java index 20ca82e..90af838 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/service/ClueFileService.java +++ b/admin/src/main/java/com/baiye/modules/distribute/service/ClueFileService.java @@ -6,10 +6,15 @@ import java.util.Map; public interface ClueFileService { + /** + * 检测文件格式 + */ + Map detection(MultipartFile file); + /** * 文件上传资源 */ - Map clueFileUpload(MultipartFile file); + void readFile(Long recordId); /** * 生成秘钥 diff --git a/admin/src/main/java/com/baiye/modules/distribute/service/ClueFollowRecordService.java b/admin/src/main/java/com/baiye/modules/distribute/service/ClueFollowRecordService.java new file mode 100644 index 0000000..b044d15 --- /dev/null +++ b/admin/src/main/java/com/baiye/modules/distribute/service/ClueFollowRecordService.java @@ -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 { + + boolean add(ClueFollowRecordEntity clueStageEntity); + +} diff --git a/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueFileServiceImpl.java b/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueFileServiceImpl.java index f9622db..fa09c2a 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueFileServiceImpl.java +++ b/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueFileServiceImpl.java @@ -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 clueFileUpload(MultipartFile multipartFile) { + public Map detection(MultipartFile multipartFile) { // 检测文件的内容格式 ExcelReader excelReader = ClueFileTestingUtil.testingExcel(multipartFile); // 保存文件 @@ -62,23 +63,28 @@ public class ClueFileServiceImpl implements ClueFileService { // 获取文件中第一行数据的来源字段 null为未知 List oneReadList = excelReader.readRow(DefaultNumberConstants.ZERO_NUMBER); List 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 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 generateSecretKey() { Map map = new HashMap<>(); diff --git a/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueFollowRecordServiceImpl.java b/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueFollowRecordServiceImpl.java new file mode 100644 index 0000000..974b23b --- /dev/null +++ b/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueFollowRecordServiceImpl.java @@ -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 + implements ClueFollowRecordService { + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean add(ClueFollowRecordEntity entity) { + List list = new ArrayList<>(); + List 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)); + } + +} diff --git a/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueRecordServiceImpl.java b/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueRecordServiceImpl.java index 92f53fa..0c72f90 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueRecordServiceImpl.java +++ b/admin/src/main/java/com/baiye/modules/distribute/service/impl/ClueRecordServiceImpl.java @@ -36,7 +36,8 @@ public class ClueRecordServiceImpl extends ExtendServiceImpl i private final ClueStageService clueStageService; + private final ClueFollowRecordMapper clueFollowRecordMapper; + private final SecurityProperties securityProperties; @Override @@ -95,20 +100,23 @@ public class ClueServiceImpl extends ExtendServiceImpl 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 i List nameList = clueLabelList.stream().map(LabelEntity::getLabelName).collect(Collectors.toList()); clueEntity.setClueLabelName(JSONUtil.toJsonStr(nameList)); } + else { + // 修改标签为空 + LambdaUpdateWrapper 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 i List organizeEntities = labelOrganizeService.queryUserList(whichUserId); // 查询上级用户阶段 List clueStageEntities = clueStageService.queryUserList(whichUserId); - + if (CollUtil.isNotEmpty(clueStageEntities)) { + List clueStageIds = clueStageEntities.stream() + .map(ClueStageEntity::getClueStageId) + .collect(Collectors.toList()); + // 查询阶段的记录 + List clueFollowRecordEntities = clueFollowRecordMapper.selectList( + new LambdaQueryWrapper().eq(ClueFollowRecordEntity::getClueId, clueId) + .in(ClueFollowRecordEntity::getClueStageId, clueStageIds)); + // 记录放入阶段中 + if (CollUtil.isNotEmpty(clueFollowRecordEntities)) { + Map> 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); diff --git a/admin/src/main/java/com/baiye/modules/distribute/service/impl/DistributeTaskServiceImpl.java b/admin/src/main/java/com/baiye/modules/distribute/service/impl/DistributeTaskServiceImpl.java index 0965685..d4539e3 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/service/impl/DistributeTaskServiceImpl.java +++ b/admin/src/main/java/com/baiye/modules/distribute/service/impl/DistributeTaskServiceImpl.java @@ -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 updateSysUserList = new ArrayList<>(); - List sysUsers = sysUserService.listByUserIds(userIdList); - Map> userIdMap = sysUsers.stream().collect(Collectors.groupingBy(SysUser::getUserId)); - // 获取文件中未分配的资源ID - List clueIds = clueService.findUndistributedClueIds(recordIdList); - // 分配 - DistributeDTO distributeDTO = new DistributeDTO(); - distributeDTO.setDeptIds(userIdList); - distributeDTO.setResourceList(clueIds); - if (taskEntity.getRuleStatus() == DefaultNumberConstants.ONE_NUMBER) { - distributeDTO.setIsWeight(true); - List weightList = userEntities.stream() - .map(DistributeTaskUserEntity::getWeight) - .collect(Collectors.toList()); - List weights = weightList.stream().map(i -> i * 10.0).collect(Collectors.toList()); - distributeDTO.setWeights(weights); - } - // 查询业务管理员用户的默认文件记录 - Map> map = null; - if (createBy == 1) { - List recordEntities = clueRecordMapper - .selectList(new LambdaQueryWrapper().in(ClueRecordEntity::getCreateBy, userIdList) - .eq(ClueRecordEntity::getRecordType, DefaultNumberConstants.ONE_NUMBER)); - map = recordEntities.stream().collect(Collectors.groupingBy(ClueRecordEntity::getCreateBy)); - } - // 分配数据 - List clueEntityList = new ArrayList<>(); - List 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 updateSysUserList = new ArrayList<>(); + List sysUsers = sysUserService.listByUserIds(userIdList); + Map> userIdMap = sysUsers.stream() + .collect(Collectors.groupingBy(SysUser::getUserId)); + // 获取文件中未分配的资源 + List 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 weightList = userEntities.stream() + .map(DistributeTaskUserEntity::getWeight) + .collect(Collectors.toList()); + List weights = weightList.stream().map(i -> i * 10.0).collect(Collectors.toList()); + distributeDTO.setWeights(weights); + } + List responseDTOS = AssignDataUtil.assignData(distributeDTO); + // 查询业务管理员用户的默认文件记录 + Map> map = null; + if (createBy == 1) { + List recordEntities = clueRecordMapper.selectList( + new LambdaQueryWrapper().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 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 taskEntities = baseMapper.selectList( - new LambdaQueryWrapper().eq(DistributeTaskEntity::getDefaultType, 0) - .in(DistributeTaskEntity::getCreateBy, userIdList)); - if (CollUtil.isNotEmpty(taskEntities)) { - List 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 taskIds) { - List distributeTaskEntities = baseMapper.selectBatchIds(taskIds); - for (DistributeTaskEntity distributeTaskEntity : distributeTaskEntities) { - this.execute(distributeTaskEntity); + private void syncExecuteTask(List userIdList) { + List taskEntities = baseMapper + .selectList(new LambdaQueryWrapper().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); + } + } } } diff --git a/admin/src/main/java/com/baiye/modules/distribute/service/impl/OutsideReqServiceImpl.java b/admin/src/main/java/com/baiye/modules/distribute/service/impl/OutsideReqServiceImpl.java index 5505ba3..403fa44 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/service/impl/OutsideReqServiceImpl.java +++ b/admin/src/main/java/com/baiye/modules/distribute/service/impl/OutsideReqServiceImpl.java @@ -75,7 +75,7 @@ public class OutsideReqServiceImpl implements OutsideReqService { new LambdaQueryWrapper().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); } diff --git a/admin/src/main/java/com/baiye/modules/distribute/service/impl/PushLinkServiceImpl.java b/admin/src/main/java/com/baiye/modules/distribute/service/impl/PushLinkServiceImpl.java index 1bd5dcb..96f7518 100644 --- a/admin/src/main/java/com/baiye/modules/distribute/service/impl/PushLinkServiceImpl.java +++ b/admin/src/main/java/com/baiye/modules/distribute/service/impl/PushLinkServiceImpl.java @@ -39,7 +39,7 @@ public class PushLinkServiceImpl extends ExtendServiceImpl().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 rowData = reader.readRow(1); + if (CollUtil.isEmpty(rowData)) { + throw new BadRequestException("空文件,请检查文件内容"); + } if (rowCount > 1000000) throw new BadRequestException("文件行数不得超过100w行,请处理"); return reader; diff --git a/admin/src/main/resources/application-dev.yml b/admin/src/main/resources/application-dev.yml index 54263b9..5f3cc76 100644 --- a/admin/src/main/resources/application-dev.yml +++ b/admin/src/main/resources/application-dev.yml @@ -19,7 +19,7 @@ business: urls: - dbPushUrl: https://aidrop.z48.cn/outside/pushClue/ + dbPushUrl: http://cs.tuoz.net:8100/outside/pushClue/ springdoc: swagger-ui: diff --git a/admin/src/main/resources/application-prod.yml b/admin/src/main/resources/application-prod.yml index a10557b..5edeab7 100644 --- a/admin/src/main/resources/application-prod.yml +++ b/admin/src/main/resources/application-prod.yml @@ -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 \ No newline at end of file + enabled: false \ No newline at end of file diff --git a/admin/src/main/resources/application-test.yml b/admin/src/main/resources/application-test.yml index 4a94cf0..c0c9e48 100644 --- a/admin/src/main/resources/application-test.yml +++ b/admin/src/main/resources/application-test.yml @@ -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: diff --git a/admin/src/main/resources/application.yml b/admin/src/main/resources/application.yml index 4033e77..1e031b1 100644 --- a/admin/src/main/resources/application.yml +++ b/admin/src/main/resources/application.yml @@ -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 端点显示 diff --git a/admin/src/main/resources/file/template.xlsx b/admin/src/main/resources/file/template.xlsx index 2db65d7..ae0c383 100644 Binary files a/admin/src/main/resources/file/template.xlsx and b/admin/src/main/resources/file/template.xlsx differ diff --git a/admin/src/main/resources/logback-spring.xml b/admin/src/main/resources/logback-spring.xml index 6f98044..7c383f1 100644 --- a/admin/src/main/resources/logback-spring.xml +++ b/admin/src/main/resources/logback-spring.xml @@ -11,7 +11,7 @@ - %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 + %highlight([%-5level]) %cyan(%d{yyyy-MM-dd#HH:mm:ss.SSS}) %yellow([Thread:%thread]) %magenta([Logger:%logger]) -> %msg%n utf-8 diff --git a/admin/src/main/resources/mapper/ClueRecordMapper.xml b/admin/src/main/resources/mapper/ClueRecordMapper.xml index 46bbd02..566fb7a 100644 --- a/admin/src/main/resources/mapper/ClueRecordMapper.xml +++ b/admin/src/main/resources/mapper/ClueRecordMapper.xml @@ -49,11 +49,12 @@ - + UPDATE tb_clue_record SET - allocation_status = #{status} + allocation_status = #{status}, + distribute_status = #{distributeStatus} where clue_record_id = #{list[0]}