Finish Task #4531 Cost:4h 修复复制合同开票单位错误
This commit is contained in:
parent
56411feb91
commit
91c7340627
33
crm-internation/.gitignore
vendored
Normal file
33
crm-internation/.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
HELP.md
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
316
crm-internation/mvnw
vendored
Executable file
316
crm-internation/mvnw
vendored
Executable 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
crm-internation/pom.xml
Normal file
99
crm-internation/pom.xml
Normal 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>
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.blueland.common.core.constan;
|
||||||
|
|
||||||
|
public class RedisConstan {
|
||||||
|
public static final String I18N = "i18n:";
|
||||||
|
}
|
@ -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";
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
}
|
@ -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("字典名称不正确");
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -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> {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
@ -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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
crm-internation/src/main/resources/application.yml
Normal file
38
crm-internation/src/main/resources/application.yml
Normal 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
|
73
crm-internation/src/main/resources/logback.xml
Normal file
73
crm-internation/src/main/resources/logback.xml
Normal 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>
|
@ -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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user