parent
b89efa1db2
commit
2bc3d8b1cb
@ -0,0 +1,33 @@ |
||||
HELP.md |
||||
target/ |
||||
!.mvn/wrapper/maven-wrapper.jar |
||||
!**/src/main/** |
||||
!**/src/test/** |
||||
|
||||
### 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/ |
||||
|
||||
### VS Code ### |
||||
.vscode/ |
||||
|
||||
*.DS_Store |
||||
@ -0,0 +1,118 @@ |
||||
/* |
||||
* Copyright 2007-present the original author or authors. |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
|
||||
import java.net.*; |
||||
import java.io.*; |
||||
import java.nio.channels.*; |
||||
import java.util.Properties; |
||||
|
||||
public class MavenWrapperDownloader { |
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.6"; |
||||
/** |
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. |
||||
*/ |
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" |
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; |
||||
|
||||
/** |
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to |
||||
* use instead of the default one. |
||||
*/ |
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH = |
||||
".mvn/wrapper/maven-wrapper.properties"; |
||||
|
||||
/** |
||||
* Path where the maven-wrapper.jar will be saved to. |
||||
*/ |
||||
private static final String MAVEN_WRAPPER_JAR_PATH = |
||||
".mvn/wrapper/maven-wrapper.jar"; |
||||
|
||||
/** |
||||
* Name of the property which should be used to override the default download url for the wrapper. |
||||
*/ |
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; |
||||
|
||||
public static void main(String args[]) { |
||||
System.out.println("- Downloader started"); |
||||
File baseDirectory = new File(args[0]); |
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); |
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); |
||||
String url = DEFAULT_DOWNLOAD_URL; |
||||
if (mavenWrapperPropertyFile.exists()) { |
||||
FileInputStream mavenWrapperPropertyFileInputStream = null; |
||||
try { |
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); |
||||
Properties mavenWrapperProperties = new Properties(); |
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); |
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); |
||||
} catch (IOException e) { |
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); |
||||
} finally { |
||||
try { |
||||
if (mavenWrapperPropertyFileInputStream != null) { |
||||
mavenWrapperPropertyFileInputStream.close(); |
||||
} |
||||
} catch (IOException e) { |
||||
// Ignore ...
|
||||
} |
||||
} |
||||
} |
||||
System.out.println("- Downloading from: " + url); |
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); |
||||
if (!outputFile.getParentFile().exists()) { |
||||
if (!outputFile.getParentFile().mkdirs()) { |
||||
System.out.println( |
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); |
||||
} |
||||
} |
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); |
||||
try { |
||||
downloadFileFromURL(url, outputFile); |
||||
System.out.println("Done"); |
||||
System.exit(0); |
||||
} catch (Throwable e) { |
||||
System.out.println("- Error downloading"); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
} |
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception { |
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { |
||||
String username = System.getenv("MVNW_USERNAME"); |
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); |
||||
Authenticator.setDefault(new Authenticator() { |
||||
@Override |
||||
protected PasswordAuthentication getPasswordAuthentication() { |
||||
return new PasswordAuthentication(username, password); |
||||
} |
||||
}); |
||||
} |
||||
URL website = new URL(urlString); |
||||
ReadableByteChannel rbc; |
||||
rbc = Channels.newChannel(website.openStream()); |
||||
FileOutputStream fos = new FileOutputStream(destination); |
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); |
||||
fos.close(); |
||||
rbc.close(); |
||||
} |
||||
|
||||
} |
||||
Binary file not shown.
@ -0,0 +1,2 @@ |
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip |
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar |
||||
@ -0,0 +1,310 @@ |
||||
#!/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 /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="`which 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/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
else |
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.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" |
||||
else |
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$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 \ |
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ |
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ |
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" |
||||
@ -0,0 +1,182 @@ |
||||
@REM ---------------------------------------------------------------------------- |
||||
@REM Licensed to the Apache Software Foundation (ASF) under one |
||||
@REM or more contributor license agreements. See the NOTICE file |
||||
@REM distributed with this work for additional information |
||||
@REM regarding copyright ownership. The ASF licenses this file |
||||
@REM to you under the Apache License, Version 2.0 (the |
||||
@REM "License"); you may not use this file except in compliance |
||||
@REM with the License. You may obtain a copy of the License at |
||||
@REM |
||||
@REM https://www.apache.org/licenses/LICENSE-2.0 |
||||
@REM |
||||
@REM Unless required by applicable law or agreed to in writing, |
||||
@REM software distributed under the License is distributed on an |
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
@REM KIND, either express or implied. See the License for the |
||||
@REM specific language governing permissions and limitations |
||||
@REM under the License. |
||||
@REM ---------------------------------------------------------------------------- |
||||
|
||||
@REM ---------------------------------------------------------------------------- |
||||
@REM Maven Start Up Batch script |
||||
@REM |
||||
@REM Required ENV vars: |
||||
@REM JAVA_HOME - location of a JDK home dir |
||||
@REM |
||||
@REM Optional ENV vars |
||||
@REM M2_HOME - location of maven2's installed home dir |
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands |
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending |
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven |
||||
@REM e.g. to debug Maven itself, use |
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 |
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files |
||||
@REM ---------------------------------------------------------------------------- |
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' |
||||
@echo off |
||||
@REM set title of command window |
||||
title %0 |
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' |
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% |
||||
|
||||
@REM set %HOME% to equivalent of $HOME |
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") |
||||
|
||||
@REM Execute a user defined script before this one |
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre |
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending |
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" |
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" |
||||
:skipRcPre |
||||
|
||||
@setlocal |
||||
|
||||
set ERROR_CODE=0 |
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal |
||||
@setlocal |
||||
|
||||
@REM ==== START VALIDATION ==== |
||||
if not "%JAVA_HOME%" == "" goto OkJHome |
||||
|
||||
echo. |
||||
echo Error: JAVA_HOME not found in your environment. >&2 |
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2 |
||||
echo location of your Java installation. >&2 |
||||
echo. |
||||
goto error |
||||
|
||||
:OkJHome |
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init |
||||
|
||||
echo. |
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2 |
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2 |
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2 |
||||
echo location of your Java installation. >&2 |
||||
echo. |
||||
goto error |
||||
|
||||
@REM ==== END VALIDATION ==== |
||||
|
||||
:init |
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". |
||||
@REM Fallback to current working directory if not found. |
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% |
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir |
||||
|
||||
set EXEC_DIR=%CD% |
||||
set WDIR=%EXEC_DIR% |
||||
:findBaseDir |
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound |
||||
cd .. |
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound |
||||
set WDIR=%CD% |
||||
goto findBaseDir |
||||
|
||||
:baseDirFound |
||||
set MAVEN_PROJECTBASEDIR=%WDIR% |
||||
cd "%EXEC_DIR%" |
||||
goto endDetectBaseDir |
||||
|
||||
:baseDirNotFound |
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR% |
||||
cd "%EXEC_DIR%" |
||||
|
||||
:endDetectBaseDir |
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig |
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion |
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a |
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% |
||||
|
||||
:endReadAdditionalConfig |
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" |
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" |
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain |
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( |
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B |
||||
) |
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central |
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data. |
||||
if exist %WRAPPER_JAR% ( |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Found %WRAPPER_JAR% |
||||
) |
||||
) else ( |
||||
if not "%MVNW_REPOURL%" == "" ( |
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
) |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ... |
||||
echo Downloading from: %DOWNLOAD_URL% |
||||
) |
||||
|
||||
powershell -Command "&{"^ |
||||
"$webclient = new-object System.Net.WebClient;"^ |
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ |
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ |
||||
"}"^ |
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ |
||||
"}" |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Finished downloading %WRAPPER_JAR% |
||||
) |
||||
) |
||||
@REM End of extension |
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will |
||||
@REM work with both Windows and non-Windows executions. |
||||
set MAVEN_CMD_LINE_ARGS=%* |
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* |
||||
if ERRORLEVEL 1 goto error |
||||
goto end |
||||
|
||||
:error |
||||
set ERROR_CODE=1 |
||||
|
||||
:end |
||||
@endlocal & set ERROR_CODE=%ERROR_CODE% |
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost |
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending |
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" |
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" |
||||
:skipRcPost |
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' |
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause |
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% |
||||
|
||||
exit /B %ERROR_CODE% |
||||
@ -0,0 +1,172 @@ |
||||
<?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.6.1</version> |
||||
<relativePath/> <!-- lookup parent from repository --> |
||||
</parent> |
||||
<groupId>edu.ncst</groupId> |
||||
<artifactId>ioreport</artifactId> |
||||
<version>0.0.1-SNAPSHOT</version> |
||||
<name>ioreport</name> |
||||
<description>ioreport project for Spring Boot</description> |
||||
<properties> |
||||
<java.version>1.8</java.version> |
||||
</properties> |
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-web</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.mybatis.spring.boot</groupId> |
||||
<artifactId>mybatis-spring-boot-starter</artifactId> |
||||
<version>2.2.0</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-devtools</artifactId> |
||||
<scope>runtime</scope> |
||||
<optional>true</optional> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>mysql</groupId> |
||||
<artifactId>mysql-connector-java</artifactId> |
||||
<scope>runtime</scope> |
||||
</dependency> |
||||
<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>1.2.35</version> |
||||
</dependency> |
||||
<!-- MyBatis --> |
||||
<dependency> |
||||
<groupId>org.mybatis.spring.boot</groupId> |
||||
<artifactId>mybatis-spring-boot-starter</artifactId> |
||||
<version>2.1.3</version> |
||||
</dependency> |
||||
<!-- MyBatis Plus --> |
||||
<dependency> |
||||
<groupId>com.baomidou</groupId> |
||||
<artifactId>mybatis-plus-boot-starter</artifactId> |
||||
<version>3.3.2</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>com.baomidou</groupId> |
||||
<artifactId>mybatis-plus-generator</artifactId> |
||||
<version>3.3.2</version> |
||||
</dependency> |
||||
<!-- 数据校验 --> |
||||
<dependency> |
||||
<groupId>javax.validation</groupId> |
||||
<artifactId>validation-api</artifactId> |
||||
<version>2.0.1.Final</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.hibernate</groupId> |
||||
<artifactId>hibernate-validator</artifactId> |
||||
<version>6.0.13.Final</version> |
||||
</dependency> |
||||
<!-- JWT --> |
||||
<dependency> |
||||
<groupId>io.jsonwebtoken</groupId> |
||||
<artifactId>jjwt</artifactId> |
||||
<version>0.9.0</version> |
||||
</dependency> |
||||
<!-- Redis --> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-data-redis</artifactId> |
||||
</dependency> |
||||
<!-- AOP --> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-aop</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.aspectj</groupId> |
||||
<artifactId>aspectjweaver</artifactId> |
||||
<version>1.9.5</version> |
||||
</dependency> |
||||
<!-- DevTools --> |
||||
<dependency> |
||||
<groupId>org.springframework</groupId> |
||||
<artifactId>springloaded</artifactId> |
||||
<version>1.2.8.RELEASE</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-devtools</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-security</artifactId> |
||||
</dependency> |
||||
<!-- swagger --> |
||||
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> |
||||
<!-- <dependency>--> |
||||
<!-- <groupId>io.springfox</groupId>--> |
||||
<!-- <artifactId>springfox-swagger2</artifactId>--> |
||||
<!-- <version>2.9.2</version>--> |
||||
<!-- </dependency>--> |
||||
<!-- <!– https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui –>--> |
||||
<!-- <dependency>--> |
||||
<!-- <groupId>io.springfox</groupId>--> |
||||
<!-- <artifactId>springfox-swagger-ui</artifactId>--> |
||||
<!-- <version>2.9.2</version>--> |
||||
<!-- </dependency>--> |
||||
|
||||
<!-- <dependency>--> |
||||
<!-- <groupId>io.springfox</groupId>--> |
||||
<!-- <artifactId>springfox-boot-starter</artifactId>--> |
||||
<!-- <version>3.0.0</version>--> |
||||
<!-- </dependency>--> |
||||
<dependency> |
||||
<groupId>com.spring4all</groupId> |
||||
<artifactId>swagger-spring-boot-starter</artifactId> |
||||
<version>1.9.1.RELEASE</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>com.google.guava</groupId> |
||||
<artifactId>guava</artifactId> |
||||
<version>25.1-jre</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-configuration-processor</artifactId> |
||||
<optional>true</optional> |
||||
</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,211 @@ |
||||
package edu.ncst.ioreport.utils.generator; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill; |
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool; |
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
||||
import com.baomidou.mybatisplus.generator.AutoGenerator; |
||||
import com.baomidou.mybatisplus.generator.InjectionConfig; |
||||
import com.baomidou.mybatisplus.generator.config.*; |
||||
import com.baomidou.mybatisplus.generator.config.po.TableFill; |
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo; |
||||
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import edu.ncst.ioreport.model.BaseEntity; |
||||
import edu.ncst.ioreport.utils.generator.converter.CustomTypeConvert; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.URL; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Slf4j |
||||
public class CodeGenerator extends AutoGenerator { |
||||
|
||||
// 项目信息
|
||||
private final ProjectInfo projectInfo = null; |
||||
|
||||
// 项目路径
|
||||
String projectPath = System.getProperty("user.dir"); |
||||
|
||||
// 包名
|
||||
private final String basePackage = "edu.ncst.ioreport"; |
||||
|
||||
// 策略配置
|
||||
private final StrategyConfig strategy = new StrategyConfig(); |
||||
|
||||
// 包配置
|
||||
private final PackageConfig packageConfig = new PackageConfig(); |
||||
|
||||
// 表格元数据
|
||||
private final HashMap<String, TableMetaInfo> tableMetaInfoMap = new HashMap<>(); |
||||
|
||||
public CodeGenerator() { |
||||
this.loadGlobalConfig(); |
||||
this.loadDatasourceConfig(); |
||||
this.loadCustomConfig(); |
||||
this.loadTemplateConfig(); |
||||
this.loadPackageConfig(); |
||||
this.loadStrategyConfig(); |
||||
} |
||||
|
||||
// 加载全局配置
|
||||
private void loadGlobalConfig() { |
||||
GlobalConfig globalConfig = new GlobalConfig(); |
||||
globalConfig.setOutputDir(projectPath + "/src/main/java"); |
||||
globalConfig.setOpen(false); |
||||
globalConfig.setSwagger2(true); |
||||
setGlobalConfig(globalConfig); |
||||
} |
||||
|
||||
// 数据源配置
|
||||
private void loadDatasourceConfig() { |
||||
DataSourceConfig dsc = new DataSourceConfig(); |
||||
dsc.setUrl("jdbc:mysql://localhost:3306/award_sys?useUnicode=true&useSSL=false&characterEncoding=utf8&allowPublicKeyRetrieval=True"); |
||||
dsc.setDriverName("com.mysql.cj.jdbc.Driver"); |
||||
dsc.setUsername("smart"); |
||||
dsc.setPassword("hblgjg@2020"); |
||||
|
||||
// 自定义类型转换
|
||||
CustomTypeConvert customTypeConvert = new CustomTypeConvert(); |
||||
dsc.setTypeConvert(customTypeConvert); |
||||
setDataSource(dsc); |
||||
} |
||||
|
||||
// 自定义配置
|
||||
private void loadCustomConfig() { |
||||
InjectionConfig cfg = new InjectionConfig() { |
||||
@Override |
||||
public void initMap() { |
||||
Map<String, Object> map = new HashMap<>(); |
||||
map.put("string", StringUtils.class); |
||||
setMap(map); |
||||
} |
||||
|
||||
public void initTableMap(TableInfo tableInfo) { |
||||
Map<String, Object> map = getMap(); |
||||
log.info(tableMetaInfoMap.get(tableInfo.getName()).toString()); |
||||
map.put("tableMetaInfo", tableMetaInfoMap.get(tableInfo.getName())); |
||||
setMap(map); |
||||
} |
||||
}; |
||||
|
||||
// 如果模板引擎是 velocity
|
||||
String templatePath = "/templates/mapper.xml.vm"; |
||||
|
||||
// 自定义输出配置
|
||||
List<FileOutConfig> focList = new ArrayList<>(); |
||||
// 自定义配置会被优先输出
|
||||
focList.add(new FileOutConfig(templatePath) { |
||||
@Override |
||||
public String outputFile(TableInfo tableInfo) { |
||||
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
|
||||
return projectPath + "/src/main/resources/mapping/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; |
||||
} |
||||
}); |
||||
|
||||
cfg.setFileOutConfigList(focList); |
||||
setCfg(cfg); |
||||
} |
||||
|
||||
// 配置模板
|
||||
private void loadTemplateConfig() { |
||||
TemplateConfig templateConfig = new TemplateConfig(); |
||||
|
||||
templateConfig.setController("templates/controller.java"); |
||||
templateConfig.setXml(null); |
||||
|
||||
setTemplate(templateConfig); |
||||
} |
||||
|
||||
// 包配置
|
||||
private void loadPackageConfig() { |
||||
packageConfig.setParent(basePackage); |
||||
setPackageInfo(packageConfig); |
||||
} |
||||
|
||||
// 策略配置
|
||||
private void loadStrategyConfig() { |
||||
strategy.setNaming(NamingStrategy.underline_to_camel); |
||||
strategy.setColumnNaming(NamingStrategy.underline_to_camel); |
||||
strategy.setEntityLombokModel(true); |
||||
strategy.setRestControllerStyle(true); |
||||
|
||||
// 填充字段
|
||||
TableFill createTimeFill = new TableFill("create_time", FieldFill.INSERT); |
||||
TableFill createUserIdFill = new TableFill("create_user_id", FieldFill.INSERT); |
||||
TableFill updateTimeFill = new TableFill("update_time", FieldFill.INSERT_UPDATE); |
||||
TableFill updateUserIdFill = new TableFill("update_user_id", FieldFill.INSERT_UPDATE); |
||||
List<TableFill> tableFillList = new ArrayList<>(); |
||||
tableFillList.add(createTimeFill); |
||||
tableFillList.add(createUserIdFill); |
||||
tableFillList.add(updateTimeFill); |
||||
tableFillList.add(updateUserIdFill); |
||||
|
||||
strategy.setTableFillList(tableFillList); |
||||
strategy.setLogicDeleteFieldName("delete_time"); |
||||
strategy.setControllerMappingHyphenStyle(true); |
||||
} |
||||
|
||||
// 加载模块信息
|
||||
public void loadModuleInfo(ModuleInfo moduleInfo) { |
||||
// 获取数据库表名称
|
||||
List<TableMetaInfo> tables = moduleInfo.getTables(); |
||||
List<String> tableNameList = new ArrayList<>(); |
||||
|
||||
for (TableMetaInfo tableMetaInfo : tables) { |
||||
tableNameList.add(tableMetaInfo.getTableName()); |
||||
tableMetaInfoMap.put(tableMetaInfo.getTableName(), tableMetaInfo); |
||||
} |
||||
|
||||
String[] tableNames = new String[tableNameList.size()]; |
||||
tableNameList.toArray(tableNames); |
||||
|
||||
// 根据配置加载策略
|
||||
strategy.setInclude(tableNames); |
||||
strategy.setTablePrefix(moduleInfo.getTablePrefix() + "_"); |
||||
|
||||
if (moduleInfo.getExtendBaseEntity()) { |
||||
strategy.setSuperEntityClass(BaseEntity.class); |
||||
strategy.setSuperEntityColumns("create_time", "create_user_id", "update_time", "update_user_id", "delete_time", "delete_user_id"); |
||||
} |
||||
|
||||
setStrategy(strategy); |
||||
|
||||
// 设置包
|
||||
String moduleName = moduleInfo.getModuleName(); |
||||
|
||||
if (moduleName != null && !moduleName.equals("")) { |
||||
packageConfig.setEntity("model." + moduleName); |
||||
packageConfig.setController("controller." + moduleName); |
||||
packageConfig.setMapper("mapper." + moduleName); |
||||
packageConfig.setServiceImpl("service.impl." + moduleName); |
||||
setPackageInfo(packageConfig); |
||||
} |
||||
} |
||||
|
||||
// 生成代码
|
||||
public void generateCode() { |
||||
execute(); |
||||
} |
||||
|
||||
// public static void main(String[] args) throws IOException {
|
||||
// ObjectMapper mapper = new ObjectMapper();
|
||||
// URL configFileURL = CodeGenerator.class.getClassLoader().getResource("project.json");
|
||||
//
|
||||
// assert configFileURL != null;
|
||||
// File configFile = new File(configFileURL.getFile());
|
||||
// ProjectInfo projectInfo = mapper.readValue(configFile, ProjectInfo.class);
|
||||
// log.info(projectInfo.toString());
|
||||
// List<ModuleInfo> modules = projectInfo.getModules();
|
||||
// for (ModuleInfo moduleInfo : modules) {
|
||||
// CodeGenerator codeGenerator = new CodeGenerator();
|
||||
// codeGenerator.loadModuleInfo(moduleInfo);
|
||||
// codeGenerator.generateCode();
|
||||
// }
|
||||
// }
|
||||
|
||||
} |
||||
@ -0,0 +1,25 @@ |
||||
package edu.ncst.ioreport.utils.generator; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class ModuleInfo { |
||||
|
||||
// 模块显示文本
|
||||
private String moduleLabel; |
||||
|
||||
// 模块名称
|
||||
private String moduleName; |
||||
|
||||
// 表格前缀
|
||||
private String tablePrefix; |
||||
|
||||
// 表格信息列表
|
||||
private List<TableMetaInfo> tables; |
||||
|
||||
// 是否继承自基类
|
||||
private Boolean extendBaseEntity = false; |
||||
|
||||
} |
||||
@ -0,0 +1,19 @@ |
||||
package edu.ncst.ioreport.utils.generator; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class ProjectInfo { |
||||
|
||||
// 项目显示文本
|
||||
private String projectLabel; |
||||
|
||||
// 项目名称
|
||||
private String projectName; |
||||
|
||||
// 模块列表
|
||||
private List<ModuleInfo> modules; |
||||
|
||||
} |
||||
@ -0,0 +1,25 @@ |
||||
package edu.ncst.ioreport.utils.generator; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
public class TableMetaInfo { |
||||
|
||||
// 表格显示文本
|
||||
private String tableLabel; |
||||
|
||||
// 表格名称
|
||||
private String tableName; |
||||
|
||||
// 是否继承自基类
|
||||
private Boolean extendBaseEntity = false; |
||||
|
||||
// 是否为关系表
|
||||
private Boolean relationTable = false; |
||||
|
||||
// 主键列表
|
||||
private List<String> primaryKeys; |
||||
|
||||
} |
||||
@ -0,0 +1,73 @@ |
||||
package edu.ncst.ioreport.utils.generator.converter; |
||||
|
||||
import com.baomidou.mybatisplus.generator.config.GlobalConfig; |
||||
import com.baomidou.mybatisplus.generator.config.ITypeConvert; |
||||
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType; |
||||
import com.baomidou.mybatisplus.generator.config.rules.IColumnType; |
||||
|
||||
public class CustomTypeConvert implements ITypeConvert { |
||||
|
||||
@Override |
||||
public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) { |
||||
String t = fieldType.toLowerCase(); |
||||
if (t.contains("char")) { |
||||
return DbColumnType.STRING; |
||||
} else if (t.contains("bigint")) { |
||||
return DbColumnType.LONG; |
||||
} else if (t.contains("tinyint(1)")) { |
||||
return DbColumnType.BOOLEAN; |
||||
} else if (t.contains("int")) { |
||||
return DbColumnType.INTEGER; |
||||
} else if (t.contains("text")) { |
||||
return DbColumnType.STRING; |
||||
} else if (t.contains("bit")) { |
||||
return DbColumnType.BOOLEAN; |
||||
} else if (t.contains("decimal")) { |
||||
return DbColumnType.BIG_DECIMAL; |
||||
} else if (t.contains("clob")) { |
||||
return DbColumnType.CLOB; |
||||
} else if (t.contains("blob")) { |
||||
return DbColumnType.BLOB; |
||||
} else if (t.contains("binary")) { |
||||
return DbColumnType.BYTE_ARRAY; |
||||
} else if (t.contains("float")) { |
||||
return DbColumnType.FLOAT; |
||||
} else if (t.contains("double")) { |
||||
return DbColumnType.DOUBLE; |
||||
} else if (t.contains("enum")) { |
||||
return DbColumnType.STRING; |
||||
} else if (t.contains("json")) { |
||||
return new JSONColumnType(); |
||||
} else if (t.contains("date") || t.contains("time") || t.contains("year")) { |
||||
switch (globalConfig.getDateType()) { |
||||
case ONLY_DATE: |
||||
return DbColumnType.DATE; |
||||
case SQL_PACK: |
||||
switch (t) { |
||||
case "date": |
||||
return DbColumnType.DATE_SQL; |
||||
case "time": |
||||
return DbColumnType.TIME; |
||||
case "year": |
||||
return DbColumnType.DATE_SQL; |
||||
default: |
||||
return DbColumnType.TIMESTAMP; |
||||
} |
||||
case TIME_PACK: |
||||
switch (t) { |
||||
case "date": |
||||
return DbColumnType.LOCAL_DATE; |
||||
case "time": |
||||
return DbColumnType.LOCAL_TIME; |
||||
case "year": |
||||
return DbColumnType.YEAR; |
||||
default: |
||||
return DbColumnType.LOCAL_DATE_TIME; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return DbColumnType.STRING; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,17 @@ |
||||
package edu.ncst.ioreport.utils.generator.converter; |
||||
|
||||
import com.baomidou.mybatisplus.generator.config.rules.IColumnType; |
||||
|
||||
public class JSONColumnType implements IColumnType { |
||||
|
||||
@Override |
||||
public String getType() { |
||||
return "HashMap<String, Object>"; |
||||
} |
||||
|
||||
@Override |
||||
public String getPkg() { |
||||
return "java.util.HashMap"; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,79 @@ |
||||
{ |
||||
"projectLabel": "出入校报备系统", |
||||
"projectName": "ioreport-mgt", |
||||
"modules": [ |
||||
{ |
||||
"moduleLabel": "系统管理", |
||||
"moduleName": "system", |
||||
"tablePrefix": "sys", |
||||
"tables": [ |
||||
{ |
||||
"tableLabel": "用户", |
||||
"tableName": "sys_user" |
||||
}, |
||||
{ |
||||
"tableLabel": "角色", |
||||
"tableName": "sys_role" |
||||
}, |
||||
{ |
||||
"tableLabel": "用户角色", |
||||
"tableName": "sys_user_role", |
||||
"relationTable": true |
||||
}, |
||||
{ |
||||
"tableLabel": "角色菜单", |
||||
"tableName": "sys_role_menu", |
||||
"relationTable": true |
||||
}, |
||||
{ |
||||
"tableLabel": "角色单位", |
||||
"tableName": "sys_role_dept", |
||||
"relationTable": true |
||||
}, |
||||
{ |
||||
"tableLabel": "菜单", |
||||
"tableName": "sys_menu" |
||||
}, |
||||
{ |
||||
"tableLabel": "字典", |
||||
"tableName": "sys_dict" |
||||
}, |
||||
{ |
||||
"tableLabel": "字典类型", |
||||
"tableName": "sys_dict_type" |
||||
}, |
||||
{ |
||||
"tableLabel": "操作日志", |
||||
"tableName": "sys_operation_log" |
||||
}, |
||||
{ |
||||
"tableLabel": "登录日志", |
||||
"tableName": "sys_login_log" |
||||
}, |
||||
{ |
||||
"tableLabel": "系统配置", |
||||
"tableName": "sys_config" |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"moduleLabel": "设备管理", |
||||
"moduleName": "equipment", |
||||
"extendBaseEntity": true, |
||||
"tables": [ |
||||
{ |
||||
"tableLabel": "设备", |
||||
"tableName": "equipment" |
||||
}, |
||||
{ |
||||
"tableLabel": "设备分类", |
||||
"tableName": "equipment_category" |
||||
}, |
||||
{ |
||||
"tableLabel": "设备制造商", |
||||
"tableName": "manufacturer" |
||||
} |
||||
] |
||||
} |
||||
] |
||||
} |
||||
@ -0,0 +1,97 @@ |
||||
package ${package.Controller}; |
||||
|
||||
import ${package.Entity}.${entity};; |
||||
import edu.ncst.equmanager.qo.Query; |
||||
import ${package.Service}.I${entity}Service; |
||||
import edu.ncst.equmanager.utils.ResponseUtils; |
||||
import edu.ncst.equmanager.utils.ResultUtils; |
||||
import edu.ncst.equmanager.vo.ListResultVO; |
||||
import edu.ncst.equmanager.vo.ResultVO; |
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.web.bind.annotation.*; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
#if(${restControllerStyle}) |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
#else |
||||
import org.springframework.stereotype.Controller; |
||||
#end |
||||
#if(${superControllerClassPackage}) |
||||
import ${superControllerClassPackage}; |
||||
#end |
||||
|
||||
/** |
||||
* $!{table.comment} 控制器 |
||||
*/ |
||||
@Api(description = "$!{table.comment} 控制器", tags = "$!{table.controllerName}") |
||||
@Slf4j |
||||
#if(${restControllerStyle}) |
||||
@RestController |
||||
#else |
||||
@Controller |
||||
#end |
||||
@RequestMapping("#if(${package.ModuleName})/${package.ModuleName}#end/#if(${controllerMappingHyphenStyle})${controllerMappingHyphen}#else${table.entityPath}#end") |
||||
#if(${kotlin}) |
||||
class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end |
||||
|
||||
#else |
||||
#if(${superControllerClass}) |
||||
public class ${table.controllerName} extends ${superControllerClass} { |
||||
#else |
||||
public class ${table.controllerName} { |
||||
#end |
||||
|
||||
private final I${entity}Service ${cfg.string.firstToLowerCase(${entity})}Service; |
||||
|
||||
public ${entity}Controller(I${entity}Service ${cfg.string.firstToLowerCase(${entity})}Service) { |
||||
this.${cfg.string.firstToLowerCase(${entity})}Service = ${cfg.string.firstToLowerCase(${entity})}Service; |
||||
} |
||||
|
||||
@ApiOperation("获取$!{table.comment}列表") |
||||
@GetMapping("/list") |
||||
public ResultVO<ListResultVO<${entity}>> get${entity}List(Query query) { |
||||
ListResultVO<${entity}> ${cfg.string.firstToLowerCase(${entity})}List = ${cfg.string.firstToLowerCase(${entity})}Service.get${entity}List(query); |
||||
|
||||
return ResultUtils.success("ok", ${cfg.string.firstToLowerCase(${entity})}List); |
||||
} |
||||
|
||||
#if(!${cfg.tableMetaInfo.relationTable}) |
||||
@ApiOperation("获取$!{table.comment}详情") |
||||
@PostMapping("/detail") |
||||
public ResultVO<${entity}> get${entity}Detail(@RequestParam Integer id) { |
||||
${entity} ${cfg.string.firstToLowerCase(${entity})}Detail = ${cfg.string.firstToLowerCase(${entity})}Service.get${entity}Detail(id); |
||||
|
||||
return ResultUtils.success("ok", ${cfg.string.firstToLowerCase(${entity})}Detail); |
||||
} |
||||
#end |
||||
|
||||
@ApiOperation("添加$!{table.comment}") |
||||
@PostMapping("/add") |
||||
public ResultVO<${entity}> add${entity}(@RequestBody ${entity} ${cfg.string.firstToLowerCase(${entity})}) { |
||||
${entity} result = ${cfg.string.firstToLowerCase(${entity})}Service.add${entity}(${cfg.string.firstToLowerCase(${entity})}); |
||||
|
||||
return ResultUtils.success("ok", result); |
||||
} |
||||
|
||||
#if(!${cfg.tableMetaInfo.relationTable}) |
||||
@ApiOperation("修改$!{table.comment}") |
||||
@PutMapping("/modify") |
||||
public ResultVO<${entity}> modify${entity}(@RequestBody ${entity} ${cfg.string.firstToLowerCase(${entity})}) { |
||||
${entity} result = ${cfg.string.firstToLowerCase(${entity})}Service.modify${entity}(${cfg.string.firstToLowerCase(${entity})}); |
||||
|
||||
return ResultUtils.success("ok", result); |
||||
} |
||||
#end |
||||
|
||||
@ApiOperation("删除$!{table.comment}") |
||||
@DeleteMapping("/delete") |
||||
public ResponseEntity<?> delete${entity}(@RequestParam Integer id) { |
||||
${cfg.string.firstToLowerCase(${entity})}Service.delete${entity}(id); |
||||
|
||||
return ResponseUtils.success("删除成功"); |
||||
} |
||||
|
||||
} |
||||
#end |
||||
@ -0,0 +1,17 @@ |
||||
package ${package.Mapper}; |
||||
|
||||
import ${package.Entity}.${entity}; |
||||
import ${superMapperClassPackage}; |
||||
import org.springframework.stereotype.Repository; |
||||
|
||||
/** |
||||
* $!{table.comment} Mapper 接口 |
||||
*/ |
||||
@Repository |
||||
#if(${kotlin}) |
||||
interface ${table.mapperName} : ${superMapperClass}<${entity}> |
||||
#else |
||||
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> { |
||||
|
||||
} |
||||
#end |
||||
@ -0,0 +1,39 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="${package.Mapper}.${table.mapperName}"> |
||||
|
||||
#if(${enableCache}) |
||||
<!-- 开启二级缓存 --> |
||||
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/> |
||||
|
||||
#end |
||||
#if(${baseResultMap}) |
||||
<!-- 通用查询映射结果 --> |
||||
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}"> |
||||
#foreach($field in ${table.fields}) |
||||
#if(${field.keyFlag})##生成主键排在第一位 |
||||
<id column="${field.name}" property="${field.propertyName}" /> |
||||
#end |
||||
#end |
||||
#foreach($field in ${table.commonFields})##生成公共字段 |
||||
<result column="${field.name}" property="${field.propertyName}" /> |
||||
#end |
||||
#foreach($field in ${table.fields}) |
||||
#if(!${field.keyFlag})##生成普通字段 |
||||
<result column="${field.name}" property="${field.propertyName}" /> |
||||
#end |
||||
#end |
||||
</resultMap> |
||||
|
||||
#end |
||||
#if(${baseColumnList}) |
||||
<!-- 通用查询结果列 --> |
||||
<sql id="Base_Column_List"> |
||||
#foreach($field in ${table.commonFields}) |
||||
${field.columnName}, |
||||
#end |
||||
${table.fieldNames} |
||||
</sql> |
||||
|
||||
#end |
||||
</mapper> |
||||
@ -0,0 +1,161 @@ |
||||
package ${package.Entity}; |
||||
|
||||
#foreach($pkg in ${table.importPackages}) |
||||
import ${pkg}; |
||||
#end |
||||
#if(${swagger2}) |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
#end |
||||
#if(${entityLombokModel}) |
||||
import lombok.Data; |
||||
import lombok.EqualsAndHashCode; |
||||
#if(${chainModel}) |
||||
import lombok.experimental.Accessors; |
||||
#end |
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; |
||||
import com.baomidou.mybatisplus.annotation.*; |
||||
#end |
||||
|
||||
/** |
||||
* $!{table.comment} |
||||
*/ |
||||
#if(${swagger2}) |
||||
@ApiModel(value="${entity}", description="$!{table.comment}") |
||||
#end |
||||
#if(${entityLombokModel}) |
||||
@Data |
||||
#if(${superEntityClass}) |
||||
@EqualsAndHashCode(callSuper = true) |
||||
#else |
||||
@EqualsAndHashCode(callSuper = false) |
||||
#end |
||||
#if(${chainModel}) |
||||
@Accessors(chain = true) |
||||
#end |
||||
#end |
||||
#if(${table.convert}) |
||||
@TableName("${table.name}") |
||||
#end |
||||
#if(${superEntityClass}) |
||||
@TableName(autoResultMap = true) |
||||
public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end { |
||||
#elseif(${activeRecord}) |
||||
public class ${entity} extends Model<${entity}> { |
||||
#else |
||||
public class ${entity} implements Serializable { |
||||
#end |
||||
|
||||
#if(${entitySerialVersionUID}) |
||||
private static final long serialVersionUID=1L; |
||||
#end |
||||
## ---------- BEGIN 字段循环遍历 ---------- |
||||
#foreach($field in ${table.fields}) |
||||
|
||||
#if(${field.keyFlag}) |
||||
#set($keyPropertyName=${field.propertyName}) |
||||
#end |
||||
#if("$!field.comment" != "") |
||||
#if(${swagger2}) |
||||
@ApiModelProperty(value = "${field.comment}") |
||||
#else |
||||
/** |
||||
* ${field.comment} |
||||
*/ |
||||
#end |
||||
#end |
||||
#if(${field.keyFlag}) |
||||
## 主键 |
||||
#if(${field.keyIdentityFlag}) |
||||
@TableId(value = "${field.annotationColumnName}", type = IdType.AUTO) |
||||
#elseif(!$null.isNull(${idType}) && "$!idType" != "") |
||||
@TableId(value = "${field.annotationColumnName}", type = IdType.${idType}) |
||||
#elseif(${field.convert}) |
||||
@TableId("${field.annotationColumnName}") |
||||
#end |
||||
## 普通字段 |
||||
#elseif(${field.fill}) |
||||
## ----- 存在字段填充设置 ----- |
||||
#if(${field.convert}) |
||||
@TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill}) |
||||
#else |
||||
@TableField(fill = FieldFill.${field.fill}) |
||||
#end |
||||
#elseif(${field.convert}) |
||||
@TableField("${field.annotationColumnName}") |
||||
#end |
||||
## 乐观锁注解 |
||||
#if(${versionFieldName}==${field.name}) |
||||
@Version |
||||
#end |
||||
## JSON 类型处理器 |
||||
#if(${field.type} == "json") |
||||
@TableField(typeHandler = JacksonTypeHandler.class) |
||||
#end |
||||
## 逻辑删除注解 |
||||
#if(${logicDeleteFieldName}==${field.name}) |
||||
@TableLogic |
||||
#end |
||||
private ${field.propertyType} ${field.propertyName}; |
||||
#end |
||||
## ---------- END 字段循环遍历 ---------- |
||||
|
||||
#if(!${entityLombokModel}) |
||||
#foreach($field in ${table.fields}) |
||||
#if(${field.propertyType.equals("boolean")}) |
||||
#set($getprefix="is") |
||||
#else |
||||
#set($getprefix="get") |
||||
#end |
||||
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() { |
||||
return ${field.propertyName}; |
||||
} |
||||
|
||||
#if(${chainModel}) |
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) { |
||||
#else |
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) { |
||||
#end |
||||
this.${field.propertyName} = ${field.propertyName}; |
||||
#if(${chainModel}) |
||||
return this; |
||||
#end |
||||
} |
||||
#end |
||||
## --foreach end--- |
||||
#end |
||||
## --end of #if(!${entityLombokModel})-- |
||||
|
||||
#if(${entityColumnConstant}) |
||||
#foreach($field in ${table.fields}) |
||||
public static final String ${field.name.toUpperCase()} = "${field.name}"; |
||||
|
||||
#end |
||||
#end |
||||
#if(${activeRecord}) |
||||
@Override |
||||
protected Serializable pkVal() { |
||||
#if(${keyPropertyName}) |
||||
return this.${keyPropertyName}; |
||||
#else |
||||
return null; |
||||
#end |
||||
} |
||||
|
||||
#end |
||||
#if(!${entityLombokModel}) |
||||
@Override |
||||
public String toString() { |
||||
return "${entity}{" + |
||||
#foreach($field in ${table.fields}) |
||||
#if($!{foreach.index}==0) |
||||
"${field.propertyName}=" + ${field.propertyName} + |
||||
#else |
||||
", ${field.propertyName}=" + ${field.propertyName} + |
||||
#end |
||||
#end |
||||
"}"; |
||||
} |
||||
#end |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
package ${package.Service}; |
||||
|
||||
import ${package.Entity}.${entity}; |
||||
import ${superServiceClassPackage}; |
||||
import edu.ncst.equmanager.vo.ListResultVO; |
||||
import edu.ncst.equmanager.qo.Query; |
||||
|
||||
/** |
||||
* $!{table.comment} 服务类 |
||||
*/ |
||||
#if(${kotlin}) |
||||
interface ${table.serviceName} : ${superServiceClass}<${entity}> |
||||
#else |
||||
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> { |
||||
|
||||
ListResultVO<${entity}> get${entity}List(Query query); |
||||
|
||||
#if(!${cfg.tableMetaInfo.relationTable}) |
||||
${entity} get${entity}Detail(Integer id); |
||||
#end |
||||
|
||||
${entity} add${entity}(${entity} ${cfg.string.firstToLowerCase(${entity})}); |
||||
|
||||
#if(!${cfg.tableMetaInfo.relationTable}) |
||||
${entity} modify${entity}(${entity} ${cfg.string.firstToLowerCase(${entity})}); |
||||
#end |
||||
|
||||
boolean delete${entity}(Integer id); |
||||
|
||||
} |
||||
#end |
||||
@ -0,0 +1,106 @@ |
||||
package ${package.ServiceImpl}; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
import ${package.Entity}.${entity}; |
||||
import ${package.Mapper}.${table.mapperName}; |
||||
import ${package.Service}.${table.serviceName}; |
||||
import ${superServiceImplClassPackage}; |
||||
import edu.ncst.equmanager.qo.Query; |
||||
import edu.ncst.equmanager.exception.BusinessException; |
||||
import edu.ncst.equmanager.exception.CodeMsg; |
||||
import edu.ncst.equmanager.vo.ListResultVO; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.transaction.annotation.Transactional; |
||||
|
||||
/** |
||||
* $!{table.comment} 服务实现类 |
||||
*/ |
||||
@Service |
||||
#if(${kotlin}) |
||||
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} { |
||||
|
||||
} |
||||
#else |
||||
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} { |
||||
|
||||
private final ${entity}Mapper ${cfg.string.firstToLowerCase(${entity})}Mapper; |
||||
|
||||
public ${entity}ServiceImpl(${entity}Mapper ${cfg.string.firstToLowerCase(${entity})}Mapper) { |
||||
this.${cfg.string.firstToLowerCase(${entity})}Mapper = ${cfg.string.firstToLowerCase(${entity})}Mapper; |
||||
} |
||||
|
||||
// 获取$!{table.comment}列表 |
||||
@Override |
||||
public ListResultVO<${entity}> get${entity}List(Query query) { |
||||
QueryWrapper<${entity}> queryWrapper = new QueryWrapper<>(); |
||||
Page<${entity}> pageRequest = query.toPageRequest(); |
||||
Page<${entity}> page = ${cfg.string.firstToLowerCase(${entity})}Mapper.selectPage(pageRequest, queryWrapper); |
||||
|
||||
// 封装返回结果 |
||||
ListResultVO<${entity}> listResultVO = new ListResultVO<>(); |
||||
listResultVO.setList(page.getRecords()); |
||||
listResultVO.setTotal(page.getTotal()); |
||||
listResultVO.setCurrent(page.getCurrent()); |
||||
|
||||
return listResultVO; |
||||
} |
||||
|
||||
#if(!${cfg.tableMetaInfo.relationTable}) |
||||
// 获取$!{table.comment}详情 |
||||
@Override |
||||
public ${entity} get${entity}Detail(Integer id) { |
||||
${entity} ${cfg.string.firstToLowerCase(${entity})} = ${cfg.string.firstToLowerCase(${entity})}Mapper.selectById(id); |
||||
return ${cfg.string.firstToLowerCase(${entity})}; |
||||
} |
||||
#end |
||||
|
||||
// 添加$!{table.comment} |
||||
@Transactional |
||||
@Override |
||||
public ${entity} add${entity}(${entity} ${cfg.string.firstToLowerCase(${entity})}) { |
||||
int insert = ${cfg.string.firstToLowerCase(${entity})}Mapper.insert(${cfg.string.firstToLowerCase(${entity})}); |
||||
#if(!${cfg.tableMetaInfo.relationTable}) |
||||
${entity} result = get${entity}Detail(${cfg.string.firstToLowerCase(${entity})}.getId()); |
||||
#end |
||||
if (insert == 1) { |
||||
#if(${cfg.tableMetaInfo.relationTable}) |
||||
return ${cfg.string.firstToLowerCase(${entity})}; |
||||
#else |
||||
return result; |
||||
#end |
||||
} else { |
||||
throw new BusinessException(CodeMsg.ADD_ERROR); |
||||
} |
||||
} |
||||
|
||||
#if(!${cfg.tableMetaInfo.relationTable}) |
||||
// 修改$!{table.comment} |
||||
@Transactional |
||||
@Override |
||||
public ${entity} modify${entity}(${entity} ${cfg.string.firstToLowerCase(${entity})}) { |
||||
int update = ${cfg.string.firstToLowerCase(${entity})}Mapper.updateById(${cfg.string.firstToLowerCase(${entity})}); |
||||
${entity} result = get${entity}Detail(${cfg.string.firstToLowerCase(${entity})}.getId()); |
||||
|
||||
if (update == 1) { |
||||
return result; |
||||
} else { |
||||
throw new BusinessException(CodeMsg.MODIFY_ERROR); |
||||
} |
||||
} |
||||
#end |
||||
|
||||
// 删除$!{table.comment} |
||||
@Transactional |
||||
@Override |
||||
public boolean delete${entity}(Integer id) { |
||||
int delete = ${cfg.string.firstToLowerCase(${entity})}Mapper.deleteById(id); |
||||
|
||||
if (delete == 1) { |
||||
return true; |
||||
} else { |
||||
throw new BusinessException(CodeMsg.DELETE_ERROR); |
||||
} |
||||
} |
||||
} |
||||
#end |
||||
@ -0,0 +1,33 @@ |
||||
package edu.ncst.ioreport; |
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; |
||||
import org.mybatis.spring.annotation.MapperScan; |
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
import com.spring4all.swagger.EnableSwagger2Doc; |
||||
import org.springframework.cache.annotation.EnableCaching; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy; |
||||
import org.springframework.transaction.annotation.EnableTransactionManagement; |
||||
|
||||
|
||||
@EnableSwagger2Doc |
||||
@SpringBootApplication |
||||
@MapperScan(basePackages = {"edu.ncst.ioreport.mapper"}) |
||||
@EnableTransactionManagement |
||||
@EnableCaching |
||||
@EnableAspectJAutoProxy(exposeProxy=true) |
||||
public class IOReprotApplication { |
||||
/** |
||||
* 分页插件 |
||||
*/ |
||||
@Bean |
||||
public PaginationInterceptor paginationInterceptor() { |
||||
return new PaginationInterceptor(); |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
SpringApplication.run(IOReprotApplication.class, args); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
package edu.ncst.ioreport.config; |
||||
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.access.AccessDeniedException; |
||||
import org.springframework.security.web.access.AccessDeniedHandler; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
@Service |
||||
public class CustomAccessDeniedHandler implements AccessDeniedHandler { |
||||
|
||||
@Autowired |
||||
private ObjectMapper objectMapper; |
||||
|
||||
@Override |
||||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { |
||||
response.setContentType("application/json;charset=UTF-8"); |
||||
Map map = new HashMap(); |
||||
map.put("code",403); |
||||
map.put("msg", "无访问权限"); |
||||
map.put("data",""); |
||||
response.setContentType("application/json"); |
||||
response.setStatus(HttpServletResponse.SC_OK); |
||||
response.getWriter().write(objectMapper.writeValueAsString(map)); |
||||
} |
||||
} |
||||
@ -0,0 +1,47 @@ |
||||
|
||||
package edu.ncst.ioreport.config; |
||||
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature; |
||||
import com.alibaba.fastjson.support.config.FastJsonConfig; |
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.http.converter.HttpMessageConverter; |
||||
|
||||
import java.nio.charset.Charset; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
@Configuration |
||||
public class JsonConfig { |
||||
|
||||
|
||||
@Bean |
||||
public HttpMessageConverter configureMessageConverters() { |
||||
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); |
||||
FastJsonConfig config = new FastJsonConfig(); |
||||
config.setSerializerFeatures( |
||||
// 保留map空的字段
|
||||
SerializerFeature.WriteMapNullValue, |
||||
// 将String类型的null转成""
|
||||
SerializerFeature.WriteNullStringAsEmpty, |
||||
// 将Number类型的null转成0
|
||||
SerializerFeature.WriteNullNumberAsZero, |
||||
// 将List类型的null转成[]
|
||||
SerializerFeature.WriteNullListAsEmpty, |
||||
// 将Boolean类型的null转成false
|
||||
SerializerFeature.WriteNullBooleanAsFalse, |
||||
// 避免循环引用
|
||||
SerializerFeature.DisableCircularReferenceDetect); |
||||
|
||||
converter.setFastJsonConfig(config); |
||||
converter.setDefaultCharset(Charset.forName("UTF-8")); |
||||
List<MediaType> mediaTypeList = new ArrayList<>(); |
||||
// 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json"
|
||||
mediaTypeList.add(MediaType.APPLICATION_JSON); |
||||
converter.setSupportedMediaTypes(mediaTypeList); |
||||
return converter; |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,208 @@ |
||||
package edu.ncst.ioreport.config; |
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import edu.ncst.ioreport.config.security.DataBaseUrlVoter; |
||||
import edu.ncst.ioreport.config.security.filter.AuthCheckFilter; |
||||
import edu.ncst.ioreport.config.security.filter.LoginFilter; |
||||
import edu.ncst.ioreport.config.security.provider.WechatIdLoginProvider; |
||||
import edu.ncst.ioreport.exception.CodeMsg; |
||||
import edu.ncst.ioreport.service.ILoginLogService; |
||||
import edu.ncst.ioreport.service.impl.UserServiceImpl; |
||||
import edu.ncst.ioreport.utils.ResultUtils; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.security.access.AccessDecisionManager; |
||||
import org.springframework.security.access.AccessDecisionVoter; |
||||
import org.springframework.security.access.vote.AuthenticatedVoter; |
||||
import org.springframework.security.access.vote.RoleVoter; |
||||
import org.springframework.security.access.vote.UnanimousBased; |
||||
import org.springframework.security.authentication.AuthenticationManager; |
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; |
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
||||
import org.springframework.security.config.http.SessionCreationPolicy; |
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
||||
import org.springframework.security.crypto.password.PasswordEncoder; |
||||
import org.springframework.security.web.access.expression.WebExpressionVoter; |
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
||||
|
||||
import java.io.PrintWriter; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 安全配置 |
||||
*/ |
||||
@Configuration |
||||
@EnableWebSecurity |
||||
@EnableGlobalMethodSecurity(securedEnabled=true) |
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter { |
||||
|
||||
@Autowired |
||||
private UserServiceImpl userService; |
||||
@Autowired |
||||
private ILoginLogService loginLogService; |
||||
@Autowired |
||||
private DataBaseUrlVoter dataBaseUrlVoter; |
||||
@Autowired |
||||
private RedisTemplate<String, String> redisCacheTemplate; |
||||
|
||||
@Autowired |
||||
private WechatIdLoginProvider wechatIdLoginProvider; |
||||
/** |
||||
* 认证失败处理类 |
||||
*/ |
||||
@Autowired |
||||
CustomAccessDeniedHandler accessDeniedHandler; |
||||
|
||||
//org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
|
||||
/** |
||||
* 解决 无法直接注入 AuthenticationManager |
||||
* |
||||
* @return |
||||
* @throws Exception |
||||
*/ |
||||
@Bean |
||||
@Override |
||||
public AuthenticationManager authenticationManagerBean() throws Exception |
||||
{ |
||||
return super.authenticationManagerBean(); |
||||
} |
||||
|
||||
/** |
||||
* 权限白名单 |
||||
* 注意:该名单下匹配的 URL 不会经过鉴权,因此也无法获取当前用户的信息 |
||||
*/ |
||||
private final String[] WHITE_LIST = { |
||||
"/v2/api-docs", |
||||
"/configuration/ui", |
||||
"/swagger-resources/**", |
||||
"/configuration/**", |
||||
"/swagger-ui.html", |
||||
"/webjars/**", |
||||
"/api/captcha.jpg", |
||||
"/websocket/**", |
||||
"/api/image/get/**", |
||||
"/common/download/**", |
||||
"/test/**", |
||||
"/*.html", |
||||
"/**/*.html", |
||||
"/**/*.css", |
||||
"/**/*.js", |
||||
"/error*" |
||||
}; |
||||
|
||||
/** |
||||
* 密码加密器 |
||||
*/ |
||||
@Bean |
||||
public PasswordEncoder passwordEncoderBean() { |
||||
return new BCryptPasswordEncoder(); |
||||
} |
||||
|
||||
/** |
||||
* 权限投票访问决策管理器 |
||||
*/ |
||||
@Bean |
||||
public AccessDecisionManager accessDecisionManager() { |
||||
List<AccessDecisionVoter<? extends Object>> decisionVoters |
||||
= Arrays.asList( |
||||
new WebExpressionVoter(), |
||||
new RoleVoter(),//主要用来判断当前请求是否具备该接口所需要的角色
|
||||
dataBaseUrlVoter, |
||||
new AuthenticatedVoter()); |
||||
return new UnanimousBased(decisionVoters);//要求所有 AccessDecisionVoter 均返回肯定的结果时,才代表授予权限。
|
||||
} |
||||
|
||||
@Override |
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth.userDetailsService(userService); |
||||
auth.authenticationProvider(wechatIdLoginProvider); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* anyRequest | 匹配所有请求路径 |
||||
* access | SpringEl表达式结果为true时可以访问 |
||||
* anonymous | 匿名可以访问 |
||||
* denyAll | 用户不能访问 |
||||
* fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录) |
||||
* hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问 |
||||
* hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问 |
||||
* hasAuthority | 如果有参数,参数表示权限,则其权限可以访问 |
||||
* hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 |
||||
* hasRole | 如果有参数,参数表示角色,则其角色可以访问 |
||||
* permitAll | 用户可以任意访问 |
||||
* rememberMe | 允许通过remember-me登录的用户访问 |
||||
* authenticated | 用户登录后可访问 |
||||
*/ |
||||
//权限验证 基于资源配置
|
||||
// HttpSecurity 及WebSecurity 作用是不一样的:
|
||||
// WebSecurity 主要针对的全局的忽略规则,
|
||||
// HttpSecurity主要是权限控制规则。
|
||||
@Override |
||||
protected void configure(HttpSecurity http) throws Exception { |
||||
|
||||
//允许跨域
|
||||
http.cors().and().anonymous().and() |
||||
// CRSF禁用,因为不使用session
|
||||
.csrf().disable() |
||||
.formLogin().disable().httpBasic().disable() |
||||
.authorizeRequests() |
||||
.accessDecisionManager(accessDecisionManager())//访问决策管理器
|
||||
.antMatchers("/api/login").permitAll() |
||||
.antMatchers("/system/init").permitAll() |
||||
// 除上面外的所有请求全部需要鉴权认证
|
||||
.anyRequest().authenticated() |
||||
.and().exceptionHandling().accessDeniedHandler(accessDeniedHandler).and() |
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); |
||||
|
||||
http.addFilterAfter(new AuthCheckFilter(redisCacheTemplate), UsernamePasswordAuthenticationFilter.class) |
||||
.addFilterAt( |
||||
new LoginFilter(authenticationManager(), loginLogService, redisCacheTemplate), UsernamePasswordAuthenticationFilter.class |
||||
) |
||||
.exceptionHandling()//登录认证失败
|
||||
.authenticationEntryPoint(((request, response, authException) -> { |
||||
response.setCharacterEncoding("utf-8"); |
||||
response.setContentType("application/json;charset=utf-8"); |
||||
|
||||
PrintWriter out = response.getWriter(); |
||||
out.write(new ObjectMapper().writeValueAsString(ResultUtils.error(CodeMsg.USER_NEED_LOGIN))); |
||||
out.flush(); |
||||
out.close(); |
||||
})); |
||||
|
||||
// 退出登录
|
||||
http.logout() |
||||
.logoutUrl("/logout") |
||||
.deleteCookies("JSESSIONID") |
||||
.logoutSuccessHandler(((request, response, authentication) -> { |
||||
PrintWriter out = response.getWriter(); |
||||
response.setContentType("application/json"); |
||||
out.write(new ObjectMapper().writeValueAsString(ResultUtils.success("注销成功"))); |
||||
out.flush(); |
||||
out.close(); |
||||
})); |
||||
} |
||||
|
||||
|
||||
// @Override
|
||||
// protected void configure(HttpSecurity httpSecurity) throws Exception{
|
||||
// //调试阶段
|
||||
// httpSecurity.csrf().disable().authorizeRequests();
|
||||
// httpSecurity.authorizeRequests().anyRequest()
|
||||
// .permitAll().and().logout().permitAll();
|
||||
// }
|
||||
|
||||
//用于配置全局的某些通用事物,例如静态资源等
|
||||
@Override |
||||
public void configure(WebSecurity web) throws Exception { |
||||
web.ignoring().antMatchers(WHITE_LIST); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,15 @@ |
||||
package edu.ncst.ioreport.config.exception; |
||||
|
||||
import org.springframework.security.core.AuthenticationException; |
||||
|
||||
public class NotBindUserException extends AuthenticationException { |
||||
|
||||
public NotBindUserException(String msg, Throwable t) { |
||||
super(msg, t); |
||||
} |
||||
|
||||
public NotBindUserException(String msg) { |
||||
super(msg); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,109 @@ |
||||
package edu.ncst.ioreport.config.security; |
||||
|
||||
import edu.ncst.ioreport.model.Role; |
||||
import edu.ncst.ioreport.service.IResourceService; |
||||
import edu.ncst.ioreport.utils.URLUtils; |
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.access.AccessDecisionVoter; |
||||
import org.springframework.security.access.ConfigAttribute; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.core.GrantedAuthority; |
||||
import org.springframework.security.web.FilterInvocation; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.util.AntPathMatcher; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* URL 鉴权投票器 |
||||
*/ |
||||
@Component |
||||
public class DataBaseUrlVoter implements AccessDecisionVoter<FilterInvocation> { |
||||
|
||||
@Autowired |
||||
private IResourceService resourceService; |
||||
|
||||
@Override |
||||
public boolean supports(ConfigAttribute attribute) { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean supports(Class<?> clazz) { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public int vote(Authentication authentication, FilterInvocation fi, Collection<ConfigAttribute> attributes) { |
||||
if (authentication == null) { |
||||
return ACCESS_DENIED; // 反对票
|
||||
} |
||||
|
||||
String url = fi.getRequestUrl(); // 当前请求的URL
|
||||
String urlWithoutQueryString = URLUtils.removeQueryString(url); |
||||
|
||||
// Current User Info
|
||||
Object details = authentication.getDetails(); |
||||
|
||||
if (details instanceof UserInfoVO) { |
||||
UserInfoVO userInfoVO = (UserInfoVO) details; |
||||
AntPathMatcher antPathMatcher = new AntPathMatcher(); |
||||
|
||||
//获取不限用户角色的资源
|
||||
List<String> permitAllResourceURLs = resourceService.getPermitAllResourceURLs(); |
||||
// Permit All Resource
|
||||
for (String permitUrl : permitAllResourceURLs) { |
||||
boolean match = antPathMatcher.match(permitUrl, urlWithoutQueryString); |
||||
if (match) { |
||||
return ACCESS_GRANTED; // 赞同票
|
||||
} |
||||
} |
||||
|
||||
// 判断用户角色信息
|
||||
// 反对票:1、没有角色信息 2、角色未绑定该资源
|
||||
// 赞成票:用户是超级管理员
|
||||
|
||||
List<String> roles = userInfoVO.getRoles(); |
||||
if (roles == null || roles.isEmpty()) { |
||||
return ACCESS_DENIED; // 反对票
|
||||
} |
||||
|
||||
List<String> roleNames = roles.stream().map(String::toString).collect(Collectors.toList()); |
||||
|
||||
// Super Admin User Always Pass
|
||||
if (roleNames.contains("SUPER_ADMIN")) { |
||||
return ACCESS_GRANTED; // 赞同票
|
||||
} |
||||
|
||||
List<String> rolesResourceList = resourceService.getRolesResourceList(roleNames);//获取目标角色绑定的资源
|
||||
|
||||
|
||||
|
||||
|
||||
// Role Resource
|
||||
if (rolesResourceList == null) { |
||||
return ACCESS_DENIED; // 反对票
|
||||
} |
||||
|
||||
for (String allowUrl : rolesResourceList) { |
||||
boolean match = antPathMatcher.match(allowUrl, urlWithoutQueryString); |
||||
if (match) { |
||||
return ACCESS_GRANTED; // 赞同票
|
||||
} |
||||
} |
||||
} |
||||
|
||||
return ACCESS_DENIED; |
||||
} |
||||
|
||||
Collection<? extends GrantedAuthority> extractAuthorities( |
||||
Authentication authentication) { |
||||
return authentication.getAuthorities(); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
@ -0,0 +1,104 @@ |
||||
package edu.ncst.ioreport.config.security.filter; |
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import edu.ncst.ioreport.config.security.token.JwtAuthenticationToken; |
||||
import edu.ncst.ioreport.exception.CodeMsg; |
||||
import edu.ncst.ioreport.model.Role; |
||||
import edu.ncst.ioreport.utils.ResponseUtils; |
||||
import edu.ncst.ioreport.utils.ResultUtils; |
||||
import edu.ncst.ioreport.vo.ResultVO; |
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import io.jsonwebtoken.Claims; |
||||
import io.jsonwebtoken.ExpiredJwtException; |
||||
import io.jsonwebtoken.Jws; |
||||
import io.jsonwebtoken.Jwts; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.security.core.GrantedAuthority; |
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority; |
||||
import org.springframework.security.core.context.SecurityContextHolder; |
||||
import org.springframework.web.filter.OncePerRequestFilter; |
||||
|
||||
import javax.servlet.FilterChain; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 用户凭证检查过滤器 |
||||
* 并不是所有的container都像我们期望的只过滤一次,servlet版本不同,表现也不同 |
||||
* OncePerRequestFilter可以保证一次请求只通过一次过滤器。推荐自定义的授权过滤器继承OncePerRequestFilter |
||||
*/ |
||||
@Slf4j |
||||
public class AuthCheckFilter extends OncePerRequestFilter { |
||||
private final RedisTemplate<String, String> stringRedisTemplate; |
||||
|
||||
public AuthCheckFilter(RedisTemplate<String, String> stringRedisTemplate) { |
||||
super(); |
||||
this.stringRedisTemplate = stringRedisTemplate; |
||||
} |
||||
@Override |
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { |
||||
String jwtToken = null; |
||||
|
||||
String authorization = request.getHeader("Authorization"); |
||||
log.info("开始鉴权====header Authorization====" +authorization); |
||||
if (authorization != null && authorization.startsWith("Bearer ")) { |
||||
jwtToken = authorization.replace("Bearer ", ""); |
||||
log.info("获取到token====header===="); |
||||
} else { |
||||
log.info("header中无token,进入过滤器链"); |
||||
filterChain.doFilter(request, response); |
||||
return; |
||||
} |
||||
|
||||
if (jwtToken == null || "".equals(jwtToken)) { |
||||
log.error("鉴权TOKEN:未获取,用户需要登录"); |
||||
ResultVO<Object> resultVO = ResultUtils.error(CodeMsg.USER_NEED_LOGIN); |
||||
ResponseUtils.output(response, resultVO); |
||||
} else { |
||||
log.info("鉴权TOKEN:" +"Bearer " + jwtToken); |
||||
} |
||||
|
||||
try { |
||||
// 解析TOKEN
|
||||
Jws<Claims> jws = Jwts.parser().setSigningKey("ncst20221003") |
||||
.parseClaimsJws(jwtToken); |
||||
|
||||
Claims claims = jws.getBody(); |
||||
String userName = claims.getSubject(); |
||||
//可以通过控制redis数据从服务端强制下线用户
|
||||
if(!stringRedisTemplate.hasKey("jwt_token:"+userName)){ |
||||
throw new ExpiredJwtException(null,jws.getBody(),"登录失效"); |
||||
} |
||||
|
||||
// 获取用户信息
|
||||
String userInfoJSON = (String) claims.get("userInfo"); |
||||
ObjectMapper objectMapper = new ObjectMapper(); |
||||
UserInfoVO userInfoVO = objectMapper.readValue(userInfoJSON, UserInfoVO.class); |
||||
|
||||
// 获取角色列表
|
||||
List<String> roles = userInfoVO.getRoles(); |
||||
List<GrantedAuthority> authorities = new ArrayList<>(); |
||||
|
||||
if (roles != null && !roles.isEmpty()) { |
||||
for (String role : roles) { |
||||
authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); |
||||
} |
||||
} |
||||
|
||||
// 将 TOKEN 存到 CONTEXT 当中
|
||||
JwtAuthenticationToken token = new JwtAuthenticationToken(userName, authorities, userInfoVO); |
||||
SecurityContextHolder.getContext().setAuthentication(token); |
||||
} catch (ExpiredJwtException e) { |
||||
ResultVO<Object> resultVO = ResultUtils.error(CodeMsg.USER_TOKEN_EXPIRED);// 用户凭证过期
|
||||
ResponseUtils.output(response, resultVO); |
||||
} finally { |
||||
filterChain.doFilter(request, response); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,208 @@ |
||||
package edu.ncst.ioreport.config.security.filter; |
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import edu.ncst.ioreport.config.security.token.WechatIdAuthenticationToken; |
||||
import edu.ncst.ioreport.exception.BusinessException; |
||||
import edu.ncst.ioreport.exception.CodeMsg; |
||||
import edu.ncst.ioreport.model.Role; |
||||
import edu.ncst.ioreport.model.User; |
||||
import edu.ncst.ioreport.service.ILoginLogService; |
||||
import edu.ncst.ioreport.utils.ResultUtils; |
||||
import edu.ncst.ioreport.vo.ResultVO; |
||||
import edu.ncst.ioreport.vo.param.UserLoginVO; |
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import io.jsonwebtoken.Jwts; |
||||
import io.jsonwebtoken.SignatureAlgorithm; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.BeanUtils; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.security.authentication.*; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.core.AuthenticationException; |
||||
import org.springframework.security.core.GrantedAuthority; |
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; |
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; |
||||
|
||||
import javax.servlet.FilterChain; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.http.Cookie; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
import java.util.Collection; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.UUID; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
/** |
||||
* 统一登录入口 |
||||
*/ |
||||
@Slf4j |
||||
public class LoginFilter extends AbstractAuthenticationProcessingFilter {//OncePerRequestFilter
|
||||
|
||||
private static final String loginUrl = "/api/login"; |
||||
|
||||
private final ILoginLogService loginLogService; |
||||
|
||||
private final RedisTemplate<String, String> stringRedisTemplate; |
||||
|
||||
private String tempToken=""; |
||||
private final int MAX_ATTEMPT = 20; |
||||
|
||||
public LoginFilter(AuthenticationManager authenticationManager, ILoginLogService loginLogService, RedisTemplate<String, String> stringRedisTemplate) { |
||||
super(new AntPathRequestMatcher(loginUrl, HttpMethod.POST.name())); |
||||
setAuthenticationManager(authenticationManager); |
||||
this.loginLogService = loginLogService; |
||||
this.stringRedisTemplate = stringRedisTemplate; |
||||
} |
||||
|
||||
/** |
||||
* 尝试登录 |
||||
* 根据登录表单的类型(type)将登录凭证分发给对应的 AuthenticationProvider |
||||
* 当前filter的认证逻辑 |
||||
*/ |
||||
@Override |
||||
public Authentication attemptAuthentication( |
||||
HttpServletRequest request, HttpServletResponse response |
||||
) throws AuthenticationException, IOException, ServletException { |
||||
UserLoginVO paramUserLoginVO = new ObjectMapper().readValue(request.getInputStream(), UserLoginVO.class); |
||||
AuthenticationManager authenticationManager = getAuthenticationManager(); |
||||
|
||||
request.setAttribute("userLoginVO", paramUserLoginVO); |
||||
log.info("尝试登录===="+ paramUserLoginVO); |
||||
|
||||
// if(paramUserLoginVO!=null&¶mUserLoginVO.getWeChatCode()!=null&¶mUserLoginVO.getWeChatCode().trim().length()>0){
|
||||
// AccessTokenDTO getAccessTokenDTO = WeChatUtils.code2session(paramUserLoginVO.getWeChatCode());
|
||||
// String weChatId = getAccessTokenDTO.getWeChatId();
|
||||
// if (weChatId != null && !"".equals(weChatId)) {
|
||||
// stringRedisTemplate.opsForValue().set("wechat_id"+weChatId,getAccessTokenDTO.getSessionKey());
|
||||
// }
|
||||
// }
|
||||
WechatIdAuthenticationToken token = new WechatIdAuthenticationToken(paramUserLoginVO.getWeChatCode()); |
||||
request.setAttribute("token", token); |
||||
return authenticationManager.authenticate(token); |
||||
} |
||||
|
||||
/** |
||||
* 登录成功 |
||||
* 无论以何种方式登录,登录成功后都向客户端返回 JWT,前端将该 JWT 临时存储到 localStorage 当中,以便后续的请求在请求头中携带 JWT。 |
||||
*/ |
||||
@Override |
||||
protected void successfulAuthentication( |
||||
HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult |
||||
) throws IOException { |
||||
Object principal = authResult.getPrincipal(); |
||||
UserInfoVO userInfoVO = new UserInfoVO(); |
||||
if (principal instanceof User) { |
||||
User user = (User) principal; |
||||
BeanUtils.copyProperties(user, userInfoVO); |
||||
} |
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper(); |
||||
String userInfoJSON = objectMapper.writeValueAsString(userInfoVO); |
||||
|
||||
UUID uuid = UUID.randomUUID(); |
||||
String jwtTokenId = uuid.toString(); |
||||
// 生成 jwt
|
||||
String jwt = Jwts.builder() |
||||
.claim("userInfo", userInfoJSON) |
||||
.setSubject(authResult.getName()) |
||||
.setExpiration(new Date(System.currentTimeMillis() + 10 * 24 * 60 * 60 * 1000)) // 10天有效
|
||||
.signWith(SignatureAlgorithm.HS512, "ncst20221003") |
||||
.setId(jwtTokenId) |
||||
.compact(); |
||||
|
||||
stringRedisTemplate.opsForValue().set("jwt_token:"+authResult.getName(),jwt,10, TimeUnit.DAYS); |
||||
// stringRedisTemplate.delete("user_attempts:"+request.getRemoteAddr());
|
||||
// 记录登录日志
|
||||
loginLogService.addLoginLog(userInfoVO.getId(), true); |
||||
|
||||
// 返回结果
|
||||
ResultVO<String> result = ResultUtils.success("登录成功", jwt); |
||||
response.setContentType("application/json;charset=utf-8"); |
||||
Cookie cookieToken = new Cookie("SYS_TOKEN", jwt); |
||||
cookieToken.setHttpOnly(true); |
||||
response.addCookie(cookieToken); |
||||
|
||||
log.info("登录成功"); |
||||
PrintWriter out = response.getWriter(); |
||||
out.print(new ObjectMapper().writeValueAsString(result)); |
||||
out.flush(); |
||||
out.close(); |
||||
} |
||||
|
||||
// 将权限列表转换成逗号分隔的字符串
|
||||
private String convertRoleToString(List<Role> roleList) { |
||||
StringBuilder roleStrings = new StringBuilder(); |
||||
|
||||
if (roleList == null) { |
||||
return ""; |
||||
} |
||||
|
||||
for (Role role : roleList) { |
||||
roleStrings.append(role.getName()).append(","); |
||||
} |
||||
|
||||
if (roleStrings.length() > 0) { |
||||
roleStrings.deleteCharAt(roleStrings.length() - 1); |
||||
} |
||||
|
||||
return roleStrings.toString(); |
||||
} |
||||
|
||||
// 将权限列表转换成逗号分隔的字符串
|
||||
private String convertAuthorityToString(Collection<? extends GrantedAuthority> authorities) { |
||||
StringBuilder authorityString = new StringBuilder(); |
||||
|
||||
for (GrantedAuthority authority : authorities) { |
||||
authorityString.append(authority.getAuthority()).append(","); |
||||
} |
||||
|
||||
if (authorityString.length() > 0) { |
||||
authorityString.deleteCharAt(authorityString.length() - 1); |
||||
} |
||||
|
||||
return authorityString.toString(); |
||||
} |
||||
|
||||
/** |
||||
* 登录失败 |
||||
* 向前端返回登录失败的错误信息 |
||||
*/ |
||||
@Override |
||||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { |
||||
ResultVO<?> resultVO; |
||||
log.debug("登录失败:"+failed); |
||||
if (failed instanceof LockedException) { |
||||
resultVO = ResultUtils.error(CodeMsg.USER_IS_LOCKED); |
||||
} else if (failed instanceof CredentialsExpiredException) { |
||||
resultVO = ResultUtils.error(CodeMsg.USER_CREDENTIALS_EXPIRED); |
||||
} else if (failed instanceof AccountExpiredException) { |
||||
resultVO = ResultUtils.error(CodeMsg.USER_ACCOUNT_EXPIRED); |
||||
} else if (failed instanceof DisabledException) { |
||||
resultVO = ResultUtils.error(CodeMsg.USER_IS_DISABLED); |
||||
} else if (failed instanceof AuthenticationException) { |
||||
Throwable cause = failed.getCause(); |
||||
if (cause instanceof BusinessException) { |
||||
BusinessException businessException = (BusinessException) cause; |
||||
resultVO = ResultUtils.error(businessException.getError()); |
||||
} else { |
||||
resultVO = ResultUtils.error(CodeMsg.USER_BAD_CREDENTIALS); |
||||
} |
||||
} else { |
||||
resultVO = ResultUtils.error(CodeMsg.LOGIN_FAIL); |
||||
} |
||||
|
||||
// 拦截后直接将错误信息反馈给前端,不经过全局异常处理器(GlobalExceptionHandler)处理
|
||||
response.setCharacterEncoding("utf-8"); |
||||
response.setContentType("application/json;charset=utf-8"); |
||||
PrintWriter out = response.getWriter(); |
||||
out.write(new ObjectMapper().writeValueAsString(resultVO)); |
||||
out.flush(); |
||||
out.close(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,60 @@ |
||||
package edu.ncst.ioreport.config.security.provider; |
||||
|
||||
|
||||
import edu.ncst.ioreport.config.exception.NotBindUserException; |
||||
import edu.ncst.ioreport.config.security.token.WechatIdAuthenticationToken; |
||||
import edu.ncst.ioreport.service.IUserService; |
||||
import edu.ncst.ioreport.utils.WeChatUtils; |
||||
import edu.ncst.ioreport.vo.SessionKey; |
||||
import lombok.SneakyThrows; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.authentication.AuthenticationProvider; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.core.AuthenticationException; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Component |
||||
@Slf4j |
||||
public class WechatIdLoginProvider implements AuthenticationProvider { |
||||
|
||||
@Autowired |
||||
private IUserService userService; |
||||
|
||||
@SneakyThrows |
||||
@Override |
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException { |
||||
log.info("进入到微信登录接口"); |
||||
// 获取 Code
|
||||
if (!(authentication instanceof WechatIdAuthenticationToken)) { |
||||
return null; |
||||
} |
||||
|
||||
WechatIdAuthenticationToken token = (WechatIdAuthenticationToken) authentication; |
||||
String code = token.getWechatCode(); |
||||
|
||||
SessionKey sessionKeyDTO = WeChatUtils.code2session(code); |
||||
|
||||
if (sessionKeyDTO == null) { |
||||
return null; |
||||
} |
||||
|
||||
String wechatId = sessionKeyDTO.getWeChatId(); |
||||
String sessionKey = sessionKeyDTO.getSessionKey(); |
||||
log.info("小程序登录成功:"+wechatId); |
||||
// 查找该 wechatID 已经绑定用户
|
||||
UserDetails userDetails = userService.loadUserByWechatId(wechatId); |
||||
|
||||
if (userDetails == null) { |
||||
throw new NotBindUserException("账号不存在"); |
||||
} else { |
||||
return new WechatIdAuthenticationToken(userDetails); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean supports(Class<?> authentication) { |
||||
return authentication.equals(WechatIdAuthenticationToken.class); |
||||
} |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
package edu.ncst.ioreport.config.security.token; |
||||
|
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import org.springframework.security.authentication.AbstractAuthenticationToken; |
||||
import org.springframework.security.core.GrantedAuthority; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* JWT认证凭证(Security Context) |
||||
*/ |
||||
public class JwtAuthenticationToken extends AbstractAuthenticationToken { |
||||
|
||||
private final Object principal; |
||||
|
||||
private final Object details; |
||||
|
||||
public JwtAuthenticationToken(Object principal, List<GrantedAuthority> authorities, UserInfoVO userInfoVO) { |
||||
super(authorities); |
||||
this.principal = principal; |
||||
this.details = userInfoVO; |
||||
this.setAuthenticated(true); |
||||
} |
||||
|
||||
@Override |
||||
public Object getCredentials() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public Object getPrincipal() { |
||||
return this.principal; |
||||
} |
||||
|
||||
@Override |
||||
public Object getDetails() { |
||||
return this.details; |
||||
} |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
package edu.ncst.ioreport.config.security.token; |
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken; |
||||
import org.springframework.security.core.GrantedAuthority; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* 手机验证码方式登录凭证 |
||||
*/ |
||||
public class MobileCaptchaAuthenticationToken extends AbstractAuthenticationToken { |
||||
|
||||
// 手机号码
|
||||
private String phoneNumber; |
||||
|
||||
// 验证码
|
||||
private String captchaCode; |
||||
|
||||
public MobileCaptchaAuthenticationToken(String phoneNumber, String captchaCode) { |
||||
super(null); |
||||
this.phoneNumber = phoneNumber; |
||||
this.captchaCode = captchaCode; |
||||
} |
||||
|
||||
public MobileCaptchaAuthenticationToken(Collection<? extends GrantedAuthority> authorities) { |
||||
super(authorities); |
||||
} |
||||
|
||||
@Override |
||||
public Object getCredentials() { |
||||
return this.phoneNumber; |
||||
} |
||||
|
||||
@Override |
||||
public Object getPrincipal() { |
||||
return this.captchaCode; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,51 @@ |
||||
package edu.ncst.ioreport.config.security.token; |
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken; |
||||
import org.springframework.security.core.GrantedAuthority; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* OpenId 登录 |
||||
*/ |
||||
public class WechatIdAuthenticationToken extends AbstractAuthenticationToken { |
||||
|
||||
private String wechatCode; |
||||
|
||||
private final Object principal; |
||||
|
||||
public WechatIdAuthenticationToken(String wechatCode) { |
||||
super(null); |
||||
this.principal = wechatCode; |
||||
this.wechatCode = wechatCode; |
||||
} |
||||
|
||||
public WechatIdAuthenticationToken(Object principal) { |
||||
super(null); |
||||
this.principal = principal; |
||||
super.setAuthenticated(true); |
||||
} |
||||
|
||||
public WechatIdAuthenticationToken(Collection<? extends GrantedAuthority> authorities) { |
||||
super(authorities); |
||||
this.principal = null; |
||||
} |
||||
|
||||
@Override |
||||
public Object getCredentials() { |
||||
return this.wechatCode; |
||||
} |
||||
|
||||
@Override |
||||
public Object getPrincipal() { |
||||
return this.principal; |
||||
} |
||||
|
||||
public String getWechatCode() { |
||||
return wechatCode; |
||||
} |
||||
|
||||
public void setWechatCode(String wechatCode) { |
||||
this.wechatCode = wechatCode; |
||||
} |
||||
} |
||||
@ -0,0 +1,132 @@ |
||||
package edu.ncst.ioreport.controller; |
||||
|
||||
|
||||
import edu.ncst.ioreport.exception.CodeMsg; |
||||
import edu.ncst.ioreport.model.Resource; |
||||
import edu.ncst.ioreport.service.IUserService; |
||||
import edu.ncst.ioreport.utils.ResponseUtils; |
||||
import edu.ncst.ioreport.utils.ResultUtils; |
||||
import edu.ncst.ioreport.vo.ResultVO; |
||||
import edu.ncst.ioreport.vo.param.QUser; |
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
@RestController |
||||
@RequestMapping("/test") |
||||
@Api(tags = "TestController") |
||||
@Slf4j |
||||
public class TestController { |
||||
|
||||
@Autowired |
||||
private IUserService userService; |
||||
|
||||
@ApiOperation("get传参,简单类型,requestParam注解") |
||||
@GetMapping("/user/detail") |
||||
@ResponseBody |
||||
public ResponseEntity getUserInfo(@RequestParam(name = "phone", required = false) String param, @RequestParam String name){ |
||||
if(param==null){ |
||||
return ResponseUtils.error(CodeMsg.PARAM_ERROR); |
||||
} |
||||
QUser queryVO = new QUser(); |
||||
queryVO.setPhone(param); |
||||
UserInfoVO user = userService.getUserInfo(queryVO); |
||||
return ResponseUtils.success(user); |
||||
} |
||||
|
||||
@ApiOperation("post传参,简单类型,requestParam注解") |
||||
@PostMapping("/user/detail00") |
||||
@ResponseBody |
||||
public ResponseEntity getUserInfo00(@RequestParam(name = "param", required = false) String param,@RequestParam String name){ |
||||
if(param==null){ |
||||
return ResponseUtils.error(CodeMsg.PARAM_ERROR); |
||||
} |
||||
QUser queryVO = new QUser(); |
||||
queryVO.setPhone(param); |
||||
UserInfoVO user = userService.getUserInfo(queryVO); |
||||
return ResponseUtils.success(user); |
||||
} |
||||
@ApiOperation("get方法传参,类接收,无注解") |
||||
@GetMapping("/user/detail1") |
||||
@ResponseBody |
||||
public UserInfoVO getUserInfo1(QUser param){ |
||||
if(param.getPhone()==null){ |
||||
String s = param.getPhone().toString(); |
||||
} |
||||
UserInfoVO user = userService.getUserInfo(param); |
||||
user.setFullName("getUserInfo1"); |
||||
return user; |
||||
} |
||||
|
||||
@ApiOperation("post方法传参,类接收,无注解") |
||||
@PostMapping("/user/detail11") |
||||
@ResponseBody |
||||
public UserInfoVO getUserInfo11(QUser param){ |
||||
if(param.getPhone()==null){ |
||||
String s = param.getPhone().toString(); |
||||
} |
||||
UserInfoVO user = userService.getUserInfo(param); |
||||
user.setFullName("getUserInfo1"); |
||||
return user; |
||||
} |
||||
|
||||
@ApiOperation("get方法传参,类接收,requestparam注解") |
||||
@GetMapping("/user/detail2") |
||||
@ResponseBody |
||||
public UserInfoVO getUserInfo2(@RequestParam QUser param){ |
||||
if(param.getPhone()==null){ |
||||
String s = param.getPhone().toString(); |
||||
} |
||||
UserInfoVO user = userService.getUserInfo(param); |
||||
user.setFullName("getUserInfo2"); |
||||
return user; |
||||
} |
||||
|
||||
@ApiOperation("post方法传参,类接收,requestparam注解") |
||||
@PostMapping("/user/detail22") |
||||
@ResponseBody |
||||
public UserInfoVO getUserInfo22(@RequestParam QUser param){ |
||||
if(param.getPhone()==null){ |
||||
String s = param.getPhone().toString(); |
||||
} |
||||
UserInfoVO user = userService.getUserInfo(param); |
||||
user.setFullName("getUserInfo22"); |
||||
return user; |
||||
} |
||||
|
||||
@ApiOperation("get方法传参,类接收,requestbody注解") |
||||
@GetMapping("/user/detail3") |
||||
@ResponseBody |
||||
public UserInfoVO getUserInfo3(@RequestBody QUser param){ |
||||
if(param.getPhone()==null){ |
||||
String s = param.getPhone().toString(); |
||||
} |
||||
UserInfoVO user = userService.getUserInfo(param); |
||||
user.setFullName("getUserInfo3"); |
||||
return user; |
||||
} |
||||
|
||||
@ApiOperation("post方法传参,类接收,requestbody注解") |
||||
@PostMapping("/user/detail4") |
||||
@ResponseBody |
||||
public UserInfoVO getUserInfo4(@RequestBody QUser param){ |
||||
if(param.getPhone()==null){ |
||||
String s = param.getPhone().toString(); |
||||
} |
||||
UserInfoVO user = userService.getUserInfo(param); |
||||
user.setFullName("getUserInfo3"); |
||||
return user; |
||||
} |
||||
|
||||
|
||||
@ApiOperation("post方法传参,类接收,requestbody注解") |
||||
@PostMapping("/user/detailResource") |
||||
@ResponseBody |
||||
public ResultVO<Resource> getUserInfoResource(@RequestBody Resource param){ |
||||
return ResultUtils.success(param); |
||||
} |
||||
} |
||||
@ -0,0 +1,56 @@ |
||||
package edu.ncst.ioreport.controller; |
||||
|
||||
|
||||
import edu.ncst.ioreport.model.User; |
||||
import edu.ncst.ioreport.service.IRoleService; |
||||
import edu.ncst.ioreport.service.IUserService; |
||||
import edu.ncst.ioreport.utils.ResponseUtils; |
||||
import edu.ncst.ioreport.utils.ResultUtils; |
||||
import edu.ncst.ioreport.vo.ListResultVO; |
||||
import edu.ncst.ioreport.vo.ResultVO; |
||||
import edu.ncst.ioreport.vo.param.CurrentUserVO; |
||||
import edu.ncst.ioreport.vo.param.QUser; |
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
; |
||||
|
||||
/** |
||||
* 用户 控制器 |
||||
*/ |
||||
@Api(description = "用户管理", tags = "UserController") |
||||
@Slf4j |
||||
@RestController |
||||
@RequestMapping("/api/user") |
||||
public class UserController { |
||||
|
||||
private final IUserService userService; |
||||
private final IRoleService roleService; |
||||
public UserController(IUserService userService, IRoleService roleService) { |
||||
this.userService = userService; |
||||
this.roleService = roleService; |
||||
} |
||||
|
||||
@ApiOperation("获取用户列表") |
||||
@GetMapping("/list") |
||||
public ResultVO<ListResultVO<User>> getUserList(QUser query) { |
||||
ListResultVO<User> userList = userService.getUserList(query); |
||||
|
||||
return ResultUtils.success("ok", userList); |
||||
} |
||||
|
||||
|
||||
@ApiOperation("获取当前用户信息") |
||||
@GetMapping("/current") |
||||
public ResultVO<UserInfoVO> getCurrentUser() { |
||||
UserInfoVO currentUserDTO = userService.getCurrentUser(); |
||||
// roleService.selectRoleAll();
|
||||
return ResultUtils.success(currentUserDTO); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,41 @@ |
||||
package edu.ncst.ioreport.exception; |
||||
|
||||
import org.springframework.security.core.AuthenticationException; |
||||
|
||||
public class BusinessException extends AuthenticationException { |
||||
|
||||
private CodeMsg codeMsg; |
||||
|
||||
public BusinessException(String msg){ |
||||
super(msg); |
||||
codeMsg = CodeMsg.BUSINESS_ERROR.fillArgs(msg); |
||||
} |
||||
|
||||
public BusinessException(CodeMsg msg){ |
||||
super(msg.getMsg()); |
||||
if(msg==null){ |
||||
msg=CodeMsg.BUSINESS_ERROR.fillArgs("未知错误"); |
||||
} |
||||
|
||||
this.codeMsg = msg; |
||||
} |
||||
public CodeMsg getError() { |
||||
if(codeMsg==null){ |
||||
codeMsg=CodeMsg.BUSINESS_ERROR.fillArgs("未知错误"); |
||||
} |
||||
return codeMsg; |
||||
} |
||||
|
||||
@Override |
||||
public String getMessage() { |
||||
if(codeMsg==null){ |
||||
String msg = super.getMessage(); |
||||
if(msg==null){ |
||||
return CodeMsg.BUSINESS_ERROR.fillArgs("未知错误").getMsg(); |
||||
} else{ |
||||
return msg; |
||||
} |
||||
} |
||||
return codeMsg.getMsg(); |
||||
} |
||||
} |
||||
@ -0,0 +1,63 @@ |
||||
package edu.ncst.ioreport.exception; |
||||
|
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class CodeMsg { |
||||
|
||||
public static final CodeMsg SUCCESS = new CodeMsg(0, "成功"); |
||||
public static final CodeMsg SUCCESS_MSG = new CodeMsg(0, "%s"); |
||||
public final static CodeMsg SERVER_ERROR = new CodeMsg(500, "服务器错误:%s"); |
||||
public static final CodeMsg PARAM_ERROR = new CodeMsg(501, "参数错误:%s"); |
||||
public static final CodeMsg GLOBAL_ERROR = new CodeMsg(502, "全局错误:%s"); |
||||
public static final CodeMsg BUSINESS_ERROR = new CodeMsg(503, "业务错误:%s");; |
||||
|
||||
public final static CodeMsg USER_NEED_LOGIN = new CodeMsg(10000, "尚未登录,请登录。"); |
||||
public final static CodeMsg USERNAME_REQUIRE_NOT_NULL = new CodeMsg(10001, "用户名不能为空"); |
||||
public final static CodeMsg PASSWORD_REQUIRE_NOT_NULL = new CodeMsg(10002, "用户密码不能为空"); |
||||
public final static CodeMsg USER_NOT_FOUND = new CodeMsg(10003, "该用户不存在。"); |
||||
public final static CodeMsg USERNAME_OR_PASSWORD_ERROR = new CodeMsg(10004, "用户名或密码错误"); |
||||
public final static CodeMsg USER_IS_LOCKED = new CodeMsg(10005, "当前IP已被锁定,请1小时后再试。"); |
||||
public final static CodeMsg USER_CREDENTIALS_EXPIRED = new CodeMsg(10006, "用户登录凭证过期,请重新登录。"); |
||||
public final static CodeMsg USER_ACCOUNT_EXPIRED = new CodeMsg(10007, "用户账号过期,请联系管理员。"); |
||||
public final static CodeMsg USER_IS_DISABLED = new CodeMsg(10008, "该用户已被禁用,请联系管理员。"); |
||||
public final static CodeMsg USER_BAD_CREDENTIALS = new CodeMsg(10009, "无效的登录凭证,请尝试重新登录"); |
||||
public final static CodeMsg USER_TOKEN_EXPIRED = new CodeMsg(10010, "用户凭证已过期,请联系管理员。"); |
||||
public final static CodeMsg NOT_GET_CURRENT_USER_INFO = new CodeMsg(10011, "无法获取当前用户信息。"); |
||||
public final static CodeMsg CAN_NOT_DATA_ACCESS = new CodeMsg(10012, "当前用户没有访问相关数据的权限。"); |
||||
public final static CodeMsg LOGIN_FAIL = new CodeMsg(10015, "登录失败,未知原因。"); |
||||
public final static CodeMsg CAPTCHA_IS_NOT_RIGHT = new CodeMsg(10018, "验证码错误。"); |
||||
public final static CodeMsg CAPTCHA_IS_EMPTY = new CodeMsg(10019, "验证码不能为空。"); |
||||
public final static CodeMsg CAPTCHA_IS_EXPIRED = new CodeMsg(10020, "验证码已过期。"); |
||||
public static final CodeMsg TEMP_TOKEN_NOT_FOUND = new CodeMsg(10021,"无法获取临时授权"); |
||||
public static final CodeMsg TEMP_TOKEN_EXPIRED = new CodeMsg(10022,"临时授权已过期"); |
||||
|
||||
/** |
||||
* 基本操作 101XX |
||||
*/ |
||||
public final static CodeMsg FETCH_ERROR = new CodeMsg(10100, "获取数据失败"); |
||||
public final static CodeMsg ADD_ERROR = new CodeMsg(10101, "添加失败%s"); |
||||
public final static CodeMsg MODIFY_ERROR = new CodeMsg(10102, "修改失败"); |
||||
public final static CodeMsg DELETE_ERROR = new CodeMsg(10103, "删除失败"); |
||||
public final static CodeMsg DELETE_ERROR_RELATION_DATA = new CodeMsg(101031, "存在关联业务数据,删除或禁用失败"); |
||||
public final static CodeMsg REPEAT_RECORD = new CodeMsg(10104, "字段与已有记录重复"); |
||||
public final static CodeMsg ENABLE_OR_DISABLE_ERROR = new CodeMsg(10105, "启用或禁用出错。"); |
||||
public final static CodeMsg CAN_FOUND_DICT = new CodeMsg(10106, "找不到字典。"); |
||||
public final static CodeMsg FORM_ERROR = new CodeMsg(10107, "表单参数错误"); |
||||
public static final CodeMsg MORE_THAN_ONE_ITEM = new CodeMsg(10108, "多余一条数据被查出"); |
||||
public static final CodeMsg ALREADY_EXIST_ITEM = new CodeMsg(10109, "数据重复"); |
||||
|
||||
|
||||
|
||||
private int code; |
||||
private String msg; |
||||
|
||||
public CodeMsg(int i, String s) { |
||||
this.code=i; |
||||
this.msg=s; |
||||
} |
||||
public CodeMsg fillArgs(Object... args) { |
||||
String message = String.format(msg, args); |
||||
return new CodeMsg(code, message); |
||||
} |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
package edu.ncst.ioreport.exception.handler; |
||||
|
||||
import edu.ncst.ioreport.exception.BusinessException; |
||||
import edu.ncst.ioreport.exception.CodeMsg; |
||||
import edu.ncst.ioreport.utils.ResponseUtils; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.web.bind.annotation.ExceptionHandler; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
import org.springframework.web.bind.annotation.RestControllerAdvice; |
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
/** |
||||
* 自定义异常处理器 |
||||
* |
||||
* @author ieflex |
||||
*/ |
||||
@RestControllerAdvice |
||||
@Slf4j |
||||
public class InterfaceExceptionHandler { |
||||
|
||||
/** |
||||
* 接口 业务异常 |
||||
*/ |
||||
@ResponseBody |
||||
@ExceptionHandler(BusinessException.class) |
||||
public ResponseEntity businessInterfaceException(BusinessException e) { |
||||
log.error(e.getMessage(), e); |
||||
return ResponseUtils.error(CodeMsg.BUSINESS_ERROR.fillArgs(e.getError())); |
||||
} |
||||
|
||||
/** |
||||
* 拦截所有运行时的全局异常 |
||||
*/ |
||||
@ExceptionHandler(RuntimeException.class) |
||||
@ResponseBody |
||||
public ResponseEntity runtimeException(RuntimeException e) { |
||||
log.error(e.getMessage(), e); |
||||
// 返回 JOSN
|
||||
return ResponseUtils.error(CodeMsg.GLOBAL_ERROR.fillArgs(e.toString())); |
||||
} |
||||
|
||||
/** |
||||
* 系统异常捕获处理 |
||||
*/ |
||||
@ExceptionHandler(Exception.class) |
||||
@ResponseBody |
||||
public ResponseEntity exception(Exception e) { |
||||
log.error(e.getMessage(), e); |
||||
return ResponseUtils.error(CodeMsg.SERVER_ERROR.fillArgs(e.toString())); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
package edu.ncst.ioreport.mapper; |
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.apache.ibatis.logging.Log; |
||||
import org.apache.ibatis.logging.LogFactory; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 自定义 Mapper 接口, 实现 自定义扩展 |
||||
* |
||||
* @param <M> mapper 泛型 |
||||
* @param <T> table 泛型 |
||||
* @param <V> vo 泛型 |
||||
* @author Lion Li |
||||
* @since 2021-05-13 |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> { |
||||
|
||||
Log log = LogFactory.getLog(BaseMapperPlus.class); |
||||
|
||||
int DEFAULT_BATCH_SIZE = 1000; |
||||
|
||||
|
||||
default List<T> selectList() { |
||||
return this.selectList(new QueryWrapper<>()); |
||||
} |
||||
|
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,9 @@ |
||||
package edu.ncst.ioreport.mapper; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import edu.ncst.ioreport.model.Resource; |
||||
import org.springframework.stereotype.Repository; |
||||
|
||||
@Repository |
||||
public interface ResourceMapper extends BaseMapper<Resource> { |
||||
} |
||||
@ -0,0 +1,25 @@ |
||||
package edu.ncst.ioreport.mapper; |
||||
|
||||
import edu.ncst.ioreport.model.Role; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 角色表 数据层 |
||||
* |
||||
* @author Lion Li |
||||
*/ |
||||
public interface RoleMapper extends BaseMapperPlus<RoleMapper, Role, Role> { |
||||
|
||||
|
||||
/** |
||||
* 根据条件分页查询角色数据 |
||||
* |
||||
* @param role 角色信息 |
||||
* @return 角色数据集合信息 |
||||
*/ |
||||
|
||||
List<Role> selectRoleList(Role role); |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,26 @@ |
||||
package edu.ncst.ioreport.mapper; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import com.baomidou.mybatisplus.core.toolkit.Constants; |
||||
import edu.ncst.ioreport.model.User; |
||||
import org.apache.ibatis.annotations.Param; |
||||
import org.springframework.stereotype.Repository; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 用户 Mapper 接口 |
||||
*/ |
||||
@Repository |
||||
|
||||
public interface UserMapper extends BaseMapper<User> { |
||||
|
||||
List<User> getUserList( @Param(Constants.WRAPPER) QueryWrapper queryWrapper); |
||||
|
||||
User getUserDetail(Integer userId); |
||||
|
||||
|
||||
User getUserByWechatId(String wechatId); |
||||
|
||||
} |
||||
@ -0,0 +1,40 @@ |
||||
package edu.ncst.ioreport.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableLogic; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
|
||||
@Data |
||||
public abstract class BaseEntity implements Serializable { |
||||
|
||||
@ApiModelProperty(value = "创建时间") |
||||
@TableField(value = "create_time", fill = FieldFill.INSERT) |
||||
private Date createTime; |
||||
|
||||
@ApiModelProperty(value = "创建人") |
||||
@TableField(value = "create_user_id", fill = FieldFill.INSERT) |
||||
private Integer createUserId; |
||||
|
||||
@ApiModelProperty(value = "最后更新时间") |
||||
@TableField(value = "last_modify_time", fill = FieldFill.INSERT_UPDATE) |
||||
private Date lastModifyTime; |
||||
|
||||
@ApiModelProperty(value = "最后更新者") |
||||
@TableField(value = "last_modify_user_id", fill = FieldFill.INSERT_UPDATE) |
||||
private Integer lastModifyUserId; |
||||
|
||||
@ApiModelProperty(value = "删除时间") |
||||
@TableField("delete_time") |
||||
@TableLogic |
||||
private Date deleteTime; |
||||
|
||||
@ApiModelProperty(value = "删除者") |
||||
@TableField("delete_user_id") |
||||
private Integer deleteUserId; |
||||
|
||||
} |
||||
@ -0,0 +1,49 @@ |
||||
package edu.ncst.ioreport.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
import lombok.EqualsAndHashCode; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 登录日志 |
||||
*/ |
||||
@ApiModel(value="LoginLog", description="登录日志") |
||||
@Data |
||||
@EqualsAndHashCode(callSuper = false) |
||||
@TableName("log_login_log") |
||||
public class LoginLog implements Serializable { |
||||
|
||||
private static final long serialVersionUID=1L; |
||||
|
||||
@ApiModelProperty(value = "ID") |
||||
@TableId(value = "id", type = IdType.AUTO) |
||||
private Integer id; |
||||
|
||||
@ApiModelProperty(value = "登录方式") |
||||
private String type; |
||||
|
||||
@ApiModelProperty(value = "用户ID") |
||||
private Integer userId; |
||||
|
||||
@ApiModelProperty(value = "登錄用户") |
||||
@TableField(exist = false) |
||||
private User user; |
||||
|
||||
@ApiModelProperty(value = "登录凭证", notes = "用户名、手机号、电子邮箱或微信登录凭证code") |
||||
private String principal; |
||||
|
||||
@ApiModelProperty(value = "IP地址") |
||||
private String ipAddress; |
||||
|
||||
@ApiModelProperty(value = "登录时间") |
||||
private Date loginTime; |
||||
|
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
package edu.ncst.ioreport.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
import lombok.EqualsAndHashCode; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.List; |
||||
|
||||
@ApiModel(value="Resource", description="资源") |
||||
@Data |
||||
@EqualsAndHashCode(callSuper = false) |
||||
@TableName("sys_resource") |
||||
public class Resource implements Serializable { |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
@ApiModelProperty(value = "资源ID") |
||||
@TableId(value = "id", type = IdType.AUTO) |
||||
private Integer id; |
||||
|
||||
@ApiModelProperty(value = "显示文本") |
||||
private String label; |
||||
|
||||
@ApiModelProperty(value = "资源名称(方法签名)") |
||||
private String name; |
||||
|
||||
@ApiModelProperty(value = "请求方法类型") |
||||
private String method; |
||||
|
||||
@ApiModelProperty(value = "链接") |
||||
private String url; |
||||
|
||||
@ApiModelProperty(value = "允许所有访问", notes = "不需要用户登录") |
||||
private Boolean permitAll = false; |
||||
|
||||
@ApiModelProperty(value = "上级菜单ID") |
||||
private Integer parentId; |
||||
|
||||
@ApiModelProperty(value = "上级菜单ID") |
||||
@TableField(exist = false) |
||||
private List<Resource> children; |
||||
|
||||
@ApiModelProperty(value = "排序") |
||||
private Integer sort; |
||||
|
||||
@ApiModelProperty(value = "是否對所有角色開放",notes = "需要用户登录") |
||||
private Boolean isForAll = true; |
||||
|
||||
} |
||||
@ -0,0 +1,58 @@ |
||||
package edu.ncst.ioreport.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableLogic; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
import lombok.EqualsAndHashCode; |
||||
|
||||
import java.util.Date; |
||||
import java.util.Objects; |
||||
|
||||
/** |
||||
* 角色 |
||||
*/ |
||||
@ApiModel(value="Role", description="角色") |
||||
@Data |
||||
@EqualsAndHashCode(callSuper = false) |
||||
@TableName("sys_role") |
||||
public class Role { |
||||
|
||||
private static final long serialVersionUID=1L; |
||||
|
||||
@ApiModelProperty(value = "角色ID") |
||||
@TableId(value = "id", type = IdType.AUTO) |
||||
private Integer id; |
||||
|
||||
@ApiModelProperty(value = "角色名称") |
||||
private String name; |
||||
|
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) return true; |
||||
|
||||
if (o == null || getClass() != o.getClass()) return false; |
||||
|
||||
Role role = (Role) o; |
||||
|
||||
return Objects.equals(name, role.name); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return Objects.hash(name); |
||||
} |
||||
|
||||
public static Role forName(String name) { |
||||
Role role = new Role(); |
||||
role.setName(name); |
||||
return role; |
||||
} |
||||
|
||||
} |
||||
|
||||
@ -0,0 +1,93 @@ |
||||
package edu.ncst.ioreport.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
import lombok.EqualsAndHashCode; |
||||
import org.springframework.security.core.GrantedAuthority; |
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
@ApiModel(value="User", description="用户") |
||||
@Data |
||||
@EqualsAndHashCode(callSuper = false) |
||||
@TableName("user") |
||||
public class User extends BaseEntity implements Serializable, UserDetails { |
||||
@ApiModelProperty(value = "用户id") |
||||
private Integer id; |
||||
@ApiModelProperty(value = "教师工号") |
||||
private String teacherID; |
||||
@ApiModelProperty(value = "用户真实名") |
||||
private String fullName; |
||||
@ApiModelProperty(value = "地址信息") |
||||
private String address; |
||||
@ApiModelProperty(value = "手机号") |
||||
private String phone; |
||||
@ApiModelProperty(value = "所属单位") |
||||
private Integer unitId; |
||||
@ApiModelProperty(value = "微信小程序id") |
||||
private Integer wechatId; |
||||
@ApiModelProperty(value = "角色列表") |
||||
@TableField(exist = false) |
||||
private List<String> roles; |
||||
@ApiModelProperty(value = "是否启用 1:启用 0:禁用") |
||||
private Boolean enable; |
||||
|
||||
|
||||
|
||||
|
||||
@Override |
||||
public Collection<? extends GrantedAuthority> getAuthorities() { |
||||
List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); |
||||
|
||||
if (this.roles != null && this.roles.size() > 0) { |
||||
List<GrantedAuthority> roleAuthority = roles.stream() |
||||
.map((role) -> new SimpleGrantedAuthority("ROLE_" + role)) |
||||
.collect(Collectors.toList()); |
||||
grantedAuthorities.addAll(roleAuthority); |
||||
} |
||||
|
||||
return grantedAuthorities; |
||||
} |
||||
|
||||
@Override |
||||
public String getPassword() { |
||||
return ""; |
||||
} |
||||
|
||||
@Override |
||||
public String getUsername() { |
||||
return teacherID; |
||||
} |
||||
|
||||
@JsonIgnore |
||||
public boolean isAccountNonExpired() { |
||||
return true; |
||||
}//用户是否未过期
|
||||
|
||||
@JsonIgnore |
||||
@Override |
||||
public boolean isAccountNonLocked() { |
||||
return true; |
||||
}//用户是否未锁定
|
||||
|
||||
@JsonIgnore |
||||
@Override |
||||
public boolean isCredentialsNonExpired() { |
||||
return true; |
||||
}//凭证是否未过期
|
||||
|
||||
@Override |
||||
public boolean isEnabled() { |
||||
return this.enable; |
||||
}//是否启用
|
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
package edu.ncst.ioreport.service; |
||||
|
||||
import edu.ncst.ioreport.model.LoginLog; |
||||
import edu.ncst.ioreport.vo.ListResultVO; |
||||
import edu.ncst.ioreport.vo.param.QLoginLog; |
||||
|
||||
/** |
||||
* 登录日志 服务类 |
||||
*/ |
||||
public interface ILoginLogService { |
||||
|
||||
// 查询登录日志列表
|
||||
ListResultVO<LoginLog> getLoginLogList(QLoginLog query); |
||||
|
||||
// 添加登录日志
|
||||
void addLoginLog(Integer userId, Boolean success); |
||||
|
||||
} |
||||
@ -0,0 +1,22 @@ |
||||
package edu.ncst.ioreport.service; |
||||
|
||||
import edu.ncst.ioreport.model.Resource; |
||||
import edu.ncst.ioreport.vo.ListResultVO; |
||||
import edu.ncst.ioreport.vo.Query; |
||||
|
||||
import java.util.List; |
||||
|
||||
public interface IResourceService { |
||||
|
||||
List<Resource> getResourceList(Query query); |
||||
|
||||
|
||||
List<Integer> getRoleResourceIds(Integer roleId); |
||||
|
||||
List<String> getRolesResourceList(List<String> roleNames); |
||||
|
||||
List<Resource> getPermitAllResourceList(); |
||||
|
||||
List<String> getPermitAllResourceURLs(); |
||||
|
||||
} |
||||
@ -0,0 +1,26 @@ |
||||
package edu.ncst.ioreport.service; |
||||
|
||||
|
||||
import edu.ncst.ioreport.model.Role; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 角色业务层 |
||||
* |
||||
*/ |
||||
public interface IRoleService { |
||||
|
||||
List<Role> insertRole() ; |
||||
|
||||
List<Role> selectRoleList(Role role); |
||||
|
||||
|
||||
/** |
||||
* 查询所有角色 |
||||
* |
||||
* @return 角色列表 |
||||
*/ |
||||
List<Role> selectRoleAll(); |
||||
|
||||
} |
||||
@ -0,0 +1,19 @@ |
||||
package edu.ncst.ioreport.service; |
||||
|
||||
import edu.ncst.ioreport.model.User; |
||||
import edu.ncst.ioreport.vo.ListResultVO; |
||||
import edu.ncst.ioreport.vo.param.CurrentUserVO; |
||||
import edu.ncst.ioreport.vo.param.QUser; |
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
|
||||
|
||||
public interface IUserService { |
||||
UserInfoVO getUserInfo(QUser query); |
||||
|
||||
ListResultVO<User> getUserList(QUser query); |
||||
|
||||
UserInfoVO getCurrentUser(); |
||||
|
||||
UserDetails loadUserByWechatId(String wechatId); |
||||
} |
||||
@ -0,0 +1,27 @@ |
||||
package edu.ncst.ioreport.service.impl; |
||||
|
||||
import edu.ncst.ioreport.model.LoginLog; |
||||
import edu.ncst.ioreport.service.ILoginLogService; |
||||
import edu.ncst.ioreport.vo.ListResultVO; |
||||
import edu.ncst.ioreport.vo.param.QLoginLog; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
/** |
||||
* 登录日志 服务实现类 |
||||
*/ |
||||
@Service |
||||
public class LoginLogServiceImpl implements ILoginLogService { |
||||
|
||||
|
||||
@Override |
||||
public ListResultVO<LoginLog> getLoginLogList(QLoginLog query) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void addLoginLog(Integer userId, Boolean success) { |
||||
|
||||
} |
||||
|
||||
//project/declarationAdd
|
||||
} |
||||
@ -0,0 +1,62 @@ |
||||
package edu.ncst.ioreport.service.impl; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
import edu.ncst.ioreport.mapper.ResourceMapper; |
||||
import edu.ncst.ioreport.model.Resource; |
||||
import edu.ncst.ioreport.service.IResourceService; |
||||
import edu.ncst.ioreport.vo.ListResultVO; |
||||
import edu.ncst.ioreport.vo.Query; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.util.*; |
||||
|
||||
@Service |
||||
public class ResourceServiceImpl implements IResourceService { |
||||
|
||||
@Autowired |
||||
private ResourceMapper resourceMapper; |
||||
|
||||
// 欲扫描的包路径
|
||||
private static final String SCAN_PACKAGE = "edu.ncst.ioreport.controller"; |
||||
|
||||
/** |
||||
* 获取资源列表 |
||||
*/ |
||||
@Override |
||||
public List<Resource> getResourceList(Query query) { |
||||
QueryWrapper<Resource> queryWrapper = new QueryWrapper<>(); |
||||
List<Resource> resources = resourceMapper.selectList(queryWrapper); |
||||
return resources; |
||||
} |
||||
|
||||
@Override |
||||
public List<Integer> getRoleResourceIds(Integer roleId) { |
||||
List<Integer> urls = new ArrayList<>(); |
||||
urls.add(1); |
||||
return urls; |
||||
} |
||||
|
||||
@Override |
||||
public List<String> getRolesResourceList(List<String> roleNames) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public List<Resource> getPermitAllResourceList() { |
||||
return null; |
||||
} |
||||
|
||||
//允许所有登录用户访问的接口列表
|
||||
@Override |
||||
public List<String> getPermitAllResourceURLs() { |
||||
List<String> urls = new ArrayList<>(); |
||||
urls.add("/api/user/current"); |
||||
urls.add("/api/records/detail"); |
||||
urls.add("/api/records/list"); |
||||
return urls; |
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
package edu.ncst.ioreport.service.impl; |
||||
|
||||
|
||||
import edu.ncst.ioreport.mapper.RoleMapper; |
||||
import edu.ncst.ioreport.model.Role; |
||||
import edu.ncst.ioreport.service.IRoleService; |
||||
import lombok.RequiredArgsConstructor; |
||||
import org.springframework.aop.framework.AopContext; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.transaction.annotation.Transactional; |
||||
|
||||
import java.util.*; |
||||
|
||||
/** |
||||
* 角色 业务层处理 |
||||
* |
||||
* @author Lion Li |
||||
*/ |
||||
@RequiredArgsConstructor |
||||
@Service |
||||
public class RoleServiceImpl implements IRoleService { |
||||
|
||||
private final RoleMapper baseMapper; |
||||
|
||||
|
||||
/** |
||||
* 根据条件分页查询角色数据 |
||||
* |
||||
* @param role 角色信息 |
||||
* @return 角色数据集合信息 |
||||
*/ |
||||
@Override |
||||
public List<Role> selectRoleList(Role role) { |
||||
return baseMapper.selectRoleList(role); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 查询所有角色 |
||||
* |
||||
* @return 角色列表 |
||||
*/ |
||||
@Override |
||||
public List<Role> selectRoleAll() { |
||||
RoleServiceImpl x = (RoleServiceImpl) AopContext.currentProxy(); |
||||
return x.selectRoleList(new Role()); |
||||
} |
||||
|
||||
@Override |
||||
@Transactional |
||||
public List<Role> insertRole() { |
||||
RoleServiceImpl x = (RoleServiceImpl) AopContext.currentProxy(); |
||||
return x.selectRoleList(new Role()); |
||||
} |
||||
} |
||||
@ -0,0 +1,78 @@ |
||||
package edu.ncst.ioreport.service.impl; |
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
import edu.ncst.ioreport.mapper.UserMapper; |
||||
import edu.ncst.ioreport.model.Role; |
||||
import edu.ncst.ioreport.model.User; |
||||
import edu.ncst.ioreport.service.IUserService; |
||||
import edu.ncst.ioreport.utils.SessionUtils; |
||||
import edu.ncst.ioreport.vo.ListResultVO; |
||||
import edu.ncst.ioreport.vo.param.CurrentUserVO; |
||||
import edu.ncst.ioreport.vo.param.QUser; |
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
import org.springframework.security.core.userdetails.UserDetailsService; |
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
@Service |
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService, UserDetailsService { |
||||
@Override |
||||
public UserInfoVO getUserInfo(QUser query) { |
||||
UserInfoVO vo = new UserInfoVO(); |
||||
vo.setTeacherID("1001"); |
||||
vo.setAddress("address 1111111"); |
||||
vo.setFullName("zhangsan"); |
||||
vo.setFullName("张三"); |
||||
return vo; |
||||
} |
||||
|
||||
@Override |
||||
public ListResultVO<User> getUserList(QUser query) { |
||||
User user = new User(); |
||||
user.setAddress("address 1111111"); |
||||
user.setTeacherID("1001"); |
||||
user.setFullName("张三"); |
||||
user.setEnable(true); |
||||
ListResultVO listResultVO = new ListResultVO(); |
||||
List list = new ArrayList<>(); |
||||
list.add(user); |
||||
listResultVO.setList(list); |
||||
return listResultVO; |
||||
} |
||||
|
||||
@Override |
||||
public UserInfoVO getCurrentUser() { |
||||
UserInfoVO user = SessionUtils.getCurrentUser(); |
||||
|
||||
return user; |
||||
} |
||||
|
||||
@Override |
||||
public UserDetails loadUserByWechatId(String wechatId) { |
||||
User user = new User(); |
||||
user.setAddress("address 1111111"); |
||||
user.setTeacherID("1001"); |
||||
user.setFullName("张三"); |
||||
List<String> roles = new ArrayList<>(); |
||||
roles.add("Admin");//Teacher;Doorman
|
||||
user.setRoles(roles); |
||||
user.setEnable(true); |
||||
return user; |
||||
} |
||||
|
||||
@Override |
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { |
||||
User user = new User(); |
||||
user.setAddress("address 1111111"); |
||||
user.setTeacherID("1001"); |
||||
user.setFullName("张三"); |
||||
List<String> roles = new ArrayList<>(); |
||||
roles.add("Admin"); |
||||
user.setEnable(true); |
||||
return user; |
||||
} |
||||
} |
||||
@ -0,0 +1,79 @@ |
||||
package edu.ncst.ioreport.utils; |
||||
|
||||
import lombok.experimental.UtilityClass; |
||||
|
||||
import java.awt.*; |
||||
import java.awt.image.BufferedImage; |
||||
import java.util.Random; |
||||
|
||||
@UtilityClass |
||||
public class CaptchaUtil { |
||||
|
||||
private int width = 200; |
||||
private int height = 50; |
||||
|
||||
public BufferedImage createImage() { |
||||
return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); |
||||
} |
||||
|
||||
public String drawRandomText(BufferedImage verifyImg) { |
||||
Graphics2D graphics = (Graphics2D) verifyImg.getGraphics(); |
||||
|
||||
graphics.setColor(Color.WHITE); |
||||
graphics.fillRect(0, 0, width, height); |
||||
Font font = new Font("Bitmap", Font.PLAIN, 54); |
||||
graphics.setFont(font); |
||||
|
||||
String baseNumLetter = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"; |
||||
StringBuilder stringBuffer = new StringBuilder(); |
||||
|
||||
int x = 10; |
||||
String ch = ""; |
||||
Random random = new Random(); |
||||
|
||||
for (int i = 0; i < 4; i++) { |
||||
graphics.setColor(getRandomColor()); |
||||
|
||||
// 设置字体旋转角度(控制小于30度)
|
||||
int degree = random.nextInt() % 30; |
||||
int dot = random.nextInt(baseNumLetter.length()); |
||||
|
||||
ch = baseNumLetter.charAt(dot) + ""; |
||||
stringBuffer.append(ch); |
||||
|
||||
// 正向旋转
|
||||
graphics.rotate(degree * Math.PI / 180, x, 45); |
||||
graphics.drawString(ch, x, 45); |
||||
|
||||
// 反向旋转
|
||||
graphics.rotate(-degree * Math.PI / 180, x, 45); |
||||
x += 48; |
||||
} |
||||
|
||||
// 绘制干扰线
|
||||
for (int i = 0; i < 6; i++) { |
||||
graphics.setColor(getRandomColor()); |
||||
graphics.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height)); |
||||
} |
||||
|
||||
// 绘制噪点
|
||||
for (int i = 0; i < 30; i++) { |
||||
int x1 = random.nextInt(width); |
||||
int y1 = random.nextInt(height); |
||||
|
||||
graphics.setColor(getRandomColor()); |
||||
graphics.fillRect(x1, y1, 2, 1); |
||||
} |
||||
|
||||
return stringBuffer.toString(); |
||||
} |
||||
|
||||
/*** |
||||
* 取随机颜色 |
||||
*/ |
||||
private Color getRandomColor() { |
||||
Random random = new Random(); |
||||
return new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
package edu.ncst.ioreport.utils; |
||||
|
||||
import javax.servlet.http.Cookie; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
|
||||
public class CookieUtils { |
||||
|
||||
/** |
||||
* 获取指定的 Cookie |
||||
*/ |
||||
public static Cookie getCookie(HttpServletRequest request, String name) { |
||||
if (name == null || "".equalsIgnoreCase(name)) { |
||||
return null; |
||||
} |
||||
|
||||
Cookie[] cookies = request.getCookies(); |
||||
|
||||
if (cookies != null) { |
||||
for (Cookie cookie : cookies) { |
||||
if (cookie.getName() != null && name.equals(cookie.getName())) { |
||||
return cookie; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,91 @@ |
||||
package edu.ncst.ioreport.utils; |
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import edu.ncst.ioreport.exception.CodeMsg; |
||||
import edu.ncst.ioreport.vo.ResultVO; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.validation.BindingResult; |
||||
import org.springframework.validation.FieldError; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
import java.io.PrintWriter; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 消息类响应工具类 |
||||
*/ |
||||
public class ResponseUtils { |
||||
|
||||
// 成功
|
||||
// 成功
|
||||
public static <T> ResponseEntity<?> success(String msg, T data) { |
||||
ResultVO<T> resultVO = new ResultVO<>(); |
||||
resultVO.setCode(0); |
||||
resultVO.setMsg(msg); |
||||
resultVO.setData(data); |
||||
|
||||
return ResponseEntity.ok(resultVO); |
||||
} |
||||
|
||||
public static ResponseEntity<?> success(Object data) { |
||||
return success("success", data); |
||||
} |
||||
|
||||
public static ResponseEntity<?> success(String msg) { |
||||
return success(msg, null); |
||||
} |
||||
|
||||
public static ResponseEntity<?> success() { |
||||
return success("success", null); |
||||
} |
||||
|
||||
// 失败
|
||||
public static <T> ResponseEntity<?> error(Integer code, String msg) { |
||||
ResultVO<T> resultVO = new ResultVO<>(); |
||||
resultVO.setCode(code); |
||||
resultVO.setMsg(msg); |
||||
return ResponseEntity.ok().body(resultVO); |
||||
} |
||||
|
||||
public static ResponseEntity<?> error(CodeMsg codeMsg) { |
||||
return error(codeMsg.getCode(), codeMsg.getMsg()); |
||||
} |
||||
|
||||
// 输出字段错误信息
|
||||
public static <T> ResponseEntity<?> fieldError(BindingResult bindingResult) { |
||||
ResultVO<T> resultVO = new ResultVO<>(); |
||||
String msg = "未知字段错误"; |
||||
|
||||
if (bindingResult.hasFieldErrors()) { |
||||
List<FieldError> fieldErrors = bindingResult.getFieldErrors(); |
||||
int count = bindingResult.getFieldErrorCount(); |
||||
|
||||
if (count > 0) { |
||||
msg = fieldErrors.get(0).getDefaultMessage(); |
||||
} |
||||
} |
||||
|
||||
resultVO.setMsg(msg); |
||||
|
||||
return ResponseEntity.ok().body(resultVO); |
||||
} |
||||
|
||||
// 调用
|
||||
public static void output(HttpServletResponse response, Object data) { |
||||
try(OutputStream out = response.getOutputStream()) { |
||||
response.setContentType("application/json;charset=utf-8"); |
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper(); |
||||
String s = objectMapper.writeValueAsString(data); |
||||
PrintWriter writer = new PrintWriter(out); |
||||
writer.print(s); |
||||
writer.flush(); |
||||
writer.close(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
package edu.ncst.ioreport.utils; |
||||
|
||||
import edu.ncst.ioreport.exception.CodeMsg; |
||||
import edu.ncst.ioreport.vo.ResultVO; |
||||
|
||||
public class ResultUtils { |
||||
|
||||
// 成功
|
||||
public static <T> ResultVO<T> success(String msg, T data) { |
||||
ResultVO<T> resultVO = new ResultVO<>(); |
||||
resultVO.setCode(0); |
||||
resultVO.setMsg(msg); |
||||
resultVO.setData(data); |
||||
|
||||
return resultVO; |
||||
} |
||||
public static <T> ResultVO<T> success(String msg) { |
||||
ResultVO<T> resultVO = new ResultVO<>(); |
||||
resultVO.setCode(0); |
||||
resultVO.setMsg(msg); |
||||
resultVO.setData(null); |
||||
|
||||
return resultVO; |
||||
} |
||||
|
||||
// 成功
|
||||
public static <T> ResultVO<T> success(T data) { |
||||
ResultVO<T> resultVO = new ResultVO<>(); |
||||
resultVO.setCode(0); |
||||
resultVO.setMsg("success"); |
||||
resultVO.setData(data); |
||||
|
||||
return resultVO; |
||||
} |
||||
// 错误
|
||||
public static <T> ResultVO<T> error(CodeMsg codeMsg) { |
||||
ResultVO<T> resultVO = new ResultVO<>(); |
||||
resultVO.setCode(codeMsg.getCode()); |
||||
resultVO.setMsg(codeMsg.getMsg()); |
||||
resultVO.setData(null); |
||||
|
||||
return resultVO; |
||||
} |
||||
|
||||
// 错误
|
||||
public static <T> ResultVO<T> error(String codeMsg) { |
||||
ResultVO<T> resultVO = new ResultVO<>(); |
||||
resultVO.setCode(500); |
||||
resultVO.setMsg(codeMsg); |
||||
resultVO.setData(null); |
||||
|
||||
return resultVO; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
package edu.ncst.ioreport.utils; |
||||
|
||||
import edu.ncst.ioreport.exception.BusinessException; |
||||
import edu.ncst.ioreport.exception.CodeMsg; |
||||
import edu.ncst.ioreport.service.IUserService; |
||||
import edu.ncst.ioreport.vo.result.UserInfoVO; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.core.context.SecurityContext; |
||||
import org.springframework.security.core.context.SecurityContextHolder; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.context.request.RequestContextHolder; |
||||
import org.springframework.web.context.request.ServletRequestAttributes; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.util.Objects; |
||||
|
||||
/** |
||||
* 会话工具类 |
||||
*/ |
||||
@Component |
||||
public class SessionUtils { |
||||
|
||||
@Autowired |
||||
private IUserService userService; |
||||
|
||||
// 获取当前用户
|
||||
public static UserInfoVO getCurrentUser() { |
||||
SecurityContext context = SecurityContextHolder.getContext(); |
||||
|
||||
if (context == null || context.getAuthentication() == null || context.getAuthentication().getDetails() == null) { |
||||
throw new BusinessException(CodeMsg.NOT_GET_CURRENT_USER_INFO); |
||||
} |
||||
|
||||
return (UserInfoVO) context.getAuthentication().getDetails(); |
||||
} |
||||
|
||||
// 获取当前用户标识
|
||||
public static Object getCurrentPrincipal() { |
||||
SecurityContext context = SecurityContextHolder.getContext(); |
||||
|
||||
return context.getAuthentication().getPrincipal(); |
||||
} |
||||
|
||||
// 获取当前 Request
|
||||
public static HttpServletRequest getRequest() { |
||||
return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); |
||||
} |
||||
|
||||
// 获取当前 Response
|
||||
public static HttpServletResponse getResponse() { |
||||
return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,25 @@ |
||||
package edu.ncst.ioreport.utils; |
||||
|
||||
import org.springframework.aop.framework.AopContext; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* spring工具类 |
||||
* |
||||
* @author Lion Li |
||||
*/ |
||||
@Component |
||||
public final class SpringUtils{ |
||||
|
||||
/** |
||||
* 获取aop代理对象 |
||||
* |
||||
* @param invoker |
||||
* @return |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public static <T> T getAopProxy(T invoker) { |
||||
return (T) AopContext.currentProxy(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,27 @@ |
||||
package edu.ncst.ioreport.utils; |
||||
|
||||
public class URLUtils { |
||||
|
||||
public static String removeQueryString(String url) { |
||||
int a = url.indexOf("?"); |
||||
int b = url.indexOf("#"); |
||||
int deleteStart = 0; |
||||
|
||||
if (a == -1 && b == -1) { |
||||
deleteStart = -1; |
||||
} else if (a != -1 && b != -1) { |
||||
deleteStart = Math.min(a, b); |
||||
} else if (a == -1) { |
||||
deleteStart = b; |
||||
} else { |
||||
deleteStart = a; |
||||
} |
||||
|
||||
if (deleteStart != -1) { |
||||
return url.substring(0, deleteStart); |
||||
} else { |
||||
return url; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,49 @@ |
||||
package edu.ncst.ioreport.utils; |
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import edu.ncst.ioreport.vo.AccessToken; |
||||
import edu.ncst.ioreport.vo.SessionKey; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.client.RestTemplate; |
||||
|
||||
@Component |
||||
public class WeChatUtils { |
||||
|
||||
private static final RestTemplate restTemplate; |
||||
|
||||
private static final String corpId = "ww17f8d10783494584"; |
||||
private static final String corpsecret = "i5t-rh8bXeNCgihcYPrG9ZPpWkivzPJ69sv570osk6I"; |
||||
|
||||
// private static final String corpId = "wwcb1e222a0708b4fc";
|
||||
// private static final String corpsecret = "uWh34kbYvxR7txvICe97mrGIuooLRfhsWi5YBPWLuAg";
|
||||
//
|
||||
static { |
||||
restTemplate = new RestTemplate(); |
||||
} |
||||
|
||||
// 根据 Code 获取 Session
|
||||
public static SessionKey code2session(String code) { |
||||
// 获取 accesstoken
|
||||
String gettoken = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpId + "&corpsecret=" + corpsecret + "&js_code=" + |
||||
code + "&grant_type=authorization_code"; |
||||
//获取Sessionid和userid
|
||||
String jscode2session = "https://qyapi.weixin.qq.com/cgi-bin/miniprogram/jscode2session?access_token=%s&js_code=%s&grant_type=authorization_code"; |
||||
|
||||
ResponseEntity<String> response = restTemplate.getForEntity(gettoken, String.class); |
||||
ObjectMapper objectMapper = new ObjectMapper(); |
||||
SessionKey session = null; |
||||
|
||||
try { |
||||
AccessToken accessToken = objectMapper.readValue(response.getBody(), AccessToken.class); |
||||
response = restTemplate.getForEntity(String.format(jscode2session, accessToken.getAccessToken(), code), String.class); |
||||
session = objectMapper.readValue(response.getBody(), SessionKey.class); |
||||
} catch (JsonProcessingException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
return session; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
package edu.ncst.ioreport.vo; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAlias; |
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class AccessToken { |
||||
@JsonAlias("access_token") |
||||
private String accessToken; |
||||
|
||||
@JsonAlias("expires_in") |
||||
private String expiresIn; |
||||
|
||||
private String errcode; |
||||
|
||||
private String errmsg; |
||||
|
||||
} |
||||
@ -0,0 +1,30 @@ |
||||
package edu.ncst.ioreport.vo; |
||||
|
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
import lombok.EqualsAndHashCode; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.List; |
||||
|
||||
@ApiModel(value = "ListResultVO", description = "分页列表数据") |
||||
@Data |
||||
@EqualsAndHashCode(callSuper = false) |
||||
public class ListResultVO<T> implements Serializable { |
||||
|
||||
private static final long serialVersionUID = -8896090499552990782L; |
||||
|
||||
@ApiModelProperty(value = "列表数据") |
||||
private List<T> list; |
||||
|
||||
@ApiModelProperty(value = "记录总数") |
||||
private Long total; |
||||
|
||||
@ApiModelProperty(value = "每页记录数") |
||||
private Long pageSize; |
||||
|
||||
@ApiModelProperty(value = "当前页码") |
||||
private Long current; |
||||
|
||||
} |
||||
@ -0,0 +1,61 @@ |
||||
package edu.ncst.ioreport.vo; |
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
import io.swagger.annotations.ApiModel; |
||||
import lombok.Data; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
@ApiModel(description = "查询参数") |
||||
@Data |
||||
public class Query implements Serializable { |
||||
|
||||
private static final long serialVersionUID = 4617734867110140874L; |
||||
|
||||
// 排序方式
|
||||
private String sorter; |
||||
|
||||
// 页码
|
||||
private Integer current = 1; |
||||
|
||||
// 每页记录数
|
||||
private Integer pageSize = 10; |
||||
|
||||
// 转换为 Pageable
|
||||
public <T> Page<T> toPageRequest() { |
||||
return new Page<>(current, pageSize); |
||||
} |
||||
|
||||
// 转换为 Sorter 对象
|
||||
public Sorter toSorter() { |
||||
if (sorter == null) { |
||||
return null; |
||||
} |
||||
|
||||
if (sorter.endsWith("_ascend")) { |
||||
String key = sorter.replace("_ascend", ""); |
||||
String column = StringUtils.camelToUnderline(key); |
||||
Sorter _sorter = new Sorter(); |
||||
|
||||
_sorter.setColumn(column); |
||||
_sorter.setKey(key); |
||||
_sorter.setIsAsc(true); |
||||
|
||||
return _sorter; |
||||
} else if (sorter.endsWith("_descend")){ |
||||
String key = sorter.replace("_descend", ""); |
||||
String column = StringUtils.camelToUnderline(key); |
||||
Sorter _sorter = new Sorter(); |
||||
|
||||
_sorter.setColumn(column); |
||||
_sorter.setKey(key); |
||||
_sorter.setIsAsc(false); |
||||
|
||||
return _sorter; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,19 @@ |
||||
package edu.ncst.ioreport.vo; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude; |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
/** |
||||
* 统一的接口返回数据格式 |
||||
*/ |
||||
@ApiModel(value = "ResultVO", description = "返回信息") |
||||
@Data |
||||
public class ResultVO<T> { |
||||
private Integer code=0; |
||||
private String msg="success"; |
||||
// 数据
|
||||
@ApiModelProperty(value = "数据", dataType = "Object",name = "data") |
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY) |
||||
private T data; |
||||
} |
||||
@ -0,0 +1,22 @@ |
||||
package edu.ncst.ioreport.vo; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAlias; |
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class SessionKey { |
||||
|
||||
@JsonAlias("userid") |
||||
private String weChatId; |
||||
|
||||
@JsonAlias("session_key") |
||||
private String sessionKey; |
||||
|
||||
private String corpid; |
||||
|
||||
private String deviceid; |
||||
|
||||
private String errcode; |
||||
|
||||
private String errmsg; |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
package edu.ncst.ioreport.vo; |
||||
|
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
|
||||
@ApiModel(description = "排序器") |
||||
@Data |
||||
public class Sorter { |
||||
|
||||
@ApiModelProperty(value = "排序关键字") |
||||
private String key; |
||||
|
||||
@ApiModelProperty(value = "是否为升序") |
||||
private Boolean isAsc = true; |
||||
|
||||
@ApiModelProperty(value = "排序列名", notes = "根据该列进行排序") |
||||
private String column; |
||||
|
||||
} |
||||
@ -0,0 +1,41 @@ |
||||
package edu.ncst.ioreport.vo.param; |
||||
|
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
|
||||
@ApiModel(description = "当前用户信息") |
||||
@Data |
||||
public class CurrentUserVO { |
||||
|
||||
@ApiModelProperty("头像链接") |
||||
private String avatar; |
||||
|
||||
@ApiModelProperty("姓名") |
||||
private String username; |
||||
|
||||
@ApiModelProperty("昵称") |
||||
private String nickname; |
||||
|
||||
@ApiModelProperty("全名") |
||||
private String fullname; |
||||
|
||||
@ApiModelProperty("角色") |
||||
private String role; |
||||
|
||||
@ApiModelProperty("头衔") |
||||
private String title; |
||||
|
||||
@ApiModelProperty("用户组") |
||||
private String group; |
||||
|
||||
@ApiModelProperty("用户ID") |
||||
private Integer userId; |
||||
|
||||
@ApiModelProperty("所在单位ID") |
||||
private Integer unitId; |
||||
|
||||
@ApiModelProperty("所在单位名称") |
||||
private Integer unitName; |
||||
|
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
package edu.ncst.ioreport.vo.param; |
||||
|
||||
import edu.ncst.ioreport.vo.Query; |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
import org.springframework.format.annotation.DateTimeFormat; |
||||
|
||||
import java.util.Date; |
||||
|
||||
@ApiModel(description = "登录日志查询对象") |
||||
@Data |
||||
public class QLoginLog extends Query { |
||||
|
||||
@ApiModelProperty(value = "关键字", notes = "用于对用户名、用户ID、用户姓名进行模糊查询") |
||||
private String keyword; |
||||
|
||||
@ApiModelProperty(value = "登录类型") |
||||
private String type; |
||||
|
||||
@ApiModelProperty(value = "开始日期") |
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
||||
private Date startTime; |
||||
|
||||
@ApiModelProperty(value = "结束日期") |
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
||||
private Date endTime; |
||||
|
||||
} |
||||
@ -0,0 +1,14 @@ |
||||
package edu.ncst.ioreport.vo.param; |
||||
|
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
@ApiModel(description = "用户信息查询") |
||||
public class QUser { |
||||
@ApiModelProperty("手机号") |
||||
private String phone; |
||||
@ApiModelProperty("姓名") |
||||
private String name; |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
package edu.ncst.ioreport.vo.param; |
||||
|
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
|
||||
@ApiModel(description = "用户登录表单") |
||||
@Data |
||||
public class UserLoginVO { |
||||
|
||||
@ApiModelProperty("微信小程序Code") |
||||
private String weChatCode; |
||||
|
||||
@ApiModelProperty("手机号") |
||||
private String phoneNumber; |
||||
|
||||
@ApiModelProperty("临时TOKEN") |
||||
private String tempToken; |
||||
|
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
package edu.ncst.ioreport.vo.result; |
||||
|
||||
import edu.ncst.ioreport.model.Role; |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
@Data |
||||
@ApiModel(description = "用户信息") |
||||
public class UserInfoVO { |
||||
@ApiModelProperty(value = "用户id") |
||||
private Integer id; |
||||
@ApiModelProperty(value = "教师工号") |
||||
private String teacherID; |
||||
@ApiModelProperty(value = "真实名") |
||||
private String fullName; |
||||
@ApiModelProperty(value = "地址信息") |
||||
private String address; |
||||
@ApiModelProperty(value = "手机号") |
||||
private String phone; |
||||
@ApiModelProperty(value = "所属单位") |
||||
private Integer unitId; |
||||
@ApiModelProperty(value = "微信id") |
||||
private String wechatID; |
||||
@ApiModelProperty(value = "角色列表") |
||||
private List<String> roles; |
||||
} |
||||
@ -0,0 +1,61 @@ |
||||
spring: |
||||
datasource: |
||||
url: jdbc:mysql://localhost:3306/iorecordsys?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai |
||||
username: smart |
||||
password: hblgjg@2020 |
||||
driver-class-name: com.mysql.cj.jdbc.Driver |
||||
hikari: |
||||
max-lifetime: 300000 |
||||
devtools: |
||||
restart: |
||||
enabled: true #设置开启热部署 |
||||
additional-paths: src/main/java #重启目录 |
||||
exclude: WEB-INF/** |
||||
application: |
||||
name: springfox-swagger |
||||
mvc: |
||||
pathmatch: |
||||
matching-strategy: ant_path_matcher |
||||
async: |
||||
request-timeout: 120000 #设置restful的api超时时间为60秒 |
||||
server: |
||||
port: 8085 |
||||
tomcat: |
||||
connection-timeout: 300000 |
||||
servlet: |
||||
encoding: |
||||
charset: utf-8 |
||||
#mybatis: |
||||
# mapper-locations: classpath:mapping/*.xml |
||||
# type-aliases-package: edu.ncst.ioreport.model |
||||
|
||||
swagger: |
||||
enable: true |
||||
title: API文档 |
||||
description: 出入校报备系统API文档 |
||||
base-package: edu.ncst.ioreport.controller |
||||
exclude-path: /error/** |
||||
termsOfServiceUrl: https://meander.net.cn |
||||
contact: |
||||
name: sage |
||||
url: www.meander.net.cn |
||||
email: sage@meander.net.cn |
||||
|
||||
logging: |
||||
config: classpath:logback.xml |
||||
level: |
||||
edu.ncst.equmanager: DEBUG |
||||
org.springframework: DEBUG |
||||
java.sql: DEBUG |
||||
# |
||||
## MyBatis Plus |
||||
mybatis-plus: |
||||
# global-config: |
||||
# db-config: |
||||
# logic-delete-field: deleteAt |
||||
# logic-delete-value: now() |
||||
# logic-not-delete-value: null |
||||
# banner: false # 关闭控制台的 LOGO |
||||
# mapper-locations: classpath*:/mapping/**/*.xml |
||||
configuration: |
||||
map-underscore-to-camel-case: false |
||||
@ -0,0 +1,57 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<configuration debug="false"> |
||||
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> |
||||
<property name="LOG_PATH" value="D:/log"/> |
||||
<!-- 定义日志格式 --> |
||||
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS,CTT} [%-5level] [%thread] [%-30.30logger{30}] %msg%n"/> |
||||
<property name="MAX_FILE_SIZE" value="10MB"/> |
||||
<property name="MAX_HISTORY" value="30"/> |
||||
<property name="CONTEXT_NAME" value="sbgl"/> |
||||
|
||||
<contextName>${CONTEXT_NAME}</contextName> |
||||
<!-- 彩色日志 --> |
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /> |
||||
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> |
||||
<!-- 控制台输出 --> |
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> |
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> |
||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> |
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS,CTT} [%thread] %-5level %logger{50} - %msg%n</pattern> |
||||
</encoder> |
||||
</appender> |
||||
<!-- 按照每天生成日志文件 --> |
||||
<!-- 控制台日志样式 --> |
||||
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS,CTT}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%15.15t]){faint} [%X{requestId}] %clr(%-40.40logger{39}){cyan} [%L] %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> |
||||
<!-- 文件日志样式 --> |
||||
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS,CTT}} ${LOG_LEVEL_PATTERN:-%5p} [%t] [%X{requestId}] %-40.40logger{39} %L : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> |
||||
|
||||
<!-- 禁用logback自身日志输出 --> |
||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener" /> |
||||
|
||||
<!-- 控制台 --> |
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> |
||||
<encoder> |
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern> |
||||
</encoder> |
||||
</appender> |
||||
|
||||
<!-- 运行日志文件 --> |
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
||||
<encoder> |
||||
<pattern>${FILE_LOG_PATTERN}</pattern> |
||||
</encoder> |
||||
<file>${LOG_PATH}/sbgl.log</file> |
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> |
||||
<fileNamePattern>${LOG_PATH}/sbgl-%d{yyyy-MM-dd}.%i.log</fileNamePattern> |
||||
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize> |
||||
<maxHistory>${MAX_HISTORY}</maxHistory> |
||||
</rollingPolicy> |
||||
</appender> |
||||
<!-- |
||||
日志输出级别 debug info error |
||||
--> |
||||
<root level="DEBUG"> |
||||
<appender-ref ref="CONSOLE"/> |
||||
<appender-ref ref="FILE"/> |
||||
</root> |
||||
</configuration> |
||||
@ -0,0 +1,13 @@ |
||||
package edu.ncst.ioreport; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
|
||||
@SpringBootTest |
||||
class IOReportApplicationTests { |
||||
|
||||
@Test |
||||
void contextLoads() { |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
/* |
||||
* Eslint config file |
||||
* Documentation: https://eslint.org/docs/user-guide/configuring/
|
||||
* Install the Eslint extension before using this feature. |
||||
*/ |
||||
module.exports = { |
||||
env: { |
||||
es6: true, |
||||
browser: true, |
||||
node: true, |
||||
}, |
||||
ecmaFeatures: { |
||||
modules: true, |
||||
}, |
||||
parserOptions: { |
||||
ecmaVersion: 2018, |
||||
sourceType: 'module', |
||||
}, |
||||
globals: { |
||||
wx: true, |
||||
App: true, |
||||
Page: true, |
||||
getCurrentPages: true, |
||||
getApp: true, |
||||
Component: true, |
||||
requirePlugin: true, |
||||
requireMiniProgram: true, |
||||
}, |
||||
// extends: 'eslint:recommended',
|
||||
rules: {}, |
||||
} |
||||
@ -0,0 +1,3 @@ |
||||
{ |
||||
"git.ignoreLimitWarning": true |
||||
} |
||||
@ -0,0 +1,13 @@ |
||||
// declare namespace API {
|
||||
// interface TableInfo<T> {
|
||||
// total: number
|
||||
// rows: Array<T>
|
||||
// code: number
|
||||
// msg: string
|
||||
// }
|
||||
// interface Result<T> {
|
||||
// msg: string,
|
||||
// data: T,
|
||||
// code: number,
|
||||
// }
|
||||
// }
|
||||
@ -0,0 +1,50 @@ |
||||
declare namespace Order { |
||||
interface submitEventDetail { |
||||
ID: string; |
||||
depart: string; |
||||
enterDate: string; |
||||
enterTime: string; |
||||
innerLocation: string; |
||||
name: string; |
||||
outerLocation: string; |
||||
phone: string; |
||||
reason: string; |
||||
orderType: string; |
||||
} |
||||
interface submitDetail { |
||||
ID: string; |
||||
depart: string; |
||||
reportDateTime: string; |
||||
innerLocation: string; |
||||
name: string; |
||||
outerLocation: string; |
||||
phone: string; |
||||
reason: string; |
||||
orderType: string; |
||||
} |
||||
interface OrderInfo { |
||||
orderType: "0" | "1" |
||||
reportDateTime: string |
||||
reportID: string |
||||
reportStatus: "0" | "1" | "2" | "3" |
||||
reviewer: string |
||||
} |
||||
interface OrderDetail extends Record<string, any> { |
||||
reportType: "0" | "1" |
||||
reportDateTime: string |
||||
reportID: string |
||||
reportStatus: "0" | "1" | "2" | "3" |
||||
reviewer: string |
||||
ID: string // 工号
|
||||
depart: string |
||||
innerLocation: string |
||||
name: string |
||||
outerLocation: string |
||||
phone: string |
||||
reason: string |
||||
auditor?: string // 审核人
|
||||
auditorDateTime?: string // 审核时间
|
||||
qrCode: string |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,113 @@ |
||||
"use strict"; |
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { |
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } |
||||
return new (P || (P = Promise))(function (resolve, reject) { |
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } |
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } |
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } |
||||
step((generator = generator.apply(thisArg, _arguments || [])).next()); |
||||
}); |
||||
}; |
||||
var __generator = (this && this.__generator) || function (thisArg, body) { |
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; |
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; |
||||
function verb(n) { return function (v) { return step([n, v]); }; } |
||||
function step(op) { |
||||
if (f) throw new TypeError("Generator is already executing."); |
||||
while (_) try { |
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; |
||||
if (y = 0, t) op = [op[0] & 2, t.value]; |
||||
switch (op[0]) { |
||||
case 0: case 1: t = op; break; |
||||
case 4: _.label++; return { value: op[1], done: false }; |
||||
case 5: _.label++; y = op[1]; op = [0]; continue; |
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue; |
||||
default: |
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } |
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } |
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } |
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } |
||||
if (t[2]) _.ops.pop(); |
||||
_.trys.pop(); continue; |
||||
} |
||||
op = body.call(thisArg, _); |
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } |
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; |
||||
} |
||||
}; |
||||
Object.defineProperty(exports, "__esModule", { value: true }); |
||||
var request_1 = require("../../utils/request"); |
||||
var BASE_URL = 'http://localhost:8080/'; |
||||
var submitOrder = function (detail) { |
||||
wx.showLoading({ title: "提交中" }); |
||||
request_1.request({ url: BASE_URL + 'api/genOrder', method: 'POST', data: detail }); |
||||
}; |
||||
var getOrderInfo = function () { return __awaiter(void 0, void 0, void 0, function () { |
||||
var res; |
||||
return __generator(this, function (_a) { |
||||
switch (_a.label) { |
||||
case 0: |
||||
wx.showLoading({ title: "加载中" }); |
||||
return [4 /*yield*/, request_1.request({ url: BASE_URL + 'api/order/list' })]; |
||||
case 1: |
||||
res = _a.sent(); |
||||
return [2 /*return*/, res.data.rows]; |
||||
} |
||||
}); |
||||
}); }; |
||||
var getOrderDetailByOrderID = function (orderID) { return __awaiter(void 0, void 0, void 0, function () { |
||||
var res; |
||||
return __generator(this, function (_a) { |
||||
switch (_a.label) { |
||||
case 0: return [4 /*yield*/, request_1.request({ url: BASE_URL + 'api/order', method: "POST", data: { orderID: orderID, } })]; |
||||
case 1: |
||||
res = _a.sent(); |
||||
return [2 /*return*/, res.data]; |
||||
} |
||||
}); |
||||
}); }; |
||||
var getOrderDetailByQrCode = function (qrCode) { return __awaiter(void 0, void 0, void 0, function () { |
||||
var res; |
||||
return __generator(this, function (_a) { |
||||
switch (_a.label) { |
||||
case 0: return [4 /*yield*/, request_1.request({ url: BASE_URL + ("api/order/" + qrCode) })]; |
||||
case 1: |
||||
res = _a.sent(); |
||||
return [2 /*return*/, res.data]; |
||||
} |
||||
}); |
||||
}); }; |
||||
var getOrderDetailFilter = function (reportType, reportStatus) { return __awaiter(void 0, void 0, void 0, function () { |
||||
var res; |
||||
return __generator(this, function (_a) { |
||||
switch (_a.label) { |
||||
case 0: return [4 /*yield*/, request_1.request({ url: BASE_URL + 'api/order/list/filter' + ("?reportType=" + (reportType || '') + "&reportStatus=" + (reportStatus || '')) })]; |
||||
case 1: |
||||
res = _a.sent(); |
||||
return [2 /*return*/, res.data.rows]; |
||||
} |
||||
}); |
||||
}); }; |
||||
var passOrder = function (orderId) { return __awaiter(void 0, void 0, void 0, function () { |
||||
var res; |
||||
return __generator(this, function (_a) { |
||||
switch (_a.label) { |
||||
case 0: return [4 /*yield*/, request_1.request({ url: BASE_URL + 'api/order/pass' + ("?orderId=" + (orderId || '')) }, { successMsg: '通过成功' })]; |
||||
case 1: |
||||
res = _a.sent(); |
||||
return [2 /*return*/, res.msg]; |
||||
} |
||||
}); |
||||
}); }; |
||||
var denyOrder = function (orderId) { return __awaiter(void 0, void 0, void 0, function () { |
||||
var res; |
||||
return __generator(this, function (_a) { |
||||
switch (_a.label) { |
||||
case 0: return [4 /*yield*/, request_1.request({ url: BASE_URL + 'api/order/deny' + ("?orderId=" + (orderId || '')) }, { successMsg: '退回成功' })]; |
||||
case 1: |
||||
res = _a.sent(); |
||||
return [2 /*return*/, res.msg]; |
||||
} |
||||
}); |
||||
}); }; |
||||
exports.default = { submitOrder: submitOrder, getOrderInfo: getOrderInfo, getOrderDetailByOrderID: getOrderDetailByOrderID, getOrderDetailFilter: getOrderDetailFilter, passOrder: passOrder, denyOrder: denyOrder, getOrderDetailByQrCode: getOrderDetailByQrCode }; |
||||
@ -0,0 +1,36 @@ |
||||
import { request } from "../../utils/request" |
||||
const BASE_URL = 'http://localhost:8080/' |
||||
const submitOrder = (detail: Order.submitDetail) => { |
||||
wx.showLoading({ title: "提交中" }) |
||||
request({ url: BASE_URL + 'api/genOrder', method: 'POST', data: detail }) |
||||
} |
||||
const getOrderInfo = async () => { |
||||
wx.showLoading({ title: "加载中" }) |
||||
const res = await request<API.Result<API.TableInfo<Order.OrderInfo>>>({ url: BASE_URL + 'api/order/list' }) |
||||
return res.data.rows; |
||||
} |
||||
const getOrderDetailByOrderID = async (orderID: string) => { |
||||
const res = await request<API.Result<Order.OrderDetail>>({ url: BASE_URL + 'api/order', method: "POST", data: { orderID, } }) |
||||
return res.data; |
||||
} |
||||
const getOrderDetailByQrCode = async (qrCode: string) => { |
||||
const res = await request<API.Result<Order.OrderDetail>>({ url: BASE_URL + `api/order/${qrCode}` }) |
||||
return res.data; |
||||
} |
||||
|
||||
const getOrderDetailFilter = async (reportType?: string, reportStatus?: string) => { |
||||
const res = await request<API.Result<API.TableInfo<API.Result<Order.OrderDetail>>>>({ url: BASE_URL + 'api/order/list/filter' + `?reportType=${reportType || ''}&reportStatus=${reportStatus || ''}` }) |
||||
return res.data.rows; |
||||
} |
||||
|
||||
const passOrder = async (orderId: string) => { |
||||
const res = await request<API.Result<never>>({ url: BASE_URL + 'api/order/pass' + `?orderId=${orderId || ''}` }, { successMsg: '通过成功' }) |
||||
return res.msg; |
||||
} |
||||
const denyOrder = async (orderId: string) => { |
||||
const res = await request<API.Result<never>>({ url: BASE_URL + 'api/order/deny' + `?orderId=${orderId || ''}` }, { successMsg: '退回成功' }) |
||||
return res.msg; |
||||
} |
||||
|
||||
|
||||
export default { submitOrder, getOrderInfo, getOrderDetailByOrderID, getOrderDetailFilter, passOrder, denyOrder, getOrderDetailByQrCode } |
||||
@ -0,0 +1,10 @@ |
||||
declare namespace User{ |
||||
|
||||
interface userInfo{ |
||||
roles:Array<string>; |
||||
ID:string;// 工号
|
||||
name: string; |
||||
phone: string;// 联系方式
|
||||
department: string; // 学院
|
||||
} |
||||
} |
||||
@ -0,0 +1,89 @@ |
||||
"use strict"; |
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { |
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } |
||||
return new (P || (P = Promise))(function (resolve, reject) { |
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } |
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } |
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } |
||||
step((generator = generator.apply(thisArg, _arguments || [])).next()); |
||||
}); |
||||
}; |
||||
var __generator = (this && this.__generator) || function (thisArg, body) { |
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; |
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; |
||||
function verb(n) { return function (v) { return step([n, v]); }; } |
||||
function step(op) { |
||||
if (f) throw new TypeError("Generator is already executing."); |
||||
while (_) try { |
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; |
||||
if (y = 0, t) op = [op[0] & 2, t.value]; |
||||
switch (op[0]) { |
||||
case 0: case 1: t = op; break; |
||||
case 4: _.label++; return { value: op[1], done: false }; |
||||
case 5: _.label++; y = op[1]; op = [0]; continue; |
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue; |
||||
default: |
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } |
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } |
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } |
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } |
||||
if (t[2]) _.ops.pop(); |
||||
_.trys.pop(); continue; |
||||
} |
||||
op = body.call(thisArg, _); |
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } |
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; |
||||
} |
||||
}; |
||||
var __importDefault = (this && this.__importDefault) || function (mod) { |
||||
return (mod && mod.__esModule) ? mod : { "default": mod }; |
||||
}; |
||||
Object.defineProperty(exports, "__esModule", { value: true }); |
||||
var constant_1 = __importDefault(require("../../utils/constant")); |
||||
var request_1 = require("../../utils/request"); |
||||
var BASE_URL = 'http://localhost:8080/'; |
||||
var qyLogin = function () { return __awaiter(void 0, void 0, void 0, function () { |
||||
return __generator(this, function (_a) { |
||||
return [2 /*return*/, new Promise(function (resolve, reject) { |
||||
return; |
||||
wx.qy.login({ |
||||
success: function (loginRes) { |
||||
resolve(loginRes); |
||||
}, |
||||
fail: function () { |
||||
wx.hideLoading(); |
||||
// 登录失败
|
||||
reject({ code: undefined }); |
||||
} |
||||
}); |
||||
})]; |
||||
}); |
||||
}); }; |
||||
var login = function () { return __awaiter(void 0, void 0, void 0, function () { |
||||
var code, token, data; |
||||
return __generator(this, function (_a) { |
||||
switch (_a.label) { |
||||
case 0: |
||||
code = ''; |
||||
if (typeof code == "undefined") { |
||||
// 登录失败
|
||||
return [2 /*return*/]; |
||||
} |
||||
return [4 /*yield*/, request_1.request({ |
||||
url: BASE_URL + 'api/login', |
||||
data: { code: code, }, |
||||
method: "POST" |
||||
})]; |
||||
case 1: |
||||
token = (_a.sent()).data.token; |
||||
wx.setStorageSync(constant_1.default.SYS_TOKEN, token); |
||||
return [4 /*yield*/, request_1.request({ url: BASE_URL + 'api/userInfo', data: token, method: "POST" })]; |
||||
case 2: |
||||
data = (_a.sent()).data; |
||||
wx.setStorageSync(constant_1.default.ROLE_LIST, data.roles); |
||||
wx.setStorageSync(constant_1.default.USER_INFO, data); |
||||
return [2 /*return*/, data]; |
||||
} |
||||
}); |
||||
}); }; |
||||
exports.default = { login: login }; |
||||
@ -0,0 +1,40 @@ |
||||
import constant from "../../utils/constant"; |
||||
import { request } from "../../utils/request"; |
||||
const BASE_URL = 'http://localhost:8080/'; |
||||
interface IqyLoginRes { |
||||
code: string, |
||||
errMsg: string, |
||||
} |
||||
const qyLogin = async () => { |
||||
return new Promise<IqyLoginRes>((resolve, reject) => { |
||||
return; |
||||
(wx as any).qy.login({ |
||||
success: (loginRes: IqyLoginRes) => { |
||||
resolve(loginRes); |
||||
}, |
||||
fail: () => { |
||||
wx.hideLoading(); |
||||
// 登录失败
|
||||
reject({ code: undefined }) |
||||
} |
||||
}); |
||||
}) |
||||
} |
||||
const login = async () => { |
||||
// const { code } = await qyLogin()
|
||||
const code = '' |
||||
if (typeof code == "undefined") { |
||||
// 登录失败
|
||||
return; |
||||
} |
||||
const { data: { token } } = await request<API.Result<{ token: string }>>({ |
||||
url: BASE_URL + 'api/login', data: { code, }, method: "POST" |
||||
}) |
||||
wx.setStorageSync(constant.SYS_TOKEN, token); |
||||
const { data } = await request<API.Result<User.userInfo>>({ url: BASE_URL + 'api/userInfo', data: token, method: "POST" }) |
||||
wx.setStorageSync(constant.ROLE_LIST, data.roles) |
||||
wx.setStorageSync(constant.USER_INFO, data) |
||||
return data; |
||||
} |
||||
|
||||
export default { login } |
||||
@ -0,0 +1,67 @@ |
||||
"use strict"; |
||||
var __importDefault = (this && this.__importDefault) || function (mod) { |
||||
return (mod && mod.__esModule) ? mod : { "default": mod }; |
||||
}; |
||||
Object.defineProperty(exports, "__esModule", { value: true }); |
||||
//TODO 门卫扫码的页面 没做
|
||||
//TODO 一堆接口
|
||||
var constant_1 = __importDefault(require("./utils/constant")); |
||||
var util_1 = require("./utils/util"); |
||||
// 路由守卫 next() 放行
|
||||
var routerBeforeEach = function (next) { |
||||
var token = wx.getStorageSync('SYS_TOKEN'); |
||||
// TODO 获取用户信息 存储
|
||||
if (token) { |
||||
// 登录成功
|
||||
next(); |
||||
return; |
||||
} |
||||
// 登录失败 的操作
|
||||
next(); |
||||
}; |
||||
var OldPage = Page; |
||||
Page = function (options) { |
||||
var oldLoad = options.onLoad; |
||||
var oldShow = options.onShow; |
||||
options.onLoad = function () { |
||||
var _this = this; |
||||
routerBeforeEach(function () { |
||||
oldLoad === null || oldLoad === void 0 ? void 0 : oldLoad.apply(_this, arguments); |
||||
}); |
||||
}; |
||||
options.onShow = function () { |
||||
var _this = this; |
||||
routerBeforeEach(function () { |
||||
oldShow === null || oldShow === void 0 ? void 0 : oldShow.apply(_this, arguments); |
||||
}); |
||||
}; |
||||
OldPage(options); |
||||
}; |
||||
// app.ts
|
||||
App({ |
||||
globalData: { |
||||
navBarHeight: 0, |
||||
menuRight: 0, |
||||
menuTop: 0, |
||||
menuHeight: 0, |
||||
}, |
||||
onLaunch: function () { |
||||
// 展示本地存储能力
|
||||
var that = this; |
||||
// 获取系统信息
|
||||
var systemInfo = wx.getSystemInfoSync(); |
||||
// 胶囊按钮位置信息
|
||||
var menuButtonInfo = wx.getMenuButtonBoundingClientRect(); |
||||
// 导航栏高度 = 状态栏高度 + 44
|
||||
that.globalData.navBarHeight = systemInfo.statusBarHeight + 44; |
||||
that.globalData.menuRight = systemInfo.screenWidth - menuButtonInfo.right; |
||||
that.globalData.menuTop = menuButtonInfo.top; |
||||
that.globalData.menuHeight = menuButtonInfo.height; |
||||
// 登录
|
||||
console.log("app.ts============"); |
||||
var userinfo = wx.getStorageSync(constant_1.default.USER_INFO); |
||||
if (!userinfo) { |
||||
util_1.wxLogin(); |
||||
} |
||||
}, |
||||
}); |
||||
@ -0,0 +1,43 @@ |
||||
{ |
||||
"pages": [ |
||||
"pages/index/index", |
||||
"pages/report/list/myReport", |
||||
"pages/report/detail/reportDetail", |
||||
"pages/logs/logs", |
||||
"pages/report/enter/enterReport", |
||||
"pages/report/out/outerReport", |
||||
"pages/audit/list/auditList", |
||||
"pages/audit/detail/index", |
||||
"pages/verfy/index", |
||||
"pages/user/info" |
||||
], |
||||
"darkmode": false, |
||||
"themeLocation": "theme.json", |
||||
"window": { |
||||
"backgroundTextStyle": "light", |
||||
"navigationBarBackgroundColor": "#fff", |
||||
"navigationStyle": "custom", |
||||
"navigationBarTitleText": "出入校报备助手", |
||||
"navigationBarTextStyle": "black" |
||||
}, |
||||
"style": "v2", |
||||
"useExtendedLib": { |
||||
"kbone": true, |
||||
"weui": true |
||||
}, |
||||
"sitemapLocation": "sitemap.json", |
||||
"usingComponents": { |
||||
"yform": "components/yform/yform", |
||||
"yinput": "components/yinput/yinput", |
||||
"yselect": "components/yselect/yselect", |
||||
"ytimePicker": "components/ypicker/timePicker/timePicker", |
||||
"ysinglePicker": "components/ypicker/singlePicker/singlePicker", |
||||
"ybutton": "components/ybutton/ybutton", |
||||
"sysFilterBar":"components/sysFilterBar/sysFilterBar", |
||||
"navigationBar": "components/navigationBar/navigationBar", |
||||
"sysCard": "./components/sysCard/sysCard", |
||||
"sysInput": "components/sysInput/sysInput", |
||||
"sysTextarea": "components/sysTextarea/sysTextarea", |
||||
"ydatePicker":"components/ypicker/datePicker/datePicker" |
||||
} |
||||
} |
||||
@ -0,0 +1,65 @@ |
||||
//TODO 门卫扫码的页面 没做
|
||||
//TODO 一堆接口
|
||||
import constant from './utils/constant'; |
||||
import {wxLogin} from './utils/util'; |
||||
|
||||
// 路由守卫 next() 放行
|
||||
const routerBeforeEach = (next: Function) => { |
||||
const token = wx.getStorageSync('SYS_TOKEN'); |
||||
// TODO 获取用户信息 存储
|
||||
|
||||
if (token) { |
||||
// 登录成功
|
||||
next() |
||||
return; |
||||
} |
||||
// 登录失败 的操作
|
||||
|
||||
next() |
||||
} |
||||
|
||||
const OldPage = Page; |
||||
Page = function (options) { |
||||
const oldLoad = options.onLoad |
||||
const oldShow = options.onShow |
||||
options.onLoad = function () { |
||||
routerBeforeEach(() => { |
||||
oldLoad?.apply(this, arguments as any) |
||||
}) |
||||
} |
||||
options.onShow = function () { |
||||
routerBeforeEach(() => { |
||||
oldShow?.apply(this, arguments as any) |
||||
}) |
||||
} |
||||
OldPage(options) |
||||
} |
||||
// app.ts
|
||||
App<IAppOption>({ |
||||
globalData: { |
||||
navBarHeight: 0, // 导航栏高度
|
||||
menuRight: 0, // 胶囊距右方间距(方保持左、右间距一致)
|
||||
menuTop: 0, // 胶囊距底部间距(保持底部间距一致)
|
||||
menuHeight: 0, // 胶囊高度(自定义内容可与胶囊高度保证一致)
|
||||
}, |
||||
onLaunch() { |
||||
// 展示本地存储能力
|
||||
const that = this; |
||||
// 获取系统信息
|
||||
const systemInfo = wx.getSystemInfoSync(); |
||||
// 胶囊按钮位置信息
|
||||
const menuButtonInfo = wx.getMenuButtonBoundingClientRect(); |
||||
// 导航栏高度 = 状态栏高度 + 44
|
||||
that.globalData.navBarHeight = systemInfo.statusBarHeight + 44; |
||||
that.globalData.menuRight = systemInfo.screenWidth - menuButtonInfo.right; |
||||
that.globalData.menuTop = menuButtonInfo.top; |
||||
that.globalData.menuHeight = menuButtonInfo.height; |
||||
// 登录
|
||||
|
||||
console.log("app.ts============") |
||||
let userinfo = wx.getStorageSync(constant.USER_INFO); |
||||
if(!userinfo){ |
||||
wxLogin(); |
||||
} |
||||
}, |
||||
}) |
||||
@ -0,0 +1,88 @@ |
||||
page { |
||||
font-family:"PingFangSC-Thin"; |
||||
font-size:small; /*微信小程序中,使用rpx做单位*/ |
||||
--color-primary: #0078D4; |
||||
--navigation-bar-color: var(--color-primary); |
||||
--color-gray-0: rgba(196, 196, 196, 0.28); |
||||
--color-border-gray-0: rgba(196, 196, 196, 0.28); |
||||
|
||||
--el-color-primary-light-3: #79bbff; |
||||
--el-color-primary-light-5: #a0cfff; |
||||
--el-color-primary-light-7: #c6e2ff; |
||||
--el-color-primary-light-8: #d9ecff; |
||||
--el-color-primary-light-9: #ecf5ff; |
||||
--el-color-primary-dark-2: #337ecc; |
||||
--el-color-success: #67c23a; |
||||
--el-color-success-light-3: #95d475; |
||||
--el-color-success-light-5: #b3e19d; |
||||
--el-color-success-light-7: #d1edc4; |
||||
--el-color-success-light-8: #e1f3d8; |
||||
--el-color-success-light-9: #f0f9eb; |
||||
--el-color-success-dark-2: #529b2e; |
||||
--el-color-warning: #e6a23c; |
||||
--el-color-warning-light-3: #eebe77; |
||||
--el-color-warning-light-5: #f3d19e; |
||||
--el-color-warning-light-7: #f8e3c5; |
||||
--el-color-warning-light-8: #faecd8; |
||||
--el-color-warning-light-9: #fdf6ec; |
||||
--el-color-warning-dark-2: #b88230; |
||||
--el-color-danger: #f56c6c; |
||||
--el-color-danger-light-3: #f89898; |
||||
--el-color-danger-light-5: #fab6b6; |
||||
--el-color-danger-light-7: #fcd3d3; |
||||
--el-color-danger-light-8: #fde2e2; |
||||
--el-color-danger-light-9: #fef0f0; |
||||
--el-color-danger-dark-2: #c45656; |
||||
--el-color-error: #f56c6c; |
||||
--el-color-error-light-3: #f89898; |
||||
--el-color-error-light-5: #fab6b6; |
||||
--el-color-error-light-7: #fcd3d3; |
||||
--el-color-error-light-8: #fde2e2; |
||||
--el-color-error-light-9: #fef0f0; |
||||
--el-color-error-dark-2: #c45656; |
||||
--el-color-info: #909399; |
||||
--el-color-info-light-3: #b1b3b8; |
||||
--el-color-info-light-5: #c8c9cc; |
||||
--el-color-info-light-7: #dedfe0; |
||||
--el-color-info-light-8: #e9e9eb; |
||||
--el-color-info-light-9: #f4f4f5; |
||||
--el-color-info-dark-2: #73767a; |
||||
--el-bg-color: #ffffff; |
||||
--el-bg-color-page: #f2f3f5; |
||||
--el-bg-color-overlay: #ffffff; |
||||
--el-text-color-primary: #303133; |
||||
--el-text-color-regular: #606266; |
||||
--el-text-color-secondary: #909399; |
||||
--el-text-color-placeholder: #a8abb2; |
||||
--el-text-color-disabled: #c0c4cc; |
||||
--el-border-color: #dcdfe6; |
||||
--el-border-color-light: #e4e7ed; |
||||
--el-border-color-lighter: #ebeef5; |
||||
--el-border-color-extra-light: #f2f6fc; |
||||
--el-border-color-dark: #d4d7de; |
||||
--el-border-color-darker: #cdd0d6; |
||||
--el-fill-color: #f0f2f5; |
||||
--el-fill-color-light: #f5f7fa; |
||||
--el-fill-color-lighter: #fafafa; |
||||
--el-fill-color-extra-light: #fafcff; |
||||
--el-fill-color-dark: #ebedf0; |
||||
--el-fill-color-darker: #e6e8eb; |
||||
--el-fill-color-blank: #ffffff; |
||||
--el-box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, .04), 0px 8px 20px rgba(0, 0, 0, .08); |
||||
--el-box-shadow-light: 0px 0px 12px rgba(0, 0, 0, .12); |
||||
--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, .12); |
||||
--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, .08), 0px 12px 32px rgba(0, 0, 0, .12), 0px 8px 16px -8px rgba(0, 0, 0, .16); |
||||
--el-disabled-bg-color: var(--el-fill-color-light); |
||||
--el-disabled-text-color: var(--el-text-color-placeholder); |
||||
--el-disabled-border-color: var(--el-border-color-light); |
||||
--el-overlay-color: rgba(0, 0, 0, .8); |
||||
--el-overlay-color-light: rgba(0, 0, 0, .7); |
||||
--el-overlay-color-lighter: rgba(0, 0, 0, .5); |
||||
--el-mask-color: rgba(255, 255, 255, .9); |
||||
--el-mask-color-extra-light: rgba(255, 255, 255, .3); |
||||
--el-border-width: 1px; |
||||
--el-border-style: solid; |
||||
--el-border-color-hover: var(--el-text-color-disabled); |
||||
--el-border: var(--el-border-width) var(--el-border-style) var(--el-border-color); |
||||
--el-svg-monochrome-grey: var(--el-border-color); |
||||
} |
||||
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 928 B |
@ -0,0 +1,30 @@ |
||||
"use strict"; |
||||
var app = getApp(); |
||||
Component({ |
||||
/** |
||||
* 组件的属性列表 |
||||
*/ |
||||
properties: { |
||||
title: String, |
||||
searchInput: Boolean, |
||||
onlyStations: Boolean, |
||||
}, |
||||
/** |
||||
* 组件的初始数据 |
||||
*/ |
||||
data: { |
||||
navBarHeight: app.globalData.navBarHeight, |
||||
menuRight: app.globalData.menuRight, |
||||
menuTop: app.globalData.menuTop - 5, |
||||
menuHeight: app.globalData.menuHeight + 10, |
||||
searchInput: false, |
||||
}, |
||||
/** |
||||
* 组件的方法列表 |
||||
*/ |
||||
methods: { |
||||
onBack: function () { |
||||
wx.navigateBack(); |
||||
} |
||||
} |
||||
}); |
||||
@ -0,0 +1,6 @@ |
||||
{ |
||||
"component": true, |
||||
"usingComponents": { |
||||
"mp-icon": "weui-miniprogram/icon/icon" |
||||
} |
||||
} |
||||
@ -0,0 +1,23 @@ |
||||
.nav-bar { |
||||
position: fixed; |
||||
width: 100%; |
||||
color: #fff; |
||||
background: var(--navigation-bar-color); |
||||
display: flex; |
||||
align-items: center; |
||||
.icon { |
||||
margin: 0 4px; |
||||
line-height: 16px; |
||||
text-align: center; |
||||
} |
||||
} |
||||
.nav-barindex{ |
||||
position: fixed; |
||||
width: 100%; |
||||
} |
||||
.navigation-title{ |
||||
font-size: 35rpx; |
||||
text-align: left; |
||||
font-weight: 900; |
||||
padding-left: 20rpx; |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
const app = getApp() |
||||
Component({ |
||||
/** |
||||
* 组件的属性列表 |
||||
*/ |
||||
properties: { |
||||
title: String, |
||||
searchInput: Boolean, |
||||
onlyStations: Boolean, |
||||
}, |
||||
|
||||
/** |
||||
* 组件的初始数据 |
||||
*/ |
||||
data: { |
||||
navBarHeight: app.globalData.navBarHeight, |
||||
menuRight: app.globalData.menuRight, |
||||
menuTop: app.globalData.menuTop - 5, |
||||
menuHeight: app.globalData.menuHeight + 10, |
||||
searchInput: false, |
||||
}, |
||||
|
||||
/** |
||||
* 组件的方法列表 |
||||
*/ |
||||
methods: { |
||||
onBack(){ |
||||
wx.navigateBack() |
||||
} |
||||
} |
||||
}) |
||||
@ -0,0 +1,10 @@ |
||||
<!-- 自定义顶部栏 --> |
||||
<view wx:if="{{!onlyStations}}" class="nav-bar" style="top:{{menuTop}}px;height:{{menuHeight}}px; min-height:{{menuHeight}}px;line-height:{{menuHeight}}px;"> |
||||
<mp-icon bindtap="onBack" class="icon" type="field" icon="back" color="white" size="{{10}}"></mp-icon> |
||||
<text class="navigation-title">{{title}}</text> |
||||
</view> |
||||
<view wx:if="{{onlyStations}}" class="nav-barindex" style="top:{{menuTop}}px;height:{{menuHeight}}px; min-height:{{menuHeight}}px;line-height:{{menuHeight}}px;"> |
||||
<text class="navigation-title">{{title}}</text> |
||||
</view> |
||||
<!-- 占位,高度与顶部栏一样 --> |
||||
<view style="height:{{navBarHeight}}px;background-color: white;"></view> |
||||
@ -0,0 +1,6 @@ |
||||
interface ISysCardClickDetail{ |
||||
reportStatus: '0' | '1' | '2' | '3', |
||||
reportType: string, |
||||
reportDateTime: string, |
||||
reviewer: string, |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
"use strict"; |
||||
var colors = { 'SCHOOL_PASS': '#DAFFA5', 'SUBMIT': '#7CE4ED', 'DEPT_PASS': '#7CE4ED', 'DENY': '#E9F0E0' }; |
||||
Component({ |
||||
// reportType: "入校报备",
|
||||
// reportDateTime: "2022-10-4 18:18:30",
|
||||
// reviewer: "张三",
|
||||
properties: { |
||||
reportStatus: String, |
||||
reportType: String, |
||||
reportDateTime: String, |
||||
reviewer: String, |
||||
}, |
||||
data: { |
||||
colors: colors, |
||||
}, |
||||
/** |
||||
* 组件的方法列表 |
||||
*/ |
||||
methods: {} |
||||
}); |
||||
@ -0,0 +1,4 @@ |
||||
{ |
||||
"component": true, |
||||
"usingComponents": {} |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue