Compare commits

..

40 Commits

Author SHA1 Message Date
pveayojnc 31f30b6a15 Update ZhxyApplication.java
4 months ago
pveayojnc 60aa90e4a1 Update UploadFile.java
4 months ago
pveayojnc 8b7ec6c9cd Update ResultCodeEnum.java
4 months ago
pveayojnc 380fbcc5b2 Update Result.java
4 months ago
pveayojnc 9bec458c97 Update MD5.java
4 months ago
pveayojnc 56e0f93811 Update LocalUploadUtil.java
4 months ago
pveayojnc 6326377e7e Update JwtHelper.java
4 months ago
pveayojnc ec15593a84 Update CreateVerifiCodeImage.java
4 months ago
pveayojnc f670e5d2f9 Update TeacherService.java
4 months ago
pveayojnc 3da0fd3c3d Update StudentService.java
4 months ago
pveayojnc 1b19682be2 Update GradeService.java
4 months ago
pveayojnc 000c509be7 Update ClazzService.java
4 months ago
pveayojnc 66e1134788 Update AdminService.java
4 months ago
pveayojnc 0dbf2804ff Update TeacherServiceImpl.java
4 months ago
pveayojnc 1d3538c720 Update StudentServiceImpl.java
4 months ago
pveayojnc 2436048a06 Update GradeServiceImpl.java
4 months ago
pveayojnc cad714caaa Update ClazzServiceImpl.java
4 months ago
pveayojnc ab55d15664 Update AdminServiceImpl.java
4 months ago
pveayojnc 43a1776190 Update Teacher.java
4 months ago
pveayojnc 36673fe094 Update Student.java
4 months ago
pveayojnc fc0674d77f Update LoginForm.java
4 months ago
pveayojnc 31cebfdc50 Update Grade.java
4 months ago
pveayojnc 3b05382d36 Update Clazz.java
4 months ago
pveayojnc a58506faab Update Admin.java
4 months ago
pveayojnc e34710b01a Update TeacherMapper.java
4 months ago
pveayojnc 120cd80c33 Update StudentMapper.java
4 months ago
pveayojnc 3f44fd811a Update GradeMapper.java
4 months ago
pveayojnc a711421bec Update ClazzMapper.java
4 months ago
pveayojnc 9d29fda262 Update AdminMapper.java
4 months ago
pveayojnc 224017a40e Update TeacherController.java
4 months ago
pveayojnc 8724505524 Update SystemController.java
4 months ago
pveayojnc e3d3185534 Update StudentController.java
4 months ago
pveayojnc ffb4e2a33f Update GradeController.java
4 months ago
pveayojnc 1bf6d8f825 Update ClazzController.java
4 months ago
pveayojnc 80e35cf1bd Update AdminController.java
4 months ago
pveayojnc 6ef529c891 Update SystemUtil.java
4 months ago
pveayojnc fe221430c6 Update Swagger2Config.java
4 months ago
pveayojnc 907aabe4c4 Update MpConfig.java
4 months ago
pveayojnc 3ea549bac1 Update ConfigurerAdapter.java
4 months ago
lzw 50dd029de9 11
4 months ago

33
.gitignore vendored

@ -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/

Binary file not shown.

@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar

@ -0,0 +1,158 @@
/*
Navicat Premium Data Transfer
Source Server : localhost_3306
Source Server Type : MySQL
Source Server Version : 80028 (8.0.28)
Source Host : localhost:3306
Source Schema : db
Target Server Type : MySQL
Target Server Version : 80028 (8.0.28)
File Encoding : 65001
Date: 05/03/2024 13:45:55
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tb_admin
-- ----------------------------
DROP TABLE IF EXISTS `tb_admin`;
CREATE TABLE `tb_admin` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`gender` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`telephone` varchar(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`address` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`portrait_path` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 105 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of tb_admin
-- ----------------------------
INSERT INTO `tb_admin` VALUES (101, 'admin', '', '21232f297a57a5a743894a0e4a801fc3', '111111@qq.com', '13866666666', '昌平', '/upload/20240305_13290833.jpg');
-- ----------------------------
-- Table structure for tb_clazz
-- ----------------------------
DROP TABLE IF EXISTS `tb_clazz`;
CREATE TABLE `tb_clazz` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`number` int NULL DEFAULT NULL,
`introducation` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`headmaster` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`telephone` varchar(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`grade_name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of tb_clazz
-- ----------------------------
INSERT INTO `tb_clazz` VALUES (1, '一年一班', 30, '大圣的一年一班好', '大圣', 'dasheng@163.com', '13866666666', '一年级');
INSERT INTO `tb_clazz` VALUES (2, '一年二班', 28, '小张的一年二班好', '小张', 'xiaozhang@163.com', '13866666666', '一年级');
INSERT INTO `tb_clazz` VALUES (3, '二年一班', 35, '小韩的二年一班好', '小韩', 'xiaohan@163.com', '13866666666', '二年级');
INSERT INTO `tb_clazz` VALUES (4, '二年二班', 30, '小强的二年二班好', '小强', 'xiaoqiang@163.com', '13866666666', '二年级');
INSERT INTO `tb_clazz` VALUES (5, '三年一班', 30, '小花的三年一班好', '小花', 'xiaohua@163.com', '13866666666', '三年级');
INSERT INTO `tb_clazz` VALUES (6, '三年二班', 30, '小赵的三年二班好', '小赵', 'xiaozhao@163.com', '13866666666', '三年级');
INSERT INTO `tb_clazz` VALUES (7, '四年一班', 30, '小赵的三年二班好', '小飞', 'xiaofei@163.com', '13866666666', '四年级');
INSERT INTO `tb_clazz` VALUES (11, '六年二班', 70, '6666666666', '李四', '511@163.com', '14785369912', '六年级');
INSERT INTO `tb_clazz` VALUES (13, '六年三班', 50, '6666666666666', '李四', '154@163.com', '17752896321', '六年级');
-- ----------------------------
-- Table structure for tb_grade
-- ----------------------------
DROP TABLE IF EXISTS `tb_grade`;
CREATE TABLE `tb_grade` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`manager` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`telephone` varchar(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`introducation` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`, `name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of tb_grade
-- ----------------------------
INSERT INTO `tb_grade` VALUES (1, '一年级', '大圣', 'dasheng@163.com', '13866666666', '大学一年级');
INSERT INTO `tb_grade` VALUES (2, '二年级', '小魏', 'xiaowei@163.com', '13866666666', '大学二年级');
INSERT INTO `tb_grade` VALUES (3, '三年级', '小李', 'xiaoli@163.com', '13666666666', '三年级,这个班级的孩子们很有才艺');
INSERT INTO `tb_grade` VALUES (4, '五年级', '小丽', 'li@123.com', '13666666666', '这个年级的同学多才多活力');
INSERT INTO `tb_grade` VALUES (5, '六年级', '小明', 'xiaoming@666.com', '13666666666', '这个年级的主任是小明');
INSERT INTO `tb_grade` VALUES (6, '四年级', '王五', '154@163.com', '15632145698', '66666666666');
-- ----------------------------
-- Table structure for tb_student
-- ----------------------------
DROP TABLE IF EXISTS `tb_student`;
CREATE TABLE `tb_student` (
`id` int NOT NULL AUTO_INCREMENT,
`sno` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`gender` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`telephone` varchar(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`address` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`introducation` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`portrait_path` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`clazz_name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of tb_student
-- ----------------------------
INSERT INTO `tb_student` VALUES (1, '1001', '张小明', '', 'e10adc3949ba59abbe56e057f20f883e', 'yinyufei@163.com', '13866666666', '北京天通苑', '这个学生学习好', '/upload/20240305_13255786.jpg', '一年一班');
INSERT INTO `tb_student` VALUES (2, '1002', '郭建超', '', 'e10adc3949ba59abbe56e057f20f883e', 'guojianchao@163.com', '13866666666', '北京昌平', '这个学生会功夫', '/upload/20240305_13260948.jpg', '一年一班');
INSERT INTO `tb_student` VALUES (3, '1003', '史汶鑫', '', 'e10adc3949ba59abbe56e057f20f883e', 'shiwenxin@163.com', '13866666666', '北京昌平', '这个学生酒量好', '/upload/20240305_13261646.jpg', '二年一班');
INSERT INTO `tb_student` VALUES (4, '1004', '高建军', '', 'e10adc3949ba59abbe56e057f20f883e', 'gaojianjun@163.com', '13866666666', '北京昌平', '这个学生会做饭', '/upload/20240305_13262677.jpg', '二年一班');
INSERT INTO `tb_student` VALUES (5, '1005', '邹伟斌', '', 'e10adc3949ba59abbe56e057f20f883e', 'zouweibin@163.com', '13866666666', '北京昌平', '这个学生能吃辣', '/upload/20240305_13263150.jpg', '三年一班');
INSERT INTO `tb_student` VALUES (6, '1006', '刘路', '', 'e10adc3949ba59abbe56e057f20f883e', 'liulu@163.com', '13866666666', '北京昌平', '这个学生是学霸', '/upload/20240305_13263696.jpg', '三年二班');
INSERT INTO `tb_student` VALUES (7, '1007', '庞家仨', '', 'e10adc3949ba59abbe56e057f20f883e', 'pangjiasan@163.com', '13866666666', '北京昌平', '这个学生海拔高', '/upload/20240305_13264443.jpg', '三年二班');
INSERT INTO `tb_student` VALUES (8, '1008', '谭帅333', '', 'e10adc3949ba59abbe56e057f20f883e', 'tanshuai@163.com', '13866666666', '北京昌平', '这个学生想考研', '/upload/20240305_13264977.jpg', '四年一班');
INSERT INTO `tb_student` VALUES (11, '1008611', '张三', '', 'e10adc3949ba59abbe56e057f20f883e', '555@163.com', '17758691236', '北京市海淀区', '这个同学有钱', '/upload/20240305_13315436.jpg', '一年一班');
-- ----------------------------
-- Table structure for tb_teacher
-- ----------------------------
DROP TABLE IF EXISTS `tb_teacher`;
CREATE TABLE `tb_teacher` (
`id` int NOT NULL AUTO_INCREMENT,
`tno` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`gender` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`telephone` varchar(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`address` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`portrait_path` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`clazz_name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of tb_teacher
-- ----------------------------
INSERT INTO `tb_teacher` VALUES (1, '101', '大圣', '', 'e10adc3949ba59abbe56e057f20f883e', 'dasheng@163.com', '13866666666', '北京昌平', '/upload/20240305_13272562.jpg', '一年一班');
INSERT INTO `tb_teacher` VALUES (2, '102', '小张', '', 'e10adc3949ba59abbe56e057f20f883e', 'xiaozhang@163.com', '13866666666', '北京海淀', '/upload/20240305_13273255.jpg', '一年二班');
INSERT INTO `tb_teacher` VALUES (3, '103', '小韩', '', 'e10adc3949ba59abbe56e057f20f883e', 'xiaohan@163.com', '13866666666', '北京朝阳', '/upload/20240305_1327379.jpg', '二年一班');
INSERT INTO `tb_teacher` VALUES (4, '104', '小强', '', 'e10adc3949ba59abbe56e057f20f883e', 'xiaoqiang@163.com', '13866666666', '北京通州', '/upload/20240305_13275819.jpg', '二年二班');
INSERT INTO `tb_teacher` VALUES (5, '105', '小花', '', 'e10adc3949ba59abbe56e057f20f883e', 'xiaohua@163.com', '13866666666', '北京顺义', '/upload/20240305_13280246.jpg', '三年一班');
INSERT INTO `tb_teacher` VALUES (6, '106', '小赵', '', 'e10adc3949ba59abbe56e057f20f883e', 'xiaozhao@163.com', '13866666666', '北京东城', '/upload/20240305_1328082.jpg', '三年二班');
INSERT INTO `tb_teacher` VALUES (7, '107', '小飞', '', 'e10adc3949ba59abbe56e057f20f883e', 'xiaofei@163.com', '13866666666', '北京西城', '/upload/20240305_13281450.jpg', '四年一班');
INSERT INTO `tb_teacher` VALUES (8, '108', '秀秀2', '', 'e10adc3949ba59abbe56e057f20f883e', '123456@123.com', '13855555555', '海淀', '/upload/20240305_13281951.jpg', '一年二班');
INSERT INTO `tb_teacher` VALUES (9, '1002', '李老师', '', 'e10adc3949ba59abbe56e057f20f883e', 'test@qq.com', '17638176639', '上海', '/upload/20240305_13282363.jpg', '一年一班');
INSERT INTO `tb_teacher` VALUES (10, '1001011', '李四', '', 'e10adc3949ba59abbe56e057f20f883e', '1587@163.com', '19512365478', '北京市昌平区', '/upload/20240305_13331656.jpg', '四年一班');
SET FOREIGN_KEY_CHECKS = 1;

316
mvnw vendored

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

188
mvnw.cmd vendored

@ -0,0 +1,188 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

@ -0,0 +1,142 @@
<?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>
<!-- 继承方式使用SpringBoot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.zsz</groupId>
<artifactId>zhxy</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>zhxy</name>
<description>zhxy</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--单元测试启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- thymeleaf支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!-- 简化POJO实体类开发 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<!--swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<!--swagger2 增强版接口文档-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
<!--开发者工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.29</version>
</dependency>
<!-- JWT生成Token-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--spring boot maven插件 , 可以将项目运行依赖的jar包打到我们的项目中-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,44 @@
package com.zsz;
import lombok.extern.slf4j.Slf4j;
// 导入 Spring Boot 的核心注解,用于标识这是一个 Spring Boot 应用程序
import org.springframework.boot.SpringApplication;
// 导入 Spring Boot 的自动配置注解,启用 Spring Boot 的自动配置功能
import org.springframework.boot.autoconfigure.SpringBootApplication;
// 导入 Spring 上下文的可配置应用上下文接口,用于获取应用程序上下文信息
import org.springframework.context.ConfigurableApplicationContext;
// 导入 Spring 环境的可配置环境接口,用于获取应用程序的配置环境信息
import org.springframework.core.env.ConfigurableEnvironment;
// 导入 Java 的网络地址类,用于获取本地主机的地址信息
import java.net.InetAddress;
// 导入 Java 的未知主机异常类,用于处理获取主机地址时可能出现的异常
import java.net.UnknownHostException;
/**
* ZhxyApplication Spring Boot
* 使 Spring Boot Lombok
*/
// 使用 Spring Boot 的 SpringBootApplication 注解,启用自动配置和组件扫描等功能
@SpringBootApplication
// 使用 Lombok 的 Slf4j 注解,自动生成日志记录器对象
@Slf4j
public class ZhxyApplication {
/**
*
* @param args
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException {
// 使用日志记录器输出服务开始启动的信息
log.info("服务开始启动~");
// 启动 Spring Boot 应用程序,并返回可配置的应用上下文对象
ConfigurableApplicationContext applicationContext = SpringApplication.run(ZhxyApplication.class, args);
// 获取应用程序的可配置环境对象
ConfigurableEnvironment env = applicationContext.getEnvironment();
// 使用日志记录器输出服务启动完成的信息,并包含本地主机的地址
log.info("-------服务启动完成:{}-------", InetAddress.getLocalHost().getHostAddress());
}
}

@ -0,0 +1,40 @@
package com.zsz.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
/**
* WebMvc
* Spring MVC
*
* @author
* @date 2018-11-30
*/
@Configuration // 标识这是一个Spring配置类
//@EnableWebMvc // 如需完全接管MVC配置可取消注释当前被注释表示保留Spring Boot自动配置
public class ConfigurerAdapter implements WebMvcConfigurer {
@Resource // 自动注入系统工具类(按名称装配)
private SystemUtil systemUtil;
// 文件存储路径前缀常量
public static final String PATH_PREFIX = "upload/";
/**
*
* URL
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 添加资源处理规则:
// 1. 当访问URL以"/upload/"开头时
// 2. 将请求映射到systemUtil.getFilePrefix()返回的本地文件系统路径
registry.addResourceHandler("/" + PATH_PREFIX + "**")
.addResourceLocations("file:" + systemUtil.getFilePrefix());
}
}

@ -0,0 +1,43 @@
package com.zsz.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MyBatis-Plus
*
* 1. MyBatis-Plus
* 2. Mapper
* 3. MyBatis-Plus
*/
@Configuration // 声明当前类是一个Spring配置类Spring容器启动时会加载这个类
@MapperScan("com.zsz.mapper") // 指定MyBatis Mapper接口的扫描路径自动注册这些接口为Bean
public class MpConfig {
/**
* MyBatis-Plus
*
* 1. SQL
* 2.
* 3.
*
* @return
*/
@Bean // 将返回对象注册为Spring容器管理的Bean
public PaginationInterceptor paginationInterceptor() {
// 创建分页拦截器实例
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 可配置项(当前被注释的示例配置):
// 设置单页最大记录数限制默认500条
// paginationInterceptor.setLimit(100);
// 设置数据库类型可选MyBatis-Plus通常能自动识别
// paginationInterceptor.setDbType(DbType.MYSQL);
return paginationInterceptor;
}
}

@ -0,0 +1,111 @@
package com.zsz.config;
import com.google.common.base.Predicates;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
/**
* Swagger2
* Swagger2RESTful API
*
*/
@Configuration // 声明为Spring配置类
@EnableSwagger2 // 启用Swagger2功能
public class Swagger2Config {
/**
* Web
* header
* @return Docket
*/
@Bean
public Docket webApiConfig(){
// ==================== 配置全局header参数 start ====================
List<Parameter> pars = new ArrayList<>();
// 用户ID参数配置
ParameterBuilder tokenPar = new ParameterBuilder();
tokenPar
.name("userId") // 参数名称
.description("用户ID") // 参数描述
.defaultValue("1") // 默认值
.modelRef(new ModelRef("string")) // 参数类型
.parameterType("header") // 参数位置header
.required(false) // 是否必填
.build();
pars
.add(tokenPar.build()); // 添加到参数列表
// 临时用户ID参数配置
ParameterBuilder tmpPar = new ParameterBuilder();
tmpPar
.name("userTempId") // 参数名称
.description("临时用户ID") // 参数描述
.defaultValue("1") // 默认值
.modelRef(new ModelRef("string")) // 参数类型
.parameterType("header") // 参数位置
.required(false) // 是否必填
.build();
pars
.add(tmpPar.build()); // 添加到参数列表
// ==================== 配置全局header参数 end ====================
return new Docket(DocumentationType.SWAGGER_2) // 指定Swagger2版本
.groupName("webApi") // 分组名称
.apiInfo(webApiInfo()) // 设置文档信息
.select()
// 指定扫描的Controller包路径
.apis(RequestHandlerSelectors.basePackage("com.zsz.controller"))
// 可选过滤配置(当前注释状态):
// 1. 只扫描带@ApiOperation注解的方法
// .apis(RequestHandlerSelectors.withClassAnnotation(ApiOperation.class))
// 2. 过滤指定路径
// .paths(Predicates.and(PathSelectors.regex("/sms/.*")))
// 3. 排除错误路径
// .paths(Predicates.not(PathSelectors.regex("/error.*")))
.build()
.globalOperationParameters(pars); // 添加全局参数
}
/**
* Web
* @return
*/
private ApiInfo webApiInfo(){
return new ApiInfoBuilder()
.title("网站-API文档") // 文档标题
.description("本文档描述了网站微服务接口定义") // 文档描述
.version("1.0") // 版本号
.contact(new Contact("atguigu", "http://atguigu.com", "512111559@qq.com")) // 联系人信息
.build();
}
/**
*
* 使
* @return
*/
private ApiInfo adminApiInfo(){
return new ApiInfoBuilder()
.title("后台管理系统-API文档")
.description("本文档描述了后台管理系统微服务接口定义")
.version("1.0")
.contact(new Contact("atguigu", "http://atguigu.com", "512111559@qq.com"))
.build();
}
}

@ -0,0 +1,69 @@
package com.zsz.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
*
*
*
* @author Mingxuan_x
* @version 1.0
* @Telephone 15135964789
* @createDate 2021/4/11 14:38
* @updateUser Mingxuan_x
* @updateDate 2021/4/11 14:38
* @updateRemark
*/
@Component // 声明为Spring组件由Spring容器管理
public class SystemUtil {
// Windows系统文件上传路径从配置文件中注入
@Value("${file.upload.windows.dir}")
private String windowsPath;
// Linux系统文件上传路径从配置文件中注入
@Value("${file.upload.linux.dir}")
private String linuxPath;
// Mac系统文件上传路径从配置文件中注入
@Value("${file.upload.mac.dir}")
private String macPath;
// 操作系统类型常量
private static final String LINUX = "linux";
private static final String WINDOWS = "windows";
/**
*
*
*
* 1.
* 2. linux/windows
* 3.
* 4. mac
*
* @return String
* @Author Mingxuan_X
* @Date 2021/4/11
*/
public String getFilePrefix() {
String systemPath = null;
// 获取操作系统名称并转为小写例如Windows 10 → windows 10
String osName = System.getProperty("os.name").toLowerCase();
// 根据操作系统类型选择对应的路径配置
if (osName.contains(LINUX)) {
systemPath
= linuxPath; // Linux系统路径
} else if (osName.contains(WINDOWS)) {
systemPath
= windowsPath; // Windows系统路径
} else {
systemPath
= macPath; // 其他系统主要是Mac路径
}
return systemPath;
}
}

@ -0,0 +1,98 @@
package com.zsz.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zsz.pojo.Admin;
import com.zsz.service.AdminService;
import com.zsz.util.MD5;
import com.zsz.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
* RESTful
* /sms/adminController
*/
@Api(tags = "管理员管理器", value = "提供管理员信息的CRUD操作") // Swagger接口分组说明
@RestController // 声明为Spring MVC控制器自动将返回值转为JSON
@RequestMapping("/sms/adminController") // 基础请求路径
public class AdminController {
@Autowired // 自动注入管理员服务层
private AdminService adminService;
/**
*
* http://localhost:8080/sms/adminController/getAllAdmin/1/3?adminName=张
*
* @param pageNo
* @param pageSize
* @param adminName
* @return
*/
@ApiOperation(value = "分页查询管理员信息", notes = "根据姓名模糊查询+分页")
@GetMapping("/getAllAdmin/{pageNo}/{pageSize}")
public Result getAllAdmin(
@ApiParam(value = "页码", example = "1", required = true)
@PathVariable("pageNo") Integer pageNo,
@ApiParam(value = "每页数量", example = "10", required = true)
@PathVariable("pageSize") Integer pageSize,
@ApiParam(value = "管理员姓名", example = "admin")
@RequestParam(required = false) String adminName) {
// 创建分页对象
Page<Admin> page = new Page<>(pageNo, pageSize);
// 调用服务层获取分页数据
Page<Admin> resultPage = adminService.getAllAdminData(page, adminName);
// 返回统一响应格式
return Result.ok(resultPage);
}
/**
*
* http://localhost:8080/sms/adminController/saveOrUpdateAdmin
*
* @param admin JSON
* @return
*/
@ApiOperation(value = "保存管理员信息", notes = "新增时自动加密密码")
@PostMapping("/saveOrUpdateAdmin")
public Result saveOrUpdateAdmin(
@ApiParam(value = "管理员信息", required = true)
@RequestBody Admin admin) {
// 新增操作时加密密码
if (admin.getId() == null || admin.getId() == 0) {
String encryptedPwd = MD5.encrypt(admin.getPassword());
admin.setPassword(encryptedPwd);
}
// 保存或更新数据
adminService.saveOrUpdate(admin);
return Result.ok();
}
/**
*
* http://localhost:8080/sms/adminController/deleteAdmin
*
* @param ids IDJSON
* @return
*/
@ApiOperation(value = "批量删除管理员", notes = "支持单个或多个ID同时删除")
@DeleteMapping("/deleteAdmin")
public Result deleteAdmin(
@ApiParam(value = "管理员ID列表", example = "[1,2,3]", required = true)
@RequestBody List<Integer> ids) {
// 批量删除操作
adminService.removeByIds(ids);
return Result.ok();
}
}

@ -0,0 +1,99 @@
package com.zsz.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zsz.pojo.Clazz;
import com.zsz.service.ClazzService;
import com.zsz.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
* CRUD
* /sms/clazzController
*/
@Api(tags = "班级管理", value = "提供班级信息的增删改查接口") // Swagger接口文档分组说明
@RestController // 声明为RESTful控制器返回值自动转为JSON
@RequestMapping("/sms/clazzController") // 控制器基础路径
public class ClazzController {
@Autowired // 自动注入班级服务层实现
private ClazzService clazzService;
/**
*
* GET /sms/clazzController/getClazzs
* @return
*/
@ApiOperation(value = "获取全部班级", notes = "返回所有班级的完整列表")
@GetMapping("/getClazzs")
public Result getClazzs() {
List<Clazz> clazzList = clazzService.getClazzs();
return Result.ok(clazzList); // 使用统一响应封装
}
/**
*
* GET /sms/clazzController/getClazzsByOpr/1/10?gradeName=&name=
* @param pageNo
* @param pageSize
* @param clazz
* @return
*/
@ApiOperation(value = "分页条件查询班级", notes = "可根据年级和班级名称筛选")
@GetMapping("/getClazzsByOpr/{pageNo}/{pageSize}")
public Result getClazzsByOpr(
@ApiParam(value = "页码", example = "1", required = true)
@PathVariable("pageNo") Integer pageNo,
@ApiParam(value = "每页数量", example = "10", required = true)
@PathVariable("pageSize") Integer pageSize,
@ApiParam("查询条件封装对象") Clazz clazz) {
// 初始化分页参数
Page<Clazz> page = new Page<>(pageNo, pageSize);
// 调用服务层获取分页数据
Page<Clazz> resultPage = clazzService.getClazzData(page, clazz);
return Result.ok(resultPage);
}
/**
*
* POST /sms/clazzController/saveOrUpdateClazz
* @param clazz JSON
* @return
*/
@ApiOperation(value = "保存班级信息", notes = "ID存在则更新不存在则新增")
@PostMapping("/saveOrUpdateClazz")
public Result saveOrUpdateClazz(
@ApiParam(value = "班级JSON数据", required = true)
@RequestBody Clazz clazz) {
clazzService
.saveOrUpdate(clazz);
return Result.ok();
}
/**
*
* DELETE /sms/clazzController/deleteClazz
* @param ids IDJSON
* @return
*/
@ApiOperation(value = "批量删除班级", notes = "支持同时删除多个班级")
@DeleteMapping("/deleteClazz")
public Result deleteClazz(
@ApiParam(value = "班级ID数组", example = "[1,2,3]", required = true)
@RequestBody List<Integer> ids) {
clazzService
.removeByIds(ids);
return Result.ok();
}
}

@ -0,0 +1,100 @@
package com.zsz.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zsz.pojo.Grade;
import com.zsz.service.GradeService;
import com.zsz.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
* RESTful
* /sms/gradeController
*/
@Api(tags = "年级管理", value = "提供年级信息的CRUD操作接口") // Swagger接口文档分组说明
@RestController // 标识为Spring MVC控制器返回值自动转为JSON
@RequestMapping("/sms/gradeController") // 控制器基础路径
public class GradeController {
@Autowired // 自动注入年级服务层实现
private GradeService gradeService;
/**
*
* GET /sms/gradeController/getGrades
* @return
*/
@ApiOperation(value = "获取全部年级列表", notes = "返回所有年级的完整列表")
@GetMapping("/getGrades")
public Result getGrades() {
List<Grade> grades = gradeService.getGrades();
return Result.ok(grades); // 使用统一响应封装
}
/**
*
* GET /sms/gradeController/getGrades/1/3?gradeName=
* @param pageNo
* @param pageSize
* @param gradeName
* @return
*/
@ApiOperation(value = "分页条件查询年级", notes = "支持按年级名称模糊查询")
@GetMapping("/getGrades/{pageNo}/{pageSize}")
public Result getGrades(
@ApiParam(value = "页码", example = "1", required = true)
@PathVariable("pageNo") Integer pageNo,
@ApiParam(value = "每页数量", example = "10", required = true)
@PathVariable("pageSize") Integer pageSize,
@ApiParam(value = "年级名称", example = "高一")
@RequestParam(required = false) String gradeName) {
// 初始化分页参数
Page<Grade> page = new Page<>(pageNo, pageSize);
// 调用服务层获取分页数据
Page<Grade> resultPage = gradeService.getGradesData(page, gradeName);
return Result.ok(resultPage);
}
/**
*
* POST /sms/gradeController/saveOrUpdateGrade
* @param grade JSON
* @return
*/
@ApiOperation(value = "保存年级信息", notes = "有ID则修改无ID则新增")
@PostMapping("/saveOrUpdateGrade")
public Result saveOrUpdateGrade(
@ApiParam(value = "年级JSON数据", required = true)
@RequestBody Grade grade) {
// 保存或更新数据根据ID自动判断
gradeService.saveOrUpdate(grade);
return Result.ok();
}
/**
*
* DELETE /sms/gradeController/deleteGrade
* @param ids IDJSON
* @return
*/
@ApiOperation(value = "批量删除年级", notes = "支持同时删除多个年级")
@DeleteMapping("/deleteGrade")
public Result deleteGrade(
@ApiParam(value = "年级ID数组", example = "[1,2,3]", required = true)
@RequestBody List<Integer> ids) {
// 批量删除操作
gradeService.removeByIds(ids);
return Result.ok();
}
}

@ -0,0 +1,113 @@
package com.zsz.controller;
// 导入 MyBatis-Plus 分页插件的 Page 类,用于实现分页查询
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入学生实体类,用于封装学生信息
import com.zsz.pojo.Student;
// 导入学生服务类,用于调用学生相关的业务逻辑
import com.zsz.service.StudentService;
// 导入 MD5 加密工具类,用于对学生密码进行加密处理
import com.zsz.util.MD5;
// 导入自定义的结果类,用于封装接口返回的数据
import com.zsz.util.Result;
// 导入 Swagger 注解,用于生成 API 文档
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
// 导入 Spring 框架的自动注入注解和 Web 相关注解
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* HTTP
*/
@Api("学生控制器")
// 标识该类为 RESTful 风格的控制器
@RestController
// 设置该控制器处理的请求路径前缀
@RequestMapping("/sms/studentController")
public class StudentController {
// 自动注入学生服务类的实例,用于调用学生相关的业务逻辑
@Autowired
StudentService studentService;
/**
*
* URL http://localhost:8080/sms/studentController/getStudentByOpr/1/3?clazzName=&name=
* @param pageNo
* @param pageSize
* @param student
* @return
*/
@ApiOperation("根据分页条件获取学生分页数据")
// 处理 GET 请求,路径中包含页码和页大小的占位符
@GetMapping("/getStudentByOpr/{pageNo}/{pageSize}")
public Result getStudentByOpr(
// 从路径中获取页码数,并使用 Swagger 注解进行参数描述
@ApiParam("分页查询的页码数") @PathVariable("pageNo") Integer pageNo,
// 从路径中获取页大小,并使用 Swagger 注解进行参数描述
@ApiParam("分页查询的页大小") @PathVariable("pageSize") Integer pageSize,
// 从请求参数中获取学生信息对象,并使用 Swagger 注解进行参数描述
@ApiParam("学生信息") Student student
){
// 创建一个 Page 对象,用于封装分页信息
Page<Student> studentPage = new Page<>(pageNo,pageSize);
// 调用学生服务类的方法,根据分页信息和学生信息进行查询
Page<Student> studentPage1 = studentService.getStudentData(studentPage,student);
// 将查询结果封装到自定义的结果对象中并返回
return Result.ok(studentPage1);
}
/**
*
* URL http://localhost:8080/sms/studentController/addOrUpdateStudent
* @param student
* @return
*/
@ApiOperation("新增或更改学生信息")
// 处理 POST 请求
@PostMapping("/addOrUpdateStudent")
public Result addOrUpdateStudent(
// 从请求体中获取学生信息对象,并使用 Swagger 注解进行参数描述
@ApiParam("请求中携带的要修改信息的学生对象") @RequestBody Student student
){
// 获取学生的 ID
Integer id = student.getId();
// 判断学生 ID 是否为空或为 0如果是则表示新增学生信息
if (null == id || 0 == id){
// 获取学生的密码
String password = student.getPassword();
// 使用 MD5 加密工具类对密码进行加密处理
String encrypt = MD5.encrypt(password);
// 将加密后的密码重新设置到学生对象中
student.setPassword(encrypt);
}
// 调用学生服务类的方法,保存或更新学生信息
studentService.saveOrUpdate(student);
// 返回操作成功的结果对象
return Result.ok();
}
/**
*
* URL http://localhost:8080/sms/studentController/delStudentById
* @param ids id
* @return
*/
@ApiOperation("删除单个或多个学生信息")
// 处理 DELETE 请求
@DeleteMapping("/delStudentById")
public Result delStudentById(
// 从请求体中获取要删除的学生 ID 集合,并使用 Swagger 注解进行参数描述
@ApiParam("要删除的学生 id 的集合") @RequestBody List<Integer> ids
){
// 调用学生服务类的方法,根据 ID 集合删除学生信息
studentService.removeByIds(ids);
// 返回操作成功的结果对象
return Result.ok();
}
}

@ -0,0 +1,368 @@
package com.zsz.controller;
// 导入 MyBatis-Plus 的条件查询包装器,用于构建查询条件
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// 导入系统工具类,可能包含一些系统级别的配置或操作方法
import com.zsz.config.SystemUtil;
// 导入管理员实体类,用于封装管理员信息
import com.zsz.pojo.Admin;
// 导入登录表单实体类,用于封装用户登录时提交的信息
import com.zsz.pojo.LoginForm;
// 导入学生实体类,用于封装学生信息
import com.zsz.pojo.Student;
// 导入教师实体类,用于封装教师信息
import com.zsz.pojo.Teacher;
// 导入管理员服务类,用于调用管理员相关的业务逻辑
import com.zsz.service.AdminService;
// 导入学生服务类,用于调用学生相关的业务逻辑
import com.zsz.service.StudentService;
// 导入教师服务类,用于调用教师相关的业务逻辑
import com.zsz.service.TeacherService;
// 导入自定义的工具类,如 MD5 加密、JWT 工具等
import com.zsz.util.*;
// 导入 Swagger 注解,用于生成 API 文档
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
// 导入 Spring 框架的自动注入注解和 Web 相关注解
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
// 导入 Spring 框架的资源注入注解
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
// 导入 Java 图像处理相关类,用于处理验证码图片
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
// 导入 Java Servlet 相关类,用于处理 HTTP 请求和响应
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
// 导入 Java 集合类,用于存储和操作数据
import java.util.LinkedHashMap;
import java.util.Map;
import static com.zsz.config.ConfigurerAdapter.PATH_PREFIX;
/**
* HTTP
*/
@Api("系统控制器")
// 标识该类为 RESTful 风格的控制器
@RestController
// 设置该控制器处理的请求路径前缀
@RequestMapping("/sms/system")
public class SystemController {
// 自动注入管理员服务类的实例,用于调用管理员相关的业务逻辑
@Autowired
AdminService adminService;
// 自动注入学生服务类的实例,用于调用学生相关的业务逻辑
@Autowired
StudentService studentService;
// 自动注入教师服务类的实例,用于调用教师相关的业务逻辑
@Autowired
TeacherService teacherService;
// 注入系统工具类的实例,可能用于系统级别的配置或操作
@Resource
private SystemUtil systemUtil;
// 注入本地文件上传工具类的实例,用于处理文件上传操作
@Resource
private LocalUploadUtil localUploadUtil;
/**
*
* URL http://localhost:8080/sms/system/headerImgUpload
* @param multipartFile
* @return
*/
@ApiOperation("头像上传")
// 处理 POST 请求,用于上传头像文件
@PostMapping("/headerImgUpload")
public Result headerImgUpload(
// 从请求中获取上传的文件,并使用 Swagger 注解进行参数描述
@RequestPart("multipartFile") MultipartFile multipartFile
) {
// 调用本地文件上传工具类的上传方法,保存图片并返回文件路径
String upload = localUploadUtil.upload(multipartFile);
// 将上传结果封装到自定义的结果对象中并返回
return Result.ok(upload);
}
/**
* token
* @param token token
* @return
*/
@ApiOperation("从请求头中的 token 信息中获取用户类型,并响应用户信息")
// 处理 GET 请求,用于根据 token 获取用户信息
@GetMapping("/getInfo")
public Result getInfoByToken(
// 从请求头中获取 token 信息,并使用 Swagger 注解进行参数描述
@ApiParam("请求头中的 token 信息") @RequestHeader("token") String token) {
// 验证 token 是否已经失效
boolean expiration = JwtHelper.isExpiration(token);
if (expiration) {
// 如果 token 失效,返回错误结果对象
return Result.build(null, ResultCodeEnum.TOKEN_ERROR);
}
// 从 token 中获取用户 ID
Long userId = JwtHelper.getUserId(token);
// 从 token 中获取用户类型
Integer userType = JwtHelper.getUserType(token);
// 创建一个有序的 Map 集合,用于存储用户类型和用户信息
Map<String, Object> stringObjectLinkedHashMap = new LinkedHashMap<>();
// 根据用户类型进行不同的处理
switch (userType) {
case 1:
// 如果是管理员类型,调用管理员服务类的方法获取管理员信息
Admin admin = adminService.getAdminById(userId);
// 将用户类型和管理员信息存入 Map 集合
stringObjectLinkedHashMap.put("userType", 1);
stringObjectLinkedHashMap.put("user", admin);
break;
case 2:
// 如果是学生类型,调用学生服务类的方法获取学生信息
Student student = studentService.getStudentById(userId);
// 将用户类型和学生信息存入 Map 集合
stringObjectLinkedHashMap.put("userType", 2);
stringObjectLinkedHashMap.put("user", student);
break;
case 3:
// 如果是教师类型,调用教师服务类的方法获取教师信息
Teacher teacher = teacherService.getTeacherById(userId);
// 将用户类型和教师信息存入 Map 集合
stringObjectLinkedHashMap.put("userType", 3);
stringObjectLinkedHashMap.put("user", teacher);
break;
}
// 将包含用户类型和用户信息的 Map 集合封装到结果对象中并返回
return Result.ok(stringObjectLinkedHashMap);
}
/**
*
* @param loginForm
* @param request HTTP
* @return token
*/
@ApiOperation("登录功能实现,首先校验验证码是否失效和正确,然后从提交的表单中判断用户类型,获取不同的响应信息")
// 处理 POST 请求,用于用户登录操作
@PostMapping("/login")
public Result login(
// 从请求体中获取用户登录提交的表单信息,并使用 Swagger 注解进行参数描述
@ApiParam("用户登录提交的表单") @RequestBody LoginForm loginForm,
// 获取 HTTP 请求对象,用于获取 session 信息
@ApiParam("请求") HttpServletRequest request) {
// 获取当前请求的 session 对象
HttpSession session = request.getSession();
// 从 session 中获取之前生成的验证码
String sessionVerifiCode = (String) session.getAttribute("verifiCode");
// 从登录表单中获取用户输入的验证码
String loginVerifiCode = loginForm.getVerifiCode();
// 1. 检查 session 中验证码是否失效
if ("".equals(sessionVerifiCode)) {
// 如果验证码失效,返回错误结果对象并提示用户刷新页面重试
return Result.fail().message("验证码失效,请刷新页面重试");
}
// 检查用户输入的验证码与 session 中的验证码是否一致(忽略大小写)
if (!loginVerifiCode.equalsIgnoreCase(sessionVerifiCode)) {
// 如果验证码输入有误,返回错误结果对象并提示用户
return Result.fail().message("验证码输入有误!");
}
// 验证码使用完毕,移除当前请求域中的验证码,防止重复使用
session.removeAttribute("verifiCode");
// 准备一个有序的 Map 集合,用于存放用户响应的信息(如 token
Map<String, Object> map = new LinkedHashMap<>();
// 2. 根据选择的用户类型去不同角色的用户表中查询用户,判断用户名和密码是否正确
switch (loginForm.getUserType()) {
case 1:
try {
// 调用管理员服务类的登录方法,根据用户提交的登录信息查询对应的管理员对象,找不到返回 null
Admin admin = adminService.login(loginForm);
if (admin != null) {
// 如果登录成功,将用户 ID 和用户类型转换为 token 口令,存入 Map 集合
map.put("token", JwtHelper.createToken(admin.getId().longValue(), 1));
} else {
// 如果用户名或密码有误,抛出运行时异常
throw new RuntimeException("用户名或者密码有误!");
}
// 将包含 token 的 Map 集合封装到结果对象中并返回
return Result.ok(map);
} catch (RuntimeException e) {
// 捕获异常,打印堆栈信息
e.printStackTrace();
// 向用户响应错误信息
return Result.fail().message(e.getMessage());
}
case 2:
try {
// 调用学生服务类的登录方法,根据用户提交的登录信息查询对应的学生对象,找不到返回 null
Student student = studentService.login(loginForm);
if (student != null) {
// 如果登录成功,将用户 ID 和用户类型转换为 token 口令,存入 Map 集合
map.put("token", JwtHelper.createToken(student.getId().longValue(), 2));
} else {
// 如果用户名或密码有误,抛出运行时异常
throw new RuntimeException("用户名或者密码有误!");
}
// 将包含 token 的 Map 集合封装到结果对象中并返回
return Result.ok(map);
} catch (RuntimeException e) {
// 捕获异常,打印堆栈信息
e.printStackTrace();
// 向用户响应错误信息
return Result.fail().message(e.getMessage());
}
case 3:
try {
// 调用教师服务类的登录方法,根据用户提交的登录信息查询对应的教师对象,找不到返回 null
Teacher teacher = teacherService.login(loginForm);
if (teacher != null) {
// 如果登录成功,将用户 ID 和用户类型转换为 token 口令,存入 Map 集合
map.put("token", JwtHelper.createToken(teacher.getId().longValue(), 3));
} else {
// 如果用户名或密码有误,抛出运行时异常
throw new RuntimeException("用户名或者密码有误!");
}
// 将包含 token 的 Map 集合封装到结果对象中并返回
return Result.ok(map);
} catch (RuntimeException e) {
// 捕获异常,打印堆栈信息
e.printStackTrace();
// 向用户响应错误信息
return Result.fail().message(e.getMessage());
}
}
// 如果以上用户类型都不匹配,返回错误结果对象并提示用户查无此人
return Result.fail().message("查无此人!");
}
/**
*
* @param request HTTP
* @param response HTTP
*/
@ApiOperation("获取验证码图片")
// 处理 GET 请求,用于获取验证码图片
@GetMapping("/getVerifiCodeImage")
public void getVerifiCodeImage(HttpServletRequest request, HttpServletResponse response) {
// 调用工具类方法获取验证码图片
BufferedImage verifiCodeImage = CreateVerifiCodeImage.getVerifiCodeImage();
// 调用工具类方法获取图片上的验证码文本
String verifiCode = new String(CreateVerifiCodeImage.getVerifiCode());
// 获取当前请求的 session 对象
HttpSession session = request.getSession();
// 将验证码文本放入 session 域,为下一次验证做准备
session.setAttribute("verifiCode", verifiCode);
// 将验证码图片响应给浏览器
try {
ImageIO.write(verifiCodeImage, "JPEG", response.getOutputStream());
} catch (IOException e) {
// 捕获异常,打印堆栈信息
e.printStackTrace();
}
}
/**
*
* URL POST http://localhost:8080/sms/system/updatePwd/admin/admin123
* @param oldPwd
* @param newPwd
* @param token token
* @return
*/
@ApiOperation("修改密码")
// 处理 POST 请求,用于修改用户密码
@PostMapping("/updatePwd/{oldPwd}/{newPwd}")
public Result updatePwd(
// 从路径中获取原密码,并使用 Swagger 注解进行参数描述
@ApiParam("原密码") @PathVariable("oldPwd") String oldPwd,
// 从路径中获取新密码,并使用 Swagger 注解进行参数描述
@ApiParam("新密码") @PathVariable("newPwd") String newPwd,
// 从请求头中获取 token 信息,并使用 Swagger 注解进行参数描述
@ApiParam("token 信息,用来判断当前登录的用户类型") @RequestHeader String token
) {
// 判断 token 是否失效
boolean expiration = JwtHelper.isExpiration(token);
if (expiration) {
// 如果 token 失效,返回错误结果对象并提示用户重新登录
return Result.fail().message("token 失效,请重新登录。");
}
// 从 token 中获取用户 ID
Long userId = JwtHelper.getUserId(token);
// 从 token 中获取用户类型
Integer userType = JwtHelper.getUserType(token);
// 请求链接中原密码和新密码都是以明文方式传输的,数据库中的密码是以密文存储的,所以要将原密码和新密码转换成密文
String encryptOldPwd = MD5.encrypt(oldPwd);
String encryptNewPwd = MD5.encrypt(newPwd);
// 根据用户类型进行不同的处理
switch (userType) {
case 1:
// 创建一个管理员查询条件包装器
QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
// 添加查询条件:用户 ID 相等
adminQueryWrapper.eq("id", userId);
// 添加查询条件:原密码相等(密文)
adminQueryWrapper.eq("password", encryptOldPwd);
// 根据查询条件查询管理员对象
Admin one = adminService.getOne(adminQueryWrapper);
if (one != null) {
// 如果查询到管理员对象,将新密码(密文)设置到对象中
one.setPassword(encryptNewPwd);
// 调用管理员服务类的保存或更新方法,更新管理员信息
adminService.saveOrUpdate(one);
} else {
// 如果原密码错误,返回错误结果对象并提示用户
return Result.fail().message("原密码错误!");
}
break;
case 2:
// 创建一个学生查询条件包装器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
// 添加查询条件:用户 ID 相等
studentQueryWrapper.eq("id", userId);
// 添加查询条件:原密码相等(密文)
studentQueryWrapper.eq("password", encryptOldPwd);
// 根据查询条件查询学生对象
Student studentServiceOne = studentService.getOne(studentQueryWrapper);
if (studentServiceOne != null) {
// 如果查询到学生对象,将新密码(密文)设置到对象中
studentServiceOne.setPassword(encryptNewPwd);
// 调用学生服务类的保存或更新方法,更新学生信息
studentService.saveOrUpdate(studentServiceOne);
} else {
// 如果原密码错误,返回错误结果对象并提示用户
return Result.fail().message("原密码错误!");
}
break;
case 3:
// 创建一个教师查询条件包装器
QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
// 添加查询条件:用户 ID 相等
teacherQueryWrapper.eq("id", userId);
// 添加查询条件:原密码相等(密文)
teacherQueryWrapper.eq("password", encryptOldPwd);
// 根据查询条件查询教师对象
Teacher teacherServiceOne = teacherService.getOne(teacherQueryWrapper);
if (teacherServiceOne != null) {
// 如果查询到教师对象,将新密码(密文)设置到对象中
teacherServiceOne.setPassword(encryptNewPwd);
// 调用教师服务类的保存或更新方法,更新教师信息
teacherService.saveOrUpdate(teacherServiceOne);
} else {
// 如果原密码错误,返回错误结果对象并提示用户
return Result.fail().message("原密码错误!");
}
break;
}
// 返回操作成功的结果对象
return Result.ok();
}
}

@ -0,0 +1,112 @@
package com.zsz.controller;
// 导入 MyBatis-Plus 的分页插件中的 Page 类,用于实现分页功能
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入教师实体类,用于封装教师相关的数据
import com.zsz.pojo.Teacher;
// 导入教师服务类,用于调用与教师相关的业务逻辑
import com.zsz.service.TeacherService;
// 导入 MD5 加密工具类,用于对教师密码进行加密处理
import com.zsz.util.MD5;
// 导入自定义的结果类,用于封装接口返回的结果信息
import com.zsz.util.Result;
// 导入 Swagger 相关注解,用于生成接口文档
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
// 导入 Spring 框架的自动注入注解和 Web 相关注解
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* HTTP
*/
@Api("教师管理器")
// 标识该类为一个 RESTful 风格的控制器
@RestController
// 设置该控制器处理的请求路径前缀
@RequestMapping("/sms/teacherController")
public class TeacherController {
// 自动注入教师服务类的实例,以便在本控制器中调用教师相关的业务方法
@Autowired
TeacherService teacherService;
/**
*
* http://localhost:8080/sms/teacherController/getTeachers/1/3?clazzName=&name=
* @param pageNo
* @param pageSize
* @param teacher
* @return
*/
@ApiOperation("根据分页条件获取教师信息")
// 处理 GET 请求,路径中包含页码和页大小的占位符
@GetMapping("/getTeachers/{pageNo}/{pageSize}")
public Result getTeachers(
// 从路径中获取分页查询的页码数,并使用 Swagger 注解描述该参数
@ApiParam("分页查询的页码数") @PathVariable("pageNo") Integer pageNo,
// 从路径中获取分页查询的页大小,并使用 Swagger 注解描述该参数
@ApiParam("分页查询的页大小") @PathVariable("pageSize") Integer pageSize,
// 从请求参数中获取教师信息对象,用于查询条件,并使用 Swagger 注解描述该参数
@ApiParam("分页查询的班级名称和教师名称") Teacher teacher
){
// 创建一个 Page 对象,用于封装分页信息,传入页码和页大小
Page<Teacher> teacherPage = new Page<>(pageNo, pageSize);
// 调用教师服务类的方法,传入分页对象和教师查询条件,获取分页的教师数据
Page<Teacher> teacherPage1 = teacherService.getTeacherData(teacherPage,teacher);
// 将获取到的分页教师数据封装到结果对象中,并返回给前端
return Result.ok(teacherPage1);
}
/**
*
* http://localhost:8080/sms/teacherController/saveOrUpdateTeacher
* @param teacher
* @return
*/
@ApiOperation("新增或者更改教师信息")
// 处理 POST 请求,用于保存或更新教师信息
@PostMapping("/saveOrUpdateTeacher")
public Result saveOrUpdateTeacher(
// 从请求体中获取要提交的教师信息对象,并使用 Swagger 注解描述该参数
@ApiParam("要提交的教师信息") @RequestBody Teacher teacher
){
// 获取教师对象的 ID
Integer id = teacher.getId();
// 判断教师对象的 ID 是否为空或为 0如果是则表示是新增教师信息
if (null == id || 0 == id){
// 获取教师的密码
String password = teacher.getPassword();
// 使用 MD5 加密工具对教师密码进行加密
String encrypt = MD5.encrypt(password);
// 将加密后的密码设置回教师对象中
teacher.setPassword(encrypt);
}
// 调用教师服务类的 saveOrUpdate 方法,保存或更新教师信息
teacherService.saveOrUpdate(teacher);
// 将操作成功的信息封装到结果对象中,并返回给前端
return Result.ok();
}
/**
*
* http://localhost:8080/sms/teacherController/deleteTeacher
* @param ids ID
* @return
*/
@ApiOperation("删除单个或多个老师信息")
// 处理 DELETE 请求,用于删除教师信息
@DeleteMapping("/deleteTeacher")
public Result deleteTeacher(
// 从请求体中获取要删除的教师 ID 列表,并使用 Swagger 注解描述该参数
@ApiParam("要删除的教师 id 列表") @RequestBody List<Integer> ids
){
// 调用教师服务类的 removeByIds 方法,根据传入的教师 ID 列表删除教师信息
teacherService.removeByIds(ids);
// 将操作成功的信息封装到结果对象中,并返回给前端
return Result.ok();
}
}

@ -0,0 +1,18 @@
package com.zsz.mapper;
// 导入 MyBatis-Plus 的核心 Mapper 接口,提供基本的数据库操作方法
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入管理员实体类,用于与数据库表进行映射
import com.zsz.pojo.Admin;
// 导入 Spring 的仓库注解,用于标识该类为数据访问层组件
import org.springframework.stereotype.Repository;
/**
* 访 MyBatis-Plus BaseMapper
*/
@Repository
// 定义管理员 Mapper 接口,泛型参数为 Admin 实体类,代表操作的实体类型
public interface AdminMapper extends BaseMapper<Admin> {
// 该接口无需编写具体方法,因为 BaseMapper 已经提供了诸如插入、更新、删除、查询等常用的数据库操作方法
// 后续如果有特殊的数据库操作需求,可以在此接口中自定义方法
}

@ -0,0 +1,18 @@
package com.zsz.mapper;
// 导入 MyBatis-Plus 提供的基础 Mapper 接口,它封装了常见的数据库操作方法
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入班级实体类,用于与数据库中班级表的数据进行映射
import com.zsz.pojo.Clazz;
// 导入 Spring 框架的注解,用于将该接口标记为数据访问层组件,交由 Spring 容器管理
import org.springframework.stereotype.Repository;
/**
* 访 MyBatis-Plus BaseMapper
*/
@Repository
// 定义班级的 Mapper 接口,通过泛型指定操作的实体类型为 Clazz
public interface ClazzMapper extends BaseMapper<Clazz> {
// 由于继承了 BaseMapper该接口已具备了如插入、更新、删除、查询等常见数据库操作的能力
// 若有特殊的数据库操作需求,可在该接口内自定义方法
}

@ -0,0 +1,18 @@
package com.zsz.mapper;
// 导入 MyBatis-Plus 提供的核心基础 Mapper 接口,该接口包含了通用的 CRUD创建、读取、更新、删除操作方法
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入年级实体类,用于将数据库中年级表的数据映射到 Java 对象
import com.zsz.pojo.Grade;
// 导入 Spring 框架的注解用于将该接口标记为数据访问层组件Spring 会自动将其纳入组件扫描并进行管理
import org.springframework.stereotype.Repository;
/**
* 访 MyBatis-Plus BaseMapper
*/
@Repository
// 定义年级 Mapper 接口,泛型指定为 Grade 类,表示该接口操作的实体对象是 Grade
public interface GradeMapper extends BaseMapper<Grade> {
// 由于继承了 BaseMapper此接口默认具备了对 Grade 实体的基本数据库操作能力,如插入、更新、删除、查询等
// 若有额外的、复杂的数据库操作需求,可以在该接口中定义自定义的方法
}

@ -0,0 +1,19 @@
package com.zsz.mapper;
// 导入 MyBatis-Plus 提供的基础 Mapper 接口,它包含了常用的数据库 CRUD 操作方法
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入学生实体类,该类用于封装学生的相关属性,与数据库中的学生表对应
import com.zsz.pojo.Student;
// 导入 Spring 框架的注解,将该接口标记为数据访问层组件,使其能被 Spring 容器管理
import org.springframework.stereotype.Repository;
/**
* 访 MyBatis-Plus BaseMapper
*/
@Repository
// 定义学生 Mapper 接口,通过泛型指定操作的实体类型为 Student
public interface StudentMapper extends BaseMapper<Student> {
// 因为继承了 BaseMapper 接口,所以该接口默认拥有对 Student 实体的基本数据库操作功能,
// 例如插入、更新、删除、查询等操作。
// 如果需要实现一些特殊的数据库操作,可以在该接口中自定义方法。
}

@ -0,0 +1,23 @@
package com.zsz.mapper;
// 引入 MyBatis-Plus 框架提供的基础 Mapper 接口,此接口封装了通用的数据库操作方法,
// 如插入、删除、更新、查询等,能显著减少重复代码的编写。
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 引入教师实体类,该类用来封装教师的相关属性,和数据库里的教师表相对应。
import com.zsz.pojo.Teacher;
// 引入 Spring 框架的 Repository 注解,它的作用是把该接口标记成数据访问层组件,
// 让 Spring 容器能够对其进行管理,同时也能在出现数据访问异常时进行恰当的转换。
import org.springframework.stereotype.Repository;
/**
* 访 MyBatis-Plus BaseMapper
*
*/
@Repository
// 定义教师 Mapper 接口,借助泛型指定操作的实体类型为 Teacher
// 这表明该接口主要针对教师表开展操作。
public interface TeacherMapper extends BaseMapper<Teacher> {
// 由于继承了 BaseMapper 接口,这个接口默认具备对 Teacher 实体的基本数据库操作能力,
// 比如插入一条教师记录、更新教师信息、删除教师记录以及查询教师信息等。
// 若有特殊的数据库操作需求,可在该接口内自定义方法。
}

@ -0,0 +1,41 @@
package com.zsz.pojo;
// 导入 MyBatis-Plus 的注解,用于配置数据库表的主键生成策略等信息
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
// 导入 Lombok 注解,用于简化实体类的代码编写
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
*/
// 使用 @Data 注解,自动生成 get、set、equals、hashCode、toString 等方法
@Data
// 使用 @NoArgsConstructor 注解,生成一个无参构造函数
@NoArgsConstructor
// 使用 @AllArgsConstructor 注解,生成一个包含所有成员变量的全参构造函数
@AllArgsConstructor
// 使用 @TableName 注解,指定该实体类对应的数据库表名为 "tb_admin"
@TableName("tb_admin")
public class Admin {
// 使用 @TableId 注解,指定该字段为主键,并且主键的值由数据库自动生成(自增)
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
// 管理员姓名
private String name;
// 管理员性别,使用 char 类型存储
private char gender;
// 管理员密码
private String password;
// 管理员邮箱
private String email;
// 管理员电话号码
private String telephone;
// 管理员地址
private String address;
// 管理员头像的图片路径
private String portraitPath;
}

@ -0,0 +1,46 @@
package com.zsz.pojo;
// 导入 MyBatis-Plus 框架提供的主键类型枚举类,用于指定主键的生成策略
import com.baomidou.mybatisplus.annotation.IdType;
// 导入 MyBatis-Plus 框架提供的表主键注解,用于标记实体类中的主键字段
import com.baomidou.mybatisplus.annotation.TableId;
// 导入 MyBatis-Plus 框架提供的表名注解,用于指定实体类对应的数据库表名
import com.baomidou.mybatisplus.annotation.TableName;
// 导入 Lombok 库提供的全参构造函数注解,使用该注解可以自动生成包含所有字段的构造函数
import lombok.AllArgsConstructor;
// 导入 Lombok 库提供的数据注解,使用该注解可以自动生成 getter、setter、toString、equals 和 hashCode 等方法
import lombok.Data;
// 导入 Lombok 库提供的无参构造函数注解,使用该注解可以自动生成无参构造函数
import lombok.NoArgsConstructor;
/**
* tb_clazz
* Lombok 使 MyBatis-Plus
*/
// 自动生成 getter、setter、toString、equals 和 hashCode 等方法
@Data
// 自动生成包含所有字段的构造函数
@AllArgsConstructor
// 自动生成无参构造函数
@NoArgsConstructor
// 指定该实体类对应数据库中的 tb_clazz 表
@TableName("tb_clazz")
public class Clazz {
// 标记 id 字段为主键,且主键采用数据库自增的方式生成
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
// 班级名称
private String name;
// 班级人数
private Integer number;
// 班级介绍
private String introducation;
// 班主任姓名
private String headmaster;
// 班主任邮箱
private String email;
// 班主任联系电话
private String telephone;
// 班级所属年级名称
private String gradeName;
}

@ -0,0 +1,42 @@
package com.zsz.pojo;
// 导入 MyBatis-Plus 框架中用于指定主键生成类型的注解
import com.baomidou.mybatisplus.annotation.IdType;
// 导入 MyBatis-Plus 框架中用于标记主键字段的注解
import com.baomidou.mybatisplus.annotation.TableId;
// 导入 MyBatis-Plus 框架中用于指定实体类对应数据库表名的注解
import com.baomidou.mybatisplus.annotation.TableName;
// 导入 Lombok 库的全参构造函数注解,使用后会自动生成包含所有字段的构造函数
import lombok.AllArgsConstructor;
// 导入 Lombok 库的 Data 注解,使用后会自动生成 getter、setter、toString、equals、hashCode 等方法
import lombok.Data;
// 导入 Lombok 库的无参构造函数注解,使用后会自动生成无参构造函数
import lombok.NoArgsConstructor;
/**
* tb_grade
* Lombok 使 MyBatis-Plus
*/
// 自动生成 getter、setter、toString、equals、hashCode 等方法
@Data
// 自动生成无参构造函数
@NoArgsConstructor
// 自动生成包含所有字段的全参构造函数
@AllArgsConstructor
// 指定该实体类对应数据库中的 tb_grade 表
@TableName("tb_grade")
public class Grade {
// 标记 id 字段为主键,并且主键采用数据库自增的方式生成
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
// 年级名称
private String name;
// 年级负责人姓名
private String manager;
// 年级负责人邮箱
private String email;
// 年级负责人联系电话
private String telephone;
// 年级介绍信息
private String introducation;
}

@ -0,0 +1,20 @@
package com.zsz.pojo;
// 导入 Lombok 库的 Data 注解,该注解能自动为类的属性生成 getter、setter、equals、hashCode、toString 等方法
import lombok.Data;
/**
* @description:
* Lombok Data
*/
@Data
public class LoginForm {
// 登录用户名
private String username;
// 登录密码
private String password;
// 登录时输入的验证码
private String verifiCode;
// 用户类型,例如管理员、学生、教师等,使用整数表示不同的用户类型
private Integer userType;
}

@ -0,0 +1,52 @@
package com.zsz.pojo;
// 导入 MyBatis-Plus 框架中用于指定主键生成类型的注解,此处会用到自增类型
import com.baomidou.mybatisplus.annotation.IdType;
// 导入 MyBatis-Plus 框架中用于标记实体类主键字段的注解
import com.baomidou.mybatisplus.annotation.TableId;
// 导入 MyBatis-Plus 框架中用于指定实体类对应数据库表名的注解
import com.baomidou.mybatisplus.annotation.TableName;
// 导入 Lombok 库的注解,用于自动生成全参构造函数
import lombok.AllArgsConstructor;
// 导入 Lombok 库的注解,用于自动生成常用的 getter、setter、toString、equals、hashCode 等方法
import lombok.Data;
// 导入 Lombok 库的注解,用于自动生成无参构造函数
import lombok.NoArgsConstructor;
/**
* tb_student
* Lombok MyBatis-Plus
*/
// 自动生成 getter、setter、toString、equals、hashCode 等方法
@Data
// 自动生成包含所有字段的全参构造函数
@AllArgsConstructor
// 自动生成无参构造函数
@NoArgsConstructor
// 指定该实体类对应数据库中的 tb_student 表
@TableName("tb_student")
public class Student {
// 标记 id 字段为主键,并且采用数据库自增的方式生成主键值
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
// 学生学号
private String sno;
// 学生姓名
private String name;
// 学生性别
private char gender;
// 学生登录密码
private String password;
// 学生电子邮箱
private String email;
// 学生联系电话
private String telephone;
// 学生家庭住址
private String address;
// 学生个人简介
private String introducation;
// 学生头像图片的存储路径
private String portraitPath;
// 学生所在班级名称
private String clazzName;
}

@ -0,0 +1,50 @@
package com.zsz.pojo;
// 导入 MyBatis-Plus 用于指定主键生成类型的注解,这里使用自增类型
import com.baomidou.mybatisplus.annotation.IdType;
// 导入 MyBatis-Plus 标记主键字段的注解
import com.baomidou.mybatisplus.annotation.TableId;
// 导入 MyBatis-Plus 指定实体类对应数据库表名的注解
import com.baomidou.mybatisplus.annotation.TableName;
// 导入 Lombok 提供的生成全参构造函数的注解
import lombok.AllArgsConstructor;
// 导入 Lombok 提供的自动生成 getter、setter、toString、equals、hashCode 等方法的注解
import lombok.Data;
// 导入 Lombok 提供的生成无参构造函数的注解
import lombok.NoArgsConstructor;
/**
* tb_teacher
* Lombok 使 MyBatis-Plus
*/
// 自动生成 getter、setter、toString、equals、hashCode 等方法
@Data
// 自动生成包含所有字段的全参构造函数
@AllArgsConstructor
// 自动生成无参构造函数
@NoArgsConstructor
// 指定该实体类对应数据库中的 tb_teacher 表
@TableName("tb_teacher")
public class Teacher {
// 标记 id 字段为主键,且主键采用数据库自增的方式生成
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
// 教师编号
private String tno;
// 教师姓名
private String name;
// 教师性别
private char gender;
// 教师登录密码
private String password;
// 教师电子邮箱
private String email;
// 教师联系电话
private String telephone;
// 教师家庭住址
private String address;
// 教师头像图片的存储路径
private String portraitPath;
// 教师所负责的班级名称
private String clazzName;
}

@ -0,0 +1,39 @@
package com.zsz.service;
// 导入 MyBatis-Plus 用于实现分页查询的 Page 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 接口
import com.baomidou.mybatisplus.extension.service.IService;
// 导入管理员实体类
import com.zsz.pojo.Admin;
// 导入用户登录表单实体类
import com.zsz.pojo.LoginForm;
/**
* MyBatis-Plus IService
* ID
*/
public interface AdminService extends IService<Admin> {
/**
*
* @param loginForm
* @return null
*/
Admin login(LoginForm loginForm);
/**
* ID
* @param userId ID
* @return null
*/
Admin getAdminById(Long userId);
/**
*
* @param adminPage
* @param adminName
* @return Page
*/
Page<Admin> getAllAdminData(Page<Admin> adminPage, String adminName);
}

@ -0,0 +1,31 @@
package com.zsz.service;
// 导入 MyBatis-Plus 用于实现分页查询的 Page 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 接口
import com.baomidou.mybatisplus.extension.service.IService;
// 导入班级实体类
import com.zsz.pojo.Clazz;
// 导入 Java 标准库中的 List 接口,用于处理集合数据
import java.util.List;
/**
* MyBatis-Plus IService
*
*/
public interface ClazzService extends IService<Clazz> {
/**
*
* @param clazzPage
* @param clazz
* @return Page Clazz
*/
Page<Clazz> getClazzData(Page<Clazz> clazzPage, Clazz clazz);
/**
*
* @return List Clazz
*/
List<Clazz> getClazzs();
}

@ -0,0 +1,32 @@
package com.zsz.service;
// 导入 MyBatis-Plus 提供的分页查询相关的 Page 类,用于处理分页查询结果
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 的通用 Service 接口,该接口提供了常见的增删改查等操作方法
import com.baomidou.mybatisplus.extension.service.IService;
// 导入年级实体类,代表数据库中的年级数据
import com.zsz.pojo.Grade;
// 导入 Java 集合框架中的 List 接口,用于存储多个年级对象
import java.util.List;
/**
* MyBatis-Plus IService
*
*/
public interface GradeService extends IService<Grade> {
/**
*
* @param gradePage
* @param gradeName
* @return Page
*/
Page<Grade> getGradesData(Page<Grade> gradePage, String gradeName);
/**
*
* @return List
*/
List<Grade> getGrades();
}

@ -0,0 +1,39 @@
package com.zsz.service;
// 导入 MyBatis-Plus 用于实现分页查询的 Page 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 接口
import com.baomidou.mybatisplus.extension.service.IService;
// 导入用户登录表单实体类
import com.zsz.pojo.LoginForm;
// 导入学生实体类
import com.zsz.pojo.Student;
/**
* MyBatis-Plus IService
* ID
*/
public interface StudentService extends IService<Student> {
/**
*
* @param loginForm
* @return null
*/
Student login(LoginForm loginForm);
/**
* ID
* @param userId ID
* @return null
*/
Student getStudentById(Long userId);
/**
*
* @param studentPage
* @param student
* @return Page
*/
Page<Student> getStudentData(Page<Student> studentPage, Student student);
}

@ -0,0 +1,37 @@
package com.zsz.service;
// 导入 MyBatis-Plus 用于分页查询的 Page 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 接口,具备基本的增删改查等功能
import com.baomidou.mybatisplus.extension.service.IService;
// 导入登录表单实体类,包含登录所需的用户名、密码等信息
import com.zsz.pojo.LoginForm;
// 导入教师实体类,代表数据库中教师表的数据结构
import com.zsz.pojo.Teacher;
/**
* MyBatis-Plus IService
*/
public interface TeacherService extends IService<Teacher> {
/**
*
* @param loginForm
* @return null
*/
Teacher login(LoginForm loginForm);
/**
* ID
* @param userId ID
* @return ID null
*/
Teacher getTeacherById(Long userId);
/**
*
* @param teacherPage
* @param teacher
* @return Page
*/
Page<Teacher> getTeacherData(Page<Teacher> teacherPage, Teacher teacher);
}

@ -0,0 +1,87 @@
package com.zsz.service.impl;
// 导入 MyBatis-Plus 的条件查询包装器,用于构建数据库查询条件
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// 导入 MyBatis-Plus 的分页插件的 Page 类,用于实现分页查询
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 实现类,简化服务层代码编写
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 导入管理员数据访问层接口
import com.zsz.mapper.AdminMapper;
// 导入管理员实体类
import com.zsz.pojo.Admin;
// 导入用户登录表单实体类
import com.zsz.pojo.LoginForm;
// 导入管理员服务层接口
import com.zsz.service.AdminService;
// 导入 MD5 加密工具类,用于对密码进行加密处理
import com.zsz.util.MD5;
// 导入 Spring 框架的 Service 注解,将该类标记为服务层组件
import org.springframework.stereotype.Service;
// 导入 Spring 框架的事务管理注解,用于开启事务支持
import org.springframework.transaction.annotation.Transactional;
// 导入 Spring 框架的工具类,用于字符串相关操作
import org.springframework.util.StringUtils;
/**
* MyBatis-Plus ServiceImpl AdminService
* ID
*/
// 将该类标记为服务层组件,指定名称为 "adminServiceImpl"
@Service("adminServiceImpl")
// 开启事务支持,确保业务操作的原子性
@Transactional
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {
/**
*
* @param loginForm
* @return null
*/
@Override
public Admin login(LoginForm loginForm) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
// 拼接查询条件:用户名相等
adminQueryWrapper.eq("name", loginForm.getUsername());
// 将用户输入的密码进行 MD5 加密后,作为查询条件:密码相等
adminQueryWrapper.eq("password", MD5.encrypt(loginForm.getPassword()));
// 使用 BaseMapper 的 selectOne 方法,根据查询条件查询数据库,返回符合条件的唯一管理员对象
Admin admin = baseMapper.selectOne(adminQueryWrapper);
return admin;
}
/**
* ID
* @param userId ID
* @return null
*/
@Override
public Admin getAdminById(Long userId) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
// 拼接查询条件:管理员 ID 相等
adminQueryWrapper.eq("id", userId);
// 使用 BaseMapper 的 selectOne 方法,根据查询条件查询数据库,返回符合条件的唯一管理员对象
return baseMapper.selectOne(adminQueryWrapper);
}
/**
*
* @param adminPage
* @param adminName
* @return Page
*/
@Override
public Page<Admin> getAllAdminData(Page<Admin> adminPage, String adminName) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
// 判断管理员姓名是否为空,如果不为空,则添加模糊查询条件
if (!StringUtils.isEmpty(adminName)) {
adminQueryWrapper.like("name", adminName);
}
// 使用 BaseMapper 的 selectPage 方法,根据分页信息和查询条件进行分页查询,返回分页结果
Page<Admin> page = baseMapper.selectPage(adminPage, adminQueryWrapper);
return page;
}
}

@ -0,0 +1,74 @@
package com.zsz.service.impl;
// 导入 MyBatis-Plus 用于构建查询条件的 QueryWrapper 类
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// 导入 MyBatis-Plus 用于实现分页查询的 Page 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 实现类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 导入班级数据访问层的 Mapper 接口
import com.zsz.mapper.ClazzMapper;
// 导入班级实体类
import com.zsz.pojo.Clazz;
// 导入班级服务层接口
import com.zsz.service.ClazzService;
// 导入 Spring 框架的 Service 注解,用于将该类标记为服务层组件
import org.springframework.stereotype.Service;
// 导入 Spring 框架的事务管理注解,用于开启事务支持
import org.springframework.transaction.annotation.Transactional;
// 导入 Spring 框架的工具类,用于字符串操作
import org.springframework.util.StringUtils;
import java.util.List;
/**
* MyBatis-Plus ServiceImpl ClazzService
*
*/
// 将该类标记为服务层组件,指定名称为 "clazzServiceImpl"
@Service("clazzServiceImpl")
// 开启事务支持,确保业务操作的原子性
@Transactional
public class ClazzServiceImpl extends ServiceImpl<ClazzMapper, Clazz> implements ClazzService {
/**
*
* @param clazzPage
* @param clazz
* @return Page
*/
@Override
public Page<Clazz> getClazzData(Page<Clazz> clazzPage, Clazz clazz) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Clazz> clazzQueryWrapper = new QueryWrapper<>();
// 判断班级对象中的年级名称是否为空,如果不为空,则添加模糊查询条件
if (!StringUtils.isEmpty(clazz.getGradeName())) {
// 添加年级名称的模糊查询条件,对应数据库表中的 grade_name 字段
clazzQueryWrapper.like("grade_name", clazz.getGradeName());
}
// 判断班级对象中的班级名称是否为空,如果不为空,则添加模糊查询条件
if (!StringUtils.isEmpty(clazz.getName())) {
// 添加班级名称的模糊查询条件,对应数据库表中的 name 字段
clazzQueryWrapper.like("name", clazz.getName());
}
// 调用 BaseMapper 的 selectPage 方法,根据分页信息和查询条件进行分页查询
Page<Clazz> selectPage = baseMapper.selectPage(clazzPage, clazzQueryWrapper);
return selectPage;
}
/**
*
* @return
*/
@Override
public List<Clazz> getClazzs() {
// 创建 QueryWrapper 对象,由于要查询所有班级,这里不添加额外的查询条件
QueryWrapper<Clazz> clazzQueryWrapper = new QueryWrapper<>();
// 调用 BaseMapper 的 selectList 方法,查询所有班级信息
return baseMapper.selectList(clazzQueryWrapper);
}
}

@ -0,0 +1,68 @@
package com.zsz.service.impl;
// 导入 MyBatis-Plus 用于构建查询条件的 QueryWrapper 类
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// 导入 MyBatis-Plus 用于实现分页查询的 Page 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 实现类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 导入年级数据访问层的 Mapper 接口
import com.zsz.mapper.GradeMapper;
// 导入年级实体类
import com.zsz.pojo.Grade;
// 导入年级服务层接口
import com.zsz.service.GradeService;
// 导入 Spring 框架的 Service 注解,用于将该类标记为服务层组件
import org.springframework.stereotype.Service;
// 导入 Spring 框架的事务管理注解,用于开启事务支持
import org.springframework.transaction.annotation.Transactional;
// 导入 Spring 框架的工具类,用于字符串操作
import org.springframework.util.StringUtils;
import java.util.List;
/**
* MyBatis-Plus ServiceImpl GradeService
*
*/
// 将该类标记为服务层组件,指定名称为 "gradeServiceImpl"
@Service("gradeServiceImpl")
// 开启事务支持,确保业务操作的原子性
@Transactional
public class GradeServiceImpl extends ServiceImpl<GradeMapper, Grade> implements GradeService {
/**
*
* @param gradePage
* @param gradeName
* @return Page
*/
@Override
public Page<Grade> getGradesData(Page<Grade> gradePage, String gradeName) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Grade> gradeQueryWrapper = new QueryWrapper<>();
// 判断年级名称是否为空,如果不为空,则添加模糊查询条件
if (!StringUtils.isEmpty(gradeName)) {
// 添加年级名称的模糊查询条件,对应数据库表中的 name 字段
gradeQueryWrapper.like("name", gradeName);
}
// 按照年级 ID 降序排序,确保新添加的年级记录排在前面
gradeQueryWrapper.orderByDesc("id");
// 调用 BaseMapper 的 selectPage 方法,根据分页信息和查询条件进行分页查询
Page<Grade> page = baseMapper.selectPage(gradePage, gradeQueryWrapper);
return page;
}
/**
*
* @return
*/
@Override
public List<Grade> getGrades() {
// 调用 BaseMapper 的 selectList 方法,传入 null 表示不添加额外的查询条件,即查询所有年级信息
return baseMapper.selectList(null);
}
}

@ -0,0 +1,100 @@
package com.zsz.service.impl;
// 导入 MyBatis-Plus 用于构建查询条件的 QueryWrapper 类
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// 导入 MyBatis-Plus 的基础 Mapper 接口
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入 MyBatis-Plus 用于实现分页查询的 Page 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 实现类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 导入学生数据访问层的 Mapper 接口
import com.zsz.mapper.StudentMapper;
// 导入管理员实体类(此处可能是多余导入,代码中未使用)
import com.zsz.pojo.Admin;
// 导入用户登录表单实体类
import com.zsz.pojo.LoginForm;
// 导入学生实体类
import com.zsz.pojo.Student;
// 导入学生服务层接口
import com.zsz.service.StudentService;
// 导入 MD5 加密工具类,用于对密码进行加密处理
import com.zsz.util.MD5;
// 导入 Spring 框架的 Service 注解,用于将该类标记为服务层组件
import org.springframework.stereotype.Service;
// 导入 Spring 框架的事务管理注解,用于开启事务支持
import org.springframework.transaction.annotation.Transactional;
// 导入 Spring 框架的工具类,用于字符串操作
import org.springframework.util.StringUtils;
/**
* MyBatis-Plus ServiceImpl StudentService
* ID
*/
// 将该类标记为服务层组件,指定名称为 "studentServiceImpl"
@Service("studentServiceImpl")
// 开启事务支持,确保业务操作的原子性
@Transactional
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
/**
*
* @param loginForm
* @return null
*/
@Override
public Student login(LoginForm loginForm) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
// 拼接查询条件:学生姓名等于登录表单中的用户名
studentQueryWrapper.eq("name", loginForm.getUsername());
// 拼接查询条件:学生密码(经过 MD5 加密)等于登录表单中的密码加密后的值
studentQueryWrapper.eq("password", MD5.encrypt(loginForm.getPassword()));
// 调用 BaseMapper 的 selectOne 方法,根据查询条件查询数据库,返回符合条件的唯一学生对象
Student student = baseMapper.selectOne(studentQueryWrapper);
return student;
}
/**
* ID
* @param userId ID
* @return null
*/
@Override
public Student getStudentById(Long userId) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
// 拼接查询条件:学生 ID 等于传入的用户 ID
studentQueryWrapper.eq("id", userId);
// 调用 BaseMapper 的 selectOne 方法,根据查询条件查询数据库,返回符合条件的唯一学生对象
return baseMapper.selectOne(studentQueryWrapper);
}
/**
*
* @param studentPage
* @param student
* @return Page
*/
@Override
public Page<Student> getStudentData(Page<Student> studentPage, Student student) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
// 判断学生对象中的班级名称是否为空,如果不为空,则添加模糊查询条件
if (!StringUtils.isEmpty(student.getClazzName())) {
// 添加班级名称的模糊查询条件,对应数据库表中的 clazz_name 字段
studentQueryWrapper.like("clazz_name", student.getClazzName());
}
// 判断学生对象中的学生姓名是否为空,如果不为空,则添加模糊查询条件
if (!StringUtils.isEmpty(student.getName())) {
// 添加学生姓名的模糊查询条件,对应数据库表中的 name 字段
studentQueryWrapper.like("name", student.getName());
}
// 调用 BaseMapper 的 selectPage 方法,根据分页信息和查询条件进行分页查询
Page<Student> studentPage1 = baseMapper.selectPage(studentPage, studentQueryWrapper);
return studentPage1;
}
}

@ -0,0 +1,97 @@
package com.zsz.service.impl;
// 导入 MyBatis-Plus 用于构建查询条件的工具类
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// 导入 MyBatis-Plus 用于实现分页查询的 Page 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入 MyBatis-Plus 提供的通用 Service 实现类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 导入教师数据访问层的 Mapper 接口
import com.zsz.mapper.TeacherMapper;
// 导入用户登录表单实体类
import com.zsz.pojo.LoginForm;
// 导入教师实体类
import com.zsz.pojo.Teacher;
// 导入教师服务层接口
import com.zsz.service.TeacherService;
// 导入 MD5 加密工具类,用于对密码进行加密处理
import com.zsz.util.MD5;
// 导入 Spring 框架的 Service 注解,用于将该类标记为服务层组件
import org.springframework.stereotype.Service;
// 导入 Spring 框架的事务管理注解,用于开启事务支持
import org.springframework.transaction.annotation.Transactional;
// 导入 Spring 框架的工具类,用于字符串操作
import org.springframework.util.StringUtils;
/**
* MyBatis-Plus ServiceImpl TeacherService
* ID
*/
// 将该类标记为服务层组件,指定名称为 "teacherServiceImpl"
@Service("teacherServiceImpl")
// 开启事务支持,确保业务操作的原子性
@Transactional
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {
/**
*
* @param loginForm
* @return null
*/
@Override
public Teacher login(LoginForm loginForm) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
// 拼接查询条件:教师姓名等于登录表单中的用户名
teacherQueryWrapper.eq("name", loginForm.getUsername());
// 拼接查询条件:教师密码(经过 MD5 加密)等于登录表单中的密码加密后的值
teacherQueryWrapper.eq("password", MD5.encrypt(loginForm.getPassword()));
// 调用 BaseMapper 的 selectOne 方法,根据查询条件查询数据库,返回符合条件的唯一教师对象
Teacher teacher = baseMapper.selectOne(teacherQueryWrapper);
return teacher;
}
/**
* ID
* @param userId ID
* @return null
*/
@Override
public Teacher getTeacherById(Long userId) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
// 拼接查询条件:教师 ID 等于传入的用户 ID
teacherQueryWrapper.eq("id", userId);
// 调用 BaseMapper 的 selectOne 方法,根据查询条件查询数据库,返回符合条件的唯一教师对象
return baseMapper.selectOne(teacherQueryWrapper);
}
/**
*
* @param teacherPage
* @param teacher
* @return Page
*/
@Override
public Page<Teacher> getTeacherData(Page<Teacher> teacherPage, Teacher teacher) {
// 创建 QueryWrapper 对象,用于构建数据库查询条件
QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
// 判断教师对象中的班级名称是否为空,如果不为空,则添加模糊查询条件
if (!StringUtils.isEmpty(teacher.getClazzName())) {
// 添加班级名称的模糊查询条件,对应数据库表中的 clazz_name 字段
teacherQueryWrapper.like("clazz_name", teacher.getClazzName());
}
// 判断教师对象中的教师姓名是否为空,如果不为空,则添加模糊查询条件
if (!StringUtils.isEmpty(teacher.getName())) {
// 添加教师姓名的模糊查询条件,对应数据库表中的 name 字段
teacherQueryWrapper.like("name", teacher.getName());
}
// 调用 BaseMapper 的 selectPage 方法,根据分页信息和查询条件进行分页查询
// 原代码中 Page 变量名首字母大写,建议改为小写,遵循 Java 命名规范
Page<Teacher> teacherPageResult = baseMapper.selectPage(teacherPage, teacherQueryWrapper);
return teacherPageResult;
}
}

@ -0,0 +1,135 @@
package com.zsz.util;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* @project: ssm_sms
* @description:
*/
public class CreateVerifiCodeImage {
// 定义验证码图片的宽度为 90 像素
private static int WIDTH = 90;
// 定义验证码图片的高度为 35 像素
private static int HEIGHT = 35;
// 定义验证码字符的大小为 20
private static int FONT_SIZE = 20;
// 用于存储生成的验证码字符数组
private static char[] verifiCode;
// 用于存储生成的验证码图片对象
private static BufferedImage verifiCodeImage;
/**
* @description:
* @param:
* @return: java.awt.image.BufferedImage
*/
public static BufferedImage getVerifiCodeImage() {
// 创建一个指定宽度、高度和图像类型TYPE_INT_BGR的 BufferedImage 对象
verifiCodeImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_BGR);
// 获取图片的 Graphics 对象,用于绘制图形和文本
Graphics graphics = verifiCodeImage.getGraphics();
// 生成验证码字符数组
verifiCode = generateCheckCode();
// 绘制验证码图片的背景
drawBackground(graphics);
// 在图片上绘制生成的验证码字符
drawRands(graphics, verifiCode);
// 释放 Graphics 对象所占用的系统资源
graphics.dispose();
// 返回生成的验证码图片
return verifiCodeImage;
}
/**
* @description:
* @param:
* @return: char
*/
public static char[] getVerifiCode() {
return verifiCode;
}
/**
* @description:
* @param:
* @return: 4 char
*/
private static char[] generateCheckCode() {
// 定义包含数字、小写字母和大写字母的字符集字符串
String chars = "0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 创建一个长度为 4 的字符数组,用于存储生成的验证码字符
char[] rands = new char[4];
// 循环 4 次,每次生成一个随机字符并存储到字符数组中
for (int i = 0; i < 4; i++) {
// 生成一个随机索引,范围是 0 到字符集长度减 1
int rand = (int) (Math.random() * (10 + 26 * 2));
// 根据随机索引从字符集中获取一个字符,并存储到字符数组中
rands[i] = chars.charAt(rand);
}
// 返回生成的验证码字符数组
return rands;
}
/**
* @description:
* @param: g Graphics
* @param: rands
* @return:
*/
private static void drawRands(Graphics g, char[] rands) {
// 设置绘制文本的字体为 Console 字体,加粗,大小为 FONT_SIZE
g.setFont(new Font("Console", Font.BOLD, FONT_SIZE));
// 遍历验证码字符数组,将每个字符绘制到图片上
for (int i = 0; i < rands.length; i++) {
// 获取一个随机颜色
g.setColor(getRandomColor());
// 在指定的 x 和 y 坐标位置绘制验证码字符
g.drawString("" + rands[i], i * FONT_SIZE + 10, 25);
}
}
/**
* @description:
* @param: g Graphics
* @return:
*/
private static void drawBackground(Graphics g) {
// 设置绘制颜色为白色
g.setColor(Color.white);
// 使用白色填充整个图片区域
g.fillRect(0, 0, WIDTH, HEIGHT);
// 绘制 200 个干扰点
for (int i = 0; i < 200; i++) {
// 生成一个随机的 x 坐标
int x = (int) (Math.random() * WIDTH);
// 生成一个随机的 y 坐标
int y = (int) (Math.random() * HEIGHT);
// 获取一个随机颜色
g.setColor(getRandomColor());
// 在指定的 x 和 y 坐标位置绘制一个 1x1 的椭圆(即一个点)
g.drawOval(x, y, 1, 1);
}
}
/**
* @description:
* @param:
* @return: java.awt.Color
*/
private static Color getRandomColor() {
// 创建一个 Random 对象,用于生成随机数
Random ran = new Random();
// 根据随机生成的红、绿、蓝分量值创建一个颜色对象并返回
return new Color(ran.nextInt(220), ran.nextInt(220), ran.nextInt(220));
}
}

@ -0,0 +1,152 @@
package com.zsz.util;
// 导入 JWT 相关的类,用于处理 JWT 的创建、解析等操作
import io.jsonwebtoken.*;
// 导入 Spring 框架的字符串工具类,用于判断字符串是否为空
import org.springframework.util.StringUtils;
// 导入日期类,用于处理时间相关的操作
import java.util.Date;
/**
* JwtHelper JWTJSON Web Token
* JWT
*/
public class JwtHelper {
// 定义 JWT 令牌的过期时间,这里设置为 24 小时,单位为毫秒
private static long tokenExpiration = 24 * 60 * 60 * 1000;
// 定义 JWT 令牌的签名密钥,用于对令牌进行签名和验证
private static String tokenSignKey = "123456";
/**
* JWT
* @param userId ID
* @param userType
* @return JWT
*/
public static String createToken(Long userId, Integer userType) {
// 使用 Jwts 构建器创建 JWT 令牌
String token = Jwts.builder()
// 设置 JWT 的主题
.setSubject("YYGH-USER")
// 设置 JWT 的过期时间,当前时间加上 tokenExpiration
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
// 在 JWT 中添加用户 ID 的声明
.claim("userId", userId)
// 注释掉的代码,可用于添加用户名的声明
// .claim("userName", userName)
// 在 JWT 中添加用户类型的声明
.claim("userType", userType)
// 使用 HS512 算法和签名密钥对 JWT 进行签名
.signWith(SignatureAlgorithm.HS512, tokenSignKey)
// 对 JWT 进行 GZIP 压缩
.compressWith(CompressionCodecs.GZIP)
// 构建最终的 JWT 令牌字符串
.compact();
return token;
}
/**
* JWT ID
* @param token JWT
* @return ID null
*/
public static Long getUserId(String token) {
// 判断令牌是否为空
if (StringUtils.isEmpty(token)) return null;
// 使用签名密钥解析 JWT 令牌
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
// 获取 JWT 中的声明信息
Claims claims = claimsJws.getBody();
// 从声明中获取用户 ID
Integer userId = (Integer) claims.get("userId");
// 将用户 ID 转换为 Long 类型并返回
return userId.longValue();
}
/**
* JWT
* @param token JWT
* @return null
*/
public static Integer getUserType(String token) {
// 判断令牌是否为空
if (StringUtils.isEmpty(token)) return null;
// 使用签名密钥解析 JWT 令牌
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
// 获取 JWT 中的声明信息
Claims claims = claimsJws.getBody();
// 从声明中获取用户类型并返回
return (Integer) (claims.get("userType"));
}
/**
* JWT
* @param token JWT
* @return
*/
public static String getUserName(String token) {
// 判断令牌是否为空
if (StringUtils.isEmpty(token)) return "";
// 使用签名密钥解析 JWT 令牌
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
// 获取 JWT 中的声明信息
Claims claims = claimsJws.getBody();
// 从声明中获取用户名并返回
return (String) claims.get("userName");
}
/**
* JWT
* @param token JWT
* @return true false
*/
public static boolean isExpiration(String token) {
try {
// 解析 JWT 令牌并获取过期时间,判断是否在当前时间之前
boolean isExpire = Jwts.parser()
.setSigningKey(tokenSignKey)
.parseClaimsJws(token)
.getBody()
.getExpiration().before(new Date());
// 没有过期,有效,返回 false
return isExpire;
} catch (Exception e) {
// 过期出现异常,返回 true
return true;
}
}
/**
* JWT
* @param token JWT
* @return JWT null
*/
public String refreshToken(String token) {
String refreshedToken;
try {
// 解析原 JWT 令牌获取声明信息
final Claims claims = Jwts.parser()
.setSigningKey(tokenSignKey)
.parseClaimsJws(token)
.getBody();
// 使用原令牌中的用户 ID 和用户类型重新生成新的 JWT 令牌
refreshedToken = JwtHelper.createToken(getUserId(token), getUserType(token));
} catch (Exception e) {
// 刷新失败,返回 null
refreshedToken = null;
}
return refreshedToken;
}
/**
* JWT
* @param args
*/
public static void main(String[] args) {
// 示例代码,可用于生成令牌并获取其中的信息
// String token = JwtHelper.createToken(1L, "lucy");
// System.out.println(token);
// System.out.println(JwtHelper.getUserId(token));
// System.out.println(JwtHelper.getUserName(token));
}
}

@ -0,0 +1,108 @@
package com.zsz.util;
// 导入自定义的系统配置类,用于获取系统相关配置信息
import com.zsz.config.SystemUtil;
// 导入 Lombok 的日志注解,可自动生成日志记录对象
import lombok.extern.slf4j.Slf4j;
// 导入 Spring 框架的 Component 注解,将该类标记为组件,以便 Spring 进行管理
import org.springframework.stereotype.Component;
// 导入 Spring 框架处理文件上传的 MultipartFile 类
import org.springframework.web.multipart.MultipartFile;
// 导入 Spring 框架的资源注入注解
import javax.annotation.Resource;
// 导入 Java 的文件操作类
import java.io.File;
// 导入 Java 的输入输出异常类
import java.io.IOException;
// 导入 Java 的日期格式化类
import java.text.SimpleDateFormat;
// 导入 Java 的日期类
import java.util.Date;
// 导入 Java 的随机数生成类
import java.util.Random;
/**
* LocalUploadUtil
*
*/
// 将该类标记为 Spring 组件,以便 Spring 自动扫描并管理
@Component
// 使用 Lombok 的 Slf4j 注解,自动生成日志记录对象
@Slf4j
public class LocalUploadUtil {
// 定义上传文件路径的前缀
public static final String PATH_PREFIX = "/upload/";
// 注入系统配置类的实例,用于获取文件保存的前缀路径
@Resource
private SystemUtil systemUtil;
/**
*
* @param file MultipartFile
* @return
*/
public String upload(MultipartFile file) {
// 生成新的文件名
String newFileName = genNewFileName(file);
// 创建本地文件夹对象,使用系统配置中的文件前缀路径
File fileDirectory = new File(systemUtil.getFilePrefix());
// 检查文件夹是否存在
if (!fileDirectory.exists()) {
// 如果文件夹不存在,则尝试创建
if (!fileDirectory.mkdir()) {
// 如果创建失败,抛出运行时异常
throw new RuntimeException("文件夹创建失败,路径为:" + fileDirectory);
}
}
try {
// 创建目标文件对象,使用系统配置的文件前缀和新生成的文件名
File destFile = new File(systemUtil.getFilePrefix() + newFileName);
// 将上传的文件传输到目标文件
file.transferTo(destFile);
} catch (IOException e) {
// 记录文件创建失败的错误日志
log.error("文件创建失败:{}", e.getMessage(), e);
// 抛出运行时异常,提示文件创建失败
throw new RuntimeException("文件创建失败:{}" + e.getMessage());
}
// 返回上传后文件的相对路径
return PATH_PREFIX + newFileName;
}
/**
*
* @param file
* @return
*/
private static String genNewFileName(MultipartFile file) {
// 创建日期格式化对象,指定日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
// 创建 StringBuilder 对象,用于构建文件名
StringBuilder fileName = new StringBuilder();
// 将当前日期格式化后添加到文件名中
fileName.append(sdf.format(new Date()));
// 生成一个 0 到 99 之间的随机数并添加到文件名中
fileName.append(new Random().nextInt(100));
// 获取文件的后缀名并添加到文件名中
fileName.append(getSuffixName(file));
// 返回生成的新文件名
return fileName.toString();
}
/**
*
* @param file
* @return
*/
private static String getSuffixName(MultipartFile file) {
// 获取文件的原始文件名
String fileName = file.getOriginalFilename();
// 从文件名中截取后缀名
String suffixName = fileName.substring(fileName.lastIndexOf("."));
// 返回文件的后缀名
return suffixName;
}
}

@ -0,0 +1,65 @@
package com.zsz.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* MD5 MD5
* final 便
*/
public final class MD5 {
/**
* MD5
* @param strSrc
* @return RuntimeException
*/
public static String encrypt(String strSrc) {
try {
// 定义十六进制字符数组,用于将字节转换为十六进制表示
char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
// 将输入的字符串转换为字节数组
byte[] bytes = strSrc.getBytes();
// 获取 MD5 算法的 MessageDigest 实例
MessageDigest md = MessageDigest.getInstance("MD5");
// 使用输入的字节数组更新摘要
md.update(bytes);
// 完成哈希计算,得到加密后的字节数组
bytes = md.digest();
// 获取加密后字节数组的长度
int j = bytes.length;
// 创建一个字符数组,长度为字节数组长度的两倍,用于存储十六进制表示
char[] chars = new char[j * 2];
// 用于记录字符数组的索引
int k = 0;
// 遍历加密后的字节数组
for (int i = 0; i < bytes.length; i++) {
// 获取当前字节
byte b = bytes[i];
// 将字节的高 4 位转换为十六进制字符并存储到字符数组中
chars[k++] = hexChars[b >>> 4 & 0xf];
// 将字节的低 4 位转换为十六进制字符并存储到字符数组中
chars[k++] = hexChars[b & 0xf];
}
// 将字符数组转换为字符串并返回
return new String(chars);
} catch (NoSuchAlgorithmException e) {
// 打印异常堆栈信息
e.printStackTrace();
// 抛出运行时异常,提示 MD5 加密出错
throw new RuntimeException("MD5加密出错+" + e);
}
}
/**
* MD5
* @param args
*/
public static void main(String[] args) {
// 对字符串 "123456" 进行加密
String encrypt = encrypt("123456");
// 打印加密后的字符串
System.out.println(encrypt);
}
}

@ -0,0 +1,154 @@
package com.zsz.util;
// 导入 Swagger 用于描述 API 模型的注解
import io.swagger.annotations.ApiModel;
// 导入 Swagger 用于描述 API 模型属性的注解
import io.swagger.annotations.ApiModelProperty;
// 导入 Lombok 的 Data 注解,自动生成 getter、setter、toString 等方法
import lombok.Data;
/**
*
*
* 使 T
*/
// 使用 Lombok 的 Data 注解,自动生成 getter、setter、toString、equals、hashCode 等方法
@Data
// 使用 Swagger 的 ApiModel 注解,描述该类是全局统一返回结果的模型
@ApiModel(value = "全局统一返回结果")
public class Result<T> {
// 使用 Swagger 的 ApiModelProperty 注解,描述该属性为返回码
@ApiModelProperty(value = "返回码")
// 存储返回码的属性
private Integer code;
// 使用 Swagger 的 ApiModelProperty 注解,描述该属性为返回消息
@ApiModelProperty(value = "返回消息")
// 存储返回消息的属性
private String message;
// 使用 Swagger 的 ApiModelProperty 注解,描述该属性为返回数据
@ApiModelProperty(value = "返回数据")
// 存储返回数据的属性,使用泛型 T 可以接受任意类型的数据
private T data;
// 无参构造函数,用于创建一个空的 Result 对象
public Result() {}
/**
* Result
* @param data
* @param <T>
* @return Result
*/
protected static <T> Result<T> build(T data) {
// 创建一个新的 Result 对象
Result<T> result = new Result<T>();
// 如果传入的数据不为空,则将数据设置到 Result 对象中
if (data != null)
result.setData(data);
// 返回构建好的 Result 对象
return result;
}
/**
* Result
* @param body
* @param resultCodeEnum
* @param <T>
* @return Result
*/
public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
// 先调用 build 方法构建一个包含数据的 Result 对象
Result<T> result = build(body);
// 从结果码枚举对象中获取返回码并设置到 Result 对象中
result.setCode(resultCodeEnum.getCode());
// 从结果码枚举对象中获取返回消息并设置到 Result 对象中
result.setMessage(resultCodeEnum.getMessage());
// 返回构建好的 Result 对象
return result;
}
/**
* Result
* @param <T>
* @return Result
*/
public static <T> Result<T> ok() {
// 调用 ok 方法,传入 null 表示不包含数据
return Result.ok(null);
}
/**
* Result
* @param data
* @param <T>
* @return Result
*/
public static <T> Result<T> ok(T data) {
// 先调用 build 方法构建一个包含数据的 Result 对象
Result<T> result = build(data);
// 调用 build 方法,传入数据和成功的结果码枚举对象,设置返回码和返回消息
return build(data, ResultCodeEnum.SUCCESS);
}
/**
* Result
* @param <T>
* @return Result
*/
public static <T> Result<T> fail() {
// 调用 fail 方法,传入 null 表示不包含数据
return Result.fail(null);
}
/**
* Result
* @param data
* @param <T>
* @return Result
*/
public static <T> Result<T> fail(T data) {
// 先调用 build 方法构建一个包含数据的 Result 对象
Result<T> result = build(data);
// 调用 build 方法,传入数据和失败的结果码枚举对象,设置返回码和返回消息
return build(data, ResultCodeEnum.FAIL);
}
/**
* Result
* @param msg
* @return Result
*/
public Result<T> message(String msg) {
// 设置返回消息
this.setMessage(msg);
// 返回当前 Result 对象,支持链式调用
return this;
}
/**
* Result
* @param code
* @return Result
*/
public Result<T> code(Integer code) {
// 设置返回码
this.setCode(code);
// 返回当前 Result 对象,支持链式调用
return this;
}
/**
*
* @return true false
*/
public boolean isOk() {
// 比较当前 Result 对象的返回码和成功的结果码是否相等
if (this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
return true;
}
return false;
}
}

@ -0,0 +1,76 @@
package com.zsz.util;
import lombok.Getter;
/**
* 使
*
*/
// 使用 Lombok 的 Getter 注解,自动为枚举类的属性生成 getter 方法
@Getter
public enum ResultCodeEnum {
// 表示操作成功的枚举常量,状态码为 200消息为 "成功"
SUCCESS(200, "成功"),
// 表示操作失败的枚举常量,状态码为 201消息为 "失败"
FAIL(201, "失败"),
// 表示服务异常的枚举常量,状态码为 2012消息为 "服务异常"
SERVICE_ERROR(2012, "服务异常"),
// 表示非法请求的枚举常量,状态码为 204消息为 "非法请求"
ILLEGAL_REQUEST(204, "非法请求"),
// 表示支付中状态的枚举常量,状态码为 205消息为 "支付中"
PAY_RUN(205, "支付中"),
// 表示参数校验错误的枚举常量,状态码为 206消息为 "参数校验错误"
ARGUMENT_VALID_ERROR(206, "参数校验错误"),
// 表示用户名或密码错误的枚举常量,状态码为 207消息为 "用户名或密码错误"
LOGIN_ERROR(207, "用户名或密码错误"),
// 表示未登录状态的枚举常量,状态码为 208消息为 "未登陆"
LOGIN_AUTH(208, "未登陆"),
// 表示没有权限的枚举常量,状态码为 209消息为 "没有权限"
PERMISSION(209, "没有权限"),
// 表示秒杀还没开始的枚举常量,状态码为 210消息为 "秒杀还没开始"
SECKILL_NO_START(210, "秒杀还没开始"),
// 表示正在秒杀排队中的枚举常量,状态码为 211消息为 "正在排队中"
SECKILL_RUN(211, "正在排队中"),
// 表示有未支付订单的枚举常量,状态码为 212消息为 "您有未支付的订单"
SECKILL_NO_PAY_ORDER(212, "您有未支付的订单"),
// 表示商品已售罄的枚举常量,状态码为 213消息为 "已售罄"
SECKILL_FINISH(213, "已售罄"),
// 表示秒杀已结束的枚举常量,状态码为 214消息为 "秒杀已结束"
SECKILL_END(214, "秒杀已结束"),
// 表示抢单成功的枚举常量,状态码为 215消息为 "抢单成功"
SECKILL_SUCCESS(215, "抢单成功"),
// 表示抢单失败的枚举常量,状态码为 216消息为 "抢单失败"
SECKILL_FAIL(216, "抢单失败"),
// 表示请求不合法的枚举常量,状态码为 217消息为 "请求不合法"
SECKILL_ILLEGAL(217, "请求不合法"),
// 表示下单成功的枚举常量,状态码为 218消息为 "下单成功"
SECKILL_ORDER_SUCCESS(218, "下单成功"),
// 表示优惠券已经领取的枚举常量,状态码为 220消息为 "优惠券已经领取"
COUPON_GET(220, "优惠券已经领取"),
// 表示优惠券已发放完毕的枚举常量,状态码为 221消息为 "优惠券已发放完毕"
COUPON_LIMIT_GET(221, "优惠券已发放完毕"),
// 2022-02-22 添加的枚举常量
// 表示长时间未操作会话已失效的枚举常量,状态码为 222消息为 "长时间未操作,会话已失效,请刷新页面后重试!"
LOGIN_CODE(222, "长时间未操作,会话已失效,请刷新页面后重试!"),
// 表示验证码错误的枚举常量,状态码为 223消息为 "验证码错误!"
CODE_ERROR(223, "验证码错误!"),
// 表示 Token 无效的枚举常量,状态码为 224消息为 "Token 无效!"
TOKEN_ERROR(224, "Token 无效!");
// 存储状态码的属性
private Integer code;
// 存储状态消息的属性
private String message;
/**
*
* @param code
* @param message
*/
private ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}

@ -0,0 +1,101 @@
package com.zsz.util;
import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @project: zhxy
* @description:
*
*/
public class UploadFile {
// 存储文件上传失败的错误信息的 Map 对象
private static Map<String, Object> error_result = new HashMap<>();
// 存储头像的上传结果信息的 Map 对象
private static Map<String, Object> upload_result = new HashMap<>();
/**
*
* @param photo MultipartFile
* @param path
* @return Map null
*/
private static Map<String, Object> uploadPhoto(MultipartFile photo, String path) {
// 限制头像大小为 20M20 * 1024 * 1024 字节)
int MAX_SIZE = 20971520;
// 获取图片的原始名称
String orginalName = photo.getOriginalFilename();
// 如果保存文件的路径不存在,则创建该目录
File filePath = new File(path);
if (!filePath.exists()) {
filePath.mkdirs();
}
// 限制上传文件的大小,如果文件大小超过限制,则设置错误信息并返回
if (photo.getSize() > MAX_SIZE) {
error_result.put("success", false);
error_result.put("msg", "上传的图片大小不能超过 20M 哟!");
return error_result;
}
// 限制上传的文件类型,定义允许的文件后缀数组
String[] suffixs = new String[]{".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".gif", ".GIF", ".bmp", ".BMP"};
// 创建后缀文件过滤器
SuffixFileFilter suffixFileFilter = new SuffixFileFilter(suffixs);
// 检查文件类型是否符合要求,如果不符合,则设置错误信息并返回
if (!suffixFileFilter.accept(new File(path + orginalName))) {
error_result.put("success", false);
error_result.put("msg", "禁止上传此类型文件! 请上传图片哟!");
return error_result;
}
return null;
}
/**
*
* @param photo MultipartFile
* @param dirPaht
* @param portraitPath
* @return Map
*/
public static Map<String, Object> getUploadResult(MultipartFile photo, String dirPaht, String portraitPath) {
// 检查文件是否为空且大小大于 0
if (!photo.isEmpty() && photo.getSize() > 0) {
// 获取图片的原始名称
String orginalName = photo.getOriginalFilename();
// 上传图片并获取错误信息(如果有)
Map<String, Object> error_result = UploadFile.uploadPhoto(photo, dirPaht);
if (error_result != null) {
return error_result;
}
// 使用 UUID 重命名图片名称uuid__原始图片名称
String newPhotoName = UUID.randomUUID() + "__" + orginalName;
// 将上传的文件保存到目标目录下
try {
photo.transferTo(new File(dirPaht + newPhotoName));
// 设置上传成功的信息,并将头像在项目中的完整路径返回
upload_result.put("success", true);
upload_result.put("portrait_path", portraitPath + newPhotoName);
} catch (IOException e) {
// 处理上传失败的情况,设置错误信息
e.printStackTrace();
upload_result.put("success", false);
upload_result.put("msg", "上传文件失败! 服务器端发生异常!");
return upload_result;
}
} else {
// 文件为空或大小为 0 时,设置上传失败的信息
upload_result.put("success", false);
upload_result.put("msg", "头像上传失败! 未找到指定图片!");
}
return upload_result;
}
}

@ -0,0 +1,45 @@
server:
port: 8080
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=UTC
username: root
password: 123456
hikari:
connection-test-query: SELECT 1
connection-timeout: 60000
idle-timeout: 500000
max-lifetime: 540000
maximum-pool-size: 12
minimum-idle: 10
pool-name: GuliHikariPool
thymeleaf:
mode: HTML5
encoding: UTF-8
cache: false
prefix: classpath:/static/
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath*:/mapper/**/*.xml
file:
upload:
windows:
dir: D:/upload/ # windows 文件上传目录,不要忘记末尾的/
linux:
dir: /temp/upload/ # linus或者macos 文件上传目录
mac:
dir: ~/upload/

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

@ -0,0 +1,169 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel=icon href=/favicon.ico>
<title>班级信息管理系统</title>
<link href=/static/css/app.2a150c78.css rel=preload as=style>
<link href=/static/css/chunk-elementUI.751bfb5e.css rel=preload as=style>
<link href=/static/css/chunk-libs.3dfb7769.css rel=preload as=style>
<link href=/static/js/app.c9219e63.js rel=preload as=script>
<link href=/static/js/chunk-elementUI.edb7fc53.js rel=preload as=script>
<link href=/static/js/chunk-libs.9892d939.js rel=preload as=script>
<link href=/static/css/chunk-elementUI.751bfb5e.css rel=stylesheet>
<link href=/static/css/chunk-libs.3dfb7769.css rel=stylesheet>
<link href=/static/css/app.2a150c78.css rel=stylesheet>
</head>
<body>
<noscript><strong>We're sorry but 班级信息管理系统 doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong></noscript>
<div id=app></div>
<script>(function (e) {
function t(t) {
for (var r, c, a = t[0], i = t[1], d = t[2], f = 0, l = []; f < a.length; f++) c = a[f], Object.prototype.hasOwnProperty.call(o, c) && o[c] && l.push(o[c][0]), o[c] = 0;
for (r in i) Object.prototype.hasOwnProperty.call(i, r) && (e[r] = i[r]);
h && h(t);
while (l.length) l.shift()();
return u.push.apply(u, d || []), n()
}
function n() {
for (var e, t = 0; t < u.length; t++) {
for (var n = u[t], r = !0, c = 1; c < n.length; c++) {
var a = n[c];
0 !== o[a] && (r = !1)
}
r && (u.splice(t--, 1), e = i(i.s = n[0]))
}
return e
}
var r = {}, c = {runtime: 0}, o = {runtime: 0}, u = [];
function a(e) {
return i.p + "static/js/" + ({}[e] || e) + "." + {
"chunk-01081519": "06d2caa6",
"chunk-24890d62": "13705e10",
"chunk-299dfd1b": "644f9fcc",
"chunk-2c5071da": "266f37e1",
"chunk-35d45b48": "4f5531a8",
"chunk-417b88dd": "20c43d0c",
"chunk-4ce4e6a0": "aa96c8ff",
"chunk-62446ae8": "5a21e53b",
"chunk-96a4e134": "ba975cc5"
}[e] + ".js"
}
function i(t) {
if (r[t]) return r[t].exports;
var n = r[t] = {i: t, l: !1, exports: {}};
return e[t].call(n.exports, n, n.exports, i), n.l = !0, n.exports
}
i.e = function (e) {
var t = [], n = {
"chunk-01081519": 1,
"chunk-299dfd1b": 1,
"chunk-2c5071da": 1,
"chunk-35d45b48": 1,
"chunk-417b88dd": 1,
"chunk-4ce4e6a0": 1,
"chunk-96a4e134": 1
};
c[e] ? t.push(c[e]) : 0 !== c[e] && n[e] && t.push(c[e] = new Promise((function (t, n) {
for (var r = "static/css/" + ({}[e] || e) + "." + {
"chunk-01081519": "6d26ba5b",
"chunk-24890d62": "31d6cfe0",
"chunk-299dfd1b": "0c55c6b3",
"chunk-2c5071da": "97dec6d1",
"chunk-35d45b48": "6d26ba5b",
"chunk-417b88dd": "6d26ba5b",
"chunk-4ce4e6a0": "71911e6b",
"chunk-62446ae8": "31d6cfe0",
"chunk-96a4e134": "2654d086"
}[e] + ".css", o = i.p + r, u = document.getElementsByTagName("link"), a = 0; a < u.length; a++) {
var d = u[a], f = d.getAttribute("data-href") || d.getAttribute("href");
if ("stylesheet" === d.rel && (f === r || f === o)) return t()
}
var l = document.getElementsByTagName("style");
for (a = 0; a < l.length; a++) {
d = l[a], f = d.getAttribute("data-href");
if (f === r || f === o) return t()
}
var h = document.createElement("link");
h.rel = "stylesheet", h.type = "text/css", h.onload = t, h.onerror = function (t) {
var r = t && t.target && t.target.src || o,
u = new Error("Loading CSS chunk " + e + " failed.\n(" + r + ")");
u.code = "CSS_CHUNK_LOAD_FAILED", u.request = r, delete c[e], h.parentNode.removeChild(h), n(u)
}, h.href = o;
var s = document.getElementsByTagName("head")[0];
s.appendChild(h)
})).then((function () {
c[e] = 0
})));
var r = o[e];
if (0 !== r) if (r) t.push(r[2]); else {
var u = new Promise((function (t, n) {
r = o[e] = [t, n]
}));
t.push(r[2] = u);
var d, f = document.createElement("script");
f.charset = "utf-8", f.timeout = 120, i.nc && f.setAttribute("nonce", i.nc), f.src = a(e);
var l = new Error;
d = function (t) {
f.onerror = f.onload = null, clearTimeout(h);
var n = o[e];
if (0 !== n) {
if (n) {
var r = t && ("load" === t.type ? "missing" : t.type), c = t && t.target && t.target.src;
l.message = "Loading chunk " + e + " failed.\n(" + r + ": " + c + ")", l.name = "ChunkLoadError", l.type = r, l.request = c, n[1](l)
}
o[e] = void 0
}
};
var h = setTimeout((function () {
d({type: "timeout", target: f})
}), 12e4);
f.onerror = f.onload = d, document.head.appendChild(f)
}
return Promise.all(t)
}, i.m = e, i.c = r, i.d = function (e, t, n) {
i.o(e, t) || Object.defineProperty(e, t, {enumerable: !0, get: n})
}, i.r = function (e) {
"undefined" !== typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {value: "Module"}), Object.defineProperty(e, "__esModule", {value: !0})
}, i.t = function (e, t) {
if (1 & t && (e = i(e)), 8 & t) return e;
if (4 & t && "object" === typeof e && e && e.__esModule) return e;
var n = Object.create(null);
if (i.r(n), Object.defineProperty(n, "default", {
enumerable: !0,
value: e
}), 2 & t && "string" != typeof e) for (var r in e) i.d(n, r, function (t) {
return e[t]
}.bind(null, r));
return n
}, i.n = function (e) {
var t = e && e.__esModule ? function () {
return e["default"]
} : function () {
return e
};
return i.d(t, "a", t), t
}, i.o = function (e, t) {
return Object.prototype.hasOwnProperty.call(e, t)
}, i.p = "/", i.oe = function (e) {
throw console.error(e), e
};
var d = window["webpackJsonp"] = window["webpackJsonp"] || [], f = d.push.bind(d);
d.push = t, d = d.slice();
for (var l = 0; l < d.length; l++) t(d[l]);
var h = f;
n()
})([]);</script>
<script src=/static/js/chunk-elementUI.edb7fc53.js></script>
<script src=/static/js/chunk-libs.9892d939.js></script>
<script src=/static/js/app.c9219e63.js></script>
</body>
</html>

@ -0,0 +1,61 @@
[
{
"name": "权限管理",
"code": "Auth",
"children": [
{
"name": "用户管理",
"code": "User",
"buttons": [
{
"name": "添加",
"code": "User.btn.add"
},
{
"name": "删除",
"code": "User.btn.remove"
},
{
"name": "分配角色",
"code": "User.btn.assgin"
}
]
},
{
"name": "角色管理",
"path": "role/list",
"code": "Role",
"buttons": [
{
"name": "删除",
"code": "Role.btn.remove"
},
{
"name": "分配权限",
"code": "Role.btn.assgin",
"toCode": "RoleAuth"
}
]
},
{
"name": "菜单管理",
"path": "code/list",
"code": "code",
"buttons": [
{
"name": "添加",
"code": "code.btn.add"
},
{
"name": "修改",
"code": "code.btn.update"
},
{
"name": "删除",
"code": "code.btn.remove"
}
]
}
]
}
]

@ -0,0 +1,13 @@
{
"menus": [
"",
"User",
"Role"
],
"buttons": [
"User.btn.add",
"User.btn.remove",
"Role.btn.assgin",
"Permission.btn.update"
]
}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.avatar-uploader .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload:hover{border-color:#409eff}.avatar-uploader-icon{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avatar{width:178px;height:178px;display:block}

@ -0,0 +1 @@
.wscn-http404-container[data-v-62f526d4]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;top:40%;left:50%}.wscn-http404[data-v-62f526d4]{position:relative;width:1200px;padding:0 50px;overflow:hidden}.wscn-http404 .pic-404[data-v-62f526d4]{position:relative;float:left;width:600px;overflow:hidden}.wscn-http404 .pic-404__parent[data-v-62f526d4]{width:100%}.wscn-http404 .pic-404__child[data-v-62f526d4]{position:absolute}.wscn-http404 .pic-404__child.left[data-v-62f526d4]{width:80px;top:17px;left:220px;opacity:0;-webkit-animation-name:cloudLeft-data-v-62f526d4;animation-name:cloudLeft-data-v-62f526d4;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}.wscn-http404 .pic-404__child.mid[data-v-62f526d4]{width:46px;top:10px;left:420px;opacity:0;-webkit-animation-name:cloudMid-data-v-62f526d4;animation-name:cloudMid-data-v-62f526d4;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1.2s;animation-delay:1.2s}.wscn-http404 .pic-404__child.right[data-v-62f526d4]{width:62px;top:100px;left:500px;opacity:0;-webkit-animation-name:cloudRight-data-v-62f526d4;animation-name:cloudRight-data-v-62f526d4;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}@-webkit-keyframes cloudLeft-data-v-62f526d4{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudLeft-data-v-62f526d4{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@-webkit-keyframes cloudMid-data-v-62f526d4{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudMid-data-v-62f526d4{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@-webkit-keyframes cloudRight-data-v-62f526d4{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}@keyframes cloudRight-data-v-62f526d4{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.wscn-http404 .bullshit[data-v-62f526d4]{position:relative;float:left;width:300px;padding:30px 0;overflow:hidden}.wscn-http404 .bullshit__oops[data-v-62f526d4]{font-size:32px;line-height:40px;color:#1482f0;margin-bottom:20px;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__headline[data-v-62f526d4],.wscn-http404 .bullshit__oops[data-v-62f526d4]{font-weight:700;opacity:0;-webkit-animation-name:slideUp-data-v-62f526d4;animation-name:slideUp-data-v-62f526d4;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__headline[data-v-62f526d4]{font-size:20px;line-height:24px;color:#222;margin-bottom:10px;-webkit-animation-delay:.1s;animation-delay:.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-62f526d4]{font-size:13px;line-height:21px;color:grey;margin-bottom:30px;-webkit-animation-delay:.2s;animation-delay:.2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-62f526d4],.wscn-http404 .bullshit__return-home[data-v-62f526d4]{opacity:0;-webkit-animation-name:slideUp-data-v-62f526d4;animation-name:slideUp-data-v-62f526d4;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__return-home[data-v-62f526d4]{display:block;float:left;width:110px;height:36px;background:#1482f0;border-radius:100px;text-align:center;color:#fff;font-size:14px;line-height:36px;cursor:pointer;-webkit-animation-delay:.3s;animation-delay:.3s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes slideUp-data-v-62f526d4{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes slideUp-data-v-62f526d4{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}

@ -0,0 +1 @@
@supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container{background-image:url(../../static/img/bg.7285dd88.jpg);background-color:#2d3a4b;background-size:cover}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container .user-type{border:none}.login-container .user-type ::v-deep.el-radio{color:#fff}.login-container[data-v-4132c592]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-4132c592]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-4132c592]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-4132c592]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-4132c592]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-4132c592]{position:relative}.login-container .title-container .title[data-v-4132c592]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-4132c592]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}

@ -0,0 +1 @@
.avatar-uploader .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload:hover{border-color:#409eff}.avatar-uploader-icon{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avatar{width:178px;height:178px;display:block}

@ -0,0 +1 @@
.avatar-uploader .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload:hover{border-color:#409eff}.avatar-uploader-icon{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avatar{width:178px;height:178px;display:block}

@ -0,0 +1 @@
.avatar-uploader .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload:hover{border-color:#409eff}.avatar-uploader-icon{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avatar{width:178px;height:178px;display:block}.avatar-box{-webkit-box-shadow:-2px 0 20px -16px;box-shadow:-2px 0 20px -16px;width:95%;height:100%}.avatar-box .user-card{min-height:calc(90vh - 200px);padding:30px 10px;text-align:center}.avatar-box .user-card .el-avatar{border-radius:50%}.avatar-box .user-card .user-personality{text-align:center}.avatar-box .user-card .user-personality p{font-size:16px}.avatar-box .user-card .user-personality .nickName{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:26px}.avatar-box .user-card .user-personality .person-info{margin-top:6px;font-size:14px;color:#999}.avatar-box .user-card .user-information{width:100%;height:100%;text-align:left}.avatar-box .user-card .user-information ul{display:inline-block;height:100%;width:100%;margin-left:20px}.avatar-box .user-card .user-information ul li{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:20px 0;font-size:16px;font-weight:400;color:#606266}.avatar-box .user-card .user-information ul li .title{margin-right:8px;font-weight:800}.user-addcount ul li{border-bottom:2px solid #f0f2f5}.user-addcount ul li .title{padding:10px;font-size:18px;color:#696969}.user-addcount ul li .desc{font-size:16px;padding:0 10px 20px 10px;color:#a9a9a9}.user-addcount ul li .desc a{color:#409eff;float:right}.user-headpic-update{width:120px;height:120px;line-height:120px;margin:0 auto;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:20px}.user-headpic-update:hover{color:#fff;background:-webkit-gradient(linear,left top,left bottom,from(hsla(0,0%,100%,.15)),to(rgba(0,0,0,.15))),radial-gradient(at top center,hsla(0,0%,100%,.4) 0,rgba(0,0,0,.4) 120%) #989898;background:linear-gradient(180deg,hsla(0,0%,100%,.15) 0,rgba(0,0,0,.15)),radial-gradient(at top center,hsla(0,0%,100%,.4) 0,rgba(0,0,0,.4) 120%) #989898;background-blend-mode:multiply,multiply}.user-headpic-update:hover .update{color:#fff}.user-headpic-update .update{height:120px;width:120px;text-align:center;color:transparent}.pointer{cursor:pointer}.code-box{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}

@ -0,0 +1 @@
.home[data-v-2bef1aba]{display:-webkit-box;display:-ms-flexbox;display:flex;height:500px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-bottom:50px}.home .title[data-v-2bef1aba]{font-size:35px;letter-spacing:2px}.home .emphasis[data-v-2bef1aba]{font-size:60px;color:#2b8775}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;-webkit-box-shadow:0 0 10px #29d,0 0 5px #29d;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translateY(-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;-webkit-box-sizing:border-box;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-299dfd1b"],{"26fc":function(t,s,i){t.exports=i.p+"static/img/404_cloud.0f4bc32b.png"},"65ec":function(t,s,i){"use strict";i("ae65")},"8cdb":function(t,s,i){"use strict";i.r(s);var a=function(){var t=this,s=t.$createElement,i=t._self._c||s;return i("div",{staticClass:"wscn-http404-container"},[i("div",{staticClass:"wscn-http404"},[t._m(0),i("div",{staticClass:"bullshit"},[i("div",{staticClass:"bullshit__oops"},[t._v("你访问的界面不存在!")]),i("div",{staticClass:"bullshit__headline"},[t._v(t._s(t.message))]),i("div",{staticClass:"bullshit__info"},[t._v("请检查你的url是否正确, 或点击下面按钮回到首页")]),i("a",{staticClass:"bullshit__return-home",attrs:{href:""}},[t._v("返回到首页")])])])])},c=[function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"pic-404"},[a("img",{staticClass:"pic-404__parent",attrs:{src:i("a36b"),alt:"404"}}),a("img",{staticClass:"pic-404__child left",attrs:{src:i("26fc"),alt:"404"}}),a("img",{staticClass:"pic-404__child mid",attrs:{src:i("26fc"),alt:"404"}}),a("img",{staticClass:"pic-404__child right",attrs:{src:i("26fc"),alt:"404"}})])}],l={name:"Page404",computed:{message:function(){return"管理员说你不能进入此页面"}}},e=l,n=(i("65ec"),i("2877")),r=Object(n["a"])(e,a,c,!1,null,"62f526d4",null);s["default"]=r.exports},a36b:function(t,s,i){t.exports=i.p+"static/img/404.a57b6f31.png"},ae65:function(t,s,i){}}]);

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2c5071da"],{2017:function(e,t,o){"use strict";o("cafe")},"9ed6":function(e,t,o){"use strict";o.r(t);var s=function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("div",{staticClass:"login-container"},[o("el-form",{ref:"loginForm",staticClass:"login-form",attrs:{model:e.loginForm,rules:e.loginRules,"auto-complete":"on","label-position":"left"}},[o("div",{staticClass:"title-container"},[o("h3",{staticClass:"title"},[e._v("智慧校园管理系统")])]),o("el-form-item",{attrs:{prop:"username"}},[o("span",{staticClass:"svg-container"},[o("svg-icon",{attrs:{"icon-class":"user"}})],1),o("el-input",{ref:"username",attrs:{placeholder:"用户名",name:"username",type:"text",tabindex:"1","auto-complete":"on"},model:{value:e.loginForm.username,callback:function(t){e.$set(e.loginForm,"username",t)},expression:"loginForm.username"}})],1),o("el-form-item",{attrs:{prop:"password"}},[o("span",{staticClass:"svg-container"},[o("svg-icon",{attrs:{"icon-class":"password"}})],1),o("el-input",{key:e.passwordType,ref:"password",attrs:{type:e.passwordType,placeholder:"密码",name:"password",tabindex:"2","auto-complete":"on"},nativeOn:{keyup:function(t){return!t.type.indexOf("key")&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.handleLogin(t)}},model:{value:e.loginForm.password,callback:function(t){e.$set(e.loginForm,"password",t)},expression:"loginForm.password"}}),o("span",{staticClass:"show-pwd",on:{click:e.showPwd}},[o("svg-icon",{attrs:{"icon-class":"password"===e.passwordType?"eye":"eye-open"}})],1)],1),o("el-form-item",{attrs:{prop:"verifiCode"}},[o("span",{staticClass:"svg-container"},[o("svg-icon",{attrs:{"icon-class":"people"}})],1),o("el-input",{ref:"verifiCode",attrs:{placeholder:"验证码",name:"verifiCode"},model:{value:e.loginForm.verifiCode,callback:function(t){e.$set(e.loginForm,"verifiCode",t)},expression:"loginForm.verifiCode"}}),o("span",{staticClass:"show-pwd",on:{click:e.updateCode}},[o("img",{attrs:{title:"点击切换验证码",src:e.codeImgUrl,alt:"#"}})])],1),o("el-form-item",{staticClass:"user-type",attrs:{prop:"userType"}},[o("el-radio-group",{model:{value:e.loginForm.userType,callback:function(t){e.$set(e.loginForm,"userType",t)},expression:"loginForm.userType"}},[o("el-radio",{attrs:{label:1}},[e._v("管理员")]),o("el-radio",{attrs:{label:2}},[e._v("学生")]),o("el-radio",{attrs:{label:3}},[e._v("教师")])],1)],1),o("el-button",{staticStyle:{width:"100%","margin-bottom":"30px"},attrs:{loading:e.loading,type:"primary"},nativeOn:{click:function(t){return t.preventDefault(),e.handleLogin(t)}}},[e._v("登 陆")])],1)],1)},r=[],n=(o("99af"),{name:"Login",data:function(){var e=function(e,t,o){t.length<2?o(new Error("用户名长度不能小于2位")):o()},t=function(e,t,o){t.length<5?o(new Error("密码长度不能小于5位")):o()};return{codeImgUrl:"".concat(this.$BASE_API,"/sms/system/getVerifiCodeImage"),loginForm:{username:"admin",password:"admin",verifiCode:null,userType:null},loginRules:{username:[{required:!0,validator:e}],password:[{required:!0,trigger:"blur",validator:t}],verifiCode:[{required:!0,message:"必须输入验证码"}],userType:[{required:!0,message:"必须选择用户类型"}]},loading:!1,passwordType:"password",redirect:void 0}},watch:{$route:{handler:function(e){this.redirect=e.query&&e.query.redirect},immediate:!0}},mounted:function(){this.updateCode()},methods:{updateCode:function(){this.codeImgUrl="".concat(this.$BASE_API,"/sms/system/getVerifiCodeImage?t=").concat(Date.now())},showPwd:function(){var e=this;"password"===this.passwordType?this.passwordType="text":this.passwordType="password",this.$nextTick((function(){e.$refs.password.focus()}))},handleLogin:function(){var e=this;this.$refs.loginForm.validate((function(t){t&&(e.loading=!0,e.$store.dispatch("user/login",e.loginForm).then((function(){e.$router.push({path:e.redirect||"/"}),e.loading=!1})).catch((function(){e.loading=!1,e.updateCode()})))}))}}}),i=n,a=(o("2017"),o("d00b"),o("2877")),l=Object(a["a"])(i,s,r,!1,null,"4132c592",null);t["default"]=l.exports},cafe:function(e,t,o){},d00b:function(e,t,o){"use strict";o("d01d")},d01d:function(e,t,o){}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-96a4e134"],{"7e65":function(e,t,s){},9406:function(e,t,s){"use strict";s.r(t);var n=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},a=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"home"},[s("h2",{staticClass:"title"},[e._v("欢迎使用"),s("span",{staticClass:"emphasis"},[e._v("班级信息")]),e._v("管理系统")])])}],c={name:"Home"},i=c,u=(s("bbb1"),s("2877")),l=Object(u["a"])(i,n,a,!1,null,"2bef1aba",null);t["default"]=l.exports},bbb1:function(e,t,s){"use strict";s("7e65")}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,19 @@
package com.zsz;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ZhxyApplicationTests {
@Test
void contextLoads() {
}
public static void main(String[] args) {
String environment = System.getProperty("os.name").toLowerCase();
System.out.println(environment);
}
}
Loading…
Cancel
Save