Finish Task #4531 Cost:4h  修复复制合同开票单位错误

This commit is contained in:
时间淡忘一切 2023-11-14 12:08:21 +08:00
commit 61ff9d75ec
26 changed files with 1892 additions and 0 deletions

7
Dockerfile_test Normal file
View File

@ -0,0 +1,7 @@
FROM openjdk:8u181-jre-alpine
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone && apk add --no-cache curl
COPY ./target/crm-internation-0.0.1-SNAPSHOT.jar /
WORKDIR /
EXPOSE 8080
CMD ["java","-jar","crm-internation-0.0.1-SNAPSHOT.jar"]

316
mvnw vendored Executable file
View File

@ -0,0 +1,316 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`\\unset -f command; \\command -v java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

99
pom.xml Normal file
View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.17</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.rzdata</groupId>
<artifactId>crm-internation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>crm-internation</name>
<description>crm翻译</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.7.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.20</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
<!-- for test only -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.42</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.900</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,15 @@
package com.blueland.common.core;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.blueland.common.core.mapper")
public class InternationApplication {
public static void main(String[] args) {
SpringApplication.run(InternationApplication.class, args);
}
}

View File

@ -0,0 +1,37 @@
package com.blueland.common.core.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 翻译配置类
*/
@Component
@ConfigurationProperties(prefix = "tm")
public class InternationConfig {
/**
* 腾讯翻译ID
*/
private static String secretId;
/**
* 腾讯翻译Key
*/
private static String secretKey;
public static String getSecretId() {
return secretId;
}
public void setSecretId(String secretId) {
InternationConfig.secretId = secretId;
}
public static String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
InternationConfig.secretKey = secretKey;
}
}

View File

@ -0,0 +1,29 @@
package com.blueland.common.core.config;
import com.blueland.common.core.domain.BaseEntity;
import com.blueland.common.core.listener.FlexCommonListener;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.keygen.KeyGenerators;
import com.mybatisflex.spring.boot.MyBatisFlexCustomizer;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisFlexConfiguration implements MyBatisFlexCustomizer {
@Override
public void customize(FlexGlobalConfig globalConfig) {
// 我们可以在这里进行一些列的初始化配置
FlexCommonListener flexCommonListener = new FlexCommonListener();
globalConfig.registerInsertListener(flexCommonListener, BaseEntity.class);
globalConfig.registerUpdateListener(flexCommonListener, BaseEntity.class);
FlexGlobalConfig.KeyConfig keyConfig = new FlexGlobalConfig.KeyConfig();
keyConfig.setKeyType(KeyType.Generator);
keyConfig.setValue(KeyGenerators.snowFlakeId);
keyConfig.setBefore(true);
globalConfig.setKeyConfig(keyConfig);
}
}

View File

@ -0,0 +1,73 @@
package com.blueland.common.core.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
@Configuration
public class RedisConfig {
/**
* RedisTemplate配置
*
* @param lettuceConnectionFactory
* @return
*/
@Bean
public KeyGenerator wiselyKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* RedisTemplate配置
*
* @param lettuceConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
// 设置序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置redisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
RedisSerializer<?> stringSerializer = new StringRedisSerializer();
// key序列化
redisTemplate.setKeySerializer(stringSerializer);
// value序列化
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// Hash key序列化
redisTemplate.setHashKeySerializer(stringSerializer);
// Hash value序列化
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

View File

@ -0,0 +1,5 @@
package com.blueland.common.core.constan;
public class RedisConstan {
public static final String I18N = "i18n:";
}

View File

@ -0,0 +1,6 @@
package com.blueland.common.core.constan;
public class SysConstan {
public static final String TYPE = "type";
public static final String LANG = "lang";
}

View File

@ -0,0 +1,170 @@
package com.blueland.common.core.controller;
import com.blueland.common.core.domain.International;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.*;
import com.blueland.common.core.result.AjaxResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import com.blueland.common.core.service.InternationalService;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
import java.util.List;
/**
* 国际化 控制层
*
* @author mybatis-flex-helper automatic generation
* @since 1.0
*/
@RestController
@RequestMapping("/international")
@Api(value = "国际化", tags = "国际化")
public class InternationalController {
@Autowired
private InternationalService internationalService;
/**
* 添加 国际化
*
* @param international 国际化
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation(value = "添加国际化", notes = "添加国际化", httpMethod = "POST")
public AjaxResult<Boolean> save(@RequestBody International international) {
return AjaxResult.operates(internationalService.insert(international));
}
/**
* 根据主键删除国际化
*
* @return {@code true} 删除成功{@code false} 删除失败
*/
@PostMapping("/remove")
@ApiOperation(value = "根据主键删除国际化", notes = "根据主键删除国际化")
public AjaxResult<Boolean> remove(@RequestBody International international) {
return AjaxResult.operates(internationalService.deleteById(international.getId()));
}
/**
* 根据主键更新国际化
*
* @param international 国际化
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PostMapping("/update")
@ApiOperation(value = "根据主键更新国际化", notes = "根据主键更新国际化")
public AjaxResult<Boolean> update(@RequestBody International international) {
return AjaxResult.operates(internationalService.updateInternational(international));
}
/**
* 查询所有国际化
*
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation(value = "查询所有国际化(根据租户)", notes = "查询所有国际化(根据租户)")
public AjaxResult<List<International>> list(@RequestBody International international) {
return AjaxResult.success(internationalService.listAll(international));
}
/**
* 返回对应的语言包
*
* @return 所有数据
*/
@GetMapping("/findLangPackage")
@ApiOperation(value = "返回对应的语言包", notes = "返回对应的语言包")
public AjaxResult findLangPackage(@RequestParam("type") @ApiParam("类型前端front后端back") String type) {
return AjaxResult.success(internationalService.findLangPackage(type));
}
/**
* 根据国际化主键获取详细信息
*
* @param id international主键
* @return 国际化详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation(value = "根据国际化主键获取详细信息", notes = "根据国际化主键获取详细信息")
public AjaxResult<International> getInfo(@PathVariable Serializable id) {
return AjaxResult.success(internationalService.getById(id));
}
/**
* 分页查询国际化
*
* @return 分页对象
*/
@PostMapping("/page")
@ApiOperation(value = "分页查询国际化", notes = "分页查询国际化")
public AjaxResult<Page<International>> page(@RequestBody International international) {
return AjaxResult.success(internationalService.pageList(international));
}
/**
* 一键复制
*
* @param targetLang 目标语言
* @param sourceLang 源语言
* @return {@link AjaxResult}<{@link Boolean}>
*/
@GetMapping("/copy")
@ApiOperation(value = "一键复制", notes = "例如:数据库只有中文,要翻译成英文")
@ApiImplicitParams(
{
@ApiImplicitParam(name = "tenantId", value = "租户id", dataType = "String", paramType = "query", required = false),
@ApiImplicitParam(name = "targetLang", value = "目标语言", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "sourceLang", value = "源语言", dataType = "String", paramType = "query", required = true)
}
)
public AjaxResult<Boolean> copy(@RequestParam("targetLang") String targetLang,
@RequestParam("sourceLang") String sourceLang,
@RequestParam(value = "tenantId", required = false) String tenantId) {
return AjaxResult.operates(internationalService.copy(targetLang, sourceLang, tenantId));
}
@GetMapping("/dowloadTemplate")
@ApiOperation(value = "下载模板", notes = "下载模板")
public void dowloadTemplate() {
internationalService.dowloadTemplate();
}
/**
* 导入
*/
@PostMapping("/importList")
@ApiOperation("导入数据")
public AjaxResult<Boolean> importList(@RequestParam("file") MultipartFile file) {
return AjaxResult.operates(internationalService.importList(file));
}
/**
* 一键复制从其他租户复制
*
* @param sourceLang 源语言
* @return {@link AjaxResult}<{@link Boolean}>
*/
@GetMapping("/tenantIdCopy")
@ApiOperation(value = "一键复制(从其他租户复制)", notes = "例如bio里面有en语言包现在要复制到AHI里面")
@ApiImplicitParams(
{
@ApiImplicitParam(name = "tenantId", value = "租户id", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "sourceLang", value = "源语言", dataType = "String", paramType = "query", required = true)
}
)
public AjaxResult<Boolean> tenantIdCopy(@RequestParam("sourceLang") String sourceLang,
String tenantId) {
return AjaxResult.operates(internationalService.tenantIdCopy(sourceLang, tenantId));
}
}

View File

@ -0,0 +1,62 @@
package com.blueland.common.core.domain;
import com.alibaba.fastjson2.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
public class BaseEntity {
/**
* 创建人
*/
@Column(value = "create_by")
@ApiModelProperty(value = "创建人")
private String createBy;
/**
* 创建时间
*/
@Column(value = "create_time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* 更新人
*/
@Column(value = "update_by")
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* 更新时间
*/
@Column(value = "update_time")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
@Column(ignore = true)
@JSONField(serialize = false)
@ApiModelProperty(value = "分页大小")
@JsonIgnore
private int pageSize;
@Column(ignore = true)
@JSONField(serialize = false)
@ApiModelProperty(value = "分页页码")
@JsonIgnore
private int pageNum;
@JsonIgnore
public Page getPage() {
return new Page(pageNum, pageSize);
}
}

View File

@ -0,0 +1,49 @@
package com.blueland.common.core.domain;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.mybatisflex.core.keygen.KeyGenerators;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 国际化 实体类
*
* @author mybatis-flex-helper automatic generation
* @since 1.0
*/
@Table(value = "t_international")
@Data
@ApiModel(value = "国际化")
public class International extends BaseEntity {
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
@ApiModelProperty(value = "主键")
private String id;
@Column(value = "code")
@ApiModelProperty(value = "编码", required = true)
private String code;
@Column(value = "name")
@ApiModelProperty(value = "名称", required = true)
private String name;
@Column(value = "lang")
@ApiModelProperty(value = "语言", required = true)
private String lang;
@Column(value = "type")
@ApiModelProperty(value = "类型前端front后端back", required = true)
private String type;
@Column(value = "tenant_id")
@ApiModelProperty(value = "租户id(后台赋值)")
private String tenantId;
}

View File

@ -0,0 +1,26 @@
package com.blueland.common.core.domain.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import com.blueland.common.core.constan.SysConstan;
@Data
public class InternationalExport {
@Excel(name = "编码", width = 20)
private String code;
@Excel(name = "名称", width = 20)
private String name;
@Excel(name = "语言", width = 20, addressList = true, dict = SysConstan.LANG)
private String lang;
@Excel(name = "类型", width = 20, addressList = true, dict = SysConstan.TYPE)
private String type;
@Excel(name = "", isColumnHidden = true)
private String tenantId;
}

View File

@ -0,0 +1,84 @@
package com.blueland.common.core.handler;
import cn.afterturn.easypoi.handler.inter.IExcelDictHandler;
import com.blueland.common.core.constan.SysConstan;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ExcelDicHandler implements IExcelDictHandler {
@Override
public List<Map> getList(String dict) {
if (SysConstan.TYPE.equals(dict)) {
return type();
} else if (SysConstan.LANG.equals(dict)) {
return lang();
}
throw new RuntimeException("字典名称不正确");
}
public List<Map> lang() {
List<Map> list = new ArrayList<>();
Map<String, String> dictMap = new HashMap<>();
dictMap.put("dictKey", "en");
dictMap.put("dictValue", "英语");
list.add(dictMap);
dictMap = new HashMap<>();
dictMap.put("dictKey", "zh");
dictMap.put("dictValue", "中文");
list.add(dictMap);
return list;
}
public List<Map> type() {
List<Map> list = new ArrayList<>();
Map<String, String> dictMap = new HashMap<>();
dictMap.put("dictKey", "front");
dictMap.put("dictValue", "前端");
list.add(dictMap);
dictMap = new HashMap<>();
dictMap.put("dictKey", "black");
dictMap.put("dictValue", "后端");
list.add(dictMap);
return list;
}
// 导出用到
@Override
public String toName(String dict, Object obj, String name, Object value) {
if (SysConstan.TYPE.equals(dict)) {
if ("front".equals(String.valueOf(value))) {
return "前端";
}
return "后端";
} else if (SysConstan.LANG.equals(dict)) {
if ("zh".equals(String.valueOf(value))) {
return "中文";
}
return "英文";
}
throw new RuntimeException("字典名称不正确");
}
// 导入用到
@Override
public String toValue(String dict, Object obj, String name, Object value) {
if (SysConstan.TYPE.equals(dict)) {
if ("前端".equals(String.valueOf(value))) {
return "front";
}
return "black";
} else if (SysConstan.LANG.equals(dict)) {
if ("中文".equals(String.valueOf(value))) {
return "zh";
}
return "en";
}
throw new RuntimeException("字典名称不正确");
}
}

View File

@ -0,0 +1,14 @@
package com.blueland.common.core.handler;
import com.blueland.common.core.result.AjaxResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExcptionHandler {
@ExceptionHandler(Exception.class)
public AjaxResult handleException(Exception e) {
e.printStackTrace();
return AjaxResult.failed(e.getMessage());
}
}

View File

@ -0,0 +1,27 @@
package com.blueland.common.core.listener;
import com.mybatisflex.annotation.InsertListener;
import com.mybatisflex.annotation.UpdateListener;
import com.blueland.common.core.domain.BaseEntity;
import com.blueland.common.core.utils.UserUtils;
import java.util.Date;
public class FlexCommonListener implements InsertListener, UpdateListener {
@Override
public void onInsert(Object o) {
BaseEntity base = (BaseEntity) o;
base.setCreateBy(UserUtils.getStaffCode());
base.setCreateTime(new Date());
base.setUpdateBy(UserUtils.getStaffCode());
base.setUpdateTime(new Date());
}
@Override
public void onUpdate(Object o) {
BaseEntity base = (BaseEntity) o;
base.setUpdateBy(UserUtils.getStaffCode());
base.setUpdateTime(new Date());
}
}

View File

@ -0,0 +1,17 @@
package com.blueland.common.core.mapper;
import com.blueland.common.core.domain.International;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 国际化 映射层
*
* @author mybatis-flex-helper automatic generation
* @since 1.0
*/
@Mapper
public interface InternationalMapper extends BaseMapper<International> {
}

View File

@ -0,0 +1,110 @@
package com.blueland.common.core.result;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author bigtian
* @Description 返回对象封装类
* @Date 2021/7/23 2:03 下午
*/
@Data
@ApiModel(value = "统一返回对象")
public class AjaxResult<T> {
@ApiModelProperty("返回信息")
private String resultMsg;
@ApiModelProperty("返回码")
private int resultCode;
@ApiModelProperty("返回数据")
private T result;
public static AjaxResult success(String msg) {
AjaxResult result = new AjaxResult();
result.setResultCode(200);
result.setResultMsg(msg);
return result;
}
public static AjaxResult success(Object data, String msg) {
AjaxResult result = new AjaxResult();
result.setResultCode(400);
result.setResultMsg(msg);
result.setResult(data);
return result;
}
public static AjaxResult success() {
AjaxResult result = new AjaxResult();
result.setResultCode(200);
result.setResultMsg("操作成功");
return result;
}
public static AjaxResult success(Object data) {
AjaxResult result = new AjaxResult();
result.setResultCode(200);
result.setResultMsg("操作成功");
result.setResult(data);
return result;
}
public static AjaxResult failed(Object data) {
AjaxResult result = new AjaxResult();
result.setResultCode(400);
result.setResultMsg("操作失败");
result.setResult(data);
return result;
}
public static AjaxResult failed() {
AjaxResult result = new AjaxResult();
result.setResultCode(400);
result.setResultMsg("操作失败");
return result;
}
public static AjaxResult failed(String msg) {
AjaxResult result = new AjaxResult();
result.setResultCode(400);
result.setResultMsg(msg);
return result;
}
public static AjaxResult failed(int code, String msg) {
AjaxResult result = new AjaxResult();
result.setResultCode(code);
result.setResultMsg(msg);
return result;
}
public static AjaxResult success(int code, String msg) {
AjaxResult result = new AjaxResult();
result.setResultCode(code);
result.setResultMsg(msg);
return result;
}
public static AjaxResult operates(Boolean flag) {
if (flag) {
return success();
}
return failed();
}
public static AjaxResult operates(Boolean flag, String msg, Object data) {
return flag ? success(data, msg) : failed(msg);
}
public static AjaxResult operates(int rows) {
if (rows > 0) {
return success();
}
return failed();
}
}

View File

@ -0,0 +1,114 @@
package com.blueland.common.core.service;
import com.blueland.common.core.domain.International;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.service.IService;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* 国际化 服务层
*
* @author mybatis-flex-helper automatic generation
* @since 1.0
*/
public interface InternationalService extends IService<International> {
/**
* 插入
*
* @param international 国际
* @return boolean
*/
boolean insert(International international);
/**
* 是否存在
*
* @param code 编码
* @param lang 语言
* @return boolean
*/
boolean exist(String code, String lang);
/**
* @return {@link List}<{@link International}>
*/
List<International> listAll(International international);
/**
* 根据语言查询
*
* @param lang 语言
* @param tenantId
* @return {@link List}<{@link International}>
*/
List<International> listByLang(String lang, String tenantId,String type);
/**
* @param international
* @return {@link List}<{@link International}>
*/
Page<List<International>> pageList(International international);
/**
* 一键复制
*
* @param targetLang 目标语言
* @param sourceLang 源语言
* @param tenantId
* @return boolean
*/
boolean copy(String targetLang, String sourceLang, String tenantId);
/**
* 更新
*
* @param international
* @return boolean
*/
boolean updateInternational(International international);
/**
* 根据id删除
*
* @param id
* @return
*/
boolean deleteById(String id);
/**
* 下载模板
*/
void dowloadTemplate();
/**
* 导入数据
*
* @param file
* @return {@link Boolean}
*/
Boolean importList(MultipartFile file);
/**
* 返回对应的语言包
* @return
*/
Map<String, Map<String, String>> findLangPackage(String type);
/**
* 租户ID副本
*
* @param sourceLang 源语言
* @param tenantId 保持ID
* @return {@link Boolean}
*/
Boolean tenantIdCopy(String sourceLang, String tenantId);
}

View File

@ -0,0 +1,299 @@
package com.blueland.common.core.service.impl;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.blueland.common.core.domain.International;
import com.blueland.common.core.domain.export.InternationalExport;
import com.blueland.common.core.handler.ExcelDicHandler;
import com.blueland.common.core.utils.RedisUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.blueland.common.core.utils.TranslateUtil;
import com.blueland.common.core.utils.UserUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import com.blueland.common.core.service.InternationalService;
import com.blueland.common.core.mapper.InternationalMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.blueland.common.core.domain.table.InternationalTableDef.INTERNATIONAL;
/**
* 国际化 服务层实现
*
* @author mybatis-flex-helper automatic generation
* @since 1.0
*/
@Service
public class InternationalServiceImpl extends ServiceImpl<InternationalMapper, International> implements InternationalService {
/**
* 插入
*
* @param international 国际
* @return boolean
*/
@Override
public boolean insert(International international) {
TranslateUtil.translate(new ArrayList<>(), "", "");
String code = international.getCode();
String lang = international.getLang();
Assert.isFalse(exist(code, lang), StrUtil.format("编码【{}】,语言【{}】已经存在", code, lang));
international.setTenantId(UserUtils.getTenantId());
boolean flag = save(international);
if (flag) {
RedisUtil.hashSet(international);
}
return flag;
}
/**
* 是否存在
*
* @param code 编码
* @param lang 语言
* @return boolean
*/
@Override
public boolean exist(String code, String lang) {
QueryWrapper queryWrapper = QueryWrapper.create()
.where(INTERNATIONAL.CODE.eq(code))
.and(INTERNATIONAL.LANG.eq(lang))
.and(INTERNATIONAL.TENANT_ID.eq(UserUtils.getTenantId()));
return exists(queryWrapper);
}
@Override
public List<International> listAll(International international) {
QueryWrapper wrapper = QueryWrapper.create()
.where(INTERNATIONAL.TENANT_ID.eq(UserUtils.getTenantId()))
.and(INTERNATIONAL.CODE.like(international.getCode(), StrUtil::isNotBlank))
.and(INTERNATIONAL.NAME.like(international.getName(), StrUtil::isNotBlank))
.and(INTERNATIONAL.LANG.like(UserUtils.getLang()))
.and(INTERNATIONAL.TYPE.like(international.getType(), StrUtil::isNotBlank))
.orderBy(INTERNATIONAL.CREATE_TIME.desc());
return list(wrapper);
}
/**
* 根据语言查询
*
* @param lang 语言
* @param tenantId
* @return {@link List}<{@link International}>
*/
@Override
public List<International> listByLang(String lang, String tenantId, String type) {
Assert.notBlank(lang, "语言不能为空");
QueryWrapper wrapper = QueryWrapper.create()
.where(INTERNATIONAL.TENANT_ID.eq(tenantId, StrUtil::isNotBlank))
.and(INTERNATIONAL.TYPE.eq(type, StrUtil::isNotBlank))
.and(INTERNATIONAL.LANG.eq(lang));
return list(wrapper);
}
@Override
public Page<List<International>> pageList(International international) {
QueryWrapper wrapper = QueryWrapper.create()
.where(INTERNATIONAL.TENANT_ID.eq(UserUtils.getTenantIdDefault(), StrUtil::isNotBlank))
.and(INTERNATIONAL.CODE.like(international.getCode(), StrUtil::isNotBlank))
.and(INTERNATIONAL.NAME.like(international.getName(), StrUtil::isNotBlank))
.and(INTERNATIONAL.LANG.like(international.getLang(), StrUtil::isNotBlank))
.and(INTERNATIONAL.TYPE.like(international.getType(), StrUtil::isNotBlank))
.orderBy(INTERNATIONAL.CREATE_TIME.desc());
return page(international.getPage(), wrapper);
}
/**
* 一键复制
*
* @param targetLang 目标语言
* @param sourceLang 源语言
* @param tenantId
* @return boolean
*/
@Override
public boolean copy(String targetLang, String sourceLang, String tenantId) {
List<International> sourceLangList = listByLang(sourceLang, tenantId, "");
List<String> nameList = sourceLangList.stream()
.map(International::getName)
.collect(Collectors.toList());
Map<String, String> tranfer = new ConcurrentHashMap<>();
ArrayList<CompletableFuture> futures = new ArrayList<>();
for (List<String> list : CollUtil.split(nameList, 400)) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
tranfer.putAll(TranslateUtil.translate(list, sourceLang, targetLang));
});
futures.add(future);
}
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
List<International> targetLangList = sourceLangList.stream()
.map(el -> {
International international = new International();
international.setCode(el.getCode());
international.setName(tranfer.get(el.getName()));
international.setLang(targetLang);
international.setType(el.getType());
international.setTenantId(UserUtils.getTenantId());
return international;
})
.collect(Collectors.toList());
boolean flag = saveBatch(targetLangList);
if (flag) {
RedisUtil.hashMultiSet(targetLang, targetLangList);
}
return flag;
}
@Override
public boolean updateInternational(International international) {
boolean flag = updateById(international);
if (flag) {
RedisUtil.hashSet(international);
}
return flag;
}
@Override
public boolean deleteById(String id) {
International international = getById(id);
boolean flag = removeById(id);
if (flag) {
RedisUtil.hashRemvoe(international);
}
return flag;
}
@Override
public void dowloadTemplate() {
try {
ExportParams exportParams = new ExportParams("国际化导入导出模板", "国际化");
exportParams.setDictHandler(new ExcelDicHandler());
exportParams.setCreateHeadRows(true);
List<InternationalExport> list = new ArrayList<>();
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, InternationalExport.class, list);
HttpServletResponse response = UserUtils.getResponse();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + new String(("template.xlsx").getBytes(), "ISO-8859-1"));
ServletOutputStream sos = response.getOutputStream();
workbook.write(sos);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Boolean importList(MultipartFile file) {
ImportParams params = new ImportParams();
params.setTitleRows(1);
params.setDictHandler(new ExcelDicHandler());
List<InternationalExport> importList;
try {
importList = ExcelImportUtil.importExcel(file.getInputStream(), InternationalExport.class, params);
// 校验数据完整性
for (InternationalExport export : importList) {
Assert.notBlank(export.getCode(), "编码不能为空");
Assert.notBlank(export.getName(), "名称不能为空");
Assert.notBlank(export.getLang(), "语言不能为空");
Assert.notBlank(export.getType(), "类型不能为空");
}
// 校验数据是否已经存在
Map<String, International> map = list(importList);
if (CollUtil.isNotEmpty(map)) {
for (InternationalExport export : importList) {
Assert.isFalse(map.containsKey(export.getCode() + export.getLang() + export.getType()),
StrUtil.format("编码【{}】语言【{}】类型【{}】已存在", export.getCode(), export.getLang(), export.getType()));
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("导入失败");
}
List<International> list = BeanUtil.copyToList(importList, International.class);
boolean flag = saveBatch(list);
if (flag) {
list.stream()
.collect(Collectors.groupingBy(International::getLang))
.forEach((k, v) -> {
RedisUtil.hashMultiSet(k, v);
});
}
return flag;
}
@Override
public Map<String, Map<String, String>> findLangPackage(String type) {
List<International> list = listByLang(UserUtils.getLang(), UserUtils.getTenantId(), type);
return list.stream()
.collect(Collectors.groupingBy(el -> StrUtil.subBefore(el.getCode(),
".",
false), Collectors.toMap(International::getCode, International::getName)));
}
@Override
public Boolean tenantIdCopy(String sourceLang, String tenantId) {
List<International> list = listByLang(sourceLang, tenantId, "").stream()
.map(el -> {
el.setTenantId(UserUtils.getTenantId());
el.setId(null);
el.setCreateBy(null);
el.setCreateTime(null);
el.setUpdateBy(null);
el.setUpdateTime(null);
return el;
})
.collect(Collectors.toList());
boolean flag = saveBatch(list);
if(flag){
RedisUtil.hashMultiSet(sourceLang, list);
}
return flag;
}
public Map<String, International> list(List<InternationalExport> list) {
QueryWrapper wrapper = QueryWrapper.create();
for (InternationalExport international : list) {
international.setTenantId(UserUtils.getTenantId());
wrapper.or(INTERNATIONAL.CODE.eq(international.getCode())
.and(INTERNATIONAL.NAME.eq(international.getName()))
.and(INTERNATIONAL.TYPE.eq(international.getType()))
.and(INTERNATIONAL.LANG.eq(international.getLang()))
.and(INTERNATIONAL.TENANT_ID.eq(UserUtils.getTenantId()))
);
}
List<International> dbList = list(wrapper);
if (CollUtil.isEmpty(dbList)) {
return new HashMap<>();
}
return dbList
.stream()
.collect(Collectors.toMap(el -> el.getCode() + el.getLang() + el.getType(), Function.identity()));
}
}

View File

@ -0,0 +1,61 @@
package com.blueland.common.core.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.blueland.common.core.constan.RedisConstan;
import com.blueland.common.core.domain.International;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class RedisUtil {
/**
* 批量添加
*
* @param lang
* @param list
*/
public static void hashMultiSet(String lang, List<International> list) {
Map<String, International> data = list.stream()
.collect(Collectors.toMap(el -> getHashKey(el), Function.identity()));
getRedisTemplate().opsForHash().putAll(getKey(lang), data);
}
@NotNull
private static String getKey(String lang) {
return UserUtils.getTenantId() + ":" + RedisConstan.I18N + lang;
}
public static RedisTemplate getRedisTemplate() {
return SpringUtil.getBean("redisTemplate");
}
/**
* 单个添加
*
* @param international
*/
public static void hashSet(International international) {
getRedisTemplate().opsForHash().put(getKey(international.getLang()), getHashKey(international), international);
}
/**
* 单个删除
*
* @param international
*/
public static void hashRemvoe(International international) {
getRedisTemplate().opsForHash().delete(getKey(international.getLang()), getHashKey(international));
}
public static String getHashKey(International international) {
return StrUtil.format("{}:{}", international.getCode(), international.getType());
}
}

View File

@ -0,0 +1,53 @@
package com.blueland.common.core.utils;
import com.blueland.common.core.config.InternationConfig;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.tmt.v20180321.TmtClient;
import com.tencentcloudapi.tmt.v20180321.models.TextTranslateBatchRequest;
import com.tencentcloudapi.tmt.v20180321.models.TextTranslateBatchResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TranslateUtil {
private static Credential INSTANCE = new Credential(InternationConfig.getSecretId(), InternationConfig.getSecretKey());
/**
* 腾讯翻译
*
* @param query 需要翻译的内容 {@link List}<{@link String}>
* @param from 源语言
* @param to 目标语言
* @return {@link Map}<{@link String}, {@link String}>
*/
public static Map<String, String> translate(List<String> query, String from, String to) {
Map<String, String> infoMap = new HashMap<>();
try {
TextTranslateBatchRequest req = new TextTranslateBatchRequest();
req.setSourceTextList(query.toArray(new String[0]));
req.setSource(from);
req.setTarget(to);
req.setProjectId(0L);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("tmt.tencentcloudapi.com");
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
TmtClient client = new TmtClient(INSTANCE, "ap-beijing", clientProfile);
TextTranslateBatchResponse resp = client.TextTranslateBatch(req);
String[] targetTextList = resp.getTargetTextList();
for (int i = 0; i < targetTextList.length; i++) {
infoMap.put(query.get(i), targetTextList[i]);
}
} catch (TencentCloudSDKException e) {
throw new RuntimeException(e);
}
return infoMap;
}
}

View File

@ -0,0 +1,95 @@
package com.blueland.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description 用户工具类
* @Date 2021/7/22 1:30 下午
* @Created BigTian
*/
@Component
public class UserUtils {
public static String getStaffCodeDefault(String staffCode) {
HttpServletRequest request = getRequest();
return Optional.ofNullable(request)
.map(el -> el.getHeader("staffPostCode"))
.orElse(staffCode);
}
public static String getStaffCode() {
HttpServletRequest request = getRequest();
return Optional.ofNullable(request)
.map(el -> el.getHeader("staffPostCode"))
.orElseThrow(() -> new RuntimeException("请求头缺少任岗编码"));
}
/**
* 获取当前登录人的租户
*
* @return String 租户编码
* @author bigtian
* @createTime 2022/5/16 10:35
* @since 6.0
*/
public static String getTenantId() {
HttpServletRequest request = getRequest();
String tenantid = Optional.ofNullable(request)
.map(el -> el.getHeader("tenantid"))
.orElseThrow(() -> new RuntimeException("请求头中没有租户"));
return tenantid;
}
public static String getTenantIdDefault() {
HttpServletRequest request = getRequest();
String tenantid = Optional.ofNullable(request)
.map(el -> el.getHeader("tenantid"))
.orElse("");
return tenantid;
}
/**
* 获取请求属性
*
* @return
*/
public static ServletRequestAttributes getRequestAttr() {
return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
}
/**
* 获取request
*/
public static HttpServletRequest getRequest() {
ServletRequestAttributes attributes = getRequestAttr();
return Optional.ofNullable(attributes).
map(ServletRequestAttributes::getRequest)
.orElse(null);
}
/**
* 获取response
*/
public static HttpServletResponse getResponse() {
ServletRequestAttributes attributes = getRequestAttr();
return attributes.getResponse();
}
public static String getLang() {
return getRequest().getLocale().getLanguage();
}
}

View File

@ -0,0 +1,38 @@
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
username: crm
password: crm@123
url: jdbc:mysql://192.168.1.13:3308/crm_usm?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
# redis:
# host: localhost
# port: 6379
redis:
database: 9
host: 192.168.1.169
password: ''
tm:
secretId: AKIDVotjKflbCYjgOr53xb093h6FApFQN5Yl
secretKey: 1oMfqmSt52kDRYR4SaUAbmiOp1yf8MM7
logging:
level:
net.rzdata.internation: debug
mybatis-flex:
type-aliases-package: com.blueland.common.core.domain
log:
path: ./logs/crm-internation
knife4j:
enable: true
openapi:
title: 国际化接口文档
group:
test1:
group-name: 国际化
api-rule: package
api-rule-resources:
- com.blueland.common.core.controller

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志存放路径 -->
<springProperty source="log.path" name="log.path" scope="context" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.blueland" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@ -0,0 +1,13 @@
package com.blueland.common.core;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class InternationApplicationTests {
@Test
void contextLoads() {
}
}