初次提交

This commit is contained in:
qinjie 2024-10-30 10:34:26 +08:00
commit 2fd68c0efd
92 changed files with 5420 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

259
mvnw vendored Executable file
View File

@ -0,0 +1,259 @@
#!/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
#
# http://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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.2
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
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"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

149
mvnw.cmd vendored Normal file
View File

@ -0,0 +1,149 @@
<# : batch portion
@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 http://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 Apache Maven Wrapper startup batch script, version 3.3.2
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
if ($env:MAVEN_USER_HOME) {
$MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
}
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

210
pom.xml Normal file
View File

@ -0,0 +1,210 @@
<?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>3.2.8</version>
<relativePath/>
</parent>
<groupId>com.isu</groupId>
<artifactId>gasWell-watch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gasWell-watch</name>
<description>gasWell-watch</description>
<url/>
<properties>
<java.version>21</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<fastjson.version>2.0.51</fastjson.version>
<mysql.version>8.0.15</mysql.version>
<mybatis.version>3.0.3</mybatis.version>
<lombok.version>1.18.34</lombok.version>
<hutool.version>5.8.29</hutool.version>
<biaomidou.version>3.5.5</biaomidou.version>
<druid.version>1.2.20</druid.version>
<easyexcel.version>3.1.0</easyexcel.version>
<jakarta.version>6.0.0</jakarta.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<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>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>${jakarta.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel-core</artifactId>
<version>${easyexcel.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>cn.dev33</groupId>-->
<!-- <artifactId>sa-token-reactor-spring-boot3-starter</artifactId>-->
<!-- <version>1.38.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${biaomidou.version}</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
<version>1.38.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 配置文件管理 -->
<profiles>
<profile>
<id>dev</id>
<activation>
<!-- 默认启动时使用开发环境配置启动 -->
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<environment>dev</environment>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<environment>test</environment>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<environment>prod</environment>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package com.isu.gaswellwatch;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GasWellWatchApplication {
public static void main(String[] args) {
SpringApplication.run(GasWellWatchApplication.class, args);
}
}

View File

@ -0,0 +1,23 @@
package com.isu.gaswellwatch.annotation;
import com.isu.gaswellwatch.enums.LogType;
import java.lang.annotation.*;
/**
* 操作日志自定义注解
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
/**
* 日志名称
*/
String description() default "";
/**
* 日志类型
*/
LogType type() default LogType.OPERATION;
}

View File

@ -0,0 +1,189 @@
package com.isu.gaswellwatch.aspect;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.thread.threadlocal.NamedThreadLocal;
import com.isu.gaswellwatch.annotation.OperationLog;
import com.isu.gaswellwatch.config.SnowflakeConfig;
import com.isu.gaswellwatch.dto.LoginDTO;
import com.isu.gaswellwatch.dto.UserOperationRecordDTO;
import com.isu.gaswellwatch.entity.Response;
import com.isu.gaswellwatch.entity.ResponseCode;
import com.isu.gaswellwatch.entity.UserOperationRecord;
import com.isu.gaswellwatch.enums.LogResult;
import com.isu.gaswellwatch.enums.LogType;
import com.isu.gaswellwatch.service.UserOperationRecordService;
import com.isu.gaswellwatch.utils.ConverterUtil;
import com.isu.gaswellwatch.utils.IpUtils;
import com.isu.gaswellwatch.utils.ServletUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
@Slf4j
public class OperationRecordAspect {
@Autowired
private SnowflakeConfig snowflakeConfig;
@Autowired
private UserOperationRecordService userOperationRecordService;
@Autowired
private HttpServletRequest request;
private static final ThreadLocal<Date> beginTimeThreadLocal = new NamedThreadLocal<Date>("ThreadLocal beginTime");
private UserOperationRecordDTO systemLog;
@Pointcut("@annotation(com.isu.gaswellwatch.annotation.OperationLog)")
public void operationRecordPointCut() {
}
@Before("operationRecordPointCut()")
public void doBefore(JoinPoint joinPoint) throws Exception {
systemLog= new UserOperationRecordDTO();
//线程绑定变量该数据只有当前请求的线程可见
Date beginTime = new Date();
beginTimeThreadLocal.set(beginTime);
//获取注解中的description属性值
String description = getControllerMethodInfo(joinPoint).get("description").toString();
Map<String, String> headers = ServletUtils.getHeaders(request);
String menu = headers.get("menu");
if (!StringUtils.isBlank(menu)) {
systemLog.setMenu(URLDecoder.decode(menu, "utf-8"));
}
//日志标题
systemLog.setName(description);
//日志类型
systemLog.setType((Integer) getControllerMethodInfo(joinPoint).get("type"));
//日志请求url
systemLog.setUri(request.getRequestURI());
//请求方式
systemLog.setRequestType(request.getMethod());
//设置请求参数
systemLog.setRequest(StringUtils.substring(Arrays.toString(joinPoint.getArgs()), 0, 1000));
//其他属性
systemLog.setIp(IpUtils.getIpAddr(request));
systemLog.setStartTime(beginTime);
}
@Around("operationRecordPointCut()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object proceed = null;
try {
proceed = proceedingJoinPoint.proceed();
if (proceed == null) {
systemLog.setResult(LogResult.ERROR.getVal());
return proceed;
}
Response response = (Response) proceed;
int code = response.getCode();
if (code == ResponseCode.SUCCESS.code()) {
systemLog.setResult(LogResult.SUCCESS.getVal());
} else {
systemLog.setResult(LogResult.ERROR.getVal());
systemLog.setErrorMsg(StringUtils.substring(response.getMessage(), 0, 1000));
}
userOperationRecordService.addOperationRecord(ConverterUtil.convert(systemLog, UserOperationRecord.class));
} catch (Exception e) {
systemLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 1000));
systemLog.setResult(LogResult.ERROR.getVal());
//入库缓存
userOperationRecordService.addOperationRecord(ConverterUtil.convert(systemLog, UserOperationRecord.class));
throw e;
}finally {
systemLog=null;
}
return proceed;
}
@After("operationRecordPointCut()")
public void doAfter(JoinPoint joinPoint) throws Exception {
Integer type = (Integer) getControllerMethodInfo(joinPoint).get("type");
//请求开始时间
long beginTime = beginTimeThreadLocal.get().getTime();
//请求结束时间
long endTime = System.currentTimeMillis();
systemLog.setEndTime(new Date(endTime));
//请求耗时
Long logElapsedTime = endTime - beginTime;
systemLog.setCostTime(logElapsedTime.intValue());
systemLog.setId(snowflakeConfig.snowflakeId());
String loginName = "";
//用户登录获取登录名
if (type.equals(LogType.LOGIN.getVal())) {
Object[] args = joinPoint.getArgs();
if (args != null && args.length > 0) {
LoginDTO loginDTO = (LoginDTO) args[0];
loginName = loginDTO.getUsername();
}
} else {
//已登录用户从satoken获取
try {
loginName = StpUtil.getLoginIdAsString();
} catch (NotLoginException e) {
e.printStackTrace();
loginName = "用户未登录";
}
}
systemLog.setUsername(loginName);
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
*/
public static Map<String, Object> getControllerMethodInfo(JoinPoint joinPoint) throws Exception {
Map<String, Object> map = new HashMap<String, Object>(16);
//获取目标类名
String targetName = joinPoint.getTarget().getClass().getName();
//获取方法名
String methodName = joinPoint.getSignature().getName();
//获取相关参数
Object[] arguments = joinPoint.getArgs();
//生成类对象
Class targetClass = Class.forName(targetName);
//获取该类中的方法
Method[] methods = targetClass.getMethods();
String description = "";
Integer type = null;
for (Method method : methods) {
if (!method.getName().equals(methodName)) {
continue;
}
Class[] clazzs = method.getParameterTypes();
if (clazzs.length != arguments.length) {
//比较方法中参数个数与从切点中获取的参数个数是否相同原因是方法可以重载哦
continue;
}
description = method.getAnnotation(OperationLog.class).description();
type = method.getAnnotation(OperationLog.class).type().getVal();
map.put("description", description);
map.put("type", type);
}
return map;
}
}

View File

@ -0,0 +1,42 @@
package com.isu.gaswellwatch.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class AsyncLogThreadPoolConfig {
private int corePoolSize=1;
private int maxPoolSize=5;
private int queueCapacity=200;
private String threadNamePrefix="userOperationRecord-";
private int keepAliveSeconds=10;
@Bean("threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix(threadNamePrefix);
executor.setKeepAliveSeconds(keepAliveSeconds);
/*
拒绝处理策略
CallerRunsPolicy()交由调用方线程运行比如 main 线程
AbortPolicy()直接抛出异常
DiscardPolicy()直接丢弃
DiscardOldestPolicy()丢弃队列中最老的任务
*/
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
executor.initialize();
return executor;
}
}

View File

@ -0,0 +1,15 @@
package com.isu.gaswellwatch.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "interface-permission")
@Data
public class InterfacePermissionSettings {
private HashMap<String, List<String>> identifier;
}

View File

@ -0,0 +1,21 @@
package com.isu.gaswellwatch.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
/**
* 添加分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

View File

@ -0,0 +1,104 @@
package com.isu.gaswellwatch.config;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.core.collection.CollectionUtil;
import com.isu.gaswellwatch.constants.UserConstant;
import com.isu.gaswellwatch.exception.BusinessException;
import com.isu.gaswellwatch.service.UserService;
import com.isu.gaswellwatch.vo.MenuVO;
import com.isu.gaswellwatch.vo.UserLoginInfoVO;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Configuration
public class SaTokenConfigure {
@Resource
private InterfacePermissionSettings settings;
@Resource
private UserService userService;
// 注册 Sa-Token全局过滤器
@Bean
public SaServletFilter getSaServletFilter() {
return new SaServletFilter()
// 拦截地址 拦截全部path
.addInclude("/**")
// 开放地址
.addExclude("/favicon.ico")
// 鉴权方法每次访问进入
.setAuth(obj -> {
// 登录校验 -- 拦截所有路由并排除/user/doLogin 用于开放登录
SaRouter.match("/**")
.notMatch( "/user/doLogin","/user/file/files")
.check(r -> {
StpUtil.checkLogin();
checkPermission();
});
})
// 异常处理方法每次setAuth函数出现异常时进入
.setError(e -> SaResult.error(e.getMessage()))
// 前置函数在每次认证函数之前执行BeforeAuth 不受 includeList excludeList 的限制所有请求都会进入
.setBeforeAuth(obj -> {
// ---------- 设置跨域响应头 ----------
SaHolder.getResponse()
// 允许指定域访问跨域资源
.setHeader("Access-Control-Allow-Origin", "*")
// 允许所有请求方式
.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
// 有效时间
.setHeader("Access-Control-Max-Age", "3600")
// 允许的header参数
.setHeader("Access-Control-Allow-Headers", "*");
});
}
private void checkPermission() {
//先判断接口是否为限制接口
HashMap<String, List<String>> identifier = settings.getIdentifier();
String res= "";
String requestPath = SaHolder.getRequest().getRequestPath();
if(identifier == null) return;
for (Map.Entry<String, List<String>> entry : identifier.entrySet()) {
if(entry.getValue().contains(requestPath)){
res = entry.getKey();
}
}
//是限制接口才校验不是直接放行
if(StringUtils.isNotBlank(res)){
//获取token对应的菜单列表
UserLoginInfoVO userLoginInfoVO = (UserLoginInfoVO) StpUtil.getTokenSession().get(UserConstant.TOKEN_SESSION);
List<MenuVO> menuList = userService.getMenuList(userLoginInfoVO.getUserVO().getUsername());
if(CollectionUtil.isEmpty(menuList)) throw new BusinessException("未获取到用户菜单");
//判断菜单和标识是否合法
String menuId = SaHolder.getRequest().getHeader(UserConstant.HEADER_MENU_ID);
if(StringUtils.isBlank(menuId)) throw new BusinessException("未获取到请求发出所在菜单");
boolean flag = false;
for (MenuVO menuVO : menuList) {
if(menuId.equals(menuVO.getId().toString())) {
if(res.equals(menuVO.getIdentifier())){
flag = true;
break;
}
}
}
if(!flag) throw new BusinessException("该用户没有接口" + requestPath +"的权限");
}
}
}

View File

@ -0,0 +1,44 @@
package com.isu.gaswellwatch.config;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class SnowflakeConfig {
/**
* 为终端ID
*/
@Value("${snowflake.worker}")
private long workerId;
/**
* 数据中心ID
*/
@Value("${snowflake.data-center}")
private long dataCenterId;
private final Snowflake snowFlake = IdUtil.createSnowflake(workerId, dataCenterId);
@PostConstruct
public void init() {
workerId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
log.info("当前机器的workId:{}", workerId);
}
public synchronized long snowflakeId() {
return snowFlake.nextId();
}
public synchronized long snowflakeId(long workerId, long dataCenterId) {
Snowflake snowflake = IdUtil.createSnowflake(workerId, dataCenterId);
return snowflake.nextId();
}
}

View File

@ -0,0 +1,28 @@
package com.isu.gaswellwatch.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
converters.addFirst(jackson2HttpMessageConverter);
}
}

View File

@ -0,0 +1,16 @@
package com.isu.gaswellwatch.constants;
public class UserConstant {
public static final String TOKEN_SESSION = "Token-Session";
public static final String MENU_LIST_PREFIX = "gwwMenuList:";
public static final String DEFAULT_PASSWORD = "123456";
public static final String NORMAL = "1";
public static final String FORBIDDEN = "2";
public static final Long MENU_ROOT_ID = 0L;
public static final Long SUPER_ADMIN_ID = 1L;
public static final String HEADER_TOKEN_NAME = "gwwToken";
public static final String HEADER_MENU_ID = "menuId";
public static final String YES = "1";
public static final String NO = "2";
}

View File

@ -0,0 +1,111 @@
package com.isu.gaswellwatch.controller;
import com.isu.gaswellwatch.annotation.OperationLog;
import com.isu.gaswellwatch.dto.MenuDTO;
import com.isu.gaswellwatch.dto.MenuEditDTO;
import com.isu.gaswellwatch.dto.MenuSortDTO;
import com.isu.gaswellwatch.entity.Response;
import com.isu.gaswellwatch.enums.LogType;
import com.isu.gaswellwatch.service.MenuService;
import com.isu.gaswellwatch.vo.MenuListVO;
import com.isu.gaswellwatch.vo.MenuTreeVO;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("menu")
public class MenuController {
/**
* 服务对象
*/
@Resource
private MenuService menuService;
/**
* 根据角色id查菜单树
* @param roleId 角色id
* @return 返回菜单树
*/
@GetMapping("/getMenuTreeByRoleId")
public Response<List<MenuTreeVO>> getMenuTreeByRoleId(@RequestParam Long roleId){
return Response.succeed(menuService.getMenuTreeByRoleId(roleId));
}
/**
* 根据角色id查菜单列表
* @param roleId 角色id
* @return 返回菜单列表
*/
@GetMapping("/getMenuListByRoleId")
public Response<List<MenuListVO>> getMenuListByRoleId(@RequestParam Long roleId){
return Response.succeed(menuService.getMenuListByRoleId(roleId));
}
/**
* 获取所有菜单树
* @return 菜单树
*/
@GetMapping("/getMenuTree")
public Response<List<MenuTreeVO>> getMenuTree(){
return Response.succeed(menuService.getMenuTree());
}
/**
* 新增
* @param menuDTO
* @return
*/
@PostMapping("/add")
@OperationLog(description = "新增菜单",type = LogType.ADD)
public Response<String> add(@RequestBody @Valid MenuDTO menuDTO){
menuService.add(menuDTO);
return Response.succeed();
}
/**
* 编辑
* @param menuEditDTO
* @return
*/
@PostMapping("/edit")
@OperationLog(description = "修改菜单",type = LogType.UPDATE)
public Response<String> edit(@RequestBody @Valid MenuEditDTO menuEditDTO){
menuService.edit(menuEditDTO);
return Response.succeed();
}
/**
* 删除
* @param ids
* @return
*/
@PostMapping("delete")
@OperationLog(description = "删除菜单",type = LogType.DELETE)
public Response<String> delete(@RequestBody List<Long> ids){
menuService.delete(ids);
return Response.succeed();
}
/**
* 修改菜单排序
* @param menuSortDTOList
* @return
*/
@PostMapping("/editSort")
@OperationLog(description = "修改菜单排序",type = LogType.UPDATE)
public Response<String> editSort(@RequestBody @Valid List<MenuSortDTO> menuSortDTOList){
menuService.editSort(menuSortDTOList);
return Response.succeed();
}
}

View File

@ -0,0 +1,54 @@
package com.isu.gaswellwatch.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.isu.gaswellwatch.annotation.OperationLog;
import com.isu.gaswellwatch.dto.RoleDTO;
import com.isu.gaswellwatch.dto.RoleEditDTO;
import com.isu.gaswellwatch.entity.Response;
import com.isu.gaswellwatch.enums.LogType;
import com.isu.gaswellwatch.service.RoleService;
import com.isu.gaswellwatch.vo.RoleVO;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("role")
public class RoleController {
/**
* 服务对象
*/
@Resource
private RoleService roleService;
@GetMapping("/page")
public Response<Page<RoleVO>> page(@RequestParam(defaultValue = "1") Integer currentPage,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) String name){
return Response.succeed(roleService.page(currentPage,pageSize,name));
}
@PostMapping("/add")
@OperationLog(description = "新增角色",type = LogType.ADD)
public Response<String> add(@RequestBody @Valid RoleDTO roleDTO){
roleService.add(roleDTO);
return Response.succeed();
}
@PostMapping("/edit")
@OperationLog(description = "修改角色",type = LogType.UPDATE)
public Response<String> edit(@RequestBody @Valid RoleEditDTO roleEditDTO){
roleService.edit(roleEditDTO);
return Response.succeed();
}
@GetMapping("/delete")
@OperationLog(description = "删除角色",type = LogType.DELETE)
public Response<String> delete(@RequestParam Long id){
roleService.delete(id);
return Response.succeed();
}
}

View File

@ -0,0 +1,21 @@
package com.isu.gaswellwatch.controller;
import com.isu.gaswellwatch.service.RoleMenuService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("roleMenu")
public class RoleMenuController {
/**
* 服务对象
*/
@Resource
private RoleMenuService roleMenuService;
}

View File

@ -0,0 +1,114 @@
package com.isu.gaswellwatch.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.isu.gaswellwatch.annotation.OperationLog;
import com.isu.gaswellwatch.dto.LoginDTO;
import com.isu.gaswellwatch.dto.ModifyPasswordDTO;
import com.isu.gaswellwatch.dto.UserDTO;
import com.isu.gaswellwatch.dto.UserEditDTO;
import com.isu.gaswellwatch.entity.Response;
import com.isu.gaswellwatch.enums.LogType;
import com.isu.gaswellwatch.service.UserService;
import com.isu.gaswellwatch.vo.MenuTreeVO;
import com.isu.gaswellwatch.vo.UserLoginInfoVO;
import com.isu.gaswellwatch.vo.UserVO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("user")
public class UserController {
/**
* 服务对象
*/
@Resource
private UserService userService;
@PostMapping("/doLogin")
@OperationLog(description = "用户登录",type = LogType.LOGIN)
public Response<UserLoginInfoVO> doLogin(@RequestBody @Valid LoginDTO loginDTO){
return Response.succeed(userService.doLogin(loginDTO));
}
@GetMapping("/getMenuTreeByToken")
public Response<List<MenuTreeVO>> getMenuTreeByToken(){
return Response.succeed(userService.getMenuTreeByToken());
}
@GetMapping("/logout")
@OperationLog(description = "用户注销",type = LogType.LOGOUT)
public Response<String> logout(){
userService.logout();
return Response.succeed();
}
@PostMapping("/modifyPassword")
public Response<String> modifyPassword(@RequestBody @Valid ModifyPasswordDTO modifyPasswordDTO){
userService.modifyPassword(modifyPasswordDTO);
return Response.succeed();
}
@GetMapping("/page")
public Response<Page<UserVO>> page(@RequestParam(defaultValue = "1") Integer currentPage ,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) String username,
@RequestParam(required = false) String name,
@RequestParam(required = false) Long roleId,
@RequestParam(required = false) String isEnable){
return Response.succeed(userService.page(currentPage,pageSize,username,name,roleId,isEnable));
}
@PostMapping("/add")
@OperationLog(description = "新增用户",type = LogType.ADD)
public Response<String> add(@RequestBody @Valid UserDTO userDTO){
userService.add(userDTO);
return Response.succeed();
}
@GetMapping("/setEnable")
public Response<String> setEnable(@RequestParam Long userId, @RequestParam String isEnable){
userService.setEnable(userId,isEnable);
return Response.succeed();
}
@PostMapping("/edit")
@OperationLog(description = "编辑用户",type = LogType.UPDATE)
public Response<String> edit(@RequestBody @Valid UserEditDTO userEditDTO){
userService.edit(userEditDTO);
return Response.succeed();
}
@GetMapping("/delete")
@OperationLog(description = "删除用户",type = LogType.DELETE)
public Response<String> delete(@RequestParam Long id){
userService.delete(id);
return Response.succeed();
}
@OperationLog(description = "重置密码",type = LogType.UPDATE)
@GetMapping("/reset")
public Response<String> reset(@RequestParam Long id){
userService.reset(id);
return Response.succeed("重置密码成功重置为123456");
}
@GetMapping("/export")
public void export(HttpServletResponse response,
@RequestParam(required = false) String username,
@RequestParam(required = false) String name,
@RequestParam(required = false) Long roleId,
@RequestParam(required = false) String isEnable) {
userService.export(response,username, name, roleId,isEnable);
}
}

View File

@ -0,0 +1,50 @@
package com.isu.gaswellwatch.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.isu.gaswellwatch.annotation.OperationLog;
import com.isu.gaswellwatch.entity.Response;
import com.isu.gaswellwatch.enums.LogType;
import com.isu.gaswellwatch.service.UserOperationRecordService;
import com.isu.gaswellwatch.vo.UserOperationRecordVO;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("userOperationRecord")
public class UserOperationRecordController {
/**
* 服务对象
*/
@Autowired
private UserOperationRecordService operationRecordService;
@GetMapping("/page")
public Response<Page<UserOperationRecordVO>> page(@RequestParam Integer currentPage,
@RequestParam Integer pageSize,
@RequestParam(required = false) Integer type,
@RequestParam(required = false) String username,
@RequestParam(required = false) String nickname,
@RequestParam(required = false) Integer result,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime) {
return Response.succeed(operationRecordService.page(currentPage, pageSize, type, username, nickname, result, startTime, endTime));
}
@GetMapping("/export")
@OperationLog(description = "日志导出",type = LogType.EXPORT)
public void export(HttpServletResponse response,
@RequestParam(required = false) Integer type,
@RequestParam(required = false) String username,
@RequestParam(required = false) String nickname,
@RequestParam(required = false) Integer result,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime) {
operationRecordService.export(response,type, username, nickname, result, startTime, endTime);
}
}

View File

@ -0,0 +1,21 @@
package com.isu.gaswellwatch.controller;
import com.isu.gaswellwatch.service.UserRoleService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("userRole")
public class UserRoleController {
/**
* 服务对象
*/
@Resource
private UserRoleService userRoleService;
}

View File

@ -0,0 +1,19 @@
package com.isu.gaswellwatch.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.isu.gaswellwatch.entity.Menu;
import com.isu.gaswellwatch.vo.MenuVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface MenuDao extends BaseMapper<Menu> {
List<MenuVO> selectRoleMenu(@Param("ids") List<Long> ids);
}

View File

@ -0,0 +1,13 @@
package com.isu.gaswellwatch.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.isu.gaswellwatch.entity.Role;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface RoleDao extends BaseMapper<Role> {
}

View File

@ -0,0 +1,13 @@
package com.isu.gaswellwatch.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.isu.gaswellwatch.entity.RoleMenu;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface RoleMenuDao extends BaseMapper<RoleMenu> {
}

View File

@ -0,0 +1,34 @@
package com.isu.gaswellwatch.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.isu.gaswellwatch.entity.User;
import com.isu.gaswellwatch.vo.UserVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserDao extends BaseMapper<User> {
Page<UserVO> page(Page<Object> page,
@Param("username") String username,
@Param("name") String name,
@Param("ids") List<Long> ids,
@Param("isEnable") String isEnable
);
List<UserVO> list(@Param("username") String username,
@Param("name") String name,
@Param("roleId") Long roleId,
@Param("isEnable") String isEnable
);
UserVO selectUserInfo(@Param("username") String username);
}

View File

@ -0,0 +1,30 @@
package com.isu.gaswellwatch.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.isu.gaswellwatch.entity.UserOperationRecord;
import com.isu.gaswellwatch.vo.UserOperationRecordVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserOperationRecordDao extends BaseMapper<UserOperationRecord> {
Page<UserOperationRecordVO> page(Page<Object> page,
@Param("type") Integer type,
@Param("username") String username,
@Param("nickname")String nickname,
@Param("result")Integer result,
@Param("startTime")String startTime,
@Param("endTime") String endTime);
List<UserOperationRecordVO> list(@Param("type") Integer type,
@Param("username") String username,
@Param("nickname")String nickname,
@Param("result")Integer result,
@Param("startTime")String startTime,
@Param("endTime") String endTime);
}

View File

@ -0,0 +1,13 @@
package com.isu.gaswellwatch.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.isu.gaswellwatch.entity.UserOperationRecord;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface UserOperationRecordMapper extends BaseMapper<UserOperationRecord> {
}

View File

@ -0,0 +1,13 @@
package com.isu.gaswellwatch.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.isu.gaswellwatch.entity.UserRole;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface UserRoleDao extends BaseMapper<UserRole> {
}

View File

@ -0,0 +1,18 @@
package com.isu.gaswellwatch.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class LoginDTO {
@NotBlank(message = "账号不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
}

View File

@ -0,0 +1,33 @@
package com.isu.gaswellwatch.dto;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MenuDTO {
//父节点
@NotNull(message = "父节点不能为空")
private Long parent;
//名称
@NotNull(message = "名称不能为空")
private String name;
//编码
private String code;
//图标
private String icon;
//顺序
private Integer sort;
//外部数据
private String extra;
private List<String> identifier;
}

View File

@ -0,0 +1,22 @@
package com.isu.gaswellwatch.dto;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MenuEditDTO {
@NotNull(message = "id不能为空")
private Long id;
@NotNull(message = "名称不能为空")
private String name;
private String extra;
}

View File

@ -0,0 +1,26 @@
package com.isu.gaswellwatch.dto;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MenuSortDTO {
@NotNull(message = "id不能为空")
private Long id;
private Long parent;
@NotNull(message = "顺序不能为空")
private Integer sort;
private List<Long> ancestors;
}

View File

@ -0,0 +1,23 @@
package com.isu.gaswellwatch.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ModifyPasswordDTO {
@NotBlank(message = "旧密码不能为空!")
private String oldPassword;
@NotBlank(message = "新密码不能为空!")
private String newPassword;
@NotBlank(message = "确认新密码不能为空!")
private String newPasswordConfirm;
}

View File

@ -0,0 +1,25 @@
package com.isu.gaswellwatch.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RoleDTO {
//名称
@NotBlank(message = "名称不能为空")
private String name;
//描述
private String description;
@NotNull(message = "角色菜单不能为空")
private List<RoleMenuDTO> roleMenuDTOList;
}

View File

@ -0,0 +1,27 @@
package com.isu.gaswellwatch.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RoleEditDTO {
@NotNull(message = "id不能为空")
private Long id;
//名称
@NotBlank(message = "名称不能为空")
private String name;
//描述
private String description;
@NotNull(message = "角色菜单不能为空")
private List<RoleMenuDTO> roleMenuDTOList;
}

View File

@ -0,0 +1,17 @@
package com.isu.gaswellwatch.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RoleMenuDTO {
private Long menuId;
private List<String> identifier;
}

View File

@ -0,0 +1,33 @@
package com.isu.gaswellwatch.dto;
import com.isu.gaswellwatch.vo.RoleVO;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {
//账户
@NotBlank(message = "账号不能为空")
@Pattern(regexp = "^(.*[a-zA-Z].*)\\d*$", message = "账号输入必须为纯字母或字母数字组合")
private String username;
//昵称
@NotBlank(message = "姓名不能为空")
private String nickname;
//手机号
private String phone;
//是否启用
private String isEnable;
@NotNull(message = "角色不能为空")
private List<RoleVO> roles;
}

View File

@ -0,0 +1,35 @@
package com.isu.gaswellwatch.dto;
import com.isu.gaswellwatch.vo.RoleVO;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserEditDTO {
@NotNull(message = "id不能为空")
private Long id;
//账户
@NotBlank(message = "账号不能为空")
@Pattern(regexp = "^(.*[a-zA-Z].*)\\d*$", message = "输入必须为纯字母或字母数字组合")
private String username;
//昵称
@NotBlank(message = "使用者不能为空")
private String nickname;
//手机号
private String phone;
//是否启用
private String isEnable;
@NotNull(message = "角色不能为空")
private List<RoleVO> roles;
}

View File

@ -0,0 +1,84 @@
package com.isu.gaswellwatch.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserOperationRecordDTO {
private Long id;
/**
* 日志类型
*/
private Integer type;
/**
* 用户名
*/
private String username;
/**
* 请求地址
*/
private String uri;
/**
* 菜单
*/
private String menu;
/**
* 请求参数
*/
private String request;
/**
* 请求类型
*/
private String requestType;
/**
* 请求结果
*/
private Integer result;
/**
* 登录ip
*/
private String ip;
/**
* 日志标题
*/
private String name;
/**
* 开始时间
*/
private Date startTime;
/**
* 错误消息
*/
private String errorMsg;
/**
* 结束时间
*/
private Date endTime;
/**
* 请求时间
*/
private long costTime;
}

View File

@ -0,0 +1,37 @@
package com.isu.gaswellwatch.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
public class Menu extends Model<Menu> {
private Long id;
//父节点
private Long parent;
//名称
private String name;
//编码
private String code;
//图标
private String icon;
//顺序
private Integer sort;
//外部数据
private String extra;
//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
//更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@ -0,0 +1,79 @@
package com.isu.gaswellwatch.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Response<T> implements Serializable {
private int code = ResponseCode.SUCCESS.code();
private String message = ResponseCode.SUCCESS.message();
private T data;
public static <T> Response<T> succeed() {
return Response.<T>builder().code(ResponseCode.SUCCESS.code()).message(ResponseCode.SUCCESS.message()).build();
}
public static <T> Response<T> succeed(String message) {
return Response.<T>builder().code(ResponseCode.SUCCESS.code()).message(message).build();
}
public static <T> Response<T> succeed(T t) {
return Response.<T>builder().code(ResponseCode.SUCCESS.code()).message(ResponseCode.SUCCESS.message()).data(t)
.build();
}
public static <T> Response<T> succeed(String message, T t) {
return Response.<T>builder().code(ResponseCode.SUCCESS.code()).message(message).data(t)
.build();
}
public static <T> Response<T> succeed(ResponseCode responseCode) {
return Response.<T>builder().code(responseCode.code()).message(responseCode.message()).build();
}
public static <T> Response<T> succeed(ResponseCode responseCode, T t) {
return Response.<T>builder().code(responseCode.code()).message(responseCode.message()).data(t)
.build();
}
public static <T> Response<T> failed() {
return Response.<T>builder().code(ResponseCode.FAILURE.code()).message(ResponseCode.FAILURE.message()).build();
}
public static <T> Response<T> failed(String message) {
return Response.<T>builder().code(ResponseCode.FAILURE.code()).message(message).build();
}
public static <T> Response<T> failed(int code, String message) {
return Response.<T>builder().code(code).message(message).build();
}
public static <T> Response<T> failed(ResponseCode responseCode) {
return Response.<T>builder().code(responseCode.code()).message(responseCode.message()).build();
}
public static <T> Response<T> failed(ResponseCode responseCode, T t) {
return Response.<T>builder().code(responseCode.code()).message(responseCode.message()).data(t).build();
}
public static <T> Response<T> failed(T t) {
return Response.<T>builder().code(ResponseCode.FAILURE.code()).message(ResponseCode.FAILURE.message()).data(t)
.build();
}
public static <T> Response<T> define(int code, T t) {
return Response.<T>builder().code(code).message(ResponseCode.SUCCESS.message()).data(t).build();
}
public static <T> Response<T> define(int code, String message, T t) {
return Response.<T>builder().code(code).message(message).data(t).build();
}
}

View File

@ -0,0 +1,51 @@
package com.isu.gaswellwatch.entity;
public enum ResponseCode {
SUCCESS(200, "操作成功"),
FAILURE(400, "操作失败"),
/**
* 参数错误代码
*/
PARAM_IS_INVALID(1001, "参数无效"),
PARAM_IS_BLANK(1002, "参数为空"),
PARAM_TYPE_BIND_ERROR(1003, "参数类型错误"),
PARAM_NOT_COMPLETE(1004, "参数缺失"),
PARAM_ERROR(1004, "参数错误"),
/**
* 用户错误代码
*/
USER_NOT_LOGIN_IN(2001, "手机号未登录"),
USER_LOGIN_ERROR(2002, "账号或密码输入有误"),
USER_ACCOUNT_FORBIDDEN(2003, "手机号被冻结"),
USER_NOT_EXIST(2004, "账号或手机号未注册"),
USER_HAS_EXISTED(2005, "账号或手机号已注册"),
USER_NOT_BIND(2006, "用户需要绑定手机号"),
USER_MORE(2007, "系统存在多个正常状态的账号或手机号,请联系管理员"),
/**
* 权限验证错误
*/
USER_AUTHORIZATION_ERROR(3001, "用户权限错误"),
USER_NO_LOGIN(3002, "尚未登录,请登录"),
/**
* 其他系统错误
*/
SYSTEM_ERROR(4001, "系统错误"),
VERIFY_CODE_ERROR(4002, "验证码错误!");
int code;
String message;
ResponseCode(int code, String message) {
this.message = message;
this.code = code;
}
public String message() {
return message;
}
public int code() {
return code;
}
}

View File

@ -0,0 +1,28 @@
package com.isu.gaswellwatch.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
public class Role extends Model<Role> {
private Long id;
//名称
private String name;
//描述
private String description;
//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
//更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@ -0,0 +1,30 @@
package com.isu.gaswellwatch.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
public class RoleMenu extends Model<RoleMenu> {
private Long id;
//角色id
private Long roleId;
//菜单id
private Long menuId;
//类型0-只能查,1-可查可控,2-编辑组态
private String identifier;
//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
//更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@ -0,0 +1,36 @@
package com.isu.gaswellwatch.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
public class User extends Model<User> {
private Long id;
//账户
private String username;
//密码
private String password;
//昵称
private String nickname;
//手机号
private String phone;
//头像
private String picture;
//是否启用
private String isEnable;
//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
//更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@ -0,0 +1,33 @@
package com.isu.gaswellwatch.entity;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserExport {
@ExcelProperty(value = "序号")
private Integer number;
@ExcelProperty(value = "账号")
private String username;
@ExcelProperty(value = "使用者")
private String nickname;
@ColumnWidth(15)
@ExcelProperty(value = "角色")
private String roles;
@ColumnWidth(12)
@ExcelProperty(value = "电话")
private String phone;
@ColumnWidth(20)
@ExcelProperty(value = "创建时间")
private String createTime;
@ExcelProperty(value = "状态")
private String status;
}

View File

@ -0,0 +1,75 @@
package com.isu.gaswellwatch.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserOperationRecord extends Model<UserOperationRecord> implements Serializable {
@Serial
private static final long serialVersionUID = -36471439361446383L;
private Long id;
/**
* 操作类型
*/
private Integer type;
/**
* 用户名
*/
private String username;
/**
* 请求地址
*/
private String uri;
/**
* 菜单
*/
private String menu;
/**
* 请求参数
*/
private String request;
/**
* 请求结果
*/
private String result;
/**
* 登录ip
*/
private String ip;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@ -0,0 +1,28 @@
package com.isu.gaswellwatch.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
public class UserRole extends Model<UserRole> {
private Long id;
//用户id
private Long userId;
//角色id
private Long roleId;
//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
//更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@ -0,0 +1,64 @@
package com.isu.gaswellwatch.enums;
public enum LogResult {
/**
* 0:登陆日志
*/
SUCCESS(0, "成功"),
/**
* 1:新增操作
*/
ERROR(1, "失败");
private Integer val;
private String desc;
public Integer getVal() {
return val;
}
public void setVal(Integer val) {
this.val = val;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
LogResult(Integer val, String desc) {
this.val = val;
this.desc = desc;
}
public static boolean contains(Integer i) {
LogResult[] values = values();
for (LogResult value : values) {
if (value.val.equals(i)) {
return true;
}
}
return false;
}
public static String getDescription(Integer i) {
if (contains(i)) {
LogResult[] values = values();
for (LogResult value : values) {
if (value.val.equals(i)) {
return value.getDesc();
}
}
}
return null;
}
}

View File

@ -0,0 +1,86 @@
package com.isu.gaswellwatch.enums;
public enum LogType {
/**
* 0:登陆日志
*/
LOGIN(0, "用户登录"),
/**
* 4:导出操作
*/
LOGOUT(1, "用户注销"),
/**
* 1:新增操作
*/
ADD(2, "新增操作"),
/**
* 2:删除操作
*/
DELETE(3, "删除操作"),
/**
* 3:修改操作
*/
UPDATE(4, "修改操作"),
/**
* 4:导出操作
*/
EXPORT(5, "导出操作"),
/**
* 5.其它操作
*/
OPERATION(6, "其他操作");
private Integer val;
private String desc;
public Integer getVal() {
return val;
}
public void setVal(Integer val) {
this.val = val;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
LogType(Integer val, String desc) {
this.val = val;
this.desc = desc;
}
public static boolean contains(Integer i) {
LogType[] values = values();
for (LogType value : values) {
if (value.val.equals(i)) {
return true;
}
}
return false;
}
public static String getDescription(Integer i) {
if (contains(i)) {
LogType[] values = values();
for (LogType value : values) {
if (value.val.equals(i)) {
return value.getDesc();
}
}
}
return null;
}
}

View File

@ -0,0 +1,136 @@
package com.isu.gaswellwatch.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class BusinessException extends RuntimeException {
/**
* <li>日志</li>
*/
private static Logger logger = LoggerFactory.getLogger(BusinessException.class);
/**
* <li>状态码</li>
*/
private Integer code = 500;
/**
* <li>字符串错误信息和i18n无关</li>
*/
private String message;
/**
* 国际化文件中需要被替换的字符集合
*/
private List<String> replaceCharacters = null;
public BusinessException(int code, String message) {
this.code = code;
this.message = message;
}
/**
* 默认构造方法
*/
public BusinessException() {
super();
}
/**
* 重载构造函数
*
* @param message
*/
public BusinessException(String message) {
this.message = message;
}
/**
* 重载构造函数
*
* @param message 消息编码
* @param replaceCharacters 国际化文件中需要被替换的字符串集合
*/
public BusinessException(String message, List<String> replaceCharacters) {
this.message = message;
this.replaceCharacters = replaceCharacters;
}
/**
* 重载构造函数
*
* @param message 消息编码
* @param replaceCharacters 国际化文件中需要被替换的字符串集合
*/
public BusinessException(String message, String... replaceCharacters) {
this.message = message;
if (replaceCharacters != null && replaceCharacters.length > 0) {
this.replaceCharacters = new ArrayList<>();
for (String replaceCharacter : replaceCharacters) {
this.replaceCharacters.add(replaceCharacter);
}
}
}
/**
* 构造方法
*
* @param message 消息编码
* @param cause 异常原因
*/
public BusinessException(String message, Throwable cause) {
super(message, cause);
this.message = message;
}
/**
* 重载构造函数
*
* @param message 消息编码
* @param replaceCharacters 国际化文件中需要被替换的字符串集合
* @param cause 错误原因
*/
public BusinessException(String message, List<String> replaceCharacters, Throwable cause) {
super(message, cause);
this.message = message;
this.replaceCharacters = replaceCharacters;
}
/**
* 获得出错信息. 读取i18N properties文件中 messageCode对应的message,并组合参数获得i18n的出错信息.
*
* @return 返回 message
*/
@Override
public String getMessage() {
logger.debug("businessException code" + message);
// 否则用messageCode查询Properties文件获得出错信息
String result = null;
// message = "Message Code is: " + messageCode + ", but can't get the message of the Message Code";
result = this.message;
// 是否有需要替换的字符
if ((replaceCharacters != null) && (replaceCharacters.size() > 0)) {
for (int i = 0; i < replaceCharacters.size(); i++) {
String tempChar = "{" + i + "}";
if (result.indexOf(tempChar) != -1) {
result = result.replace(tempChar, replaceCharacters.get(i));
}
}
}
return result;
}
}

View File

@ -0,0 +1,127 @@
package com.isu.gaswellwatch.exception;
import com.isu.gaswellwatch.entity.Response;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import java.net.ConnectException;
import java.util.stream.Collectors;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 拦截自定义业务异常
**/
@ExceptionHandler(value = BusinessException.class)
public Response<?> baseErrorHandler(HttpServletRequest request, BusinessException e) {
log.error("【请求接口地址:{}】 业务逻辑错误信息:{}", request.getRequestURI(), e.getMessage());
return Response.failed(e.getCode(), e.getMessage());
}
/**
* 拦截微服务调用失败异常
**/
@ExceptionHandler(value = OpenFeignCallException.class)
public Response<?> openFeignCallErrorHandler(HttpServletRequest request, OpenFeignCallException e) {
log.error("请求接口地址:{}", request.getRequestURI());
log.error("异常类:{}", e.getClass().getName());
log.error("微服务调用异常信息如下:\n {}", ExceptionUtils.getStackTrace(e));
return Response.failed(e.getCode(), e.getMessage());
}
/**
* 拦截未知异常
**/
@ExceptionHandler(value = Exception.class)
public Response<?> exceptionHandler(HttpServletRequest request, Exception e) {
log.error("请求接口地址:{}", request.getRequestURI());
log.error("异常类:{}", e.getClass().getName());
log.error("异常堆栈信息如下:\n {}", ExceptionUtils.getStackTrace(e));
if (e instanceof MethodArgumentNotValidException) {
BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
if (bindingResult.hasErrors()) {
String msg = bindingResult.getFieldErrors().stream().map(FieldError::getDefaultMessage)
.collect(Collectors.joining("<br>"));
return Response.failed(msg);
}
return Response.failed(e.getMessage());
} else if (e instanceof ConnectException) {
return Response.failed("服务请求错误!");
} else if (e instanceof BusinessException) {
return Response.failed(e.getMessage());
} else if (e instanceof MaxUploadSizeExceededException) {
return Response.failed("上传文件大小超过最大限制");
} else {
return Response.failed("系统异常!");
}
}
/**
* 拦截所有controller方法中所有参数加了
* <code>@Valid</code>注解的方法
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public Response<String> handlerParamErrorException(HttpServletRequest request, MethodArgumentNotValidException e) {
BindingResult result = e.getBindingResult();
String message = result.getFieldErrors().get(0).getDefaultMessage();
log.error("【请求接口地址:{}】触发异常类:{} 参数错误信息:{}", request.getRequestURL().toString(), e.getClass(), message);
return Response.failed(message);
}
/**
* 拦截前端用户乱输入引起的参数类型不匹配
*/
@ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
public Response<String> handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
log.error("name:{}, propertyName:{}, message:{}, parameter:{}, localizedMessage:{}, value:{}",
e.getName(), e.getPropertyName(), e.getMessage(),
e.getParameter(), e.getLocalizedMessage(),
e.getValue()
);
return Response.failed("【参数名】:" + e.getName() + "参数类型不匹配");
}
/**
* 拦截参数转换异常
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
public Response<String> handlerHttpMessageNotReadableException(HttpServletRequest request, HttpMessageNotReadableException e) {
log.error("【请求接口地址:{}】触发异常类:{} 参数转换:{}", request.getRequestURI(), e.getClass(), e.getMessage());
return Response.failed("参数类型不匹配");
}
/**
* 拦截请求方法错误异常
*/
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
public Response<String> handlerHttpRequestMethodNotSupportedException(HttpServletRequest request, HttpRequestMethodNotSupportedException e) {
log.error("请求接口地址:{},触发异常类:{} 请求方法不支持", request.getRequestURI(), e.getClass());
return Response.failed("不支持的请求方法");
}
/**
* 拦截 Http Servlet请求缺少参数异常进行友好返回给前端
*/
@ExceptionHandler(value = MissingServletRequestParameterException.class)
public Response<String> handlerMissingServletRequestParameterException(HttpServletRequest request, MissingServletRequestParameterException e) {
String translationMsg = "【参数名】:".concat(e.getParameterName())
.concat(",【参数类型】:").concat(e.getParameterType())
.concat(",【错误消息】:").concat("请求缺少该参数");
String rawMsg = e.getLocalizedMessage();
log.error("请求接口地址:{},触发异常类:{}, 异常消息:{}", request.getRequestURI(), e.getClass(), rawMsg);
return Response.failed(translationMsg);
}
}

View File

@ -0,0 +1,32 @@
package com.isu.gaswellwatch.exception;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class OpenFeignCallException extends RuntimeException {
/**
* <li>状态码</li>
*/
private Integer code = 400;
/**
* <li>字符串错误信息</li>
*/
private String message;
public OpenFeignCallException(String message) {
super(message);
this.message = message;
}
public OpenFeignCallException(Integer code, String message) {
super(message);
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,23 @@
package com.isu.gaswellwatch.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.isu.gaswellwatch.dto.MenuDTO;
import com.isu.gaswellwatch.dto.MenuEditDTO;
import com.isu.gaswellwatch.dto.MenuSortDTO;
import com.isu.gaswellwatch.entity.Menu;
import com.isu.gaswellwatch.vo.MenuListVO;
import com.isu.gaswellwatch.vo.MenuTreeVO;
import java.util.List;
public interface MenuService extends IService<Menu> {
List<MenuTreeVO> getMenuTreeByRoleId(Long roleId);
List<MenuListVO> getMenuListByRoleId(Long roleId);
List<MenuTreeVO> getMenuTree();
void add(MenuDTO menuDTO);
void edit(MenuEditDTO menuEditDTO);
void delete(List<Long> ids);
void editSort(List<MenuSortDTO> menuSortDTOList);
}

View File

@ -0,0 +1,9 @@
package com.isu.gaswellwatch.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.isu.gaswellwatch.entity.RoleMenu;
public interface RoleMenuService extends IService<RoleMenu> {
}

View File

@ -0,0 +1,17 @@
package com.isu.gaswellwatch.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.isu.gaswellwatch.dto.RoleDTO;
import com.isu.gaswellwatch.dto.RoleEditDTO;
import com.isu.gaswellwatch.entity.Role;
import com.isu.gaswellwatch.vo.RoleVO;
public interface RoleService extends IService<Role> {
Page<RoleVO> page(Integer currentPage, Integer pageSize, String name);
void add(RoleDTO roleDTO);
void edit(RoleEditDTO roleEditDTO);
void delete(Long id);
}

View File

@ -0,0 +1,16 @@
package com.isu.gaswellwatch.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.isu.gaswellwatch.entity.UserOperationRecord;
import com.isu.gaswellwatch.vo.UserOperationRecordVO;
import jakarta.servlet.http.HttpServletResponse;
public interface UserOperationRecordService extends IService<UserOperationRecord> {
void addOperationRecord(UserOperationRecord operationRecord);
Page<UserOperationRecordVO> page(Integer currentPage, Integer pageSize, Integer type, String username, String nickname, Integer result, String startTime, String endTime);
void export(HttpServletResponse response, Integer type, String username, String nickname, Integer result, String startTime, String endTime);
}

View File

@ -0,0 +1,9 @@
package com.isu.gaswellwatch.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.isu.gaswellwatch.entity.UserRole;
public interface UserRoleService extends IService<UserRole> {
}

View File

@ -0,0 +1,32 @@
package com.isu.gaswellwatch.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.isu.gaswellwatch.dto.LoginDTO;
import com.isu.gaswellwatch.dto.ModifyPasswordDTO;
import com.isu.gaswellwatch.dto.UserDTO;
import com.isu.gaswellwatch.dto.UserEditDTO;
import com.isu.gaswellwatch.entity.User;
import com.isu.gaswellwatch.vo.MenuTreeVO;
import com.isu.gaswellwatch.vo.MenuVO;
import com.isu.gaswellwatch.vo.UserLoginInfoVO;
import com.isu.gaswellwatch.vo.UserVO;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
public interface UserService extends IService<User> {
UserLoginInfoVO doLogin(LoginDTO loginDTO);
List<MenuTreeVO> getMenuTreeByToken();
void logout();
void modifyPassword(ModifyPasswordDTO modifyPasswordDTO);
Page<UserVO> page(Integer currentPage, Integer pageSize, String username, String name, Long roleId, String isEnable);
void add(UserDTO userDTO);
void edit(UserEditDTO userEditDTO);
void delete(Long id);
void reset(Long id);
void export(HttpServletResponse response, String username, String name, Long roleId, String isEnable);
void setEnable(Long userId, String isEnable);
List<MenuVO> getMenuList(String username);
}

View File

@ -0,0 +1,173 @@
package com.isu.gaswellwatch.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isu.gaswellwatch.constants.UserConstant;
import com.isu.gaswellwatch.config.SnowflakeConfig;
import com.isu.gaswellwatch.dao.MenuDao;
import com.isu.gaswellwatch.dto.MenuDTO;
import com.isu.gaswellwatch.dto.MenuEditDTO;
import com.isu.gaswellwatch.dto.MenuSortDTO;
import com.isu.gaswellwatch.entity.Menu;
import com.isu.gaswellwatch.entity.RoleMenu;
import com.isu.gaswellwatch.service.MenuService;
import com.isu.gaswellwatch.service.RoleMenuService;
import com.isu.gaswellwatch.utils.ConverterUtil;
import com.isu.gaswellwatch.vo.MenuListVO;
import com.isu.gaswellwatch.vo.MenuTreeVO;
import com.isu.gaswellwatch.vo.MenuVO;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
@Service("menuService")
@Transactional(rollbackFor = Exception.class)
public class MenuServiceImpl extends ServiceImpl<MenuDao, Menu> implements MenuService {
@Resource
private MenuDao menuDao;
@Resource
private SnowflakeConfig snowflakeConfig;
@Resource
private RoleMenuService roleMenuService;
@Override
public List<MenuTreeVO> getMenuTreeByRoleId(Long roleId){
if(roleId != null) return getMenuTreeByRoleIds(Collections.singletonList(roleId));
return new ArrayList<>();
}
@Override
public List<MenuListVO> getMenuListByRoleId(Long roleId){
List<MenuVO> menuVOS = menuDao.selectRoleMenu(Collections.singletonList(roleId));
if(CollectionUtil.isEmpty(menuVOS)) return new ArrayList<>();
Map<Long, List<MenuVO>> map = menuVOS.stream().collect(Collectors.groupingBy(MenuVO::getId));
return map.entrySet().stream().map(entry -> {
Long id = entry.getKey();
List<MenuVO> objects = entry.getValue();
List<String> identifier = objects.stream().map(MenuVO::getIdentifier).filter(StringUtils::isNotBlank).toList();
return new MenuListVO(id, objects.getFirst().getParent(), objects.getFirst().getName(), objects.getFirst().getCode(),
objects.getFirst().getIcon(), objects.getFirst().getSort(), objects.getFirst().getExtra(), identifier);
}).toList();
}
@Override
public List<MenuTreeVO> getMenuTree(){
List<MenuTreeVO> convert = ConverterUtil.convert(list(), MenuTreeVO.class);
if(convert == null) return new ArrayList<>();
return buildTree(convert, UserConstant.MENU_ROOT_ID);
}
@Override
public void add(MenuDTO menuDTO){
Menu convert = ConverterUtil.convert(menuDTO, Menu.class);
long menuId = snowflakeConfig.snowflakeId();
convert.setId(menuId);
save(convert);
//超管
if(CollectionUtil.isEmpty(menuDTO.getIdentifier())){
roleMenuService.save(RoleMenu.builder().id(snowflakeConfig.snowflakeId()).roleId(UserConstant.SUPER_ADMIN_ID).menuId(menuId).build());
}else{
List<RoleMenu> list = new ArrayList<>();
menuDTO.getIdentifier().forEach(s->{
list.add(RoleMenu.builder().id(snowflakeConfig.snowflakeId()).roleId(UserConstant.SUPER_ADMIN_ID).menuId(menuId).identifier(s).build());
});
roleMenuService.saveBatch(list);
}
}
@Override
public void edit(MenuEditDTO menuEditDTO){
update(new UpdateWrapper<Menu>().lambda().eq(Menu::getId,menuEditDTO.getId()).set(Menu::getName,menuEditDTO.getName())
.set(Menu::getExtra,menuEditDTO.getExtra()));
}
@Override
public void delete(List<Long> ids){
//删除菜单
removeBatchByIds(ids);
//删除菜单与角色关联
roleMenuService.remove(new LambdaQueryWrapper<RoleMenu>().in(RoleMenu::getMenuId,ids));
}
@Override
public void editSort(List<MenuSortDTO> menuSortDTOList){
//更新菜单信息
if(CollectionUtil.isEmpty(menuSortDTOList)) return;
Map<Long, MenuSortDTO> map = menuSortDTOList.stream().collect(Collectors.toMap(MenuSortDTO::getId, menuSortDTO -> menuSortDTO, (v1, v2) -> v2));
List<Long> list = menuSortDTOList.stream().map(MenuSortDTO::getId).toList();
List<Menu> menuList = list(new LambdaQueryWrapper<Menu>().in(Menu::getId, list));
if(!CollectionUtil.isEmpty(menuList)){
menuList.forEach(menu -> {
menu.setSort(map.get(menu.getId()).getSort());
if(map.get(menu.getId()).getParent() != null){
menu.setParent(map.get(menu.getId()).getParent());
}
});
}
updateBatchById(menuList);
//将移动后未勾选的父菜单也勾选
List<RoleMenu> res = new ArrayList<>();
Long menuId = null;
List<Long> ancestors = null;
for(MenuSortDTO menuSortDTO : menuSortDTOList){
if(!CollectionUtil.isEmpty(menuSortDTO.getAncestors())){
menuId = menuSortDTO.getId();
ancestors = menuSortDTO.getAncestors();
}
}
if(menuId != null){
List<RoleMenu> roleMenuList = roleMenuService.list(new LambdaQueryWrapper<RoleMenu>().eq(RoleMenu::getMenuId, menuId));
if(!CollectionUtil.isEmpty(roleMenuList)){
List<Long> roleIds = roleMenuList.stream().map(RoleMenu::getRoleId).toList();
List<RoleMenu> roleMenus = roleMenuService.list(new LambdaQueryWrapper<RoleMenu>().in(RoleMenu::getRoleId, roleIds));
//带有拖动菜单对应的每个角色的所有菜单
Map<Long, List<Long>> collect = roleMenus.stream().collect(Collectors.groupingBy(RoleMenu::getRoleId, Collectors.mapping(RoleMenu::getMenuId, Collectors.toList())));
for(Map.Entry<Long, List<Long>> entry : collect.entrySet()){
Set<Long> set = new HashSet<>(entry.getValue());
for(Long ancestor : ancestors){
if(!set.contains(ancestor)){
res.add(RoleMenu.builder().id(snowflakeConfig.snowflakeId()).roleId(entry.getKey()).menuId(ancestor).build());
}
}
}
roleMenuService.saveBatch(res);
}
}
}
public List<MenuTreeVO> getMenuTreeByRoleIds(List<Long> ids){
List<MenuVO> menuVOS = menuDao.selectRoleMenu(ids);
if(CollectionUtil.isEmpty(menuVOS)) return new ArrayList<>();
Map<Long, List<MenuVO>> map = menuVOS.stream().collect(Collectors.groupingBy(MenuVO::getId));
List<MenuTreeVO> collect = map.entrySet().stream().map(entry -> {
Long id = entry.getKey();
List<MenuVO> objects = entry.getValue();
List<String> identifier = objects.stream().map(MenuVO::getIdentifier).filter(StringUtils::isNotBlank).toList();
return new MenuTreeVO(id, objects.getFirst().getParent(), objects.getFirst().getName(), objects.getFirst().getCode(),
objects.getFirst().getIcon(), objects.getFirst().getSort(), objects.getFirst().getExtra(), identifier, null);
}).toList();
if(CollectionUtil.isEmpty(collect)) return new ArrayList<>();
return buildTree(collect,UserConstant.MENU_ROOT_ID);
}
private List<MenuTreeVO> buildTree(List<MenuTreeVO> menuTreeVO,Long parentId){
return menuTreeVO.stream()
// 筛选父节点
.filter(t -> t.getParent().equals(parentId))
// 递归设置子节点
.peek(item -> item.setChildren(buildTree(menuTreeVO,item.getId())))
.sorted(Comparator.comparing(MenuTreeVO::getSort))
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,15 @@
package com.isu.gaswellwatch.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isu.gaswellwatch.dao.RoleMenuDao;
import com.isu.gaswellwatch.entity.RoleMenu;
import com.isu.gaswellwatch.service.RoleMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("roleMenuService")
@Transactional(rollbackFor = Exception.class)
public class RoleMenuServiceImpl extends ServiceImpl<RoleMenuDao, RoleMenu> implements RoleMenuService {
}

View File

@ -0,0 +1,108 @@
package com.isu.gaswellwatch.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isu.gaswellwatch.config.SnowflakeConfig;
import com.isu.gaswellwatch.constants.UserConstant;
import com.isu.gaswellwatch.dao.RoleDao;
import com.isu.gaswellwatch.dto.RoleDTO;
import com.isu.gaswellwatch.dto.RoleEditDTO;
import com.isu.gaswellwatch.dto.RoleMenuDTO;
import com.isu.gaswellwatch.entity.Role;
import com.isu.gaswellwatch.entity.RoleMenu;
import com.isu.gaswellwatch.entity.UserRole;
import com.isu.gaswellwatch.exception.BusinessException;
import com.isu.gaswellwatch.service.RoleMenuService;
import com.isu.gaswellwatch.service.RoleService;
import com.isu.gaswellwatch.service.UserRoleService;
import com.isu.gaswellwatch.utils.ConverterUtil;
import com.isu.gaswellwatch.vo.RoleVO;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Service("roleService")
@Transactional(rollbackFor = Exception.class)
public class RoleServiceImpl extends ServiceImpl<RoleDao, Role> implements RoleService {
@Resource
private SnowflakeConfig snowflakeConfig;
@Resource
private RoleMenuService roleMenuService;
@Resource
private UserRoleService userRoleService;
@Override
public Page<RoleVO> page(Integer currentPage, Integer pageSize, String name){
Page<Role> page = page(new Page<>(currentPage, pageSize), new LambdaQueryWrapper<Role>().like(StringUtils.isNotBlank(name), Role::getName, name).orderByDesc(Role::getCreateTime));
return ConverterUtil.convertPage(page,RoleVO.class);
}
@Override
public void add(RoleDTO roleDTO){
//查重
List<Role> list = list(new LambdaQueryWrapper<Role>().eq(Role::getName, roleDTO.getName()));
if(CollectionUtil.isNotEmpty(list)) {
throw new BusinessException("已有角色,请重新输入");
}
Long roleId = snowflakeConfig.snowflakeId();
save(Role.builder().id(roleId).name(roleDTO.getName()).description(roleDTO.getDescription()).build());
//关联
addRelation(roleDTO.getRoleMenuDTOList(), roleId);
}
@Override
public void edit(RoleEditDTO roleEditDTO){
List<Role> list = list(new LambdaQueryWrapper<Role>().eq(Role::getName, roleEditDTO.getName()).ne(Role::getId, roleEditDTO.getId()));
if(CollectionUtil.isNotEmpty(list)) {
throw new BusinessException("角色名称已存在,请重新输入");
}
updateById(ConverterUtil.convert(roleEditDTO, Role.class));
//关联
roleMenuService.remove(new LambdaQueryWrapper<RoleMenu>().eq(RoleMenu::getRoleId,roleEditDTO.getId()));
addRelation(roleEditDTO.getRoleMenuDTOList(), roleEditDTO.getId());
}
@Override
public void delete(Long id){
//如果角色绑定了用户 不能删除
List<UserRole> list = userRoleService.list(new LambdaQueryWrapper<UserRole>().eq(UserRole::getRoleId, id));
if(CollectionUtil.isNotEmpty(list)) {
throw new BusinessException("该角色已和用户绑定,不能删除");
}
//如果是超管角色 不能删除
if(Objects.equals(id, UserConstant.SUPER_ADMIN_ID)) {
throw new BusinessException("该角色为超管角色,不能删除");
}
//删除
removeById(id);
roleMenuService.remove(new LambdaQueryWrapper<RoleMenu>().eq(RoleMenu::getRoleId,id));
}
private void addRelation(List<RoleMenuDTO> roleMenuDTOList, Long roleId) {
if(!CollectionUtil.isEmpty(roleMenuDTOList)){
List<RoleMenu> roleMenus = new ArrayList<>();
roleMenuDTOList.forEach(roleMenuDTO -> {
if(CollectionUtil.isEmpty(roleMenuDTO.getIdentifier())){
roleMenus.add(RoleMenu.builder().id(snowflakeConfig.snowflakeId()).roleId(roleId).menuId(roleMenuDTO.getMenuId()).build());
}else {
roleMenuDTO.getIdentifier().forEach(identifier -> {
roleMenus.add(RoleMenu.builder().id(snowflakeConfig.snowflakeId()).roleId(roleId).menuId(roleMenuDTO.getMenuId()).identifier(identifier).build());
});
}
});
roleMenuService.saveBatch(roleMenus);
}
}
}

View File

@ -0,0 +1,159 @@
package com.isu.gaswellwatch.service.impl;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isu.gaswellwatch.dao.UserOperationRecordDao;
import com.isu.gaswellwatch.dao.UserOperationRecordMapper;
import com.isu.gaswellwatch.entity.UserOperationRecord;
import com.isu.gaswellwatch.enums.LogResult;
import com.isu.gaswellwatch.enums.LogType;
import com.isu.gaswellwatch.service.UserOperationRecordService;
import com.isu.gaswellwatch.thread.AsyncLogTaskFactory;
import com.isu.gaswellwatch.thread.AsyncLogThreadPoolManager;
import com.isu.gaswellwatch.utils.ConverterUtil;
import com.isu.gaswellwatch.vo.LoginRecordExportVO;
import com.isu.gaswellwatch.vo.UserOperationRecordExportVO;
import com.isu.gaswellwatch.vo.UserOperationRecordVO;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
@Service("userOperationRecordService")
@Transactional(rollbackFor = Exception.class)
public class UserOperationRecordServiceImpl extends ServiceImpl<UserOperationRecordMapper, UserOperationRecord> implements UserOperationRecordService {
/**
* 操作记录批处理条数
*/
public static int CACHE_BASE_CAPACITY = 400;
/**
* 操作记录缓存队列最大存储大小CACHE_BASE_CAPACITY+CACHE_MAX_INCREMENT
*/
public static int CACHE_MAX_INCREMENT = 2000;
/**
* 缓存在插入数据库前先存入此
*/
public final LinkedBlockingQueue<UserOperationRecord> CACHE = new LinkedBlockingQueue<>(CACHE_BASE_CAPACITY + CACHE_MAX_INCREMENT);
/**
* 信号量用于标记当前是否有任务正在执行{@code true}表示当前无任务进行
*/
private volatile boolean taskFinish = true;
@Autowired
private UserOperationRecordDao userOperationRecordDao;
@Override
public void addOperationRecord(UserOperationRecord operationRecord) {
CACHE.add(operationRecord);
if (CACHE.size() >= CACHE_BASE_CAPACITY && taskFinish) {
synchronized (this) {
if(taskFinish){
try {
AsyncLogThreadPoolManager.getInstance().execute(new AsyncLogTaskFactory(this).batchSaveRecord());
} catch (Exception e) {
e.printStackTrace();
} finally {
// 任务执行完毕后修改标志位
taskFinish = true;
}
}
}
}
}
/**
* 每分钟入库任务
*/
@Scheduled(cron = "0 0/1 * * * ?")
public void doTask() {
if (taskFinish) {
synchronized (this) {
if (taskFinish) {
taskFinish = false;
try {
AsyncLogThreadPoolManager.getInstance().execute(new AsyncLogTaskFactory(this).batchSaveRecord());
} catch (Exception e) {
e.printStackTrace();
} finally {
// 任务执行完毕后修改标志位
taskFinish = true;
}
}
}
}
}
@Override
public Page<UserOperationRecordVO> page(Integer currentPage, Integer pageSize, Integer type, String username, String nickname, Integer result, String startTime, String endTime) {
return userOperationRecordDao.page(new Page<>(currentPage,pageSize),type,username,nickname,result,startTime,endTime);
}
@Override
public void export(HttpServletResponse response, Integer type, String username, String nickname, Integer result, String startTime, String endTime) {
if(type== LogType.LOGIN.getVal()){
exportLoginLog(response,type,username,nickname,result,startTime,endTime);
return;
}
List<UserOperationRecordVO> list=userOperationRecordDao.list(type,username,nickname,result,startTime,endTime);
List<UserOperationRecordExportVO> export = ConverterUtil.convert(list, UserOperationRecordExportVO.class);
if(!CollectionUtils.isEmpty(export)) {
for (UserOperationRecordExportVO userOperationRecordExportVO : export) {
userOperationRecordExportVO.setTypeDesc(LogType.getDescription(userOperationRecordExportVO.getType()));
userOperationRecordExportVO.setResultDesc(LogResult.getDescription(userOperationRecordExportVO.getResult()));
}
}
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = null;
try {
ServletOutputStream outputStream = response.getOutputStream();
fileName = URLEncoder.encode("操作日志", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(outputStream)
// 这里放入动态头
.head(UserOperationRecordExportVO.class).sheet("data")
// 当然这里数据也可以用 List<List<String>> 去传入
.doWrite(export);
} catch (Exception e) {
log.error(e.getMessage());
}
}
public void exportLoginLog(HttpServletResponse response, Integer type, String username, String nickname, Integer result, String startTime, String endTime) {
List<UserOperationRecordVO> list=userOperationRecordDao.list(type,username,nickname,result,startTime,endTime);
List<LoginRecordExportVO> export = ConverterUtil.convert(list, LoginRecordExportVO.class);
if(!CollectionUtils.isEmpty(export)) {
for (LoginRecordExportVO loginRecordExportVO : export) {
loginRecordExportVO.setResultDesc(LogResult.getDescription(loginRecordExportVO.getResult()));
}
}
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = null;
try {
ServletOutputStream outputStream = response.getOutputStream();
fileName = URLEncoder.encode("登录日志", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(outputStream)
// 这里放入动态头
.head(LoginRecordExportVO.class).sheet("data")
// 当然这里数据也可以用 List<List<String>> 去传入
.doWrite(export);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}

View File

@ -0,0 +1,15 @@
package com.isu.gaswellwatch.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isu.gaswellwatch.dao.UserRoleDao;
import com.isu.gaswellwatch.entity.UserRole;
import com.isu.gaswellwatch.service.UserRoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("userRoleService")
@Transactional(rollbackFor = Exception.class)
public class UserRoleServiceImpl extends ServiceImpl<UserRoleDao, UserRole> implements UserRoleService {
}

View File

@ -0,0 +1,261 @@
package com.isu.gaswellwatch.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isu.gaswellwatch.config.SnowflakeConfig;
import com.isu.gaswellwatch.constants.UserConstant;
import com.isu.gaswellwatch.dao.MenuDao;
import com.isu.gaswellwatch.dao.UserDao;
import com.isu.gaswellwatch.dto.LoginDTO;
import com.isu.gaswellwatch.dto.ModifyPasswordDTO;
import com.isu.gaswellwatch.dto.UserDTO;
import com.isu.gaswellwatch.dto.UserEditDTO;
import com.isu.gaswellwatch.entity.User;
import com.isu.gaswellwatch.entity.UserExport;
import com.isu.gaswellwatch.entity.UserRole;
import com.isu.gaswellwatch.exception.BusinessException;
import com.isu.gaswellwatch.service.UserRoleService;
import com.isu.gaswellwatch.service.UserService;
import com.isu.gaswellwatch.utils.ConverterUtil;
import com.isu.gaswellwatch.vo.*;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
@Service("userService")
@Transactional
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
@Resource
private UserDao userDao;
@Resource
private UserRoleService userRoleService;
@Resource
private SnowflakeConfig snowflakeConfig;
@Resource
private MenuServiceImpl menuService;
@Resource
private MenuDao menuDao;
@Override
public UserLoginInfoVO doLogin(LoginDTO loginDTO){
User user = getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, loginDTO.getUsername()));
if(user == null) throw new BusinessException("账号不存在");
if(UserConstant.FORBIDDEN.equals(user.getIsEnable())) throw new BusinessException("账号已被禁用,请联系管理员");
if(!loginDTO.getPassword().equals(user.getPassword())) throw new BusinessException("账号密码错误");
StpUtil.login(loginDTO.getUsername());
UserLoginInfoVO userLoginInfoVO = buildTokenSession(loginDTO.getUsername());
StpUtil.getTokenSession().set(UserConstant.TOKEN_SESSION, userLoginInfoVO);
String tokenValue = StpUtil.getTokenValue();
userLoginInfoVO.setToken(tokenValue);
return userLoginInfoVO;
}
@Override
public List<MenuTreeVO> getMenuTreeByToken(){
UserLoginInfoVO userLoginInfoVO = (UserLoginInfoVO) StpUtil.getTokenSession().get(UserConstant.TOKEN_SESSION);
UserVO userVO = userDao.selectUserInfo(userLoginInfoVO.getUserVO().getUsername());
if(userVO != null){
if(!CollectionUtil.isEmpty(userVO.getRoles())){
List<Long> list = userVO.getRoles().stream().map(RoleVO::getId).toList();
return menuService.getMenuTreeByRoleIds(list);
}
}
return new ArrayList<>();
}
@Override
public void logout(){
StpUtil.logout();
}
@Override
public void modifyPassword(ModifyPasswordDTO modifyPasswordDTO){
UserLoginInfoVO userLoginInfoVO = (UserLoginInfoVO) StpUtil.getTokenSession().get(UserConstant.TOKEN_SESSION);
User user = getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, userLoginInfoVO.getUserVO().getUsername()));
if(!modifyPasswordDTO.getOldPassword().equals(user.getPassword())) throw new BusinessException("密码错误");
if(!modifyPasswordDTO.getNewPassword().equals(modifyPasswordDTO.getNewPasswordConfirm())) throw new BusinessException("确认新密码跟新密码不一致");
user.setPassword(modifyPasswordDTO.getNewPassword());
updateById(user);
StpUtil.logout();
}
@Override
public Page<UserVO> page(Integer currentPage, Integer pageSize, String username, String name, Long roleId, String isEnable){
List<Long> userIds = null;
if(roleId != null){
List<UserRole> list = userRoleService.list(new LambdaQueryWrapper<UserRole>().eq(UserRole::getRoleId, roleId));
if(!CollectionUtils.isEmpty(list)){
userIds = list.stream().map(UserRole::getUserId).toList();
}else{
return new Page<>();
}
}
return userDao.page(new Page<>(currentPage, pageSize),username,name,userIds,isEnable);
}
@Override
public void add(UserDTO userDTO){
if(StringUtils.isNotBlank(userDTO.getPhone()) && !Pattern.matches("^\\d{11}$", userDTO.getPhone())){
throw new BusinessException("手机号必须是11位纯数字");
}
//查重
List<User> users = list(new LambdaQueryWrapper<User>().eq(User::getUsername, userDTO.getUsername()));
if(!CollectionUtils.isEmpty(users)){
throw new BusinessException("账号已存在,请重新输入");
}
//用户新增
User user = ConverterUtil.convert(userDTO, User.class);
user.setId(snowflakeConfig.snowflakeId());
user.setPassword(DigestUtil.sha1Hex(UserConstant.DEFAULT_PASSWORD));
save(user);
//关联新增
addRelation(userDTO.getRoles(), user);
}
@Override
public void edit(UserEditDTO userEditDTO){
if(StringUtils.isNotBlank(userEditDTO.getPhone()) && !Pattern.matches("^\\d{11}$", userEditDTO.getPhone())){
throw new BusinessException("手机号必须是11位纯数字");
}
//用户更新
List<User> list = list(new LambdaQueryWrapper<User>().eq(User::getUsername, userEditDTO.getUsername()).ne(User::getId, userEditDTO.getId()));
if(CollectionUtil.isNotEmpty(list)) throw new BusinessException("账号已存在,请重新输入");
User user = ConverterUtil.convert(userEditDTO, User.class);
updateById(user);
//关联更新
userRoleService.remove(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, user.getId()));
addRelation(userEditDTO.getRoles(), user);
}
@Override
public void delete(Long id){
//如果是超管 不能删除
if(Objects.equals(id, UserConstant.SUPER_ADMIN_ID)) throw new BusinessException("该用户为内置超管用户,不能删除");
User byId = getById(id);
if(byId != null){
removeById(id);
userRoleService.remove(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, id));
StpUtil.kickout(byId.getUsername());
}
}
@Override
public void reset(Long id){
User byId = getById(id);
if(byId != null){
update(new LambdaUpdateWrapper<User>().eq(User::getId, id).set(User::getPassword, DigestUtil.sha1Hex("123456")));
StpUtil.kickout(byId.getUsername());
}
}
@Override
public void setEnable(Long userId, String isEnable){
User byId = getById(userId);
if(byId != null){
update(new LambdaUpdateWrapper<User>().eq(User::getId, userId).set(User::getIsEnable, isEnable));
if(UserConstant.FORBIDDEN.equals(isEnable)) StpUtil.kickout(byId.getUsername());
}
}
@Override
public void export(HttpServletResponse response, String username, String name, Long roleId, String isEnable){
List<UserVO> list = userDao.list(username, name, roleId, isEnable);
List<UserExport> exportList = new ArrayList<>();
if(!CollectionUtils.isEmpty(list)){
int i= 1;
for(UserVO userVO : list){
//角色
StringBuilder roles = new StringBuilder();
if(!CollectionUtils.isEmpty(userVO.getRoles())){
for(int k = 0;k < userVO.getRoles().size();k++){
if( k == 0){
roles = new StringBuilder(userVO.getRoles().getFirst().getName());
}else {
roles.append(",").append(userVO.getRoles().get(k).getName());
}
}
}
//状态
String status;
if(UserConstant.NORMAL.equals(userVO.getIsEnable())){
status = "正常";
}else{
status = "冻结";
}
exportList.add(UserExport.builder().number(i).username(userVO.getUsername()).nickname(userVO.getNickname())
.roles(roles.toString()).phone(userVO.getPhone()).createTime(userVO.getCreateTime()).status(status).build());
i++;
}
}
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = null;
try {
ServletOutputStream outputStream = response.getOutputStream();
fileName = URLEncoder.encode("用户", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
if (!CollectionUtils.isEmpty(exportList)) {
EasyExcel.write(outputStream)
// 这里放入动态头
.head(UserExport.class).sheet("data")
// 当然这里数据也可以用 List<List<String>> 去传入
.doWrite(exportList);
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
@Override
public List<MenuVO> getMenuList(String username){
UserVO userVO = userDao.selectUserInfo(username);
if(userVO != null) {
if (!CollectionUtil.isEmpty(userVO.getRoles())) {
List<Long> list = userVO.getRoles().stream().map(RoleVO::getId).toList();
return menuDao.selectRoleMenu(list);
}
}
return new ArrayList<>();
}
private UserLoginInfoVO buildTokenSession(String username){
UserLoginInfoVO userInfoVO = new UserLoginInfoVO();
UserVO userVO = userDao.selectUserInfo(username);
if(userVO != null){
userInfoVO.setUserVO(userVO);
}
return userInfoVO;
}
private void addRelation(List<RoleVO> roles, User user) {
if (roles != null && !roles.isEmpty()) {
List<UserRole> userRoles = new ArrayList<>();
roles.stream().map(RoleVO::getId).toList().forEach(roleId -> {
userRoles.add(UserRole.builder().id(snowflakeConfig.snowflakeId()).userId(user.getId()).roleId(roleId).build());
});
userRoleService.saveBatch(userRoles);
}
}
}

View File

@ -0,0 +1,54 @@
package com.isu.gaswellwatch.thread;
import com.isu.gaswellwatch.entity.UserOperationRecord;
import com.isu.gaswellwatch.service.impl.UserOperationRecordServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;
@Slf4j
public class AsyncLogTaskFactory {
/**
* 记录操作日志
* @param operationLog 操作日志信息
* @return 任务task
*/
private final UserOperationRecordServiceImpl operationRecordService;
public AsyncLogTaskFactory(UserOperationRecordServiceImpl operationRecordService) {
this.operationRecordService = operationRecordService;
}
public TimerTask batchSaveRecord() {
return new TimerTask() {
@Override
public void run() {
// 进行日志持久化操作
if(operationRecordService.CACHE.isEmpty()){
return;
}
List<UserOperationRecord> operationRecords = new ArrayList<>(operationRecordService.CACHE_BASE_CAPACITY);
try {
for (int i = 1; i <= operationRecordService.CACHE_BASE_CAPACITY; i++) {
if (operationRecordService.CACHE.isEmpty()) {
break;
}
operationRecords.add(operationRecordService.CACHE.poll());
}
if(CollectionUtils.isEmpty(operationRecords)){
return;
}
operationRecordService.saveBatch(operationRecords);
log.info("操作记录处理程序开始执行入库,本次入库条数:{}", operationRecords.size());
}catch (Exception e) {
e.printStackTrace();
}
}
};
}
}

View File

@ -0,0 +1,40 @@
package com.isu.gaswellwatch.thread;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.TimerTask;
public class AsyncLogThreadPoolManager {
/**
* 单例模式确保类只有一个实例
*/
private AsyncLogThreadPoolManager() {
}
/**
* 饿汉式在类加载的时候立刻进行实例化
*/
private static final AsyncLogThreadPoolManager INSTANCE = new AsyncLogThreadPoolManager();
public static AsyncLogThreadPoolManager getInstance() {
return INSTANCE;
}
/**
* 异步操作任务调度线程池
*/
private final ThreadPoolTaskExecutor executor = SpringUtil.getBean("threadPoolTaskExecutor", ThreadPoolTaskExecutor.class);
/**
* 执行任务
*
* @param task 任务
*/
public void execute(TimerTask task) {
executor.execute(task);
}
}

View File

@ -0,0 +1,71 @@
package com.isu.gaswellwatch.utils;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.isu.gaswellwatch.vo.TreeVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ConverterUtil {
private static final Logger logger = LoggerFactory.getLogger(ConverterUtil.class);
public static <T> T convert(Object source, Class<T> tClass) {
T tar = ReflectUtil.newInstanceIfPossible(tClass);
BeanUtil.copyProperties(source, tar);
return tar;
}
public static <T> List<T> convert(List<?> source, Class<T> tClass) {
if(CollUtil.isEmpty(source)) {
return null;
}
return source.stream().map(o -> {
T tar = ReflectUtil.newInstanceIfPossible(tClass);
BeanUtil.copyProperties(o,tar);
return tar;
}).collect(Collectors.toList());
}
public static <T> IPage<T> convertIPage(IPage<?> source, Class<T> tClass) {
IPage<T> result = new Page<>();
if(null == source){
return result ;
}
BeanUtil.copyProperties(source,result);
result.setRecords(convert(source.getRecords(),tClass));
return result;
}
public static <T> Page<T> convertPage(Page<?> source, Class<T> tClass) {
Page<T> result = new Page<>();
if(null == source){
return result ;
}
BeanUtil.copyProperties(source,result);
result.setRecords(convert(source.getRecords(),tClass));
return result;
}
public static <T extends TreeVO> List<T> convertListToTree(List<T> list, Long parentId) {
if(CollUtil.isEmpty(list)) return new ArrayList<>() ;
return list.stream()
// 筛选父节点
.filter(t -> t.getParent().equals(parentId))
// 递归设置子节点
.peek(item -> item.setChildren(convertListToTree(list,item.getId())))
//排序
//.sorted(Comparator.comparing(TreeVO::getSort))
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,177 @@
package com.isu.gaswellwatch.utils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Slf4j
public class IpUtils {
public static String getIpAddr(HttpServletRequest request) {
if (request == null) {
return null;
}
String ip = null;
// X-Forwarded-ForSquid 服务代理
String ipAddresses = request.getHeader("X-Forwarded-For");
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
// Proxy-Client-IPapache 服务代理
ipAddresses = request.getHeader("Proxy-Client-IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
// WL-Proxy-Client-IPweblogic 服务代理
ipAddresses = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
// HTTP_CLIENT_IP有些代理服务器
ipAddresses = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
// X-Real-IPnginx服务代理
ipAddresses = request.getHeader("X-Real-IP");
}
// 有些网络通过多层代理那么获取到的ip就会有多个一般都是通过逗号,分割开来并且第一个ip为客户端的真实IP
if (ipAddresses != null && ipAddresses.length() != 0) {
ip = ipAddresses.split(",")[0];
log.info("***********************"+ ipAddresses);
}
// 还是不能获取到最后再通过request.getRemoteAddr();获取
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
ip = request.getRemoteAddr();
}
return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
}
public static boolean internalIp(String ip) {
byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip);
}
private static boolean internalIp(byte[] addr) {
if (addr == null || addr.length < 2) {
return true;
}
final byte b0 = addr[0];
final byte b1 = addr[1];
// 10.x.x.x/8
final byte SECTION_1 = 0x0A;
// 172.16.x.x/12
final byte SECTION_2 = (byte) 0xAC;
final byte SECTION_3 = (byte) 0x10;
final byte SECTION_4 = (byte) 0x1F;
// 192.168.x.x/16
final byte SECTION_5 = (byte) 0xC0;
final byte SECTION_6 = (byte) 0xA8;
switch (b0) {
case SECTION_1:
return true;
case SECTION_2:
if (b1 >= SECTION_3 && b1 <= SECTION_4) {
return true;
}
case SECTION_5:
switch (b1) {
case SECTION_6:
return true;
}
default:
return false;
}
}
/**
* 将IPv4地址转换成字节
*
* @param text IPv4地址
* @return byte 字节
*/
public static byte[] textToNumericFormatV4(String text) {
if (text.length() == 0) {
return null;
}
byte[] bytes = new byte[4];
String[] elements = text.split("\\.", -1);
try {
long l;
int i;
switch (elements.length) {
case 1:
l = Long.parseLong(elements[0]);
if ((l < 0L) || (l > 4294967295L)) {
return null;
}
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 2:
l = Integer.parseInt(elements[0]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]);
if ((l < 0L) || (l > 16777215L)) {
return null;
}
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 3:
for (i = 0; i < 2; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
l = Integer.parseInt(elements[2]);
if ((l < 0L) || (l > 65535L)) {
return null;
}
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 4:
for (i = 0; i < 4; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
break;
default:
return null;
}
} catch (NumberFormatException e) {
return null;
}
return bytes;
}
public static String getHostIp() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
}
return "127.0.0.1";
}
public static String getHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
}
return "未知";
}
}

View File

@ -0,0 +1,55 @@
package com.isu.gaswellwatch.utils;
import jakarta.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
public class ServletUtils {
/**
* 内容编码
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncode(String str) {
try {
return URLEncoder.encode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 内容解码
*
* @param str 内容
* @return 解码后的内容
*/
public static String urlDecode(String str) {
try {
return URLDecoder.decode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
return "";
} catch (NullPointerException n) {
return null;
}
}
public static Map<String, String> getHeaders(HttpServletRequest request) {
Map<String, String> map = new LinkedHashMap<>();
Enumeration<String> enumeration = request.getHeaderNames();
if (enumeration != null) {
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
}
}

View File

@ -0,0 +1,53 @@
package com.isu.gaswellwatch.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
log.info("ApplicationContext配置成功,applicationContext=" + SpringUtil.applicationContext);
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
public static void registerBean(String beanName, BeanDefinitionBuilder beanDefinitionBuilder) {
if (StringUtils.isBlank(beanName) || beanDefinitionBuilder == null) {
return;
}
ConfigurableApplicationContext context = (ConfigurableApplicationContext) getApplicationContext();
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();
beanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
}
}

View File

@ -0,0 +1,586 @@
package com.isu.gaswellwatch.utils;
import cn.hutool.core.lang.Dict;
import cn.hutool.extra.expression.ExpressionUtil;
import com.isu.gaswellwatch.exception.BusinessException;
import com.isu.gaswellwatch.vo.UnitTreeVO;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class UnitsUtils {
/**
* 四舍五入
*
* @param value - 原始数值
* @param original - 原始单位
* @param need - 转换的单位
* @return BigDecimal - 转换后的值
*/
public static BigDecimal conversion(BigDecimal value, String original, String need) {
return conversion(value, original, need, 2);
}
/**
* 指定小数点位数四舍五入
*
* @param value - 原始数值
* @param original - 原始单位
* @param need - 转换的单位
* @param scale - 小数点位数
* @return BigDecimal - 转换后的值
*/
public static BigDecimal conversion(BigDecimal value, String original, String need, final Integer scale) {
//适应一个单位在多个分类中的情况但不支持一个分类中有相同两个单位的情况
List<UnitsEnum> unitEnums = getUnitEnum(original);
UnitsEnum originalUnitEnum = null;
UnitsEnum needUnitEnum = null;
for (UnitsEnum unitsEnum : unitEnums) {
UnitsEnum tempUnitEnum = getUnitEnum(need, unitsEnum);
if (tempUnitEnum != null && tempUnitEnum != UnitsEnum.UN_KNOWN) {
needUnitEnum = tempUnitEnum;
originalUnitEnum = unitsEnum;
break;
}
}
if (needUnitEnum == null) throw new BusinessException(original + "不支持转计量单位:" + need);
return conversion(value, originalUnitEnum, needUnitEnum, scale);
}
/**
* 使用默认为数2 need 的小数点位数四舍五入
*
* @param value - 原始数值
* @param original - 原始单位
* @param need - 转换的单位
* @return BigDecimal - 转换后的值
*/
public static BigDecimal conversion(BigDecimal value, UnitsEnum original, UnitsEnum need) {
String needString = need.conversionExpression;
int scale = 2;
if (needString.indexOf('.') > 0) {
scale = needString.substring(needString.indexOf('.')).length() - 1;
}
return conversion(value, original, need, scale);
}
/**
* 转换主方法指定小数点位数四舍五入
*
* @param value - 原始数值
* @param original - 原始单位
* @param need - 转换的单位
* @param scale - 小数点位数
* @return BigDecimal - 数值
*/
public static BigDecimal conversion(BigDecimal value, UnitsEnum original, UnitsEnum need, final Integer scale) {
if (original == UnitsEnum.UN_KNOWN || need == UnitsEnum.UN_KNOWN) {
throw new BusinessException("存在不支持的计量单位参数");
}
if (original.category != need.category) {
throw new BusinessException(String.format("转换计量单位不统一 %s:%s 不能转换为 %s:%s ", original.category.name, original.units, need.category.name, need.units));
}
if (value == null) {
return BigDecimal.ZERO;
}
//转单位基数值
String originalExpression = original.getConversionBaseUnitExpression();
String conversionExpression = need.getConversionBaseUnitExpression();
if (StringUtils.isBlank(originalExpression) || StringUtils.isBlank(conversionExpression))
return BigDecimal.ZERO;
if (!originalExpression.contains("a") && !conversionExpression.contains("a")) {
//都是倍数转换
return value.multiply(new BigDecimal(conversionExpression)).divide(new BigDecimal(originalExpression), scale, RoundingMode.HALF_UP);
}
//非倍数转换,表达式计算
conversionExpression = need.getConversionExpression();
//转基数的情况
if (StringUtils.isBlank(conversionExpression)) conversionExpression = need.getConversionBaseUnitExpression();
value = evaluate(originalExpression, value);
return evaluate(conversionExpression, value).setScale(scale, RoundingMode.HALF_UP);
}
private static BigDecimal evaluate(String expression, BigDecimal value) {
try {
if (!expression.contains("a")) {
return value.divide(new BigDecimal(expression));
} else {
Dict dict = Dict.create()
.set("a", value);
return new BigDecimal(ExpressionUtil.eval(expression, dict).toString());
}
} catch (Exception e) {
throw new BusinessException("表达式计算异常");
}
}
public static void main(String[] args) {
long s = System.currentTimeMillis();
System.out.println(conversion(new BigDecimal(1), "kgCO2e/MJ", "tCO2e/MJ",4));
System.out.println(System.currentTimeMillis() - s);
}
/**
* 获取计量单位枚举
*
* @param unit - 计量单位名称
* @param unitsEnumParam 指定计量单位的类型可以为空
* @return UnitsEnum - 计量单位
*/
public static UnitsEnum getUnitEnum(String unit, UnitsEnum unitsEnumParam) {
if (StringUtils.isBlank(unit)) {
throw new BusinessException("存在不支持的计量单位参数:" + unit);
}
if (unitsEnumParam != null) {
for (UnitsEnum unitEnum : UnitsEnum.values()) {
if (unitEnum.getCategory() == unitsEnumParam.getCategory() && unitEnum.getUnits().equals(unit)) {
return unitEnum;
}
}
} else {
for (UnitsEnum unitEnum : UnitsEnum.values()) {
if (unitEnum.getUnits().equals(unit)) {
return unitEnum;
}
}
}
return UnitsEnum.UN_KNOWN;
}
/**
* 获取计量单位枚举
*
* @param unit - 计量单位名称
* @return UnitsEnum - 计量单位
*/
public static List<UnitsEnum> getUnitEnum(String unit) {
if (StringUtils.isBlank(unit)) {
throw new BusinessException("存在不支持的计量单位参数:" + unit);
}
List<UnitsEnum> unitsEnums = new ArrayList<>();
for (UnitsEnum unitEnum : UnitsEnum.values()) {
if (unitEnum.getUnits().equals(unit)) {
unitsEnums.add(unitEnum);
}
}
if (unitsEnums.size() == 0) throw new BusinessException("存在不支持的计量单位参数:" + unit);
return unitsEnums;
}
@Getter
public enum UnitsEnum {
/**
* 长度计量单位
*/
LG_KM(CategoryEnum.LENGTH, "km", "0.001", "千米"),
LG_M(CategoryEnum.LENGTH, "m", "1", ""),
LG_DM(CategoryEnum.LENGTH, "dm", "10", "分米"),
LG_CM(CategoryEnum.LENGTH, "cm", "100", "厘米"),
LG_MM(CategoryEnum.LENGTH, "mm", "1000", "毫米"),
LG_UM(CategoryEnum.LENGTH, "um", "1000000", "微米"),
LG_NM(CategoryEnum.LENGTH, "nm", "1000000000", "纳米"),
LG_INCH(CategoryEnum.LENGTH, "in", "39.3700787", "英寸"),
LG_FOOT(CategoryEnum.LENGTH, "ft", "3.2808399", "英尺"),
LG_MILES(CategoryEnum.LENGTH, "mi", "0.00062137", "英里"),
LG_NAUTICAL_MILE(CategoryEnum.LENGTH, "nmile", "0.00053996", "海里"),
/**
* 温度计量单位
*/
TG_DEGREE_CELSIUS(CategoryEnum.TEMPERATURE, "", "1", "摄氏度"),
TG_FAHRENHEIT_SCALE(CategoryEnum.TEMPERATURE, "", "(a-32)*5/9", "(a*9/5) + 32", "华氏度"),
TG_KELVIN_SCALE(CategoryEnum.TEMPERATURE, "K", "a-273.15", "a+273.15", "开氏度"),
/**
* 质量计量单位
*/
EG_T(CategoryEnum.WEIGHT, "t", "0.001", ""),
EG_KG(CategoryEnum.WEIGHT, "kg", "1", "千克"),
EG_G(CategoryEnum.WEIGHT, "g", "1000", ""),
EG_MG(CategoryEnum.WEIGHT, "mg", "1000000", "毫克"),
EG_UG(CategoryEnum.WEIGHT, "μg", "1000000000", "微克"),
EG_LB(CategoryEnum.WEIGHT, "lb", "2.2046226", ""),
EG_OZ(CategoryEnum.WEIGHT, "oz", "35.2739619", "盎司"),
EG_CT(CategoryEnum.WEIGHT, "ct", "5000", "克拉"),
/**
* 速度计量单位
*/
TS_KM(CategoryEnum.SPEED, "km/h", "1", "公里/小时"),
TS_M(CategoryEnum.SPEED, "m/s", "3.6", "米/秒"),
TS_MILES(CategoryEnum.SPEED, "mi/h", "0.62137119", "英里/小时"),
TS_NAUTICAL_MILE(CategoryEnum.SPEED, "nmile/h", "0.5399568", "海里/小时"),
TS_KNOT(CategoryEnum.SPEED, "knot", "0.5399568", ""),
TS_MACH(CategoryEnum.SPEED, "mach", "0.00080985", "马赫"),
/**
* 面积计量单位
*/
AR_M2(CategoryEnum.AREA, "", "1", "平方米"),
AR_KM2(CategoryEnum.AREA, "km²", "0.000001", "平方千米"),
/**
* 体积计量单位
*/
VOL_M3(CategoryEnum.VOLUME, "", "1", "立方米"),
VOL_T(CategoryEnum.VOLUME, "t", "1", ""),
VOL_DM3(CategoryEnum.VOLUME, "dm³", "1000", "立方分米"),
VOL_CM3(CategoryEnum.VOLUME, "cm³", "1000000", "立方厘米"),
VOL_MM3(CategoryEnum.VOLUME, "mm³", "1000000000", "立方毫米"),
VOL_L(CategoryEnum.VOLUME, "l", "1000", ""),
VOL_DL(CategoryEnum.VOLUME, "dl", "10000", "分升"),
VOL_CL(CategoryEnum.VOLUME, "cl", "100000", "厘升"),
VOL_ML(CategoryEnum.VOLUME, "ml", "1000000", "毫升"),
/**
* 压强计量单位
*/
P_ATM(CategoryEnum.PRESSURE, "atm", "1", "标准大气压"),
P_PA(CategoryEnum.PRESSURE, "Pa", "101325", "帕斯卡"),
P_HPA(CategoryEnum.PRESSURE, "hPa", "1013.25", "百帕"),
P_KPA(CategoryEnum.PRESSURE, "KPa", "101.325", "千帕"),
P_MPA(CategoryEnum.PRESSURE, "MPa", "0.101325", "兆帕"),
/**
* 有功功率计量单位
*/
AP_W(CategoryEnum.ACTIVE_POWER, "W", "1000", ""),
AP_KW(CategoryEnum.ACTIVE_POWER, "kW", "1", "千瓦"),
AP_MW(CategoryEnum.ACTIVE_POWER, "MW", "0.001", "兆瓦"),
/**
* 无功功率计量单位
*/
RP_VAR(CategoryEnum.REACTIVE_POWER, "Var", "1000", "乏尔"),
RP_KVAR(CategoryEnum.REACTIVE_POWER, "kVar", "1", "千乏尔"),
RP_MVAR(CategoryEnum.REACTIVE_POWER, "MVar", "0.001", "兆乏尔"),
/**
* 视在功率计量单位
*/
VA_VA(CategoryEnum.APPARENT_POWER, "VA", "1000", "伏安"),
VA_KVA(CategoryEnum.APPARENT_POWER, "kVA", "1", "千伏安"),
VA_MVA(CategoryEnum.APPARENT_POWER, "MVA", "0.001", "兆伏安"),
/**
* 时间
*/
T_YEAR(CategoryEnum.TIME, "yr", "1", ""),
T_MONTH(CategoryEnum.TIME, "month", "12", ""),
T_D(CategoryEnum.TIME, "d", "365", ""),
T_WEEK(CategoryEnum.TIME, "week", "52.1428571", ""),
T_HOUR(CategoryEnum.TIME, "h", "8760", "小时"),
T_MINUTE(CategoryEnum.TIME, "min", "525600", "分钟"),
T_SECOND(CategoryEnum.TIME, "s", "31536000", ""),
/**
* 角度
*/
DEG_D(CategoryEnum.APPARENT_POWER, "°", "1", ""),
DEG_F(CategoryEnum.APPARENT_POWER, "'", "60", ""),
DEG_M(CategoryEnum.APPARENT_POWER, "\"", "3600", ""),
/**
* 密度
*/
DY_MGM3(CategoryEnum.DENSITY, "mg/m³", "1", "毫克每立方米"),
DY_UGM3(CategoryEnum.DENSITY, "μg/m³", "0.001", "微克每立方米"),
DY_PPM(CategoryEnum.DENSITY, "ppm", "0.000001", "百万分比浓度"),
DY_MGL(CategoryEnum.DENSITY, "mg/L", "1000", "毫克每升"),
/**
* 角度
*/
TO_JOULE(CategoryEnum.THERMO, "J", "1", "焦耳"),
TO_KILOJOULE(CategoryEnum.THERMO, "kJ", "0.001", "千焦"),
TO_MEGAJOULE(CategoryEnum.THERMO, "MJ", "0.000001", "兆焦"),
TO_GIGAJOULE(CategoryEnum.THERMO, "GJ", "0.000000001", "吉焦"),
/**
* 流量
*/
F1_M3S(CategoryEnum.FLOW_ONE, "m³/s", "1", "立方米每秒"),
F1_M3M(CategoryEnum.FLOW_ONE, "m³/min", "0.06", "立方米每分钟"),
F1_M3H(CategoryEnum.FLOW_ONE, "m³/h", "0.001", "立方米每小时"),
F2_LS(CategoryEnum.FLOW_TWO, "L/s", "1", "升每秒"),
F2_LM(CategoryEnum.FLOW_TWO, "L/min", "60", "升每分钟"),
F2_LH(CategoryEnum.FLOW_TWO, "L/h", "3600", "升每小时"),
/**
* 照度
*/
ILL_LM(CategoryEnum.ILLUMINANCE, "1Lm/m²", "1", "平方米流明"),
ILL_LX(CategoryEnum.ILLUMINANCE, "Lx", "1", "勒克斯"),
/**
* 电流计量单位
*/
CURRENT_A(CategoryEnum.CURRENT, "A", "1", ""),
CURRENT_MA(CategoryEnum.CURRENT, "mA", "0.001", "毫安"),
CURRENT_UA(CategoryEnum.CURRENT, "μA", "0.000001", "微安"),
/**
* 电压计量单位
*/
VOLT_V(CategoryEnum.VOLTAGE, "V", "1", "伏特"),
VOLT_KV(CategoryEnum.VOLTAGE, "Kv", "0.001", "千伏"),
/**
* 电量计量单位
*/
POWER_W(CategoryEnum.POWER, "Wh", "1", "瓦时"),
POWER_KW(CategoryEnum.POWER, "kWh", "0.001", "千瓦时"),
POWER_MW(CategoryEnum.POWER, "MWh", "0.000001", "兆瓦时"),
POWER_GW(CategoryEnum.POWER, "GWh", "0.000000001", "吉瓦时"),
/**
* 热当量
*/
HC1_TCE(CategoryEnum.HEAT_CAPACITY1, "tce", "1", "吨标准煤"),
HC1_KGCE(CategoryEnum.HEAT_CAPACITY1, "kgce", "1000", "千克标准煤"),
HC2_TCE(CategoryEnum.HEAT_CAPACITY2, "tce/m³", "1", "吨标准煤/立方米"),
HC2_KGCE(CategoryEnum.HEAT_CAPACITY2, "kgce/m³", "1000", "千克标准煤/立方米"),
HC3_TCE(CategoryEnum.HEAT_CAPACITY3, "tce/kg", "1", "吨标准煤/千克"),
HC3_KGCE(CategoryEnum.HEAT_CAPACITY3, "kgce/kg", "1000", "千克标准煤/千克"),
HC4_TCE(CategoryEnum.HEAT_CAPACITY4, "tce/MJ", "1", "吨标准煤/兆焦"),
HC4_KGCE(CategoryEnum.HEAT_CAPACITY4, "kgce/MJ", "1000", "千克标准煤/兆焦"),
HC5_TCE(CategoryEnum.HEAT_CAPACITY5, "tce/GJ", "1", "吨标准煤/吉焦"),
HC5_KGCE(CategoryEnum.HEAT_CAPACITY5, "kgce/GJ", "1000", "千克标准煤/吉焦"),
HC6_TCE(CategoryEnum.HEAT_CAPACITY6, "tce/t", "1", "吨标准煤/吨"),
HC6_KGCE(CategoryEnum.HEAT_CAPACITY6, "kgce/t", "1000", "千克标准煤/吨"),
HC7_TCE(CategoryEnum.HEAT_CAPACITY7, "tce/L", "1", "吨标准煤/升"),
HC7_KGCE(CategoryEnum.HEAT_CAPACITY7, "kgce/L", "1000", "千克标准煤/升"),
HC8_TCE(CategoryEnum.HEAT_CAPACITY8, "tce/kWh", "1", "吨标准煤/千瓦时"),
HC8_KGCE(CategoryEnum.HEAT_CAPACITY8, "kgce/kWh", "1000", "千克标准煤/千瓦时"),
CEF1_TCO(CategoryEnum.CEF1, "tCO2e", "1", "吨二氧化碳当量"),
CEF1_KGCO(CategoryEnum.CEF1, "KgCO2e", "1000", "千克二氧化碳当量"),
CEF2_TCO(CategoryEnum.CEF2, "tCO2e/m³", "1", "吨二氧化碳当量/立方米"),
CEF2_KGCO(CategoryEnum.CEF2, "KgCO2e/m³", "1000", "千克二氧化碳当量/立方米"),
CEF3_TCO(CategoryEnum.CEF3, "tCO2e/t", "1", "吨二氧化碳当量/吨"),
CEF3_KGCO(CategoryEnum.CEF3, "KgCO2e/t", "1000", "千克二氧化碳当量/吨"),
CEF4_TCO(CategoryEnum.CEF4, "tCO2e/kg", "1", "吨二氧化碳当量/千克"),
CEF4_KGCO(CategoryEnum.CEF4, "KgCO2e/kg", "1000", "千克二氧化碳当量/千克"),
CEF5_TCO(CategoryEnum.CEF5, "tCO2e/L", "1", "吨二氧化碳当量/升"),
CEF5_KGCO(CategoryEnum.CEF5, "KgCO2e/L", "1000", "千克二氧化碳当量/升"),
CEF6_TCO(CategoryEnum.CEF6, "tCO2e/MWh", "1", "吨二氧化碳当量/千瓦时"),
CEF6_KGCO(CategoryEnum.CEF6, "KgCO2e/kWh", "1000", "千克二氧化碳当量/千瓦时"),
CEF7_TCO(CategoryEnum.CEF7, "tCO2e/GJ", "1", "吨二氧化碳当量/吉焦"),
CEF7_KGCO(CategoryEnum.CEF7, "KgCO2e/GJ", "1000", "千克二氧化碳当量/吉焦"),
CEF7_TCOMJ(CategoryEnum.CEF7, "tCO2e/MJ", "0.001", "吨二氧化碳每兆焦"),
CEF7_KGCOMJ(CategoryEnum.CEF7, "kgCO2e/MJ", "1", "千克二氧化碳每兆焦"),
/**
* 未知
*/
UN_KNOWN(CategoryEnum.UN_KNOWN, "未知", "0", "未知");
/**
* 计量类别
*/
private final CategoryEnum category;
/**
* 计量单位
*/
private final String units;
/**
* 换算表达式
*/
private final String conversionBaseUnitExpression;
/**
* 换算表达式
*/
private final String conversionExpression;
/**
* 描述
*/
private final String description;
UnitsEnum(CategoryEnum category, String units, String conversionBaseUnitExpression, String description) {
this.category = category;
this.units = units;
this.conversionBaseUnitExpression = conversionBaseUnitExpression;
this.description = description;
this.conversionExpression = ""; // 设置默认值为空字符串
}
UnitsEnum(CategoryEnum category, String units, String conversionBaseUnitExpression, String conversionExpression, String description) {
this.category = category;
this.units = units;
this.conversionBaseUnitExpression = conversionBaseUnitExpression;
this.conversionExpression = conversionExpression;
this.description = description;
}
}
/**
* 计量类别
*/
@Getter
public enum CategoryEnum {
/**
* 长度
*/
LENGTH("Length", "长度"),
/**
* 质量
*/
WEIGHT("Weight", "质量"),
/**
* 温度
*/
TEMPERATURE("Temperature", "温度"),
/**
* 速度
*/
SPEED("Speed", "速度"),
AREA("Area", "面积"),
VOLUME("Volume", "体积"),
PRESSURE("Pressure", "压强"),
ACTIVE_POWER("ActivePower", "有功功率"),
REACTIVE_POWER("ReactivePower", "无功功率"),
APPARENT_POWER("ApparentPower", "视在功率"),
TIME("Time", "时间"),
ANGLE("Angle", "角度"),
/**
* 密度
*/
DENSITY("Density", "密度"),
/**
* 热工
*/
THERMO("Thermo", "热工"),
/**
* 流量
*/
FLOW_ONE("Flow1", "流量(立方米)"),
FLOW_TWO("Flow2", "流量(升)"),
ILLUMINANCE("Illuminance", "照度"),
/**
* 电流
*/
CURRENT("Current", "电流"),
/**
* 电压
*/
VOLTAGE("Voltage", "电压"),
/**
* 电量
*/
POWER("Power", "电量"),
UN_KNOWN("un_known", "未知"),
HEAT_CAPACITY1("HeatCapacity1", "热当量"),
HEAT_CAPACITY2("HeatCapacity2", "热当量"),
HEAT_CAPACITY3("HeatCapacity3", "热当量"),
HEAT_CAPACITY4("HeatCapacity4", "热当量"),
HEAT_CAPACITY5("HeatCapacity5", "热当量"),
HEAT_CAPACITY6("HeatCapacity6", "热当量"),
HEAT_CAPACITY7("HeatCapacity7", "热当量"),
HEAT_CAPACITY8("HeatCapacity8", "热当量"),
CEF1("CarbonEmissionFactor1", "碳排放因子"),
CEF2("CarbonEmissionFactor2", "碳排放因子"),
CEF3("CarbonEmissionFactor3", "碳排放因子"),
CEF4("CarbonEmissionFactor4", "碳排放因子"),
CEF5("CarbonEmissionFactor5", "碳排放因子"),
CEF6("CarbonEmissionFactor6", "碳排放因子"),
CEF7("CarbonEmissionFactor7", "碳排放因子"),
CEF8("CarbonEmissionFactor8", "碳排放因子"),
;
/**
* 类别名称
*/
private final String name;
/**
* 描述
*/
private final String description;
CategoryEnum(String name, String description) {
this.name = name;
this.description = description;
}
}
public static List<String> getUnitList(String category) {
UnitsEnum[] units = UnitsEnum.values();
if (StringUtils.isNotBlank(category)) {
List<String> categoryByDes = getCategoryByDes(category);
if (CollectionUtils.isEmpty(categoryByDes)) return new ArrayList<>();
return Arrays.stream(units).filter(unitsEnum ->
categoryByDes.contains(unitsEnum.getCategory().getName()))
.map(UnitsEnum::getUnits).collect(Collectors.toList());
}
return Arrays.stream(units).map(UnitsEnum::getUnits).collect(Collectors.toList());
}
public static List<String> getCategoryByDes(String description) {
CategoryEnum[] values = CategoryEnum.values();
return Arrays.stream(values).filter(categoryEnum -> categoryEnum.getDescription().equals(description)).map(CategoryEnum::getName).collect(Collectors.toList());
}
/**
* 获取计量单位类型列表
*/
public static List<String> getCategoryList() {
CategoryEnum[] values = CategoryEnum.values();
return Arrays.stream(values).filter(s-> !s.getDescription().equals("未知")).map(CategoryEnum::getDescription).distinct().collect(Collectors.toList());
}
public static List<UnitTreeVO> buildTree(){
List<UnitTreeVO> result=new ArrayList<>();
List<String> categoryList = getCategoryList();
for (String category : categoryList) {
result.add(UnitTreeVO.builder().label(category).children(getUnitList(category)).build());
}
return result;
}
}

View File

@ -0,0 +1,63 @@
package com.isu.gaswellwatch.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class LoginRecordExportVO {
/**
* 用户名
*/
@ExcelProperty("账号")
private String username;
/**
* 用户姓名
*/
@ExcelProperty("使用者")
private String nickname;
/**
* 请求结果
*/
@ExcelIgnore
private Integer result;
/**
* 请求结果
*/
@ExcelProperty("调用结果")
private String resultDesc;
/**
* 登录ip
*/
@ExcelProperty("调用ip")
private String ip;
/**
* 错误消息
*/
@ExcelProperty("错误信息")
private String errorMsg;
/**
* 创建时间
*/
@ExcelProperty("操作时间")
private String createTime;
}

View File

@ -0,0 +1,30 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MenuListVO {
private Long id;
//父节点
private Long parent;
//名称
private String name;
//编码
private String code;
//图标
private String icon;
//顺序
private Integer sort;
//外部数据
private String extra;
//标识符
private List<String> identifier;
}

View File

@ -0,0 +1,33 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MenuTreeVO {
private Long id;
//父节点
private Long parent;
//名称
private String name;
//编码
private String code;
//图标
private String icon;
//顺序
private Integer sort;
//外部数据
private String extra;
//标识符
private List<String> identifier;
private List<MenuTreeVO> children;
}

View File

@ -0,0 +1,35 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MenuVO {
private Long id;
//父节点
private Long parent;
//名称
private String name;
//编码
private String code;
//图标
private String icon;
//顺序
private Integer sort;
//外部数据
private String extra;
//标识符
private String identifier;
}

View File

@ -0,0 +1,20 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RoleVO implements Serializable {
private Long id;
//名称
private String name;
//描述
private String description;
}

View File

@ -0,0 +1,24 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TreeVO<T> {
private Long id;
//父编码
private Long parent;
//排序
private Integer sort;
private List<T> children;
}

View File

@ -0,0 +1,17 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UnitTreeVO {
private String label;
private List<String> children;
}

View File

@ -0,0 +1,16 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserLoginInfoVO {
private String token;
private UserVO userVO;
}

View File

@ -0,0 +1,108 @@
package com.isu.gaswellwatch.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserOperationRecordExportVO {
/**
* 日志类型
*/
@ExcelIgnore
private Integer type;
/**
* 日志类型
*/
@ExcelProperty("日志类型")
private String typeDesc;
/**
* 用户名
*/
@ExcelProperty("账号")
private String username;
/**
* 用户姓名
*/
@ExcelProperty("使用者")
private String nickname;
/**
* 请求地址
*/
@ExcelProperty("调用地址")
private String uri;
/**
* 菜单
*/
@ExcelProperty("调用菜单")
private String menu;
/**
* 请求参数
*/
@ExcelProperty("请求参数")
private String request;
/**
* 请求类型
*/
@ExcelProperty("请求类型")
private String requestType;
/**
* 请求结果
*/
@ExcelIgnore
private Integer result;
/**
* 请求结果
*/
@ExcelProperty("调用结果")
private String resultDesc;
/**
* 登录ip
*/
@ExcelProperty("调用ip")
private String ip;
/**
* 日志标题
*/
@ExcelProperty("接口信息")
private String name;
/**
* 错误消息
*/
@ExcelProperty("错误信息")
private String errorMsg;
/**
* 创建时间
*/
@ExcelProperty("操作时间")
private String createTime;
/**
* 请求时间
*/
@ExcelProperty("请求时间(毫秒)")
private long costTime;
}

View File

@ -0,0 +1,83 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserOperationRecordVO {
private Long id;
/**
* 日志类型
*/
private Integer type;
/**
* 用户名
*/
private String username;
/**
* 用户姓名
*/
private String nickname;
/**
* 请求地址
*/
private String uri;
/**
* 菜单
*/
private String menu;
/**
* 请求参数
*/
private String request;
/**
* 请求类型
*/
private String requestType;
/**
* 请求结果
*/
private Integer result;
/**
* 登录ip
*/
private String ip;
/**
* 日志标题
*/
private String name;
/**
* 错误消息
*/
private String errorMsg;
/**
* 创建时间
*/
private String createTime;
/**
* 请求时间
*/
private long costTime;
}

View File

@ -0,0 +1,30 @@
package com.isu.gaswellwatch.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserVO implements Serializable {
private Long id;
//账户
private String username;
//昵称
private String nickname;
//手机号
private String phone;
//是否启用
private String isEnable;
private List<RoleVO> roles;
//创建时间
private String createTime;
}

View File

@ -0,0 +1,7 @@
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3306/gaswellwatch?characterEncoding=UTF-8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: QINjie5111.com
driver-class-name: com.mysql.cj.jdbc.Driver

View File

View File

View File

@ -0,0 +1,35 @@
spring:
application:
name: gasWell-watch
servlet:
multipart:
max-file-size: 100MB #-1 无限制
max-request-size: 200MB #指定为100MB -1无限制
profiles:
active: @environment@
server:
port: 8090
sa-token:
# token 名称同时也是cookie名称
token-name: token
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: false
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: false
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true
# 关闭cookie
is-read-cookie: false
snowflake:
worker: 0
data-center: 1

View File

@ -0,0 +1,20 @@
<?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="com.isu.gaswellwatch.dao.MenuDao">
<select id="selectRoleMenu" resultType="com.isu.gaswellwatch.vo.MenuVO">
select distinct m.id, m.parent, m.name, m.code, m.icon, m.sort, ru.identifier, m.extra
from role_menu ru
left join menu m on ru.menu_id = m.id
<where>
<if test="ids!=null and ids.size >0 ">
ru.role_id in
<foreach item="id" collection="ids" index="index" open="(" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
</mapper>

View File

@ -0,0 +1,93 @@
<?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="com.isu.gaswellwatch.dao.UserDao">
<resultMap id="userVOResultMap" type="com.isu.gaswellwatch.vo.UserVO">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="nickname" property="nickname"/>
<result column="phone" property="phone"/>
<result column="is_enable" property="isEnable"/>
<result column="create_time" property="createTime"/>
<collection property="roles" javaType="java.util.List" ofType="com.isu.gaswellwatch.vo.RoleVO">
<id column="roleId" property="id"/>
<result column="roleName" property="name"/>
<result column="roleDescription" property="description"/>
</collection>
</resultMap>
<select id="list" resultMap="userVOResultMap">
select u.id, u.username, u.nickname, u.phone, u.is_enable, u.create_time, r.id as roleId, r.name as roleName, r.description as roleDescription
from user u
left join user_role t on u.id = t.user_id
left join role r on t.role_id = r.id
<where>
<if test="username!=null and username!='' ">
and u.username LIKE CONCAT('%',#{username},'%')
</if>
<if test="name!=null and name!='' ">
and u.nickname LIKE CONCAT('%',#{name},'%')
</if>
<if test="isEnable!=null and isEnable!='' ">
and u.is_enable = #{isEnable}
</if>
<if test="roleId!=null and roleId!='' ">
and r.id = #{roleId}
</if>
</where>
order by u.create_time desc
</select>
<resultMap id="userVOPageMap" type="com.isu.gaswellwatch.vo.UserVO">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="nickname" property="nickname"/>
<result column="phone" property="phone"/>
<result column="is_enable" property="isEnable"/>
<result column="create_time" property="createTime"/>
<collection property="roles" javaType="java.util.List" ofType="com.isu.gaswellwatch.vo.RoleVO" select="getUserRoles" column="{user_id=id}">
</collection>
</resultMap>
<select id="page" resultMap="userVOPageMap">
select u.id, u.username, u.nickname, u.phone, u.is_enable, u.create_time
from user u
<where>
<if test="username!=null and username!='' ">
and u.username LIKE CONCAT('%',#{username},'%')
</if>
<if test="name!=null and name!='' ">
and u.nickname LIKE CONCAT('%',#{name},'%')
</if>
<if test="isEnable!=null and isEnable!='' ">
and u.is_enable = #{isEnable}
</if>
<if test="ids!=null and ids.size >0 ">
and u.id in
<foreach item="id" collection="ids" index="index" open="(" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
order by u.create_time desc
</select>
<select id="getUserRoles" resultType="com.isu.gaswellwatch.vo.RoleVO">
SELECT r.id, r.name, r.description
FROM role r
LEFT JOIN user_role ur ON ur.role_id=r.id
where ur.user_id=#{user_id}
</select>
<select id="selectUserInfo" resultMap="userVOResultMap">
select u.id, u.username, u.nickname, u.phone, u.is_enable, r.id as roleId, r.name as roleName, r.description as roleDescription
from user u
left join user_role t on u.id = t.user_id
left join role r on t.role_id = r.id
where u.username = #{username}
</select>
</mapper>

View File

@ -0,0 +1,74 @@
<?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="com.isu.gaswellwatch.dao.UserOperationRecordDao">
<resultMap id="userVOResultMap" type="com.isu.gaswellwatch.vo.UserOperationRecordVO">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="type" property="type"/>
<result column="uri" property="uri"/>
<result column="menu" property="menu"/>
<result column="nickname" property="nickname"/>
<result column="create_time" property="createTime"/>
<result column="request" property="request"/>
<result column="request_type" property="requestType"/>
<result column="result" property="result"/>
<result column="ip" property="ip"/>
<result column="name" property="name"/>
<result column="error_msg" property="errorMsg"/>
<result column="cost_time" property="costTime"/>
</resultMap>
<select id="page" resultMap="userVOResultMap">
select r.id, r.username, u.nickname, r.type, r.uri, r.create_time, r.menu , r.name , r.request ,r.request_type,r.result,r.ip,r.error_msg,r.cost_time
from user_operation_record r
left join user u on u.username = r.username
<where>
<if test="type!=null">
and r.type =#{type}
</if>
<if test="username!=null and username!='' ">
and r.username LIKE CONCAT('%',#{username},'%')
</if>
<if test="nickname!=null and nickname!='' ">
and u.nickname LIKE CONCAT('%',#{nickname},'%')
</if>
<if test="result!=null">
and r.result = #{result}
</if>
<if test="startTime!=null and startTime!='' ">
and date_format(r.create_time,'%Y-%m-%d') &gt;= date_format(#{startTime},'%Y-%m-%d')
</if>
<if test="endTime!=null and endTime!='' ">
and date_format(r.create_time,'%Y-%m-%d') &lt;= date_format(#{endTime},'%Y-%m-%d ')
</if>
</where>
order by r.create_time desc
</select>
<select id="list" resultMap="userVOResultMap">
select r.id, r.username, u.nickname, r.type, r.uri, r.create_time, r.menu , r.name , r.request ,r.request_type,r.result,r.ip,r.error_msg,r.cost_time
from user_operation_record r
left join user u on u.username = r.username
<where>
<if test="type!=null">
and r.type =#{type}
</if>
<if test="username!=null and username!='' ">
and r.username LIKE CONCAT('%',#{username},'%')
</if>
<if test="nickname!=null and nickname!='' ">
and u.nickname LIKE CONCAT('%',#{nickname},'%')
</if>
<if test="result!=null">
and r.result = #{result}
</if>
<if test="startTime!=null and startTime!='' ">
and date_format(r.create_time,'%Y-%m-%d') &gt;= date_format(#{startTime},'%Y-%m-%d')
</if>
<if test="endTime!=null and endTime!='' ">
and date_format(r.create_time,'%Y-%m-%d') &lt;= date_format(#{endTime},'%Y-%m-%d')
</if>
</where>
order by r.create_time desc
</select>
</mapper>

View File

@ -0,0 +1,7 @@
<?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="com.isu.gaswellwatch.dao.UserOperationRecordMapper">
</mapper>

View File

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