commit 01909c60c6d3c0ce948e71dc44f2f57a3e53e8e3 Author: enoch Date: Tue Apr 6 10:27:08 2021 +0800 init diff --git a/README.md b/README.md new file mode 100644 index 0000000..7467e1f --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +## 平台简介 + +* 本仓库为RuoYi-Vue的单应用版本,保持同步更新。 +* 配套前端代码地址[RuoYi-Vue-UI](https://gitee.com/y_project/RuoYi-Vue/tree/master/ruoyi-ui)。 +* 前端采用Vue、Element UI。 +* 后端采用Spring Boot、Spring Security、Redis & Jwt。 +* 权限认证使用Jwt,支持多终端认证系统。 +* 支持加载动态权限菜单,多方式轻松权限控制。 +* 高效率开发,使用代码生成器可以一键生成前后端代码。 +* 提供了一个Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。 +* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud) +* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)   +* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)   + +## 内置功能 + +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 +2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 +3. 岗位管理:配置系统用户所属担任职务。 +4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 +5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 +6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 +7. 参数管理:对系统动态配置常用参数。 +8. 通知公告:系统通知公告信息发布维护。 +9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 +10. 登录日志:系统登录日志记录查询包含登录异常。 +11. 在线用户:当前系统中活跃用户状态监控。 +12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 +13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 +14. 系统接口:根据业务代码自动生成相关的api接口文档。 +15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 +16. 缓存监控:对系统的缓存信息查询,命令统计等。 +17. 在线构建器:拖动表单元素生成相应的HTML代码。 +18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 + +## 在线体验 + +- admin/admin123 +- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。 + +演示地址:http://vue.ruoyi.vip +文档地址:http://doc.ruoyi.vip + +## 演示图 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +## 若依前后端分离交流群 + +QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) 点击按钮入群。 \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..3899b0b --- /dev/null +++ b/build.gradle @@ -0,0 +1,112 @@ +/* + * This file was generated by the Gradle 'init' task. + */ +//声明gradle脚本自身需要使用的资源,优先执行 +buildscript { + ext { + springBootVersion = '2.2.4.RELEASE' + } + repositories { + maven { url 'https://maven.aliyun.com/nexus/content/groups/public' } + maven { url 'https://maven.aliyun.com/repository/spring/' } + jcenter() + mavenCentral() + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" + } + // java编译的时候缺省状态下会因为中文字符而失败 + +} +//allprojects 所有项目共享的配置 +allprojects { + apply plugin: 'idea' + apply plugin: 'java-library' + apply plugin: 'org.springframework.boot' //使用springboot插件 + apply plugin: 'io.spring.dependency-management' //版本管理插件 + version = '1.0' + sourceCompatibility = 8 + targetCompatibility = 8 +} + +repositories { + mavenLocal() + maven { + url = 'http://maven.aliyun.com/nexus/content/groups/public/' + } + + maven { + url = 'http://repo.maven.apache.org/maven2' + } +} + +dependencies { + + testCompile 'org.springframework.boot:spring-boot-starter-test' + + + compile 'org.springframework.boot:spring-boot-starter' + compile 'org.springframework.boot:spring-boot-starter-aop' + compile 'org.springframework.boot:spring-boot-starter-web' + compile 'org.springframework.boot:spring-boot-devtools' + compile 'org.springframework.boot:spring-boot-starter-security' + compile 'org.springframework.boot:spring-boot-starter-jdbc' + + //mail + implementation 'org.springframework.boot:spring-boot-starter-mail' + + + + compile 'org.apache.commons:commons-pool2:2.7.0' + compile 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3' + compile 'com.github.pagehelper:pagehelper-spring-boot-starter:1.3.0' + compile 'com.alibaba:druid-spring-boot-starter:1.2.4' + compile 'org.apache.commons:commons-lang3:3.9' + compile 'commons-io:commons-io:2.5' + compile 'commons-fileupload:commons-fileupload:1.3.3' + compile 'eu.bitwalker:UserAgentUtils:1.21' + compile 'com.alibaba:fastjson:1.2.75' + compile 'org.springframework:spring-context-support:5.2.12.RELEASE' + compile 'io.jsonwebtoken:jjwt:0.9.1' + compile 'io.springfox:springfox-swagger2:2.9.2' + compile 'io.swagger:swagger-annotations:1.5.21' + compile 'io.swagger:swagger-models:1.5.21' + compile 'io.springfox:springfox-swagger-ui:2.9.2' + compile 'com.github.oshi:oshi-core:5.3.6' + compile 'org.apache.poi:poi-ooxml:4.1.2' + compile 'org.apache.velocity:velocity:1.7' + compile 'com.github.penggle:kaptcha:2.3.2' + compile 'mysql:mysql-connector-java:8.0.22' + + //lombok + implementation 'org.projectlombok:lombok:1.18.12' + // commons + implementation 'commons-lang:commons-lang:2.6' + // OSS + implementation 'com.aliyun.oss:aliyun-sdk-oss:3.10.2' + // okhttp + implementation 'com.squareup.okhttp3:okhttp:3.10.0' + //mybatis-plus + implementation 'com.baomidou:mybatis-plus-boot-starter:3.4.2' + //mybatis-plus-generator + implementation 'com.baomidou:mybatis-plus-generator:3.3.2' + //freemarker + implementation 'org.springframework.boot:spring-boot-starter-freemarker' + + + implementation 'com.squareup.okhttp3:okhttp:3.10.0' + + implementation 'org.bitcoinj:bitcoinj-core:0.14.7' + compile 'org.apache.httpcomponents:httpclient:4.5.6' + compile 'org.apache.httpcomponents:httpcore:4.4.14' +} + +group = 'cn.sliyun' +version = '0.1.0' +description = 'system' +sourceCompatibility = '1.8' + + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..5c2d1cf Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..cb4a7e9 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Dec 14 15:14:12 CST 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +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 +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +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 + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem 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, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..3c956a3 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,5 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'sliyun' diff --git a/sliyun-system.sh b/sliyun-system.sh new file mode 100644 index 0000000..ec8cc92 --- /dev/null +++ b/sliyun-system.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +AppName=sliyun-system.jar + +#JVM参数 +JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" +APP_HOME=`pwd` +LOG_PATH=$APP_HOME/logs/$AppName.log + +if [ "$1" = "" ]; +then + echo -e "\033[0;31m 未输入操作名 \033[0m \033[0;34m {start|stop|restart|status} \033[0m" + exit 1 +fi + +if [ "$AppName" = "" ]; +then + echo -e "\033[0;31m 未输入应用名 \033[0m" + exit 1 +fi + +function start() +{ + PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` + + if [ x"$PID" != x"" ]; then + echo "$AppName is running..." + else + nohup java -jar $JVM_OPTS target/$AppName > /dev/null 2>&1 & + echo "Start $AppName success..." + fi +} + +function stop() +{ + echo "Stop $AppName" + + PID="" + query(){ + PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` + } + + query + if [ x"$PID" != x"" ]; then + kill -TERM $PID + echo "$AppName (pid:$PID) exiting..." + while [ x"$PID" != x"" ] + do + sleep 1 + query + done + echo "$AppName exited." + else + echo "$AppName already stopped." + fi +} + +function restart() +{ + stop + sleep 2 + start +} + +function status() +{ + PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l` + if [ $PID != 0 ];then + echo "$AppName is running..." + else + echo "$AppName is not running..." + fi +} + +case $1 in + start) + start;; + stop) + stop;; + restart) + restart;; + status) + status;; + *) + +esac diff --git a/sql/a_sliyun.sql b/sql/a_sliyun.sql new file mode 100644 index 0000000..0a08e4d --- /dev/null +++ b/sql/a_sliyun.sql @@ -0,0 +1,688 @@ +/* + Navicat Premium Data Transfer + + Source Server : asliyun + Source Server Type : MySQL + Source Server Version : 80018 + Source Host : rm-wz99smt6zjv8tt10x1250109m.mysql.rds.aliyuncs.com:3306 + Source Schema : a_sliyun + + Target Server Type : MySQL + Target Server Version : 80018 + File Encoding : 65001 + + Date: 15/03/2021 21:34:16 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for sys_config +-- ---------------------------- +DROP TABLE IF EXISTS `sys_config`; +CREATE TABLE `sys_config` ( + `config_id` int(5) NOT NULL AUTO_INCREMENT COMMENT '参数主键', + `config_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数名称', + `config_key` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数键名', + `config_value` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数键值', + `config_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'N' COMMENT '系统内置(Y是 N否)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`config_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '参数配置表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_config +-- ---------------------------- +INSERT INTO `sys_config` VALUES (1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', '2021-03-07 17:11:54', '', NULL, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow'); +INSERT INTO `sys_config` VALUES (2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', '2021-03-07 17:11:54', '', NULL, '初始化密码 123456'); +INSERT INTO `sys_config` VALUES (3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', '2021-03-07 17:11:54', '', NULL, '深色主题theme-dark,浅色主题theme-light'); + +-- ---------------------------- +-- Table structure for sys_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dept`; +CREATE TABLE `sys_dept` ( + `dept_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '部门id', + `parent_id` bigint(20) NULL DEFAULT 0 COMMENT '父部门id', + `ancestors` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '祖级列表', + `dept_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '部门名称', + `order_num` int(4) NULL DEFAULT 0 COMMENT '显示顺序', + `leader` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '负责人', + `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '部门状态(0正常 1停用)', + `del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`dept_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 201 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部门表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_dept +-- ---------------------------- +INSERT INTO `sys_dept` VALUES (100, 0, '0', '算力云', 0, '算力云', '', 'yingzikeji@gmail.com', '0', '0', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 19:24:08'); +INSERT INTO `sys_dept` VALUES (101, 100, '0,100', '广州研发中心', 1, '算力云', '15888888888', 'yingzikeji@gmail.com', '0', '0', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 19:24:08'); +INSERT INTO `sys_dept` VALUES (102, 100, '0,100', '长沙分公司', 2, '若依', '15888888888', 'ry@qq.com', '0', '2', 'admin', '2021-03-07 17:11:54', '', NULL); +INSERT INTO `sys_dept` VALUES (103, 101, '0,100,101', '研发部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-03-07 17:11:54', '', NULL); +INSERT INTO `sys_dept` VALUES (104, 101, '0,100,101', '市场部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-03-07 17:11:54', '', NULL); +INSERT INTO `sys_dept` VALUES (105, 101, '0,100,101', '测试部门', 3, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2021-03-07 17:11:54', '', NULL); +INSERT INTO `sys_dept` VALUES (106, 101, '0,100,101', '财务部门', 4, '若依', '15888888888', 'ry@qq.com', '0', '2', 'admin', '2021-03-07 17:11:54', '', NULL); +INSERT INTO `sys_dept` VALUES (107, 101, '0,100,101', '运维部门', 5, '若依', '15888888888', 'ry@qq.com', '0', '2', 'admin', '2021-03-07 17:11:54', '', NULL); +INSERT INTO `sys_dept` VALUES (108, 102, '0,100,102', '市场部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '2', 'admin', '2021-03-07 17:11:54', '', NULL); +INSERT INTO `sys_dept` VALUES (109, 102, '0,100,102', '财务部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '2', 'admin', '2021-03-07 17:11:54', '', NULL); +INSERT INTO `sys_dept` VALUES (200, 100, '0,100', '广州运营中心', 2, NULL, NULL, NULL, '0', '0', 'admin', '2021-03-14 19:24:30', '', NULL); + +-- ---------------------------- +-- Table structure for sys_dict_data +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_data`; +CREATE TABLE `sys_dict_data` ( + `dict_code` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典编码', + `dict_sort` int(4) NULL DEFAULT 0 COMMENT '字典排序', + `dict_label` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典标签', + `dict_value` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典键值', + `dict_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型', + `css_class` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '样式属性(其他样式扩展)', + `list_class` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表格回显样式', + `is_default` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'N' COMMENT '是否默认(Y是 N否)', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`dict_code`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典数据表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_dict_data +-- ---------------------------- +INSERT INTO `sys_dict_data` VALUES (1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '性别男'); +INSERT INTO `sys_dict_data` VALUES (2, 2, '女', '1', 'sys_user_sex', '', '', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '性别女'); +INSERT INTO `sys_dict_data` VALUES (3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '性别未知'); +INSERT INTO `sys_dict_data` VALUES (4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '显示菜单'); +INSERT INTO `sys_dict_data` VALUES (5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '隐藏菜单'); +INSERT INTO `sys_dict_data` VALUES (6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '停用状态'); +INSERT INTO `sys_dict_data` VALUES (8, 1, '正常', '0', 'sys_job_status', '', 'primary', 'Y', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (9, 2, '暂停', '1', 'sys_job_status', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '停用状态'); +INSERT INTO `sys_dict_data` VALUES (10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '默认分组'); +INSERT INTO `sys_dict_data` VALUES (11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '系统分组'); +INSERT INTO `sys_dict_data` VALUES (12, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '系统默认是'); +INSERT INTO `sys_dict_data` VALUES (13, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '系统默认否'); +INSERT INTO `sys_dict_data` VALUES (14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '通知'); +INSERT INTO `sys_dict_data` VALUES (15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '公告'); +INSERT INTO `sys_dict_data` VALUES (16, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (17, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '关闭状态'); +INSERT INTO `sys_dict_data` VALUES (18, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '新增操作'); +INSERT INTO `sys_dict_data` VALUES (19, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '修改操作'); +INSERT INTO `sys_dict_data` VALUES (20, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '删除操作'); +INSERT INTO `sys_dict_data` VALUES (21, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '授权操作'); +INSERT INTO `sys_dict_data` VALUES (22, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '导出操作'); +INSERT INTO `sys_dict_data` VALUES (23, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '导入操作'); +INSERT INTO `sys_dict_data` VALUES (24, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '强退操作'); +INSERT INTO `sys_dict_data` VALUES (25, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '生成操作'); +INSERT INTO `sys_dict_data` VALUES (26, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '清空操作'); +INSERT INTO `sys_dict_data` VALUES (27, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (28, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '停用状态'); + +-- ---------------------------- +-- Table structure for sys_dict_type +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_type`; +CREATE TABLE `sys_dict_type` ( + `dict_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典主键', + `dict_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典名称', + `dict_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`dict_id`) USING BTREE, + UNIQUE INDEX `dict_type`(`dict_type`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典类型表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_dict_type +-- ---------------------------- +INSERT INTO `sys_dict_type` VALUES (1, '用户性别', 'sys_user_sex', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '用户性别列表'); +INSERT INTO `sys_dict_type` VALUES (2, '菜单状态', 'sys_show_hide', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '菜单状态列表'); +INSERT INTO `sys_dict_type` VALUES (3, '系统开关', 'sys_normal_disable', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '系统开关列表'); +INSERT INTO `sys_dict_type` VALUES (4, '任务状态', 'sys_job_status', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '任务状态列表'); +INSERT INTO `sys_dict_type` VALUES (5, '任务分组', 'sys_job_group', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '任务分组列表'); +INSERT INTO `sys_dict_type` VALUES (6, '系统是否', 'sys_yes_no', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '系统是否列表'); +INSERT INTO `sys_dict_type` VALUES (7, '通知类型', 'sys_notice_type', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '通知类型列表'); +INSERT INTO `sys_dict_type` VALUES (8, '通知状态', 'sys_notice_status', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '通知状态列表'); +INSERT INTO `sys_dict_type` VALUES (9, '操作类型', 'sys_oper_type', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '操作类型列表'); +INSERT INTO `sys_dict_type` VALUES (10, '系统状态', 'sys_common_status', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '登录状态列表'); + +-- ---------------------------- +-- Table structure for sys_job +-- ---------------------------- +DROP TABLE IF EXISTS `sys_job`; +CREATE TABLE `sys_job` ( + `job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务ID', + `job_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务名称', + `job_group` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'DEFAULT' COMMENT '任务组名', + `invoke_target` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调用目标字符串', + `cron_expression` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT 'cron执行表达式', + `misfire_policy` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '3' COMMENT '计划执行错误策略(1立即执行 2执行一次 3放弃执行)', + `concurrent` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '是否并发执行(0允许 1禁止)', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1暂停)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '备注信息', + PRIMARY KEY (`job_id`, `job_name`, `job_group`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务调度表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_job +-- ---------------------------- +INSERT INTO `sys_job` VALUES (1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_job` VALUES (2, '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_job` VALUES (3, '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', '2021-03-07 17:11:54', '', NULL, ''); + +-- ---------------------------- +-- Table structure for sys_job_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_job_log`; +CREATE TABLE `sys_job_log` ( + `job_log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务日志ID', + `job_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务名称', + `job_group` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务组名', + `invoke_target` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调用目标字符串', + `job_message` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '日志信息', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '执行状态(0正常 1失败)', + `exception_info` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '异常信息', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`job_log_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务调度日志表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for sys_logininfor +-- ---------------------------- +DROP TABLE IF EXISTS `sys_logininfor`; +CREATE TABLE `sys_logininfor` ( + `info_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '访问ID', + `user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '用户账号', + `ipaddr` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '登录IP地址', + `login_location` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '登录地点', + `browser` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '浏览器类型', + `os` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '操作系统', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '登录状态(0成功 1失败)', + `msg` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '提示消息', + `login_time` datetime(0) NULL DEFAULT NULL COMMENT '访问时间', + PRIMARY KEY (`info_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统访问记录' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_logininfor +-- ---------------------------- +INSERT INTO `sys_logininfor` VALUES (1, 'admin', '192.168.1.102', '内网IP', 'Chrome 8', 'Windows 10', '0', '退出成功', '2021-03-14 20:22:49'); +INSERT INTO `sys_logininfor` VALUES (2, 'admin', '192.168.1.102', '内网IP', 'Chrome 8', 'Windows 10', '0', '登录成功', '2021-03-14 20:52:18'); +INSERT INTO `sys_logininfor` VALUES (3, 'admin', '192.168.1.102', '内网IP', 'Chrome 8', 'Windows 10', '0', '退出成功', '2021-03-14 21:02:24'); +INSERT INTO `sys_logininfor` VALUES (4, 'admin', '192.168.1.102', '内网IP', 'Chrome 8', 'Windows 10', '0', '登录成功', '2021-03-14 21:02:27'); +INSERT INTO `sys_logininfor` VALUES (5, 'admin', '192.168.1.102', '内网IP', 'Chrome 8', 'Windows 10', '0', '退出成功', '2021-03-14 21:05:10'); +INSERT INTO `sys_logininfor` VALUES (6, 'admin', '192.168.1.102', '内网IP', 'Chrome 8', 'Windows 10', '0', '登录成功', '2021-03-14 21:14:42'); +INSERT INTO `sys_logininfor` VALUES (7, 'admin', '192.168.1.102', '内网IP', 'Chrome 8', 'Windows 10', '0', '退出成功', '2021-03-14 22:13:37'); +INSERT INTO `sys_logininfor` VALUES (8, 'admin', '192.168.1.102', '内网IP', 'Chrome 8', 'Windows 10', '0', '登录成功', '2021-03-14 22:19:23'); +INSERT INTO `sys_logininfor` VALUES (9, 'admin', '192.168.1.101', '内网IP', 'Chrome 8', 'Windows 10', '0', '登录成功', '2021-03-15 21:05:04'); +INSERT INTO `sys_logininfor` VALUES (10, 'admin', '192.168.1.101', '内网IP', 'Chrome 8', 'Windows 10', '0', '登录成功', '2021-03-15 21:27:04'); + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_menu`; +CREATE TABLE `sys_menu` ( + `menu_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '菜单ID', + `menu_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单名称', + `parent_id` bigint(20) NULL DEFAULT 0 COMMENT '父菜单ID', + `order_num` int(4) NULL DEFAULT 0 COMMENT '显示顺序', + `path` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '路由地址', + `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件路径', + `is_frame` int(1) NULL DEFAULT 1 COMMENT '是否为外链(0是 1否)', + `is_cache` int(1) NULL DEFAULT 0 COMMENT '是否缓存(0缓存 1不缓存)', + `menu_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '菜单类型(M目录 C菜单 F按钮)', + `visible` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '菜单状态(0显示 1隐藏)', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '菜单状态(0正常 1停用)', + `perms` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限标识', + `icon` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '#' COMMENT '菜单图标', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '备注', + PRIMARY KEY (`menu_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2014 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '菜单权限表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_menu +-- ---------------------------- +INSERT INTO `sys_menu` VALUES (1, '系统管理', 0, 5, 'system', NULL, 1, 0, 'M', '0', '0', '', 'system', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 22:04:12', '系统管理目录'); +INSERT INTO `sys_menu` VALUES (2, '系统监控', 0, 6, 'monitor', NULL, 1, 0, 'M', '0', '0', '', 'monitor', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 22:04:19', '系统监控目录'); +INSERT INTO `sys_menu` VALUES (3, '系统工具', 0, 7, 'tool', NULL, 1, 0, 'M', '0', '0', '', 'tool', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 22:04:26', '系统工具目录'); +INSERT INTO `sys_menu` VALUES (4, '帮助', 0, 8, 'http://aopcloud.com/', NULL, 0, 0, 'M', '0', '0', '', 'guide', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 22:04:31', '若依官网地址'); +INSERT INTO `sys_menu` VALUES (100, '用户管理', 1, 1, 'user', 'system/user/index', 1, 0, 'C', '0', '0', 'system:user:list', 'user', 'admin', '2021-03-07 17:11:54', '', NULL, '用户管理菜单'); +INSERT INTO `sys_menu` VALUES (101, '角色管理', 1, 2, 'role', 'system/role/index', 1, 0, 'C', '0', '0', 'system:role:list', 'peoples', 'admin', '2021-03-07 17:11:54', '', NULL, '角色管理菜单'); +INSERT INTO `sys_menu` VALUES (102, '菜单管理', 1, 3, 'menu', 'system/menu/index', 1, 0, 'C', '0', '0', 'system:menu:list', 'treeTable', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 19:27:26', '菜单管理菜单'); +INSERT INTO `sys_menu` VALUES (103, '部门管理', 1, 4, 'dept', 'system/dept/index', 1, 0, 'C', '0', '0', 'system:dept:list', 'tree', 'admin', '2021-03-07 17:11:54', '', NULL, '部门管理菜单'); +INSERT INTO `sys_menu` VALUES (104, '岗位管理', 1, 5, 'post', 'system/post/index', 1, 0, 'C', '0', '0', 'system:post:list', 'post', 'admin', '2021-03-07 17:11:54', '', NULL, '岗位管理菜单'); +INSERT INTO `sys_menu` VALUES (105, '字典管理', 1, 6, 'dict', 'system/dict/index', 1, 0, 'C', '0', '0', 'system:dict:list', 'dict', 'admin', '2021-03-07 17:11:54', '', NULL, '字典管理菜单'); +INSERT INTO `sys_menu` VALUES (106, '参数设置', 1, 7, 'config', 'system/config/index', 1, 0, 'C', '0', '0', 'system:config:list', 'edit', 'admin', '2021-03-07 17:11:54', '', NULL, '参数设置菜单'); +INSERT INTO `sys_menu` VALUES (107, '通知公告', 2004, 1, 'notice', 'system/notice/index', 1, 0, 'C', '0', '0', 'system:notice:list', 'message', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 20:16:02', '通知公告菜单'); +INSERT INTO `sys_menu` VALUES (108, '日志管理', 1, 9, 'log', '', 1, 0, 'M', '0', '0', '', 'log', 'admin', '2021-03-07 17:11:54', '', NULL, '日志管理菜单'); +INSERT INTO `sys_menu` VALUES (111, '数据监控', 2, 3, 'druid', 'monitor/druid/index', 1, 0, 'C', '0', '0', 'monitor:druid:list', 'druid', 'admin', '2021-03-07 17:11:54', '', NULL, '数据监控菜单'); +INSERT INTO `sys_menu` VALUES (112, '服务监控', 2, 4, 'server', 'monitor/server/index', 1, 0, 'C', '0', '0', 'monitor:server:list', 'server', 'admin', '2021-03-07 17:11:54', '', NULL, '服务监控菜单'); +INSERT INTO `sys_menu` VALUES (116, '系统接口', 3, 3, 'swagger', 'tool/swagger/index', 1, 0, 'C', '0', '0', 'tool:swagger:list', 'swagger', 'admin', '2021-03-07 17:11:54', '', NULL, '系统接口菜单'); +INSERT INTO `sys_menu` VALUES (500, '操作日志', 108, 1, 'operlog', 'monitor/operlog/index', 1, 0, 'C', '0', '0', 'monitor:operlog:list', 'form', 'admin', '2021-03-07 17:11:54', '', NULL, '操作日志菜单'); +INSERT INTO `sys_menu` VALUES (501, '登录日志', 108, 2, 'logininfor', 'monitor/logininfor/index', 1, 0, 'C', '0', '0', 'monitor:logininfor:list', 'logininfor', 'admin', '2021-03-07 17:11:54', '', NULL, '登录日志菜单'); +INSERT INTO `sys_menu` VALUES (1001, '用户查询', 100, 1, '', '', 1, 0, 'F', '0', '0', 'system:user:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1002, '用户新增', 100, 2, '', '', 1, 0, 'F', '0', '0', 'system:user:add', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1003, '用户修改', 100, 3, '', '', 1, 0, 'F', '0', '0', 'system:user:edit', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1004, '用户删除', 100, 4, '', '', 1, 0, 'F', '0', '0', 'system:user:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1005, '用户导出', 100, 5, '', '', 1, 0, 'F', '0', '0', 'system:user:export', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1006, '用户导入', 100, 6, '', '', 1, 0, 'F', '0', '0', 'system:user:import', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1007, '重置密码', 100, 7, '', '', 1, 0, 'F', '0', '0', 'system:user:resetPwd', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1008, '角色查询', 101, 1, '', '', 1, 0, 'F', '0', '0', 'system:role:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1009, '角色新增', 101, 2, '', '', 1, 0, 'F', '0', '0', 'system:role:add', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1010, '角色修改', 101, 3, '', '', 1, 0, 'F', '0', '0', 'system:role:edit', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1011, '角色删除', 101, 4, '', '', 1, 0, 'F', '0', '0', 'system:role:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1012, '角色导出', 101, 5, '', '', 1, 0, 'F', '0', '0', 'system:role:export', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1013, '菜单查询', 102, 1, '', '', 1, 0, 'F', '0', '0', 'system:menu:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1014, '菜单新增', 102, 2, '', '', 1, 0, 'F', '0', '0', 'system:menu:add', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1015, '菜单修改', 102, 3, '', '', 1, 0, 'F', '0', '0', 'system:menu:edit', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1016, '菜单删除', 102, 4, '', '', 1, 0, 'F', '0', '0', 'system:menu:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1017, '部门查询', 103, 1, '', '', 1, 0, 'F', '0', '0', 'system:dept:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1018, '部门新增', 103, 2, '', '', 1, 0, 'F', '0', '0', 'system:dept:add', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1019, '部门修改', 103, 3, '', '', 1, 0, 'F', '0', '0', 'system:dept:edit', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1020, '部门删除', 103, 4, '', '', 1, 0, 'F', '0', '0', 'system:dept:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1021, '岗位查询', 104, 1, '', '', 1, 0, 'F', '0', '0', 'system:post:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1022, '岗位新增', 104, 2, '', '', 1, 0, 'F', '0', '0', 'system:post:add', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1023, '岗位修改', 104, 3, '', '', 1, 0, 'F', '0', '0', 'system:post:edit', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1024, '岗位删除', 104, 4, '', '', 1, 0, 'F', '0', '0', 'system:post:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1025, '岗位导出', 104, 5, '', '', 1, 0, 'F', '0', '0', 'system:post:export', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1026, '字典查询', 105, 1, '#', '', 1, 0, 'F', '0', '0', 'system:dict:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1027, '字典新增', 105, 2, '#', '', 1, 0, 'F', '0', '0', 'system:dict:add', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1028, '字典修改', 105, 3, '#', '', 1, 0, 'F', '0', '0', 'system:dict:edit', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1029, '字典删除', 105, 4, '#', '', 1, 0, 'F', '0', '0', 'system:dict:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1030, '字典导出', 105, 5, '#', '', 1, 0, 'F', '0', '0', 'system:dict:export', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1031, '参数查询', 106, 1, '#', '', 1, 0, 'F', '0', '0', 'system:config:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1032, '参数新增', 106, 2, '#', '', 1, 0, 'F', '0', '0', 'system:config:add', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1033, '参数修改', 106, 3, '#', '', 1, 0, 'F', '0', '0', 'system:config:edit', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1034, '参数删除', 106, 4, '#', '', 1, 0, 'F', '0', '0', 'system:config:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1035, '参数导出', 106, 5, '#', '', 1, 0, 'F', '0', '0', 'system:config:export', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1036, '公告查询', 107, 1, '#', '', 1, 0, 'F', '0', '0', 'system:notice:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1037, '公告新增', 107, 2, '#', '', 1, 0, 'F', '0', '0', 'system:notice:add', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1038, '公告修改', 107, 3, '#', '', 1, 0, 'F', '0', '0', 'system:notice:edit', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1039, '公告删除', 107, 4, '#', '', 1, 0, 'F', '0', '0', 'system:notice:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1040, '操作查询', 500, 1, '#', '', 1, 0, 'F', '0', '0', 'monitor:operlog:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1041, '操作删除', 500, 2, '#', '', 1, 0, 'F', '0', '0', 'monitor:operlog:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1042, '日志导出', 500, 4, '#', '', 1, 0, 'F', '0', '0', 'monitor:operlog:export', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1043, '登录查询', 501, 1, '#', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:query', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1044, '登录删除', 501, 2, '#', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:remove', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1045, '日志导出', 501, 3, '#', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:export', '#', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2001, 'TokenView', 3, 5, 'https://tokenview.com', NULL, 0, 1, 'C', '0', '0', '', 'guide', 'admin', '2021-03-14 19:36:05', 'admin', '2021-03-14 19:49:10', ''); +INSERT INTO `sys_menu` VALUES (2002, '会员管理', 0, 1, 'member', NULL, 1, 0, 'M', '0', '0', '', 'peoples', 'admin', '2021-03-14 19:51:55', 'admin', '2021-03-14 21:41:01', ''); +INSERT INTO `sys_menu` VALUES (2003, '货币系统', 0, 2, 'coin', NULL, 1, 0, 'M', '0', '0', '', 'dollar', 'admin', '2021-03-14 19:52:49', 'admin', '2021-03-14 22:00:46', ''); +INSERT INTO `sys_menu` VALUES (2004, '广告系统', 0, 4, 'ad', NULL, 1, 0, 'M', '0', '0', '', 'message', 'admin', '2021-03-14 19:54:17', 'admin', '2021-03-14 22:03:54', ''); +INSERT INTO `sys_menu` VALUES (2005, '会员列表', 2002, 1, 'MemberList', 'member/MemberList', 1, 0, 'C', '0', '0', '', 'user', 'admin', '2021-03-14 20:03:41', 'admin', '2021-03-14 21:43:21', ''); +INSERT INTO `sys_menu` VALUES (2006, '货币列表', 2003, 1, 'CoinList', 'coin/CoinList', 1, 0, 'C', '0', '0', '', 'euro', 'admin', '2021-03-14 20:05:37', 'admin', '2021-03-14 21:59:54', ''); +INSERT INTO `sys_menu` VALUES (2007, '算力包', 2003, 2, 'HashPackageList', 'coin/CoinHashPackageList', 1, 0, 'C', '0', '0', '', 'gold', 'admin', '2021-03-14 20:07:49', 'admin', '2021-03-14 22:00:03', ''); +INSERT INTO `sys_menu` VALUES (2008, '地址列表', 2003, 3, 'AddressList', 'coin/CoinAddressList', 1, 0, 'C', '0', '0', '', 'cloud', 'admin', '2021-03-14 20:11:04', 'admin', '2021-03-14 22:00:10', ''); +INSERT INTO `sys_menu` VALUES (2009, '广告列表', 2004, 2, 'ad/AdList', 'ad/AdList', 1, 0, 'C', '0', '0', '', 'sound', 'admin', '2021-03-14 20:14:21', 'admin', '2021-03-14 21:17:15', ''); +INSERT INTO `sys_menu` VALUES (2010, '财务系统', 0, 3, 'finance', NULL, 1, 0, 'M', '0', '0', '', 'property-safety', 'admin', '2021-03-14 22:01:52', 'admin', '2021-03-14 22:02:53', ''); +INSERT INTO `sys_menu` VALUES (2011, '财务报表', 2010, 1, 'dashboard', NULL, 1, 0, 'M', '0', '0', '', 'pie-chart', 'admin', '2021-03-14 22:05:40', 'admin', '2021-03-14 22:07:54', ''); +INSERT INTO `sys_menu` VALUES (2012, '订单列表', 2010, 2, 'order', NULL, 1, 0, 'M', '0', '0', '', 'bar-chart', 'admin', '2021-03-14 22:06:04', 'admin', '2021-03-14 22:08:07', ''); +INSERT INTO `sys_menu` VALUES (2013, '交易记录', 2010, 3, 'records', NULL, 1, 0, 'M', '0', '0', '', 'build', 'admin', '2021-03-14 22:07:36', 'admin', '2021-03-14 22:08:52', ''); + +-- ---------------------------- +-- Table structure for sys_notice +-- ---------------------------- +DROP TABLE IF EXISTS `sys_notice`; +CREATE TABLE `sys_notice` ( + `notice_id` int(4) NOT NULL AUTO_INCREMENT COMMENT '公告ID', + `notice_title` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公告标题', + `notice_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公告类型(1通知 2公告)', + `notice_content` longblob NULL COMMENT '公告内容', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '公告状态(0正常 1关闭)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`notice_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '通知公告表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_notice +-- ---------------------------- +INSERT INTO `sys_notice` VALUES (1, '温馨提醒:2018-07-01 若依新版本发布啦', '2', 0xE696B0E78988E69CACE58685E5AEB90A, '0', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 19:20:28', '管理员'); +INSERT INTO `sys_notice` VALUES (2, '维护通知:2018-07-01 若依系统凌晨维护', '1', 0xE7BBB4E68AA4E58685E5AEB9, '0', 'admin', '2021-03-07 17:11:54', '', NULL, '管理员'); +INSERT INTO `sys_notice` VALUES (10, '测试', '2', 0x61640A, '0', 'admin', '2021-03-14 20:15:26', '', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_oper_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_oper_log`; +CREATE TABLE `sys_oper_log` ( + `oper_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主键', + `title` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '模块标题', + `business_type` int(2) NULL DEFAULT 0 COMMENT '业务类型(0其它 1新增 2修改 3删除)', + `method` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '方法名称', + `request_method` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '请求方式', + `operator_type` int(1) NULL DEFAULT 0 COMMENT '操作类别(0其它 1后台用户 2手机端用户)', + `oper_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '操作人员', + `dept_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '部门名称', + `oper_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '请求URL', + `oper_ip` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '主机地址', + `oper_location` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '操作地点', + `oper_param` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '请求参数', + `json_result` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '返回参数', + `status` int(1) NULL DEFAULT 0 COMMENT '操作状态(0正常 1异常)', + `error_msg` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '错误消息', + `oper_time` datetime(0) NULL DEFAULT NULL COMMENT '操作时间', + PRIMARY KEY (`oper_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 74 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '操作日志记录' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_oper_log +-- ---------------------------- +INSERT INTO `sys_oper_log` VALUES (1, '操作日志', 9, 'com.ruoyi.project.monitor.controller.SysOperlogController.clean()', 'DELETE', 1, 'admin', NULL, '/monitor/operlog/clean', '192.168.1.102', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:28:52'); +INSERT INTO `sys_oper_log` VALUES (2, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"2\",\"menuName\":\"TokenView\",\"params\":{},\"parentId\":3,\"isCache\":\"0\",\"path\":\"https://www.baidu.com/\",\"children\":[],\"createTime\":1615767447000,\"updateBy\":\"admin\",\"isFrame\":\"0\",\"menuId\":2000,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:31:33'); +INSERT INTO `sys_oper_log` VALUES (3, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"5\",\"menuName\":\"百度\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"https://www.baidu.com/\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"0\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:36:05'); +INSERT INTO `sys_oper_log` VALUES (4, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"5\",\"menuName\":\"TokenView\",\"params\":{},\"parentId\":3,\"isCache\":\"0\",\"path\":\"https://tokenview.com/\",\"children\":[],\"createTime\":1615768565000,\"isFrame\":\"0\",\"menuId\":2001,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"修改菜单\'TokenView\'失败,菜单名称已存在\",\"code\":500}', 0, NULL, '2021-03-14 19:36:42'); +INSERT INTO `sys_oper_log` VALUES (5, '菜单管理', 3, 'com.ruoyi.project.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/2000', '192.168.1.102', '内网IP', '{menuId=2000}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:36:53'); +INSERT INTO `sys_oper_log` VALUES (6, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"5\",\"menuName\":\"TokenView\",\"params\":{},\"parentId\":3,\"isCache\":\"0\",\"path\":\"https://tokenview.com/\",\"children\":[],\"createTime\":1615768565000,\"updateBy\":\"admin\",\"isFrame\":\"0\",\"menuId\":2001,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:37:05'); +INSERT INTO `sys_oper_log` VALUES (7, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"5\",\"menuName\":\"TokenView\",\"params\":{},\"parentId\":3,\"isCache\":\"1\",\"path\":\"https://tokenview.com/\",\"children\":[],\"createTime\":1615768565000,\"updateBy\":\"admin\",\"isFrame\":\"0\",\"menuId\":2001,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"1\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:38:17'); +INSERT INTO `sys_oper_log` VALUES (8, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"5\",\"menuName\":\"TokenView\",\"params\":{},\"parentId\":3,\"isCache\":\"1\",\"path\":\"https://tokenview.com/\",\"children\":[],\"createTime\":1615768565000,\"updateBy\":\"admin\",\"isFrame\":\"0\",\"menuId\":2001,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:40:50'); +INSERT INTO `sys_oper_log` VALUES (9, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"5\",\"menuName\":\"TokenView\",\"params\":{},\"parentId\":3,\"isCache\":\"1\",\"path\":\"https://tokenview.com\",\"children\":[],\"createTime\":1615768565000,\"updateBy\":\"admin\",\"isFrame\":\"0\",\"menuId\":2001,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:47:16'); +INSERT INTO `sys_oper_log` VALUES (10, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"5\",\"menuName\":\"TokenView\",\"params\":{},\"parentId\":3,\"isCache\":\"1\",\"path\":\"https://tokenview.com\",\"children\":[],\"createTime\":1615768565000,\"updateBy\":\"admin\",\"isFrame\":\"0\",\"menuId\":2001,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:49:10'); +INSERT INTO `sys_oper_log` VALUES (11, '菜单管理', 3, 'com.ruoyi.project.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/110', '192.168.1.102', '内网IP', '{menuId=110}', '{\"msg\":\"菜单已分配,不允许删除\",\"code\":500}', 0, NULL, '2021-03-14 19:50:05'); +INSERT INTO `sys_oper_log` VALUES (12, '角色管理', 2, 'com.ruoyi.project.system.controller.SysRoleController.edit()', 'PUT', 1, 'admin', NULL, '/system/role', '192.168.1.102', '内网IP', '{\"flag\":false,\"roleId\":2,\"admin\":false,\"remark\":\"普通角色\",\"dataScope\":\"2\",\"delFlag\":\"0\",\"params\":{},\"roleSort\":\"2\",\"deptCheckStrictly\":true,\"createTime\":1615158714000,\"updateBy\":\"admin\",\"menuCheckStrictly\":true,\"roleKey\":\"common\",\"roleName\":\"普通角色\",\"menuIds\":[4,111,112,116,1001,100,1,1002,1003,1004,1005,1006,1007,1008,101,1009,1010,1011,1012,1013,102,1014,1015,1016,1017,103,1018,1019,1020,1021,104,1022,1023,1024,1025,1026,105,1027,1028,1029,1030,1031,106,1032,1033,1034,1035,1036,107,1037,1038,1039,1040,500,108,1041,1042,1043,501,1044,1045,3,2],\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:50:42'); +INSERT INTO `sys_oper_log` VALUES (13, '菜单管理', 3, 'com.ruoyi.project.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/110', '192.168.1.102', '内网IP', '{menuId=110}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:50:55'); +INSERT INTO `sys_oper_log` VALUES (14, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"1\",\"menuName\":\"会员管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"member\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:51:55'); +INSERT INTO `sys_oper_log` VALUES (15, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"3\",\"menuName\":\"财务管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"w\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:52:49'); +INSERT INTO `sys_oper_log` VALUES (16, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"3\",\"menuName\":\"广告系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"ad\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:54:17'); +INSERT INTO `sys_oper_log` VALUES (17, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"system\",\"orderNum\":\"2\",\"menuName\":\"系统管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"system\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":1,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:56:00'); +INSERT INTO `sys_oper_log` VALUES (18, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"monitor\",\"orderNum\":\"5\",\"menuName\":\"系统监控\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"monitor\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:56:13'); +INSERT INTO `sys_oper_log` VALUES (19, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"tool\",\"orderNum\":\"6\",\"menuName\":\"系统工具\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"tool\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":3,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:56:20'); +INSERT INTO `sys_oper_log` VALUES (20, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"7\",\"menuName\":\"帮助\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"http://aopcloud.com/\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"0\",\"menuId\":4,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:56:26'); +INSERT INTO `sys_oper_log` VALUES (21, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"system\",\"orderNum\":\"4\",\"menuName\":\"系统管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"system\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":1,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:56:38'); +INSERT INTO `sys_oper_log` VALUES (22, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"peoples\",\"orderNum\":\"1\",\"menuName\":\"会员管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"member\",\"children\":[],\"createTime\":1615769515000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2002,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:58:28'); +INSERT INTO `sys_oper_log` VALUES (23, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"dollar\",\"orderNum\":\"3\",\"menuName\":\"财务管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"w\",\"children\":[],\"createTime\":1615769569000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2003,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 19:59:25'); +INSERT INTO `sys_oper_log` VALUES (24, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"3\",\"menuName\":\"广告系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"ad\",\"children\":[],\"createTime\":1615769657000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2004,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:01:16'); +INSERT INTO `sys_oper_log` VALUES (25, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"1\",\"menuName\":\"会员列表\",\"params\":{},\"parentId\":2002,\"isCache\":\"0\",\"path\":\"member/list\",\"component\":\"member/list\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"C\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:03:41'); +INSERT INTO `sys_oper_log` VALUES (26, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"user\",\"orderNum\":\"1\",\"menuName\":\"会员列表\",\"params\":{},\"parentId\":2002,\"isCache\":\"0\",\"path\":\"member/list\",\"component\":\"\",\"children\":[],\"createTime\":1615770221000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2005,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:04:24'); +INSERT INTO `sys_oper_log` VALUES (27, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"1\",\"menuName\":\"货币列表\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"f/coin/list\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:05:37'); +INSERT INTO `sys_oper_log` VALUES (28, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"euro\",\"orderNum\":\"1\",\"menuName\":\"货币列表\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"f/coin/list\",\"children\":[],\"createTime\":1615770337000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2006,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:06:05'); +INSERT INTO `sys_oper_log` VALUES (29, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"gold\",\"orderNum\":\"2\",\"menuName\":\"算力包\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"f/coin/package\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:07:49'); +INSERT INTO `sys_oper_log` VALUES (30, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"cloud\",\"orderNum\":\"3\",\"menuName\":\"地址列表\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"f/member/address\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"C\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:11:04'); +INSERT INTO `sys_oper_log` VALUES (31, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"1\",\"menuName\":\"通知公告\",\"params\":{},\"parentId\":2004,\"isCache\":\"0\",\"path\":\"notice\",\"component\":\"system/notice/index\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":107,\"menuType\":\"C\",\"perms\":\"system:notice:list\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:12:08'); +INSERT INTO `sys_oper_log` VALUES (32, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"sound\",\"orderNum\":\"2\",\"menuName\":\"广告列表\",\"params\":{},\"parentId\":2004,\"isCache\":\"0\",\"path\":\"ad/a/list\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"C\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:14:21'); +INSERT INTO `sys_oper_log` VALUES (33, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"1\",\"menuName\":\"通知公告\",\"params\":{},\"parentId\":2004,\"isCache\":\"0\",\"path\":\"notice\",\"component\":\"system/notice/index\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":107,\"menuType\":\"C\",\"perms\":\"system:notice:list\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:14:41'); +INSERT INTO `sys_oper_log` VALUES (34, '通知公告', 1, 'com.ruoyi.project.system.controller.SysNoticeController.add()', 'POST', 1, 'admin', NULL, '/system/notice', '192.168.1.102', '内网IP', '{\"noticeContent\":\"ad\\n\",\"createBy\":\"admin\",\"noticeType\":\"2\",\"params\":{},\"noticeTitle\":\"测试\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:15:26'); +INSERT INTO `sys_oper_log` VALUES (35, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"1\",\"menuName\":\"通知公告\",\"params\":{},\"parentId\":2004,\"isCache\":\"0\",\"path\":\"notice\",\"component\":\"system/notice/index\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":107,\"menuType\":\"C\",\"perms\":\"system:notice:list\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 20:16:02'); +INSERT INTO `sys_oper_log` VALUES (36, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"sound\",\"orderNum\":\"2\",\"menuName\":\"广告列表\",\"params\":{},\"parentId\":2004,\"isCache\":\"0\",\"path\":\"ad/AdList\",\"component\":\"ad/AdList\",\"children\":[],\"createTime\":1615770861000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2009,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:17:15'); +INSERT INTO `sys_oper_log` VALUES (37, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"user\",\"orderNum\":\"1\",\"menuName\":\"会员列表\",\"params\":{},\"parentId\":2002,\"isCache\":\"0\",\"path\":\"member/list\",\"component\":\"\",\"children\":[],\"createTime\":1615770221000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2005,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:37:27'); +INSERT INTO `sys_oper_log` VALUES (38, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"user\",\"orderNum\":\"1\",\"menuName\":\"会员列表\",\"params\":{},\"parentId\":2002,\"isCache\":\"0\",\"path\":\"member/MemberList\",\"component\":\"\",\"children\":[],\"createTime\":1615770221000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2005,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:38:49'); +INSERT INTO `sys_oper_log` VALUES (39, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"user\",\"orderNum\":\"1\",\"menuName\":\"会员列表\",\"params\":{},\"parentId\":2002,\"isCache\":\"0\",\"path\":\"MemberList\",\"component\":\"\",\"children\":[],\"createTime\":1615770221000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2005,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:39:21'); +INSERT INTO `sys_oper_log` VALUES (40, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"peoples\",\"orderNum\":\"1\",\"menuName\":\"会员管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"member\",\"children\":[],\"createTime\":1615769515000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2002,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:40:56'); +INSERT INTO `sys_oper_log` VALUES (41, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"peoples\",\"orderNum\":\"1\",\"menuName\":\"会员管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"member\",\"children\":[],\"createTime\":1615769515000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2002,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:41:01'); +INSERT INTO `sys_oper_log` VALUES (42, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"user\",\"orderNum\":\"1\",\"menuName\":\"会员列表\",\"params\":{},\"parentId\":2002,\"isCache\":\"0\",\"path\":\"MemberList\",\"component\":\"MemberList\",\"children\":[],\"createTime\":1615770221000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2005,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:41:10'); +INSERT INTO `sys_oper_log` VALUES (43, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"user\",\"orderNum\":\"1\",\"menuName\":\"会员列表\",\"params\":{},\"parentId\":2002,\"isCache\":\"0\",\"path\":\"MemberList\",\"component\":\"member/MemberList\",\"children\":[],\"createTime\":1615770221000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2005,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:43:21'); +INSERT INTO `sys_oper_log` VALUES (44, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"euro\",\"orderNum\":\"1\",\"menuName\":\"货币列表\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"coin/CoinList\",\"children\":[],\"createTime\":1615770337000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2006,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:45:43'); +INSERT INTO `sys_oper_log` VALUES (45, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"euro\",\"orderNum\":\"1\",\"menuName\":\"货币列表\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"coin/CoinList\",\"component\":\"coin/CoinList\",\"children\":[],\"createTime\":1615770337000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2006,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:46:09'); +INSERT INTO `sys_oper_log` VALUES (46, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"gold\",\"orderNum\":\"2\",\"menuName\":\"算力包\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"coin/HashPackageList\",\"component\":\"coin/HashPackageList\",\"children\":[],\"createTime\":1615770469000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2007,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:47:00'); +INSERT INTO `sys_oper_log` VALUES (47, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"cloud\",\"orderNum\":\"3\",\"menuName\":\"地址列表\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"coin/CoinAddressList\",\"component\":\"coin/CoinAddressList\",\"children\":[],\"createTime\":1615770664000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2008,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:47:24'); +INSERT INTO `sys_oper_log` VALUES (48, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"gold\",\"orderNum\":\"2\",\"menuName\":\"算力包\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"coin/HashPackageList\",\"component\":\"coin/HashPackageList\",\"children\":[],\"createTime\":1615770469000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2007,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:48:28'); +INSERT INTO `sys_oper_log` VALUES (49, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"gold\",\"orderNum\":\"2\",\"menuName\":\"算力包\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"coin/CoinHashPackageList\",\"component\":\"coin/CoinHashPackageList\",\"children\":[],\"createTime\":1615770469000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2007,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:50:33'); +INSERT INTO `sys_oper_log` VALUES (50, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"dollar\",\"orderNum\":\"3\",\"menuName\":\"货币系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"coin\",\"children\":[],\"createTime\":1615769569000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2003,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:59:29'); +INSERT INTO `sys_oper_log` VALUES (51, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"euro\",\"orderNum\":\"1\",\"menuName\":\"货币列表\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"CoinList\",\"component\":\"coin/CoinList\",\"children\":[],\"createTime\":1615770337000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2006,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 21:59:54'); +INSERT INTO `sys_oper_log` VALUES (52, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"gold\",\"orderNum\":\"2\",\"menuName\":\"算力包\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"HashPackageList\",\"component\":\"coin/CoinHashPackageList\",\"children\":[],\"createTime\":1615770469000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2007,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:00:03'); +INSERT INTO `sys_oper_log` VALUES (53, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"cloud\",\"orderNum\":\"3\",\"menuName\":\"地址列表\",\"params\":{},\"parentId\":2003,\"isCache\":\"0\",\"path\":\"AddressList\",\"component\":\"coin/CoinAddressList\",\"children\":[],\"createTime\":1615770664000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2008,\"menuType\":\"C\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:00:10'); +INSERT INTO `sys_oper_log` VALUES (54, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"dollar\",\"orderNum\":\"2\",\"menuName\":\"货币系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"coin\",\"children\":[],\"createTime\":1615769569000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2003,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:00:46'); +INSERT INTO `sys_oper_log` VALUES (55, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"3\",\"menuName\":\"财务系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"finance\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:01:52'); +INSERT INTO `sys_oper_log` VALUES (56, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"4\",\"menuName\":\"广告系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"ad\",\"children\":[],\"createTime\":1615769657000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2004,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:02:02'); +INSERT INTO `sys_oper_log` VALUES (57, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"property-safety\",\"orderNum\":\"3\",\"menuName\":\"财务系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"finance\",\"children\":[],\"createTime\":1615777312000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2010,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:02:53'); +INSERT INTO `sys_oper_log` VALUES (58, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"5\",\"menuName\":\"广告系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"ad\",\"children\":[],\"createTime\":1615769657000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2004,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:03:15'); +INSERT INTO `sys_oper_log` VALUES (59, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"6\",\"menuName\":\"广告系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"ad\",\"children\":[],\"createTime\":1615769657000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2004,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:03:21'); +INSERT INTO `sys_oper_log` VALUES (60, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"7\",\"menuName\":\"广告系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"ad\",\"children\":[],\"createTime\":1615769657000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2004,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:03:26'); +INSERT INTO `sys_oper_log` VALUES (61, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"8\",\"menuName\":\"广告系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"ad\",\"children\":[],\"createTime\":1615769657000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2004,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:03:30'); +INSERT INTO `sys_oper_log` VALUES (62, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"message\",\"orderNum\":\"4\",\"menuName\":\"广告系统\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"ad\",\"children\":[],\"createTime\":1615769657000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2004,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:03:54'); +INSERT INTO `sys_oper_log` VALUES (63, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"monitor\",\"orderNum\":\"5\",\"menuName\":\"系统监控\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"monitor\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:04:03'); +INSERT INTO `sys_oper_log` VALUES (64, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"system\",\"orderNum\":\"5\",\"menuName\":\"系统管理\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"system\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":1,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:04:12'); +INSERT INTO `sys_oper_log` VALUES (65, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"monitor\",\"orderNum\":\"6\",\"menuName\":\"系统监控\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"monitor\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:04:19'); +INSERT INTO `sys_oper_log` VALUES (66, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"tool\",\"orderNum\":\"7\",\"menuName\":\"系统工具\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"tool\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":3,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:04:26'); +INSERT INTO `sys_oper_log` VALUES (67, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"guide\",\"orderNum\":\"8\",\"menuName\":\"帮助\",\"params\":{},\"parentId\":0,\"isCache\":\"0\",\"path\":\"http://aopcloud.com/\",\"children\":[],\"createTime\":1615158714000,\"updateBy\":\"admin\",\"isFrame\":\"0\",\"menuId\":4,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:04:31'); +INSERT INTO `sys_oper_log` VALUES (68, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"1\",\"menuName\":\"财务报表\",\"params\":{},\"parentId\":2010,\"isCache\":\"0\",\"path\":\"dashboard\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:05:40'); +INSERT INTO `sys_oper_log` VALUES (69, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"2\",\"menuName\":\"订单列表\",\"params\":{},\"parentId\":2010,\"isCache\":\"0\",\"path\":\"order\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:06:04'); +INSERT INTO `sys_oper_log` VALUES (70, '菜单管理', 1, 'com.ruoyi.project.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"orderNum\":\"3\",\"menuName\":\"交易记录\",\"params\":{},\"parentId\":2010,\"isCache\":\"0\",\"path\":\"records\",\"createBy\":\"admin\",\"children\":[],\"isFrame\":\"1\",\"menuType\":\"M\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:07:36'); +INSERT INTO `sys_oper_log` VALUES (71, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"pie-chart\",\"orderNum\":\"1\",\"menuName\":\"财务报表\",\"params\":{},\"parentId\":2010,\"isCache\":\"0\",\"path\":\"dashboard\",\"children\":[],\"createTime\":1615777540000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2011,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:07:54'); +INSERT INTO `sys_oper_log` VALUES (72, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"bar-chart\",\"orderNum\":\"2\",\"menuName\":\"订单列表\",\"params\":{},\"parentId\":2010,\"isCache\":\"0\",\"path\":\"order\",\"children\":[],\"createTime\":1615777564000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2012,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:08:07'); +INSERT INTO `sys_oper_log` VALUES (73, '菜单管理', 2, 'com.ruoyi.project.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', NULL, '/system/menu', '192.168.1.102', '内网IP', '{\"visible\":\"0\",\"icon\":\"build\",\"orderNum\":\"3\",\"menuName\":\"交易记录\",\"params\":{},\"parentId\":2010,\"isCache\":\"0\",\"path\":\"records\",\"children\":[],\"createTime\":1615777656000,\"updateBy\":\"admin\",\"isFrame\":\"1\",\"menuId\":2013,\"menuType\":\"M\",\"perms\":\"\",\"status\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2021-03-14 22:08:52'); + +-- ---------------------------- +-- Table structure for sys_post +-- ---------------------------- +DROP TABLE IF EXISTS `sys_post`; +CREATE TABLE `sys_post` ( + `post_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '岗位ID', + `post_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '岗位编码', + `post_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '岗位名称', + `post_sort` int(4) NOT NULL COMMENT '显示顺序', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '状态(0正常 1停用)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`post_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '岗位信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_post +-- ---------------------------- +INSERT INTO `sys_post` VALUES (1, 'ceo', '董事长', 1, '0', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_post` VALUES (2, 'se', '项目经理', 2, '0', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_post` VALUES (3, 'hr', '人力资源', 3, '0', 'admin', '2021-03-07 17:11:54', '', NULL, ''); +INSERT INTO `sys_post` VALUES (4, 'user', '普通员工', 4, '0', 'admin', '2021-03-07 17:11:54', '', NULL, ''); + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role`; +CREATE TABLE `sys_role` ( + `role_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色ID', + `role_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称', + `role_key` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色权限字符串', + `role_sort` int(4) NOT NULL COMMENT '显示顺序', + `data_scope` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', + `menu_check_strictly` tinyint(1) NULL DEFAULT 1 COMMENT '菜单树选择项是否关联显示', + `dept_check_strictly` tinyint(1) NULL DEFAULT 1 COMMENT '部门树选择项是否关联显示', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色状态(0正常 1停用)', + `del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`role_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_role +-- ---------------------------- +INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, '1', 1, 1, '0', '0', 'admin', '2021-03-07 17:11:54', '', NULL, '超级管理员'); +INSERT INTO `sys_role` VALUES (2, '普通角色', 'common', 2, '2', 1, 1, '0', '0', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 19:50:42', '普通角色'); + +-- ---------------------------- +-- Table structure for sys_role_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role_dept`; +CREATE TABLE `sys_role_dept` ( + `role_id` bigint(20) NOT NULL COMMENT '角色ID', + `dept_id` bigint(20) NOT NULL COMMENT '部门ID', + PRIMARY KEY (`role_id`, `dept_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色和部门关联表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_role_dept +-- ---------------------------- +INSERT INTO `sys_role_dept` VALUES (2, 100); +INSERT INTO `sys_role_dept` VALUES (2, 101); +INSERT INTO `sys_role_dept` VALUES (2, 105); + +-- ---------------------------- +-- Table structure for sys_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role_menu`; +CREATE TABLE `sys_role_menu` ( + `role_id` bigint(20) NOT NULL COMMENT '角色ID', + `menu_id` bigint(20) NOT NULL COMMENT '菜单ID', + PRIMARY KEY (`role_id`, `menu_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色和菜单关联表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_role_menu +-- ---------------------------- +INSERT INTO `sys_role_menu` VALUES (2, 1); +INSERT INTO `sys_role_menu` VALUES (2, 2); +INSERT INTO `sys_role_menu` VALUES (2, 3); +INSERT INTO `sys_role_menu` VALUES (2, 4); +INSERT INTO `sys_role_menu` VALUES (2, 100); +INSERT INTO `sys_role_menu` VALUES (2, 101); +INSERT INTO `sys_role_menu` VALUES (2, 102); +INSERT INTO `sys_role_menu` VALUES (2, 103); +INSERT INTO `sys_role_menu` VALUES (2, 104); +INSERT INTO `sys_role_menu` VALUES (2, 105); +INSERT INTO `sys_role_menu` VALUES (2, 106); +INSERT INTO `sys_role_menu` VALUES (2, 107); +INSERT INTO `sys_role_menu` VALUES (2, 108); +INSERT INTO `sys_role_menu` VALUES (2, 111); +INSERT INTO `sys_role_menu` VALUES (2, 112); +INSERT INTO `sys_role_menu` VALUES (2, 116); +INSERT INTO `sys_role_menu` VALUES (2, 500); +INSERT INTO `sys_role_menu` VALUES (2, 501); +INSERT INTO `sys_role_menu` VALUES (2, 1001); +INSERT INTO `sys_role_menu` VALUES (2, 1002); +INSERT INTO `sys_role_menu` VALUES (2, 1003); +INSERT INTO `sys_role_menu` VALUES (2, 1004); +INSERT INTO `sys_role_menu` VALUES (2, 1005); +INSERT INTO `sys_role_menu` VALUES (2, 1006); +INSERT INTO `sys_role_menu` VALUES (2, 1007); +INSERT INTO `sys_role_menu` VALUES (2, 1008); +INSERT INTO `sys_role_menu` VALUES (2, 1009); +INSERT INTO `sys_role_menu` VALUES (2, 1010); +INSERT INTO `sys_role_menu` VALUES (2, 1011); +INSERT INTO `sys_role_menu` VALUES (2, 1012); +INSERT INTO `sys_role_menu` VALUES (2, 1013); +INSERT INTO `sys_role_menu` VALUES (2, 1014); +INSERT INTO `sys_role_menu` VALUES (2, 1015); +INSERT INTO `sys_role_menu` VALUES (2, 1016); +INSERT INTO `sys_role_menu` VALUES (2, 1017); +INSERT INTO `sys_role_menu` VALUES (2, 1018); +INSERT INTO `sys_role_menu` VALUES (2, 1019); +INSERT INTO `sys_role_menu` VALUES (2, 1020); +INSERT INTO `sys_role_menu` VALUES (2, 1021); +INSERT INTO `sys_role_menu` VALUES (2, 1022); +INSERT INTO `sys_role_menu` VALUES (2, 1023); +INSERT INTO `sys_role_menu` VALUES (2, 1024); +INSERT INTO `sys_role_menu` VALUES (2, 1025); +INSERT INTO `sys_role_menu` VALUES (2, 1026); +INSERT INTO `sys_role_menu` VALUES (2, 1027); +INSERT INTO `sys_role_menu` VALUES (2, 1028); +INSERT INTO `sys_role_menu` VALUES (2, 1029); +INSERT INTO `sys_role_menu` VALUES (2, 1030); +INSERT INTO `sys_role_menu` VALUES (2, 1031); +INSERT INTO `sys_role_menu` VALUES (2, 1032); +INSERT INTO `sys_role_menu` VALUES (2, 1033); +INSERT INTO `sys_role_menu` VALUES (2, 1034); +INSERT INTO `sys_role_menu` VALUES (2, 1035); +INSERT INTO `sys_role_menu` VALUES (2, 1036); +INSERT INTO `sys_role_menu` VALUES (2, 1037); +INSERT INTO `sys_role_menu` VALUES (2, 1038); +INSERT INTO `sys_role_menu` VALUES (2, 1039); +INSERT INTO `sys_role_menu` VALUES (2, 1040); +INSERT INTO `sys_role_menu` VALUES (2, 1041); +INSERT INTO `sys_role_menu` VALUES (2, 1042); +INSERT INTO `sys_role_menu` VALUES (2, 1043); +INSERT INTO `sys_role_menu` VALUES (2, 1044); +INSERT INTO `sys_role_menu` VALUES (2, 1045); + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user`; +CREATE TABLE `sys_user` ( + `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `dept_id` bigint(20) NULL DEFAULT NULL COMMENT '部门ID', + `user_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户账号', + `nick_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户昵称', + `user_type` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '00' COMMENT '用户类型(00系统用户)', + `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '用户邮箱', + `phonenumber` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '手机号码', + `sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)', + `avatar` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '头像地址', + `password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '密码', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '帐号状态(0正常 1停用)', + `del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `login_ip` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '最后登录IP', + `login_date` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`user_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_user +-- ---------------------------- +INSERT INTO `sys_user` VALUES (1, 103, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', '2021-03-07 17:11:54', 'admin', '2021-03-07 17:11:54', '', NULL, '管理员'); +INSERT INTO `sys_user` VALUES (2, 101, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', '2021-03-07 17:11:54', 'admin', '2021-03-07 17:11:54', 'admin', '2021-03-14 19:22:46', '测试员'); + +-- ---------------------------- +-- Table structure for sys_user_post +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_post`; +CREATE TABLE `sys_user_post` ( + `user_id` bigint(20) NOT NULL COMMENT '用户ID', + `post_id` bigint(20) NOT NULL COMMENT '岗位ID', + PRIMARY KEY (`user_id`, `post_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户与岗位关联表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_user_post +-- ---------------------------- +INSERT INTO `sys_user_post` VALUES (1, 1); +INSERT INTO `sys_user_post` VALUES (2, 2); + +-- ---------------------------- +-- Table structure for sys_user_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_role`; +CREATE TABLE `sys_user_role` ( + `user_id` bigint(20) NOT NULL COMMENT '用户ID', + `role_id` bigint(20) NOT NULL COMMENT '角色ID', + PRIMARY KEY (`user_id`, `role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户和角色关联表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_user_role +-- ---------------------------- +INSERT INTO `sys_user_role` VALUES (1, 1); +INSERT INTO `sys_user_role` VALUES (2, 2); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/main/java/cn/sliyun/CodeGenerator.java b/src/main/java/cn/sliyun/CodeGenerator.java new file mode 100644 index 0000000..829511b --- /dev/null +++ b/src/main/java/cn/sliyun/CodeGenerator.java @@ -0,0 +1,112 @@ +package cn.sliyun; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.generator.AutoGenerator; +import com.baomidou.mybatisplus.generator.InjectionConfig; +import com.baomidou.mybatisplus.generator.config.*; +import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; +import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; + +import java.util.Scanner; + +public class CodeGenerator { + + + private static String pack = "cn.sliyun"; + private static String parent = pack+".api"; + + private static String moduleName = ""; + private static String projectPath = System.getProperty("user.dir") + "/" + moduleName; + + /** + *

+ * 读取控制台内容 + *

+ */ + public static String scanner(String tip) { + + Scanner scanner = new Scanner(System.in); + StringBuilder help = new StringBuilder(); + help.append("请输入" + tip + ":"); + System.out.println(help.toString()); + if (scanner.hasNext()) { + String ipt = scanner.next(); + if (StringUtils.isNotBlank(ipt)) { + return ipt; + } + } + throw new MybatisPlusException("请输入正确的" + tip + "!"); + } + + public static void main(String[] args) { + // 代码生成器 + AutoGenerator mpg = new AutoGenerator(); + + // 全局配置 + GlobalConfig gc = new GlobalConfig(); +// String projectPath = System.getProperty("user.dir"); + gc.setOutputDir(projectPath + "/src/main/java/"); +// gc.setOutputDir(projectPath); + gc.setAuthor("Enoch"); + gc.setOpen(false); + gc.setIdType(IdType.AUTO); + // gc.setSwagger2(true); 实体属性 Swagger2 注解 + mpg.setGlobalConfig(gc); + + // 数据源配置 + DataSourceConfig dsc = new DataSourceConfig(); + dsc.setUrl("jdbc:mysql://rm-wz99smt6zjv8tt10x1250109m.mysql.rds.aliyuncs.com:3306/sliyun?characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false"); + // dsc.setSchemaName("public"); + dsc.setDriverName("com.mysql.cj.jdbc.Driver"); + dsc.setUsername("sliyun"); + dsc.setPassword("Nf46KD8MCTN3jWKZ"); + mpg.setDataSource(dsc); + + // 包配置 + PackageConfig pc = new PackageConfig(); + pc.setModuleName(scanner("模块名")); + pc.setParent(parent); + mpg.setPackageInfo(pc); + + // 自定义配置 + InjectionConfig cfg = new InjectionConfig() { + @Override + public void initMap() { + // to do nothing + } + }; + + + // 配置模板 + TemplateConfig templateConfig = new TemplateConfig(); + + // 配置自定义输出模板 + //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别 + // templateConfig.setEntity("templates/entity2.java"); + // templateConfig.setService(); + // templateConfig.setController(); + + templateConfig.setXml(null); + mpg.setTemplate(templateConfig); + + // 策略配置 + StrategyConfig strategy = new StrategyConfig(); + strategy.setNaming(NamingStrategy.underline_to_camel); + strategy.setColumnNaming(NamingStrategy.underline_to_camel); +// strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!"); + strategy.setEntityLombokModel(false); + strategy.setRestControllerStyle(true); + // 公共父类 +// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!"); + // 写于父类中的公共字段 +// strategy.setSuperEntityColumns("id"); + strategy.setInclude(scanner("表名,多个英文逗号分割").split(",")); + strategy.setControllerMappingHyphenStyle(true); + strategy.setTablePrefix("sly_","sys_"); + mpg.setStrategy(strategy); + mpg.setTemplateEngine(new FreemarkerTemplateEngine()); + mpg.execute(); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/SLYApplication.java b/src/main/java/cn/sliyun/SLYApplication.java new file mode 100644 index 0000000..420218f --- /dev/null +++ b/src/main/java/cn/sliyun/SLYApplication.java @@ -0,0 +1,19 @@ +package cn.sliyun; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +/** + * 启动程序 + * + * @author ruoyi + */ +@SpringBootApplication +public class SLYApplication { + public static void main(String[] args) { + // System.setProperty("spring.devtools.restart.enabled", "false"); + SpringApplication.run(SLYApplication.class, args); + } +} diff --git a/src/main/java/cn/sliyun/SLYServletInitializer.java b/src/main/java/cn/sliyun/SLYServletInitializer.java new file mode 100644 index 0000000..866d57d --- /dev/null +++ b/src/main/java/cn/sliyun/SLYServletInitializer.java @@ -0,0 +1,18 @@ +package cn.sliyun; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +/** + * web容器中进行部署 + * + * @author ruoyi + */ +public class SLYServletInitializer extends SpringBootServletInitializer +{ + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) + { + return application.sources(SLYApplication.class); + } +} diff --git a/src/main/java/cn/sliyun/api/ad/controller/AdItemController.java b/src/main/java/cn/sliyun/api/ad/controller/AdItemController.java new file mode 100644 index 0000000..5424e1d --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/controller/AdItemController.java @@ -0,0 +1,43 @@ +package cn.sliyun.api.ad.controller; + + +import cn.sliyun.api.ad.entity.AdEntity; +import cn.sliyun.api.ad.service.impl.AdItemServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.web.bind.annotation.*; + +import org.springframework.stereotype.Controller; + +import javax.annotation.Resource; + +/** + *

+ * 广告表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/swipe") +public class AdItemController { + @Resource + private AdItemServiceImpl itemService; + + + @PostMapping("/create") + public Result create(@RequestBody AdEntity entity) { + return itemService.create(entity); + } + + @GetMapping("/list") + public Result list() { + return itemService.getAll(); + } + + + @PostMapping("/delete") + public Result delete(int id) { + return itemService.delete(id); + } +} diff --git a/src/main/java/cn/sliyun/api/ad/controller/AdPositionController.java b/src/main/java/cn/sliyun/api/ad/controller/AdPositionController.java new file mode 100644 index 0000000..5c1155d --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/controller/AdPositionController.java @@ -0,0 +1,44 @@ +package cn.sliyun.api.ad.controller; + + +import cn.sliyun.api.ad.entity.AdEntity; +import cn.sliyun.api.ad.service.impl.AdItemServiceImpl; +import cn.sliyun.api.ad.service.impl.ItemServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.web.bind.annotation.*; + +import org.springframework.stereotype.Controller; + +import javax.annotation.Resource; + +/** + *

+ * 广告位表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/swipe/position") +public class AdPositionController { + @Resource + private AdItemServiceImpl itemService; + + + @PostMapping("/create") + public Result create(@RequestBody AdEntity entity) { + return itemService.create(entity); + } + + @GetMapping("/list") + public Result list() { + return itemService.getAll(); + } + + + @PostMapping("/delete") + public Result delete(int id) { + return itemService.delete(id); + } +} diff --git a/src/main/java/cn/sliyun/api/ad/entity/Ad.java b/src/main/java/cn/sliyun/api/ad/entity/Ad.java new file mode 100644 index 0000000..b804fe3 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/entity/Ad.java @@ -0,0 +1,51 @@ +package cn.sliyun.api.ad.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * Banner表格 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class Ad implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * banner 名称,广告位名称 + */ + private String name; + + /** + * banner 描述 + */ + private String description; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/src/main/java/cn/sliyun/api/ad/entity/AdEntity.java b/src/main/java/cn/sliyun/api/ad/entity/AdEntity.java new file mode 100644 index 0000000..99cad5b --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/entity/AdEntity.java @@ -0,0 +1,55 @@ +package cn.sliyun.api.ad.entity; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class AdEntity { + + + @Min(value = 1,message = "广告位ID不能为空") + public int adId; + @NotBlank(message = "广告位事件类型不能为空") + public String eventType; + @NotBlank(message = "广告位事件不能为空") + public String event; + @NotBlank(message = "广告位封面不能为空") + public String img; + + public int getAdId() { + return adId; + } + + public void setAdId(int adId) { + this.adId = adId; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public String getEvent() { + return event; + } + + public void setEvent(String event) { + this.event = event; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } +} diff --git a/src/main/java/cn/sliyun/api/ad/entity/AdItem.java b/src/main/java/cn/sliyun/api/ad/entity/AdItem.java new file mode 100644 index 0000000..cb68713 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/entity/AdItem.java @@ -0,0 +1,177 @@ +package cn.sliyun.api.ad.entity; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.time.LocalDateTime; +import java.io.Serializable; +import java.time.format.DateTimeFormatter; + +/** + *

+ * 广告表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_ad_item") +public class AdItem implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 广告位ID id + */ + private Integer adId; + + /** + * imgage id + */ + @JsonIgnore + private String imgOssFile; + + /** + * 广告事件 + */ + private String actionEvent; + + /** + * 广告事件类型 + */ + private String actionType; + + /** + * 创建时间 + */ + + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @JsonIgnore + private LocalDateTime updateTime; + + + @TableField(exist = false) + private String imgUrl; + + @TableField(exist = false) + private String adPosition = "App 首页Banner"; + + @TableField(exist = false) + private String eventName = "链接跳转"; + + @TableField(exist = false) + private String time ; + + + public void setTime(String time) { + this.time = time; + } + + public String getTime() { + DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return dtf2.format(createTime); + } + + + + public String getImgUrl() { + return AliyunOSSUtil.getInstance().getFileUrl(imgOssFile); + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + public String getAdPosition() { + return adPosition; + } + + public void setAdPosition(String adPosition) { + this.adPosition = adPosition; + } + + public String getEventName() { + return eventName; + } + + public void setEventName(String eventName) { + this.eventName = eventName; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public Integer getAdId() { + return adId; + } + + public void setAdId(Integer adId) { + this.adId = adId; + } + public String getImgOssFile() { + return imgOssFile; + } + + public void setImgOssFile(String imgOssFile) { + this.imgOssFile = imgOssFile; + } + public String getActionEvent() { + return actionEvent; + } + + public void setActionEvent(String actionEvent) { + this.actionEvent = actionEvent; + } + public String getActionType() { + return actionType; + } + + public void setActionType(String actionType) { + this.actionType = actionType; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "AdItem{" + + "id=" + id + + ", adId=" + adId + + ", imgOssFile=" + imgOssFile + + ", actionEvent=" + actionEvent + + ", actionType=" + actionType + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/ad/entity/AdPosition.java b/src/main/java/cn/sliyun/api/ad/entity/AdPosition.java new file mode 100644 index 0000000..c4bcc5d --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/entity/AdPosition.java @@ -0,0 +1,94 @@ +package cn.sliyun.api.ad.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 广告位表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_ad_position") +public class AdPosition implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 广告位名称 + */ + private String name; + + /** + * 广告位名称 + */ + private String description; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "AdPosition{" + + "id=" + id + + ", name=" + name + + ", description=" + description + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/ad/entity/Item.java b/src/main/java/cn/sliyun/api/ad/entity/Item.java new file mode 100644 index 0000000..4356273 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/entity/Item.java @@ -0,0 +1,177 @@ +package cn.sliyun.api.ad.entity; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; + +import java.beans.Transient; +import java.time.LocalDateTime; +import java.io.Serializable; +import java.time.format.DateTimeFormatter; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * Banner item 表格 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("ad_item") +public class Item implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * banner id + */ + private Integer adId; + + /** + * image + */ + @JsonIgnore + private String ossFileName; + + /** + * event + */ + private String actionEvent; + + /** + * 类型 + */ + private String actionType; + + /** + * 创建时间 + */ + @JsonIgnore + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @JsonIgnore + private LocalDateTime updateTime; + + @TableField(exist = false) + private String imgUrl; + + @TableField(exist = false) + private String adPosition = "App 首页Banner"; + + @TableField(exist = false) + private String eventName = "链接跳转"; + + @TableField(exist = false) + private String time ; + + + public void setTime(String time) { + this.time = time; + } + + public String getTime() { + DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return dtf2.format(createTime); + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getAdId() { + return adId; + } + + public void setAdId(Integer adId) { + this.adId = adId; + } + + public String getOssFileName() { + return ossFileName; + } + + public void setOssFileName(String ossFileName) { + this.ossFileName = ossFileName; + } + + public String getActionEvent() { + return actionEvent; + } + + public void setActionEvent(String actionEvent) { + this.actionEvent = actionEvent; + } + + public String getActionType() { + return actionType; + } + + public void setActionType(String actionType) { + this.actionType = actionType; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + public String getImgUrl() { + return AliyunOSSUtil.getInstance().getFileUrl(ossFileName); + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + public String getAdPosition() { + return adPosition; + } + + public void setAdPosition(String adPosition) { + this.adPosition = adPosition; + } + + public String getEventName() { + return eventName; + } + + public void setEventName(String eventName) { + this.eventName = eventName; + } +} diff --git a/src/main/java/cn/sliyun/api/ad/mapper/AdItemMapper.java b/src/main/java/cn/sliyun/api/ad/mapper/AdItemMapper.java new file mode 100644 index 0000000..86e58d2 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/mapper/AdItemMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.ad.mapper; + +import cn.sliyun.api.ad.entity.AdItem; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 广告表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface AdItemMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/ad/mapper/AdMapper.java b/src/main/java/cn/sliyun/api/ad/mapper/AdMapper.java new file mode 100644 index 0000000..ed1363d --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/mapper/AdMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.ad.mapper; + +import cn.sliyun.api.ad.entity.Ad; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Banner表格 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +public interface AdMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/ad/mapper/AdPositionMapper.java b/src/main/java/cn/sliyun/api/ad/mapper/AdPositionMapper.java new file mode 100644 index 0000000..1e34e41 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/mapper/AdPositionMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.ad.mapper; + +import cn.sliyun.api.ad.entity.AdPosition; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 广告位表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface AdPositionMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/ad/mapper/ItemMapper.java b/src/main/java/cn/sliyun/api/ad/mapper/ItemMapper.java new file mode 100644 index 0000000..cba124f --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/mapper/ItemMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.ad.mapper; + +import cn.sliyun.api.ad.entity.Item; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Banner item 表格 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +public interface ItemMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/ad/service/IAdItemService.java b/src/main/java/cn/sliyun/api/ad/service/IAdItemService.java new file mode 100644 index 0000000..3576cec --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/service/IAdItemService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.ad.service; + +import cn.sliyun.api.ad.entity.AdItem; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 广告表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IAdItemService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/ad/service/IAdPositionService.java b/src/main/java/cn/sliyun/api/ad/service/IAdPositionService.java new file mode 100644 index 0000000..1ab8b1b --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/service/IAdPositionService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.ad.service; + +import cn.sliyun.api.ad.entity.AdPosition; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 广告位表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IAdPositionService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/ad/service/IAdService.java b/src/main/java/cn/sliyun/api/ad/service/IAdService.java new file mode 100644 index 0000000..4e91ed7 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/service/IAdService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.ad.service; + +import cn.sliyun.api.ad.entity.Ad; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * Banner表格 服务类 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +public interface IAdService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/ad/service/IItemService.java b/src/main/java/cn/sliyun/api/ad/service/IItemService.java new file mode 100644 index 0000000..3a91962 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/service/IItemService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.ad.service; + +import cn.sliyun.api.ad.entity.Item; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * Banner item 表格 服务类 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +public interface IItemService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/ad/service/impl/AdItemServiceImpl.java b/src/main/java/cn/sliyun/api/ad/service/impl/AdItemServiceImpl.java new file mode 100644 index 0000000..bb33453 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/service/impl/AdItemServiceImpl.java @@ -0,0 +1,45 @@ +package cn.sliyun.api.ad.service.impl; + +import cn.sliyun.api.ad.entity.AdEntity; +import cn.sliyun.api.ad.entity.AdItem; +import cn.sliyun.api.ad.mapper.AdItemMapper; +import cn.sliyun.api.ad.service.IAdItemService; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; + +/** + *

+ * 广告表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class AdItemServiceImpl extends ServiceImpl implements IAdItemService { + public Result create(AdEntity adEntity) { + AdItem item = new AdItem(); + item.setAdId(adEntity.adId); + item.setActionType(adEntity.eventType); + item.setActionEvent(adEntity.event); + item.setImgOssFile(adEntity.getImg()); + item.setCreateTime(LocalDateTime.now()); + item.setUpdateTime(LocalDateTime.now()); + save(item); + return ResultGenerator.genSuccessResult(item); + } + + public Result delete(int id) { + removeById(id); + return ResultGenerator.genSuccessResult(); + } + + public Result getAll() { + return ResultGenerator.genSuccessResult(list()); + } +} + diff --git a/src/main/java/cn/sliyun/api/ad/service/impl/AdPositionServiceImpl.java b/src/main/java/cn/sliyun/api/ad/service/impl/AdPositionServiceImpl.java new file mode 100644 index 0000000..08d31d3 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/service/impl/AdPositionServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.ad.service.impl; + +import cn.sliyun.api.ad.entity.AdPosition; +import cn.sliyun.api.ad.mapper.AdPositionMapper; +import cn.sliyun.api.ad.service.IAdPositionService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 广告位表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class AdPositionServiceImpl extends ServiceImpl implements IAdPositionService { + +} diff --git a/src/main/java/cn/sliyun/api/ad/service/impl/AdServiceImpl.java b/src/main/java/cn/sliyun/api/ad/service/impl/AdServiceImpl.java new file mode 100644 index 0000000..2fc7c83 --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/service/impl/AdServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.ad.service.impl; + +import cn.sliyun.api.ad.entity.Ad; +import cn.sliyun.api.ad.mapper.AdMapper; +import cn.sliyun.api.ad.service.IAdService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * Banner表格 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +@Service +public class AdServiceImpl extends ServiceImpl implements IAdService { + +} diff --git a/src/main/java/cn/sliyun/api/ad/service/impl/ItemServiceImpl.java b/src/main/java/cn/sliyun/api/ad/service/impl/ItemServiceImpl.java new file mode 100644 index 0000000..82f22ed --- /dev/null +++ b/src/main/java/cn/sliyun/api/ad/service/impl/ItemServiceImpl.java @@ -0,0 +1,46 @@ +package cn.sliyun.api.ad.service.impl; + +import cn.sliyun.api.ad.entity.AdEntity; +import cn.sliyun.api.ad.entity.Item; +import cn.sliyun.api.ad.mapper.ItemMapper; +import cn.sliyun.api.ad.service.IItemService; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; + +/** + *

+ * Banner item 表格 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +@Service +public class ItemServiceImpl extends ServiceImpl implements IItemService { + + public Result create(AdEntity adEntity) { + System.out.println(adEntity.img); + Item item = new Item(); + item.setAdId(adEntity.adId); + item.setActionType(adEntity.eventType); + item.setActionEvent(adEntity.event); + item.setOssFileName(adEntity.getImg()); + item.setCreateTime(LocalDateTime.now()); + item.setUpdateTime(LocalDateTime.now()); + save(item); + return ResultGenerator.genSuccessResult(item); + } + + public Result delete(int id) { + removeById(id); + return ResultGenerator.genSuccessResult(); + } + + public Result getAll() { + return ResultGenerator.genSuccessResult(list()); + } +} diff --git a/src/main/java/cn/sliyun/api/admin/controller/DictController.java b/src/main/java/cn/sliyun/api/admin/controller/DictController.java new file mode 100644 index 0000000..9812bcf --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/controller/DictController.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 字典表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/admin/dict") +public class DictController { + +} diff --git a/src/main/java/cn/sliyun/api/admin/controller/LoginLogController.java b/src/main/java/cn/sliyun/api/admin/controller/LoginLogController.java new file mode 100644 index 0000000..921b3d3 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/controller/LoginLogController.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 登录记录 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/admin/login-log") +public class LoginLogController { + +} diff --git a/src/main/java/cn/sliyun/api/admin/controller/OperationLogController.java b/src/main/java/cn/sliyun/api/admin/controller/OperationLogController.java new file mode 100644 index 0000000..a26950b --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/controller/OperationLogController.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 操作日志 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/admin/operation-log") +public class OperationLogController { + +} diff --git a/src/main/java/cn/sliyun/api/admin/controller/RelationController.java b/src/main/java/cn/sliyun/api/admin/controller/RelationController.java new file mode 100644 index 0000000..26e979f --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/controller/RelationController.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 角色和菜单关联表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/admin/relation") +public class RelationController { + +} diff --git a/src/main/java/cn/sliyun/api/admin/controller/RoleController.java b/src/main/java/cn/sliyun/api/admin/controller/RoleController.java new file mode 100644 index 0000000..78fd917 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/controller/RoleController.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 角色表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/admin/role") +public class RoleController { + +} diff --git a/src/main/java/cn/sliyun/api/admin/controller/UserController.java b/src/main/java/cn/sliyun/api/admin/controller/UserController.java new file mode 100644 index 0000000..4336335 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/controller/UserController.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 管理员表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/admin/user") +public class UserController { + +} diff --git a/src/main/java/cn/sliyun/api/admin/entity/Dict.java b/src/main/java/cn/sliyun/api/admin/entity/Dict.java new file mode 100644 index 0000000..b7a3aca --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/entity/Dict.java @@ -0,0 +1,106 @@ +package cn.sliyun.api.admin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; + +/** + *

+ * 字典表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sys_dict") +public class Dict implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 排序 + */ + private Integer num; + + /** + * 父级字典 + */ + private Integer pid; + + /** + * 名称 + */ + private String name; + + /** + * 提示 + */ + private String tips; + + /** + * 值 + */ + private String code; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public Integer getNum() { + return num; + } + + public void setNum(Integer num) { + this.num = num; + } + public Integer getPid() { + return pid; + } + + public void setPid(Integer pid) { + this.pid = pid; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public String getTips() { + return tips; + } + + public void setTips(String tips) { + this.tips = tips; + } + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + @Override + public String toString() { + return "Dict{" + + "id=" + id + + ", num=" + num + + ", pid=" + pid + + ", name=" + name + + ", tips=" + tips + + ", code=" + code + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/admin/entity/LoginLog.java b/src/main/java/cn/sliyun/api/admin/entity/LoginLog.java new file mode 100644 index 0000000..5fa2127 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/entity/LoginLog.java @@ -0,0 +1,133 @@ +package cn.sliyun.api.admin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 登录记录 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sys_login_log") +public class LoginLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 日志名称 + */ + private String logname; + + /** + * 管理员id + */ + private Integer userid; + + /** + * 是否执行成功 + */ + private String succeed; + + /** + * 具体消息 + */ + private String message; + + /** + * 登录ip + */ + private String ip; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getLogname() { + return logname; + } + + public void setLogname(String logname) { + this.logname = logname; + } + public Integer getUserid() { + return userid; + } + + public void setUserid(Integer userid) { + this.userid = userid; + } + public String getSucceed() { + return succeed; + } + + public void setSucceed(String succeed) { + this.succeed = succeed; + } + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "LoginLog{" + + "id=" + id + + ", logname=" + logname + + ", userid=" + userid + + ", succeed=" + succeed + + ", message=" + message + + ", ip=" + ip + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/admin/entity/OperationLog.java b/src/main/java/cn/sliyun/api/admin/entity/OperationLog.java new file mode 100644 index 0000000..4595979 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/entity/OperationLog.java @@ -0,0 +1,159 @@ +package cn.sliyun.api.admin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 操作日志 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sys_operation_log") +public class OperationLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 日志类型 + */ + private String logtype; + + /** + * 日志名称 + */ + private String logname; + + /** + * 用户id + */ + private Integer userid; + + /** + * 类名称 + */ + private String classname; + + /** + * 方法名称 + */ + private String method; + + /** + * 是否成功 + */ + private String succeed; + + /** + * 备注 + */ + private String message; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getLogtype() { + return logtype; + } + + public void setLogtype(String logtype) { + this.logtype = logtype; + } + public String getLogname() { + return logname; + } + + public void setLogname(String logname) { + this.logname = logname; + } + public Integer getUserid() { + return userid; + } + + public void setUserid(Integer userid) { + this.userid = userid; + } + public String getClassname() { + return classname; + } + + public void setClassname(String classname) { + this.classname = classname; + } + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + public String getSucceed() { + return succeed; + } + + public void setSucceed(String succeed) { + this.succeed = succeed; + } + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "OperationLog{" + + "id=" + id + + ", logtype=" + logtype + + ", logname=" + logname + + ", userid=" + userid + + ", classname=" + classname + + ", method=" + method + + ", succeed=" + succeed + + ", message=" + message + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/admin/entity/Relation.java b/src/main/java/cn/sliyun/api/admin/entity/Relation.java new file mode 100644 index 0000000..0d6256e --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/entity/Relation.java @@ -0,0 +1,67 @@ +package cn.sliyun.api.admin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; + +/** + *

+ * 角色和菜单关联表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sys_relation") +public class Relation implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 菜单id + */ + private Long menuid; + + /** + * 角色id + */ + private Integer roleid; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public Long getMenuid() { + return menuid; + } + + public void setMenuid(Long menuid) { + this.menuid = menuid; + } + public Integer getRoleid() { + return roleid; + } + + public void setRoleid(Integer roleid) { + this.roleid = roleid; + } + + @Override + public String toString() { + return "Relation{" + + "id=" + id + + ", menuid=" + menuid + + ", roleid=" + roleid + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/admin/entity/Role.java b/src/main/java/cn/sliyun/api/admin/entity/Role.java new file mode 100644 index 0000000..b14ff04 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/entity/Role.java @@ -0,0 +1,119 @@ +package cn.sliyun.api.admin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; + +/** + *

+ * 角色表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sys_role") +public class Role implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 序号 + */ + private Integer num; + + /** + * 父角色id + */ + private Integer pid; + + /** + * 角色名称 + */ + private String name; + + /** + * 部门名称 + */ + private Integer deptid; + + /** + * 提示 + */ + private String tips; + + /** + * 保留字段(暂时没用) + */ + private Integer version; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public Integer getNum() { + return num; + } + + public void setNum(Integer num) { + this.num = num; + } + public Integer getPid() { + return pid; + } + + public void setPid(Integer pid) { + this.pid = pid; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public Integer getDeptid() { + return deptid; + } + + public void setDeptid(Integer deptid) { + this.deptid = deptid; + } + public String getTips() { + return tips; + } + + public void setTips(String tips) { + this.tips = tips; + } + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + @Override + public String toString() { + return "Role{" + + "id=" + id + + ", num=" + num + + ", pid=" + pid + + ", name=" + name + + ", deptid=" + deptid + + ", tips=" + tips + + ", version=" + version + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/admin/entity/User.java b/src/main/java/cn/sliyun/api/admin/entity/User.java new file mode 100644 index 0000000..385104c --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/entity/User.java @@ -0,0 +1,224 @@ +package cn.sliyun.api.admin.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 管理员表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sys_user") +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 头像 + */ + private String avatar; + + /** + * 账号 + */ + private String account; + + /** + * 密码 + */ + private String password; + + /** + * md5密码盐 + */ + private String salt; + + /** + * 名字 + */ + private String name; + + /** + * 生日 + */ + private LocalDateTime birthday; + + /** + * 性别(1:男 2:女) + */ + private Integer sex; + + /** + * 电子邮件 + */ + private String email; + + /** + * 电话 + */ + private String phone; + + /** + * 角色id + */ + private String roleid; + + /** + * 部门id + */ + private Integer deptid; + + /** + * 状态(1:启用 2:冻结 3:删除) + */ + private Integer status; + + /** + * 创建时间 + */ + private LocalDateTime createtime; + + /** + * 保留字段 + */ + private Integer version; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + public String getSalt() { + return salt; + } + + public void setSalt(String salt) { + this.salt = salt; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public LocalDateTime getBirthday() { + return birthday; + } + + public void setBirthday(LocalDateTime birthday) { + this.birthday = birthday; + } + public Integer getSex() { + return sex; + } + + public void setSex(Integer sex) { + this.sex = sex; + } + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + public String getRoleid() { + return roleid; + } + + public void setRoleid(String roleid) { + this.roleid = roleid; + } + public Integer getDeptid() { + return deptid; + } + + public void setDeptid(Integer deptid) { + this.deptid = deptid; + } + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + public LocalDateTime getCreatetime() { + return createtime; + } + + public void setCreatetime(LocalDateTime createtime) { + this.createtime = createtime; + } + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", avatar=" + avatar + + ", account=" + account + + ", password=" + password + + ", salt=" + salt + + ", name=" + name + + ", birthday=" + birthday + + ", sex=" + sex + + ", email=" + email + + ", phone=" + phone + + ", roleid=" + roleid + + ", deptid=" + deptid + + ", status=" + status + + ", createtime=" + createtime + + ", version=" + version + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/admin/mapper/DictMapper.java b/src/main/java/cn/sliyun/api/admin/mapper/DictMapper.java new file mode 100644 index 0000000..4448807 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/mapper/DictMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.mapper; + +import cn.sliyun.api.admin.entity.Dict; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 字典表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface DictMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/admin/mapper/LoginLogMapper.java b/src/main/java/cn/sliyun/api/admin/mapper/LoginLogMapper.java new file mode 100644 index 0000000..34c000f --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/mapper/LoginLogMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.mapper; + +import cn.sliyun.api.admin.entity.LoginLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 登录记录 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface LoginLogMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/admin/mapper/OperationLogMapper.java b/src/main/java/cn/sliyun/api/admin/mapper/OperationLogMapper.java new file mode 100644 index 0000000..385c235 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/mapper/OperationLogMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.mapper; + +import cn.sliyun.api.admin.entity.OperationLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 操作日志 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface OperationLogMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/admin/mapper/RelationMapper.java b/src/main/java/cn/sliyun/api/admin/mapper/RelationMapper.java new file mode 100644 index 0000000..a0f48aa --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/mapper/RelationMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.mapper; + +import cn.sliyun.api.admin.entity.Relation; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 角色和菜单关联表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface RelationMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/admin/mapper/RoleMapper.java b/src/main/java/cn/sliyun/api/admin/mapper/RoleMapper.java new file mode 100644 index 0000000..b7d25ad --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/mapper/RoleMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.mapper; + +import cn.sliyun.api.admin.entity.Role; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 角色表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface RoleMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/admin/mapper/UserMapper.java b/src/main/java/cn/sliyun/api/admin/mapper/UserMapper.java new file mode 100644 index 0000000..1522368 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/mapper/UserMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.mapper; + +import cn.sliyun.api.admin.entity.User; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 管理员表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface UserMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/IDictService.java b/src/main/java/cn/sliyun/api/admin/service/IDictService.java new file mode 100644 index 0000000..7aca488 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/IDictService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.service; + +import cn.sliyun.api.admin.entity.Dict; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 字典表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IDictService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/ILoginLogService.java b/src/main/java/cn/sliyun/api/admin/service/ILoginLogService.java new file mode 100644 index 0000000..43868c6 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/ILoginLogService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.service; + +import cn.sliyun.api.admin.entity.LoginLog; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 登录记录 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface ILoginLogService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/IOperationLogService.java b/src/main/java/cn/sliyun/api/admin/service/IOperationLogService.java new file mode 100644 index 0000000..4b3ad4d --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/IOperationLogService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.service; + +import cn.sliyun.api.admin.entity.OperationLog; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 操作日志 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IOperationLogService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/IRelationService.java b/src/main/java/cn/sliyun/api/admin/service/IRelationService.java new file mode 100644 index 0000000..60990b0 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/IRelationService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.service; + +import cn.sliyun.api.admin.entity.Relation; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 角色和菜单关联表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IRelationService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/IRoleService.java b/src/main/java/cn/sliyun/api/admin/service/IRoleService.java new file mode 100644 index 0000000..bf144ba --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/IRoleService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.service; + +import cn.sliyun.api.admin.entity.Role; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 角色表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IRoleService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/IUserService.java b/src/main/java/cn/sliyun/api/admin/service/IUserService.java new file mode 100644 index 0000000..5be7e11 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/IUserService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.admin.service; + +import cn.sliyun.api.admin.entity.User; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 管理员表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IUserService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/impl/DictServiceImpl.java b/src/main/java/cn/sliyun/api/admin/service/impl/DictServiceImpl.java new file mode 100644 index 0000000..70485a1 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/impl/DictServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.service.impl; + +import cn.sliyun.api.admin.entity.Dict; +import cn.sliyun.api.admin.mapper.DictMapper; +import cn.sliyun.api.admin.service.IDictService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 字典表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class DictServiceImpl extends ServiceImpl implements IDictService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/impl/LoginLogServiceImpl.java b/src/main/java/cn/sliyun/api/admin/service/impl/LoginLogServiceImpl.java new file mode 100644 index 0000000..2d4df09 --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/impl/LoginLogServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.service.impl; + +import cn.sliyun.api.admin.entity.LoginLog; +import cn.sliyun.api.admin.mapper.LoginLogMapper; +import cn.sliyun.api.admin.service.ILoginLogService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 登录记录 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class LoginLogServiceImpl extends ServiceImpl implements ILoginLogService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/impl/OperationLogServiceImpl.java b/src/main/java/cn/sliyun/api/admin/service/impl/OperationLogServiceImpl.java new file mode 100644 index 0000000..531d61d --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/impl/OperationLogServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.service.impl; + +import cn.sliyun.api.admin.entity.OperationLog; +import cn.sliyun.api.admin.mapper.OperationLogMapper; +import cn.sliyun.api.admin.service.IOperationLogService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 操作日志 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class OperationLogServiceImpl extends ServiceImpl implements IOperationLogService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/impl/RelationServiceImpl.java b/src/main/java/cn/sliyun/api/admin/service/impl/RelationServiceImpl.java new file mode 100644 index 0000000..517503a --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/impl/RelationServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.service.impl; + +import cn.sliyun.api.admin.entity.Relation; +import cn.sliyun.api.admin.mapper.RelationMapper; +import cn.sliyun.api.admin.service.IRelationService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 角色和菜单关联表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class RelationServiceImpl extends ServiceImpl implements IRelationService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/impl/RoleServiceImpl.java b/src/main/java/cn/sliyun/api/admin/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..98f265f --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/impl/RoleServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.service.impl; + +import cn.sliyun.api.admin.entity.Role; +import cn.sliyun.api.admin.mapper.RoleMapper; +import cn.sliyun.api.admin.service.IRoleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 角色表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class RoleServiceImpl extends ServiceImpl implements IRoleService { + +} diff --git a/src/main/java/cn/sliyun/api/admin/service/impl/UserServiceImpl.java b/src/main/java/cn/sliyun/api/admin/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..388c12f --- /dev/null +++ b/src/main/java/cn/sliyun/api/admin/service/impl/UserServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.admin.service.impl; + +import cn.sliyun.api.admin.entity.User; +import cn.sliyun.api.admin.mapper.UserMapper; +import cn.sliyun.api.admin.service.IUserService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 管理员表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class UserServiceImpl extends ServiceImpl implements IUserService { + +} diff --git a/src/main/java/cn/sliyun/api/app/AppController.java b/src/main/java/cn/sliyun/api/app/AppController.java new file mode 100644 index 0000000..ae23eb4 --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/AppController.java @@ -0,0 +1,30 @@ +package cn.sliyun.api.app; + + +import cn.sliyun.api.app.service.service.impl.AppServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; + + +@RestController +@RequestMapping("/app") +public class AppController { + + @Resource + public AppServiceImpl appService; + + + @PostMapping("/uploadImg") + public Result uploadImg(MultipartFile file) { + return appService.upload(file); + } + + + +} diff --git a/src/main/java/cn/sliyun/api/app/DashboardController.java b/src/main/java/cn/sliyun/api/app/DashboardController.java new file mode 100644 index 0000000..81b8622 --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/DashboardController.java @@ -0,0 +1,33 @@ +package cn.sliyun.api.app; + + +import cn.sliyun.api.app.service.service.impl.AppServiceImpl; +import cn.sliyun.api.app.service.service.impl.DashboardServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; + + +@RestController +@RequestMapping("/console") +public class DashboardController { + + @Resource + public DashboardServiceImpl appService; + + + @GetMapping("/dashboard") + public Result dashboard() { + return appService.dashboard(); + } + + + + + +} diff --git a/src/main/java/cn/sliyun/api/app/controller/BeamImgController.java b/src/main/java/cn/sliyun/api/app/controller/BeamImgController.java new file mode 100644 index 0000000..c7e3da8 --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/controller/BeamImgController.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.app.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * img 表格 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +@RestController +@RequestMapping("/app/beam-img") +public class BeamImgController { + +} diff --git a/src/main/java/cn/sliyun/api/app/entity/BeamImg.java b/src/main/java/cn/sliyun/api/app/entity/BeamImg.java new file mode 100644 index 0000000..3ad256c --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/entity/BeamImg.java @@ -0,0 +1,107 @@ +package cn.sliyun.api.app.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * img 表格 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class BeamImg implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * OSS fileName + + */ + private String ossFileName; + + /** + * file_md5 + */ + private String ossFileMd5; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getOssFileName() { + return ossFileName; + } + + public void setOssFileName(String ossFileName) { + this.ossFileName = ossFileName; + } + + public String getOssFileMd5() { + return ossFileMd5; + } + + public void setOssFileMd5(String ossFileMd5) { + this.ossFileMd5 = ossFileMd5; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } +} diff --git a/src/main/java/cn/sliyun/api/app/mapper/BeamImgMapper.java b/src/main/java/cn/sliyun/api/app/mapper/BeamImgMapper.java new file mode 100644 index 0000000..0b4fd82 --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/mapper/BeamImgMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.app.mapper; + +import cn.sliyun.api.app.entity.BeamImg; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * img 表格 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +public interface BeamImgMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/app/service/IBeamImgService.java b/src/main/java/cn/sliyun/api/app/service/IBeamImgService.java new file mode 100644 index 0000000..cc6b5ae --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/service/IBeamImgService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.app.service; + +import cn.sliyun.api.app.entity.BeamImg; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * img 表格 服务类 + *

+ * + * @author Enoch + * @since 2021-02-21 + */ +public interface IBeamImgService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/app/service/service/IAppService.java b/src/main/java/cn/sliyun/api/app/service/service/IAppService.java new file mode 100644 index 0000000..c3bba9b --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/service/service/IAppService.java @@ -0,0 +1,10 @@ +package cn.sliyun.api.app.service.service; + +import cn.sliyun.common.core.Result; +import org.springframework.web.multipart.MultipartFile; + +public interface IAppService { + + Result upload(MultipartFile file); + +} diff --git a/src/main/java/cn/sliyun/api/app/service/service/IDashboardService.java b/src/main/java/cn/sliyun/api/app/service/service/IDashboardService.java new file mode 100644 index 0000000..a47fd86 --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/service/service/IDashboardService.java @@ -0,0 +1,4 @@ +package cn.sliyun.api.app.service.service; + +public interface IDashboardService { +} diff --git a/src/main/java/cn/sliyun/api/app/service/service/impl/AppServiceImpl.java b/src/main/java/cn/sliyun/api/app/service/service/impl/AppServiceImpl.java new file mode 100644 index 0000000..18fa3b7 --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/service/service/impl/AppServiceImpl.java @@ -0,0 +1,23 @@ +package cn.sliyun.api.app.service.service.impl; + +import cn.sliyun.api.app.service.service.IAppService; +import cn.sliyun.common.utils.AliyunOSSUtil; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.util.HashMap; +import java.util.Map; + +@Service +public class AppServiceImpl implements IAppService { + + + @Override + public Result upload(MultipartFile file) { + String objPath = AliyunOSSUtil.getInstance().uploadImage(file); + return ResultGenerator.genSuccessResult(objPath); + } + +} diff --git a/src/main/java/cn/sliyun/api/app/service/service/impl/DashboardServiceImpl.java b/src/main/java/cn/sliyun/api/app/service/service/impl/DashboardServiceImpl.java new file mode 100644 index 0000000..7914ed7 --- /dev/null +++ b/src/main/java/cn/sliyun/api/app/service/service/impl/DashboardServiceImpl.java @@ -0,0 +1,105 @@ +package cn.sliyun.api.app.service.service.impl; + +import cn.sliyun.dotwallet.DotWalletManager; +import cn.sliyun.dotwallet.entity.BlockBean; +import com.alibaba.fastjson.JSON; +import cn.sliyun.api.app.service.service.IDashboardService; +import cn.sliyun.api.member.service.impl.MemberServiceImpl; +import cn.sliyun.api.order.entity.Order; +import cn.sliyun.api.order.service.impl.OrderServiceImpl; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class DashboardServiceImpl implements IDashboardService { + + + @Resource + private MemberServiceImpl memberService; + + @Resource + private OrderServiceImpl orderService; + + public Result dashboard() { + + Map map = new HashMap(); + Map member = new HashMap(); + Map order = new HashMap(); + Map coinAddress = new HashMap(); + Map pay = new HashMap(); + Map sales = new HashMap(); + + member.put("total", "" + memberService.count()); + member.put("week", "" + memberService.getBaseMapper().getWeekList()); + member.put("today", "" + 10000); + + int unpaid = orderService.count(new QueryWrapper().eq("status", 0)); + int success = orderService.count(new QueryWrapper().ne("status", 0)); + order.put("total", "" + orderService.count()); + order.put("proportion", success == 0 ? "--%" : (unpaid / success * 100) + "%"); + order.put("unpaid", "" + unpaid); + order.put("success", "" + success); + order.put("cancel", "" + orderService.count(new QueryWrapper().eq("status", 1))); + + + coinAddress.put("total", "" + 9999); + coinAddress.put("btc", "" + 100); + coinAddress.put("bth", "" + 300); + coinAddress.put("ltc", "" + 909); + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.select("sum(total_amount) as totalAmount"); +// queryWrapper.ne("status",0); + Map objectMap = orderService.getMap(queryWrapper); + BigDecimal sumCount = new BigDecimal("0.00"); + System.out.println("--------:" + JSON.toJSONString(objectMap)); + if (null!=objectMap&&objectMap.size() > 0 && null!=objectMap.get("totalAmount")){ + sumCount = (BigDecimal) objectMap.get("totalAmount"); + } + sales.put("total", "" + sumCount); + sales.put("week", "" + 452); + sales.put("today", "" + 20); + + long startTime = 1616924237; + long endTime = System.currentTimeMillis() / 1000; + List blockList = DotWalletManager.getInstance().getBlockList(startTime, endTime); + + + double block = 0; + for (int i = 0; i < blockList.size(); i++) { + block = block + blockList.get(i).getRewards(); + } + + List list = new ArrayList<>(); + + for (int i = 0; i < 7; i++) { + Map a = new HashMap(); + a.put("count", "" + i); + a.put("day", System.currentTimeMillis() / 1000); + + list.add(a); + } + + pay.put("total", "" + 1000); + pay.put("list", list); + + map.put("member", member); + map.put("order", order); + map.put("coinAddress", coinAddress); + map.put("pay", pay); + map.put("sales", sales); + map.put("profit", block); + return ResultGenerator.genSuccessResult(map); + } +} diff --git a/src/main/java/cn/sliyun/api/auth/controller/AuthController.java b/src/main/java/cn/sliyun/api/auth/controller/AuthController.java new file mode 100644 index 0000000..aa5d2b9 --- /dev/null +++ b/src/main/java/cn/sliyun/api/auth/controller/AuthController.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.auth.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +@RestController +@RequestMapping("/auth") +public class AuthController { + + @RequestMapping("/login") + public Object login() { + List list = new ArrayList(); + list.add("1"); + list.add(2); + return list; + } +} diff --git a/src/main/java/cn/sliyun/api/coin/controller/CoinController.java b/src/main/java/cn/sliyun/api/coin/controller/CoinController.java new file mode 100644 index 0000000..9b23382 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/controller/CoinController.java @@ -0,0 +1,86 @@ +package cn.sliyun.api.coin.controller; + + +import cn.sliyun.api.coin.entity.CoinAction; +import cn.sliyun.api.coin.service.impl.CoinServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + + +/** + *

+ * 货币类型表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/coin") +public class CoinController { + @Resource + private CoinServiceImpl mCoinServiceImpl; + + @PostMapping("/create") + public Result create(@RequestBody @Valid CoinAction action) { +// if (icon != null) { +// try { +// //当前项目下路径 +// String realPath = System.getProperty("user.dir") + new String("/beam-system/src/main/resources/" + UPLOAD_PATH_PREFIX); +// System.out.println("-----------上传文件保存的路径【" + realPath + "】-----------"); +// //存放上传文件的文件夹 +// File folder = new File(realPath); +// System.out.println("-----------存放上传文件的文件夹【" + folder.getAbsolutePath() + "】-----------"); +// System.out.println("-----------输出文件夹绝对路径 -- 这里的绝对路径是相当于当前项目的路径而不是“容器”路径【" + folder.getAbsolutePath() + "】-----------"); +// if (!folder.isDirectory()) { +// //递归生成文件夹 +// folder.mkdirs(); +// } +// //获取原始的名字 方法是得到原来的文件名在客户机的文件系统名称 +// String oldName = icon.getOriginalFilename(); +// System.out.println("-----------文件原始的名字【" + oldName + "】-----------"); +// //新命名=随机UUID+原始文件的后缀名 +// String newName = "img_coin_" + System.currentTimeMillis() + oldName.substring(oldName.lastIndexOf(".")); +// System.out.println("-----------文件要保存后的新名字【" + newName + "】-----------"); +// File newFile = new File(folder.getAbsolutePath().replace("\\", "/") + File.separator + newName); +// System.out.println("-----------getAbsolutePath【" + newFile.getAbsolutePath() + "】-----------"); +// //将图片保存到static文件夹里 +// icon.transferTo(newFile); +// System.out.println("-----------getAbsolutePath【" + newFile.exists() + "/" + newFile.isFile() + "】-----------"); +// String filePath = "/images/" + newName; +// System.out.println("icon:" + filePath); +// BeamImg img = new BeamImg(); +//// img.setUrl(filePath); +//// img.setDescription("coin create icon"); +//// img.setImgMd5(""); +//// img.setCreateBy("coin create icon"); +//// img.setCreateTime(LocalDateTime.now()); +//// img.setUpdateTime(LocalDateTime.now()); +// mImgService.save(img); +// return mCoinServiceImpl.create(img.getId(), name, description); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + return mCoinServiceImpl.create(action); + } + + @PostMapping("/edit") + public Result editCoin(@RequestBody CoinAction action) { + return mCoinServiceImpl.edit(action); + } + + @PostMapping("/delete") + public Result deleteCoin(@RequestBody CoinAction action) { + return mCoinServiceImpl.delete(action.getId()); + } + + @GetMapping("/list") + public Result list(@RequestParam(defaultValue = "1") int pageNo, + @RequestParam(defaultValue = "20") int pageSize) { + return mCoinServiceImpl.getList(pageNo, pageSize); + } +} diff --git a/src/main/java/cn/sliyun/api/coin/controller/CoinPackageController.java b/src/main/java/cn/sliyun/api/coin/controller/CoinPackageController.java new file mode 100644 index 0000000..96a4ca5 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/controller/CoinPackageController.java @@ -0,0 +1,46 @@ +package cn.sliyun.api.coin.controller; + + +import cn.sliyun.api.coin.entity.CoinPackage; +import cn.sliyun.api.coin.service.impl.CoinPackageServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +/** + *

+ * 算力包 前端控制器 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +@RestController +@RequestMapping("/coin/package") +public class CoinPackageController { + @Resource + private CoinPackageServiceImpl coinPackageService; + + @PostMapping("/create") + public Result create(@RequestBody @Valid CoinPackage entity) { + return coinPackageService.create(entity); + } + + @PostMapping("/edit") + public Result edit(@RequestBody CoinPackage entity) { + return coinPackageService.edit(entity); + } + + @PostMapping("/delete") + public Result delete(@RequestBody CoinPackage entity) { + return coinPackageService.delete(entity.getId()); + } + + + @GetMapping("/list") + public Result list(@RequestParam(required = false ,defaultValue = "0") int coinId) { + return coinPackageService.getList(coinId); + } +} diff --git a/src/main/java/cn/sliyun/api/coin/controller/CoinPackageUnitController.java b/src/main/java/cn/sliyun/api/coin/controller/CoinPackageUnitController.java new file mode 100644 index 0000000..70d594d --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/controller/CoinPackageUnitController.java @@ -0,0 +1,34 @@ +package cn.sliyun.api.coin.controller; + + +import cn.sliyun.api.coin.service.impl.CoinPackageServiceImpl; +import cn.sliyun.api.coin.service.impl.CoinPackageUnitServiceImpl; +import cn.sliyun.api.coin.service.impl.CoinServiceImpl; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + *

+ * 算力包单位 前端控制器 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +@RestController +@RequestMapping("/coin/package/unit") +public class CoinPackageUnitController { + + @Resource + private CoinPackageUnitServiceImpl coinPackageService; + @GetMapping("/list") + public Result list() { + return ResultGenerator.genSuccessResult(coinPackageService.list()); + } +} diff --git a/src/main/java/cn/sliyun/api/coin/entity/Coin.java b/src/main/java/cn/sliyun/api/coin/entity/Coin.java new file mode 100644 index 0000000..09309ce --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/entity/Coin.java @@ -0,0 +1,128 @@ +package cn.sliyun.api.coin.entity; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 货币类型表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_coin") +public class Coin implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 英文名称 + */ + private String enName; + + /** + * 中文名称 + */ + private String cnName; + + /** + * img name + */ + @JsonIgnore + private String imgOssFile; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + + + @TableField(exist = false) + public String icon ; + + + + public String getIcon() { + return AliyunOSSUtil.getInstance().getFileUrl(imgOssFile); + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getEnName() { + return enName; + } + + public void setEnName(String enName) { + this.enName = enName; + } + public String getCnName() { + return cnName; + } + + public void setCnName(String cnName) { + this.cnName = cnName; + } + public String getImgOssFile() { + return imgOssFile; + } + + public void setImgOssFile(String imgOssFile) { + this.imgOssFile = imgOssFile; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "Coin{" + + "id=" + id + + ", enName=" + enName + + ", cnName=" + cnName + + ", imgOssFile=" + imgOssFile + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/coin/entity/CoinAction.java b/src/main/java/cn/sliyun/api/coin/entity/CoinAction.java new file mode 100644 index 0000000..7175c44 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/entity/CoinAction.java @@ -0,0 +1,57 @@ +package cn.sliyun.api.coin.entity; + +import javax.validation.constraints.NotBlank; +import java.io.File; + + +public class CoinAction { + + private int id; + @NotBlank(message = "货币名称不能为空") + private String cnName; + @NotBlank(message = "货币简写不能为空") + private String enName; + @NotBlank(message = "货币Icon不能为空") + private String imgOssFile; + private String description; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getEnName() { + return enName; + } + + public void setEnName(String enName) { + this.enName = enName; + } + + public String getCnName() { + return cnName; + } + + public void setCnName(String cnName) { + this.cnName = cnName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getImgOssFile() { + return imgOssFile; + } + + public void setImgOssFile(String imgOssFile) { + this.imgOssFile = imgOssFile; + } +} diff --git a/src/main/java/cn/sliyun/api/coin/entity/CoinPackage.java b/src/main/java/cn/sliyun/api/coin/entity/CoinPackage.java new file mode 100644 index 0000000..c61f813 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/entity/CoinPackage.java @@ -0,0 +1,171 @@ +package cn.sliyun.api.coin.entity; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 算力包 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +@TableName("sly_coin_package") +public class CoinPackage implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 包名称 + */ + @NotBlank(message = "算力包名称不能为空") + private String title; + + /** + * 单价 + */ + @DecimalMin(value = "1", message = "算力包单价必须大0") + @NotNull(message = "算力包单价必须大0") + private BigDecimal price; + + /** + * 算力包 单位数量 + */ + @NotNull(message = "算力包单位数量不能为空") + private Integer number; + + /** + * 最小时间 + */ + private Integer duration; + + /** + * 算力包单位ID + */ + @NotNull(message = "算力包名单位ID不能为空") + private Long packageUnitId; + + /** + * 算力包单位名称 + */ + @NotBlank(message = "算力包单位名称不能为空") + private String packageUnitName; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + + public Long getPackageUnitId() { + return packageUnitId; + } + + public void setPackageUnitId(Long packageUnitId) { + this.packageUnitId = packageUnitId; + } + + public String getPackageUnitName() { + return packageUnitName; + } + + public void setPackageUnitName(String packageUnitName) { + this.packageUnitName = packageUnitName; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + this.number = number; + } + + public Integer getDuration() { + return duration; + } + + public void setDuration(Integer duration) { + this.duration = duration; + } + + @Override + public String toString() { + return "CoinPackage{" + + "id=" + id + + ", title='" + title + '\'' + + ", price=" + price + + ", number=" + number + + ", duration=" + duration + + ", packageUnitId=" + packageUnitId + + ", packageUnitName='" + packageUnitName + '\'' + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + '}'; + } +} diff --git a/src/main/java/cn/sliyun/api/coin/entity/CoinPackageUnit.java b/src/main/java/cn/sliyun/api/coin/entity/CoinPackageUnit.java new file mode 100644 index 0000000..2a1634f --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/entity/CoinPackageUnit.java @@ -0,0 +1,103 @@ +package cn.sliyun.api.coin.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 算力包单位 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +@TableName("sly_coin_package_unit") +public class CoinPackageUnit implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 单位名称 + */ + private String title; + + /** + * 备注 + */ + private String remarks; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getRemarks() { + return remarks; + } + + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "CoinPackageUnit{" + + "id=" + id + + ", title='" + title + '\'' + + ", remarks='" + remarks + '\'' + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + '}'; + } +} diff --git a/src/main/java/cn/sliyun/api/coin/mapper/CoinMapper.java b/src/main/java/cn/sliyun/api/coin/mapper/CoinMapper.java new file mode 100644 index 0000000..9941e2e --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/mapper/CoinMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.coin.mapper; + +import cn.sliyun.api.coin.entity.Coin; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 货币类型表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface CoinMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/coin/mapper/CoinPackageMapper.java b/src/main/java/cn/sliyun/api/coin/mapper/CoinPackageMapper.java new file mode 100644 index 0000000..b534fb1 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/mapper/CoinPackageMapper.java @@ -0,0 +1,29 @@ +package cn.sliyun.api.coin.mapper; + +import cn.sliyun.api.coin.entity.CoinPackage; +import cn.sliyun.api.member.entity.MemberCoinAddress; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * 算力包 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +public interface CoinPackageMapper extends BaseMapper { + + + /** + * @return + */ +// @Select("SELECT sly_coin_package.*,sly_coin.`cn_name` AS cnName ,sly_coin.`en_name` AS enName ,sly_coin.`img_oss_file` AS imgOssFile FROM sly_coin_package, sly_coin WHERE sly_coin_package.coin_id=sly_coin.id ") + @Select("SELECT sly_coin_package.* FROM sly_coin_package ") + List getList(); + + +} diff --git a/src/main/java/cn/sliyun/api/coin/mapper/CoinPackageUnitMapper.java b/src/main/java/cn/sliyun/api/coin/mapper/CoinPackageUnitMapper.java new file mode 100644 index 0000000..3ddb73f --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/mapper/CoinPackageUnitMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.coin.mapper; + +import cn.sliyun.api.coin.entity.CoinPackageUnit; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 算力包单位 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +public interface CoinPackageUnitMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/coin/service/ICoinPackageService.java b/src/main/java/cn/sliyun/api/coin/service/ICoinPackageService.java new file mode 100644 index 0000000..6f97c05 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/service/ICoinPackageService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.coin.service; + +import cn.sliyun.api.coin.entity.CoinPackage; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 算力包 服务类 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +public interface ICoinPackageService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/coin/service/ICoinPackageUnitService.java b/src/main/java/cn/sliyun/api/coin/service/ICoinPackageUnitService.java new file mode 100644 index 0000000..104bf89 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/service/ICoinPackageUnitService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.coin.service; + +import cn.sliyun.api.coin.entity.CoinPackageUnit; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 算力包单位 服务类 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +public interface ICoinPackageUnitService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/coin/service/ICoinService.java b/src/main/java/cn/sliyun/api/coin/service/ICoinService.java new file mode 100644 index 0000000..1d2e4d4 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/service/ICoinService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.coin.service; + +import cn.sliyun.api.coin.entity.Coin; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 货币类型表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface ICoinService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/coin/service/impl/CoinPackageServiceImpl.java b/src/main/java/cn/sliyun/api/coin/service/impl/CoinPackageServiceImpl.java new file mode 100644 index 0000000..a33bb61 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/service/impl/CoinPackageServiceImpl.java @@ -0,0 +1,47 @@ +package cn.sliyun.api.coin.service.impl; + +import com.alibaba.fastjson.JSON; +import cn.sliyun.api.coin.entity.CoinPackage; +import cn.sliyun.api.coin.mapper.CoinPackageMapper; +import cn.sliyun.api.coin.service.ICoinPackageService; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 算力包 服务实现类 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +@Service +public class CoinPackageServiceImpl extends ServiceImpl implements ICoinPackageService { + + public Result create(CoinPackage entity) { + System.out.println("create:"+JSON.toJSONString(entity)); + save(entity); + return ResultGenerator.genSuccessResult(entity.getId()); + } + + public Result edit(CoinPackage entity) { + System.out.println("edit:"+JSON.toJSONString(entity)); + updateById(entity); + return ResultGenerator.genSuccessResult(entity); + + } + + public Result delete(long id) { + removeById(id); + return ResultGenerator.genSuccessResult(); + + } + + public Result getList(int coinId) { + return ResultGenerator.genSuccessResult(list()); + + } +} diff --git a/src/main/java/cn/sliyun/api/coin/service/impl/CoinPackageUnitServiceImpl.java b/src/main/java/cn/sliyun/api/coin/service/impl/CoinPackageUnitServiceImpl.java new file mode 100644 index 0000000..d03072c --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/service/impl/CoinPackageUnitServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.coin.service.impl; + +import cn.sliyun.api.coin.entity.CoinPackageUnit; +import cn.sliyun.api.coin.mapper.CoinPackageUnitMapper; +import cn.sliyun.api.coin.service.ICoinPackageUnitService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 算力包单位 服务实现类 + *

+ * + * @author Enoch + * @since 2021-03-01 + */ +@Service +public class CoinPackageUnitServiceImpl extends ServiceImpl implements ICoinPackageUnitService { + +} diff --git a/src/main/java/cn/sliyun/api/coin/service/impl/CoinServiceImpl.java b/src/main/java/cn/sliyun/api/coin/service/impl/CoinServiceImpl.java new file mode 100644 index 0000000..fed10d3 --- /dev/null +++ b/src/main/java/cn/sliyun/api/coin/service/impl/CoinServiceImpl.java @@ -0,0 +1,74 @@ +package cn.sliyun.api.coin.service.impl; + +import cn.sliyun.api.coin.entity.Coin; +import cn.sliyun.api.coin.mapper.CoinMapper; +import cn.sliyun.api.coin.service.ICoinService; +import cn.sliyun.api.coin.entity.CoinAction; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * 货币类型表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class CoinServiceImpl extends ServiceImpl implements ICoinService { + + + public Result add(CoinAction coinAction) { + Coin coin = new Coin(); + BeanUtils.copyProperties(coinAction, coin); + baseMapper.insert(coin); + return ResultGenerator.genSuccessResult(); + } + + public Result edit(CoinAction coinAction) { + Coin mCoin = baseMapper.selectOne(new QueryWrapper().ge("id", coinAction.getId())); + if (mCoin == null) { + return ResultGenerator.genFailResult("货币类型不存在"); + } + BeanUtils.copyProperties(coinAction, mCoin); + baseMapper.update(mCoin, new UpdateWrapper<>()); + return ResultGenerator.genSuccessResult(); + } + + public Result delete(int deleteId) { + baseMapper.deleteById(deleteId); + return ResultGenerator.genSuccessResult("删除成功"); + } + + public Result getList(Integer pageIndex, Integer size) { + Page page = new Page<>(pageIndex, size); + Page userMyPage = page(page); + Map map = new HashMap(); + map.put("count", userMyPage.getTotal()); + map.put("page", userMyPage.getCurrent()); + map.put("list", userMyPage.getRecords()); + return ResultGenerator.genSuccessResult(map); + } + + public Result create(CoinAction action) { + Coin coin = new Coin(); + coin.setImgOssFile("" + action.getImgOssFile()); + coin.setCnName(action.getCnName()); + coin.setEnName(action.getEnName()); + coin.setCreateTime(LocalDateTime.now()); + coin.setUpdateTime(LocalDateTime.now()); + baseMapper.insert(coin); + return ResultGenerator.genSuccessResult(); + } +} diff --git a/src/main/java/cn/sliyun/api/member/controller/MemberCoinAddressController.java b/src/main/java/cn/sliyun/api/member/controller/MemberCoinAddressController.java new file mode 100644 index 0000000..6940059 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/controller/MemberCoinAddressController.java @@ -0,0 +1,46 @@ +package cn.sliyun.api.member.controller; + + +import cn.sliyun.api.member.service.impl.MemberCoinAddressServiceImpl; +import cn.sliyun.api.wallet.service.impl.AddressServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.web.bind.annotation.*; + +import org.springframework.stereotype.Controller; + +import javax.annotation.Resource; +import java.util.HashMap; + +/** + *

+ * 会员货币地址表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/address") +public class MemberCoinAddressController { + + + + @Resource + private MemberCoinAddressServiceImpl service; + + + @GetMapping("/list") + public Result getList() { + return service.getList(); + } + + + @PostMapping("/delete") + public Result create(@RequestBody HashMap map) { + return service.delete((Integer) map.get("id")); + } + + + + +} diff --git a/src/main/java/cn/sliyun/api/member/controller/MemberCoinRecordController.java b/src/main/java/cn/sliyun/api/member/controller/MemberCoinRecordController.java new file mode 100644 index 0000000..89df476 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/controller/MemberCoinRecordController.java @@ -0,0 +1,21 @@ +package cn.sliyun.api.member.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 会员挖矿记录表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/member/member-coin-record") +public class MemberCoinRecordController { + +} diff --git a/src/main/java/cn/sliyun/api/member/controller/MemberController.java b/src/main/java/cn/sliyun/api/member/controller/MemberController.java new file mode 100644 index 0000000..a6a00f6 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/controller/MemberController.java @@ -0,0 +1,74 @@ +package cn.sliyun.api.member.controller; + + +import cn.sliyun.api.member.service.impl.MemberServiceImpl; +import cn.sliyun.api.user.entity.UpdateUserEntity; +import cn.sliyun.api.user.entity.UserActionBean; +import cn.sliyun.api.user.service.impl.BeamUserServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import org.springframework.stereotype.Controller; + +import javax.annotation.Resource; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import java.util.Map; + +/** + *

+ * 会员表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/member") +public class MemberController { + @Resource + MemberServiceImpl beamUserService; + + @PostMapping("/register") + public Result register(@RequestBody @Valid UserActionBean register) { + return beamUserService.register(register); + } + + @PostMapping("/edit") + public Result edit(@RequestHeader @NotBlank String token, @RequestBody @Valid UpdateUserEntity user) { + return beamUserService.edit(token, user); + } + + @PostMapping("/updateStatus") + public Result edit(@RequestBody Map params) { + return beamUserService.updateStatus(params); + } + + + @PostMapping("/delete") + public Result delete(@RequestBody Map params) { + return beamUserService.onDelete(params); + } + + + + @GetMapping("/info") + public Result getInfo(@RequestHeader @NotBlank String token) { + return beamUserService.getInfo(token); + } + + @PostMapping("/updatePassword") + public Result updatePassword(@RequestBody @Valid UserActionBean actionBean) { + return beamUserService.updatePassword(actionBean); + } + + @GetMapping("/list") + public Result list(@RequestParam(defaultValue = "1") int pageNo,@RequestParam(defaultValue = "20") int pageSize) { + return beamUserService.getList(pageNo, pageSize); + } + + + + +} diff --git a/src/main/java/cn/sliyun/api/member/controller/MemberLevelController.java b/src/main/java/cn/sliyun/api/member/controller/MemberLevelController.java new file mode 100644 index 0000000..9d16a57 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/controller/MemberLevelController.java @@ -0,0 +1,21 @@ +package cn.sliyun.api.member.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 会员等级表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/member/member-level") +public class MemberLevelController { + +} diff --git a/src/main/java/cn/sliyun/api/member/controller/MemberLoginLogController.java b/src/main/java/cn/sliyun/api/member/controller/MemberLoginLogController.java new file mode 100644 index 0000000..c6729c3 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/controller/MemberLoginLogController.java @@ -0,0 +1,21 @@ +package cn.sliyun.api.member.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 会员登录记录 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/member/member-login-log") +public class MemberLoginLogController { + +} diff --git a/src/main/java/cn/sliyun/api/member/controller/MemberStatisticsInfoController.java b/src/main/java/cn/sliyun/api/member/controller/MemberStatisticsInfoController.java new file mode 100644 index 0000000..ce64375 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/controller/MemberStatisticsInfoController.java @@ -0,0 +1,21 @@ +package cn.sliyun.api.member.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 会员统计信息 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/member/member-statistics-info") +public class MemberStatisticsInfoController { + +} diff --git a/src/main/java/cn/sliyun/api/member/entity/Member.java b/src/main/java/cn/sliyun/api/member/entity/Member.java new file mode 100644 index 0000000..30a2ac2 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/entity/Member.java @@ -0,0 +1,278 @@ +package cn.sliyun.api.member.entity; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; + +import java.time.LocalDate; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 会员表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_member") +public class Member implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String memberSn; + + private Long memberLevelId; + + /** + * 用户名 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 昵称 + */ + private String nickname; + + /** + * 头像 + */ + @JsonIgnore + private String avatarOssFile; + + /** + * 手机号码 + */ + private String phone; + + /** + * 帐号启用状态:0->禁用;1->启用; 2->删除 + */ + private Integer status; + + /** + * 性别:0->未知;1->男;2->女 + */ + private Integer gender; + + /** + * 生日 + */ + private LocalDate birthday; + + /** + * 所做城市 + */ + private String city; + + /** + * 个性签名 + */ + private String personalizedSignature; + + /** + * 用户来源 + */ + private Integer sourceType; + + /** + * 0 正常 1 删除 + */ + private Integer isDelete; + /** + * 注册时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + + + + @TableField(exist = false) + private String avatar; + + + public String getAvatar() { + return AliyunOSSUtil.getInstance().getFileUrl(avatarOssFile); + } + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getMemberSn() { + return memberSn; + } + + public void setMemberSn(String memberSn) { + this.memberSn = memberSn; + } + + public Long getMemberLevelId() { + return memberLevelId; + } + + public void setMemberLevelId(Long memberLevelId) { + this.memberLevelId = memberLevelId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatarOssFile() { + return avatarOssFile; + } + + public void setAvatarOssFile(String avatarOssFile) { + this.avatarOssFile = avatarOssFile; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getGender() { + return gender; + } + + public void setGender(Integer gender) { + this.gender = gender; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getPersonalizedSignature() { + return personalizedSignature; + } + + public void setPersonalizedSignature(String personalizedSignature) { + this.personalizedSignature = personalizedSignature; + } + + public Integer getSourceType() { + return sourceType; + } + + public void setSourceType(Integer sourceType) { + this.sourceType = sourceType; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + public Integer getIsDelete() { + return isDelete; + } + + public void setIsDelete(Integer isDelete) { + this.isDelete = isDelete; + } + + @Override + public String toString() { + return "Member{" + + "id=" + id + + ", memberLevelId=" + memberLevelId + + ", username=" + username + + ", password=" + password + + ", nickname=" + nickname + + ", avatarOssFile=" + avatarOssFile + + ", phone=" + phone + + ", status=" + status + + ", gender=" + gender + + ", birthday=" + birthday + + ", city=" + city + + ", personalizedSignature=" + personalizedSignature + + ", sourceType=" + sourceType + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/member/entity/MemberCoinAddress.java b/src/main/java/cn/sliyun/api/member/entity/MemberCoinAddress.java new file mode 100644 index 0000000..79c6ce8 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/entity/MemberCoinAddress.java @@ -0,0 +1,164 @@ +package cn.sliyun.api.member.entity; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 会员货币地址表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_member_coin_address") +public class MemberCoinAddress implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 货币ID + */ + private Integer coinId; + + /** + * 用户ID + */ + private Integer memberId; + + /** + * 钱包地址 + */ + private String address; + + /** + * coin 描述 + */ + private String description; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + + /** + * 英文名称 + */ + @TableField(exist = false) + private String enName; + + /** + * 中文名称 + */ + @TableField(exist = false) + private String cnName; + + /** + * img name + */ + @JsonIgnore + private String imgOssFile; + + @TableField(exist = false) + public String icon ; + + public String getEnName() { + return enName; + } + + public void setEnName(String enName) { + this.enName = enName; + } + + public String getCnName() { + return cnName; + } + + public void setCnName(String cnName) { + this.cnName = cnName; + } + + public String getIcon() { + return AliyunOSSUtil.getInstance().getFileUrl(imgOssFile); + } + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public Integer getCoinId() { + return coinId; + } + + public void setCoinId(Integer coinId) { + this.coinId = coinId; + } + public Integer getMemberId() { + return memberId; + } + + public void setMemberId(Integer memberId) { + this.memberId = memberId; + } + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "MemberCoinAddress{" + + "id=" + id + + ", coinId=" + coinId + + ", memberId=" + memberId + + ", address=" + address + + ", description=" + description + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/member/entity/MemberCoinRecord.java b/src/main/java/cn/sliyun/api/member/entity/MemberCoinRecord.java new file mode 100644 index 0000000..3254fcf --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/entity/MemberCoinRecord.java @@ -0,0 +1,157 @@ +package cn.sliyun.api.member.entity; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 会员挖矿记录表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_member_coin_record") +public class MemberCoinRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 货币ID + */ + private Integer coinId; + + /** + * 用户ID + */ + private Long memberId; + + /** + * 钱包地址 + */ + private String address; + + /** + * 收益 + */ + private BigDecimal profit; + + /** + * 记录编号 + */ + private String recordSn; + + /** + * 订单编号 + */ + private String orderSn; + + /** + * 备注 + */ + private String remarks; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public Integer getCoinId() { + return coinId; + } + + public void setCoinId(Integer coinId) { + this.coinId = coinId; + } + public Long getMemberId() { + return memberId; + } + + public void setMemberId(Long memberId) { + this.memberId = memberId; + } + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + public BigDecimal getProfit() { + return profit; + } + + public void setProfit(BigDecimal profit) { + this.profit = profit; + } + public String getRecordSn() { + return recordSn; + } + + public void setRecordSn(String recordSn) { + this.recordSn = recordSn; + } + public String getOrderSn() { + return orderSn; + } + + public void setOrderSn(String orderSn) { + this.orderSn = orderSn; + } + public String getRemarks() { + return remarks; + } + + public void setRemarks(String remarks) { + this.remarks = remarks; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "MemberCoinRecord{" + + "id=" + id + + ", coinId=" + coinId + + ", memberId=" + memberId + + ", address=" + address + + ", profit=" + profit + + ", recordSn=" + recordSn + + ", orderSn=" + orderSn + + ", remarks=" + remarks + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/member/entity/MemberLevel.java b/src/main/java/cn/sliyun/api/member/entity/MemberLevel.java new file mode 100644 index 0000000..6cd34b2 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/entity/MemberLevel.java @@ -0,0 +1,160 @@ +package cn.sliyun.api.member.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 会员等级表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_member_level") +public class MemberLevel implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String name; + + private Integer growthPoint; + + /** + * 是否为默认等级:0->不是;1->是 + */ + private Integer defaultStatus; + + /** + * 是否有签到特权 + */ + private Integer priviledgeSignIn; + + /** + * 是否有专享活动特权 + */ + private Integer priviledgePromotion; + + /** + * 是否有会员价格特权 + */ + private Integer priviledgeMemberPrice; + + /** + * 是否有生日特权 + */ + private Integer priviledgeBirthday; + + private String note; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public Integer getGrowthPoint() { + return growthPoint; + } + + public void setGrowthPoint(Integer growthPoint) { + this.growthPoint = growthPoint; + } + public Integer getDefaultStatus() { + return defaultStatus; + } + + public void setDefaultStatus(Integer defaultStatus) { + this.defaultStatus = defaultStatus; + } + public Integer getPriviledgeSignIn() { + return priviledgeSignIn; + } + + public void setPriviledgeSignIn(Integer priviledgeSignIn) { + this.priviledgeSignIn = priviledgeSignIn; + } + public Integer getPriviledgePromotion() { + return priviledgePromotion; + } + + public void setPriviledgePromotion(Integer priviledgePromotion) { + this.priviledgePromotion = priviledgePromotion; + } + public Integer getPriviledgeMemberPrice() { + return priviledgeMemberPrice; + } + + public void setPriviledgeMemberPrice(Integer priviledgeMemberPrice) { + this.priviledgeMemberPrice = priviledgeMemberPrice; + } + public Integer getPriviledgeBirthday() { + return priviledgeBirthday; + } + + public void setPriviledgeBirthday(Integer priviledgeBirthday) { + this.priviledgeBirthday = priviledgeBirthday; + } + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "MemberLevel{" + + "id=" + id + + ", name=" + name + + ", growthPoint=" + growthPoint + + ", defaultStatus=" + defaultStatus + + ", priviledgeSignIn=" + priviledgeSignIn + + ", priviledgePromotion=" + priviledgePromotion + + ", priviledgeMemberPrice=" + priviledgeMemberPrice + + ", priviledgeBirthday=" + priviledgeBirthday + + ", note=" + note + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/member/entity/MemberLoginLog.java b/src/main/java/cn/sliyun/api/member/entity/MemberLoginLog.java new file mode 100644 index 0000000..2954681 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/entity/MemberLoginLog.java @@ -0,0 +1,118 @@ +package cn.sliyun.api.member.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 会员登录记录 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_member_login_log") +public class MemberLoginLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Long memberId; + + private String ip; + + private String city; + + /** + * 登录类型:0->PC;1->android;2->ios;3->小程序 + */ + private Integer loginType; + + private String province; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public Long getMemberId() { + return memberId; + } + + public void setMemberId(Long memberId) { + this.memberId = memberId; + } + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + public Integer getLoginType() { + return loginType; + } + + public void setLoginType(Integer loginType) { + this.loginType = loginType; + } + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "MemberLoginLog{" + + "id=" + id + + ", memberId=" + memberId + + ", ip=" + ip + + ", city=" + city + + ", loginType=" + loginType + + ", province=" + province + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/member/entity/MemberStatisticsInfo.java b/src/main/java/cn/sliyun/api/member/entity/MemberStatisticsInfo.java new file mode 100644 index 0000000..d6b675d --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/entity/MemberStatisticsInfo.java @@ -0,0 +1,141 @@ +package cn.sliyun.api.member.entity; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 会员统计信息 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_member_statistics_info") +public class MemberStatisticsInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Long memberId; + + /** + * 累计消费金额 + */ + private BigDecimal consumeAmount; + + /** + * 订单数量 + */ + private Integer orderCount; + + /** + * 登录次数 + */ + private Integer loginCount; + + /** + * 钱包地址数量 + */ + private Integer coinAddressCount; + + /** + * 最后一次下订单时间 + */ + private LocalDateTime recentOrderTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public Long getMemberId() { + return memberId; + } + + public void setMemberId(Long memberId) { + this.memberId = memberId; + } + public BigDecimal getConsumeAmount() { + return consumeAmount; + } + + public void setConsumeAmount(BigDecimal consumeAmount) { + this.consumeAmount = consumeAmount; + } + public Integer getOrderCount() { + return orderCount; + } + + public void setOrderCount(Integer orderCount) { + this.orderCount = orderCount; + } + public Integer getLoginCount() { + return loginCount; + } + + public void setLoginCount(Integer loginCount) { + this.loginCount = loginCount; + } + public Integer getCoinAddressCount() { + return coinAddressCount; + } + + public void setCoinAddressCount(Integer coinAddressCount) { + this.coinAddressCount = coinAddressCount; + } + public LocalDateTime getRecentOrderTime() { + return recentOrderTime; + } + + public void setRecentOrderTime(LocalDateTime recentOrderTime) { + this.recentOrderTime = recentOrderTime; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "MemberStatisticsInfo{" + + "id=" + id + + ", memberId=" + memberId + + ", consumeAmount=" + consumeAmount + + ", orderCount=" + orderCount + + ", loginCount=" + loginCount + + ", coinAddressCount=" + coinAddressCount + + ", recentOrderTime=" + recentOrderTime + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/member/mapper/MemberCoinAddressMapper.java b/src/main/java/cn/sliyun/api/member/mapper/MemberCoinAddressMapper.java new file mode 100644 index 0000000..407532e --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/mapper/MemberCoinAddressMapper.java @@ -0,0 +1,26 @@ +package cn.sliyun.api.member.mapper; + +import cn.sliyun.api.member.entity.MemberCoinAddress; +import cn.sliyun.api.wallet.entity.Address; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * 会员货币地址表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface MemberCoinAddressMapper extends BaseMapper { + + + /** + * @return + */ + @Select("SELECT sly_member_coin_address.*,sly_coin.`cn_name` AS cnName ,sly_coin.`en_name` AS enName ,sly_coin.`img_oss_file` AS imgOssFile FROM sly_member_coin_address, sly_coin WHERE sly_member_coin_address.coin_id=sly_coin.id ") + List getAddressList(); +} diff --git a/src/main/java/cn/sliyun/api/member/mapper/MemberCoinRecordMapper.java b/src/main/java/cn/sliyun/api/member/mapper/MemberCoinRecordMapper.java new file mode 100644 index 0000000..be45d67 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/mapper/MemberCoinRecordMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.mapper; + +import cn.sliyun.api.member.entity.MemberCoinRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 会员挖矿记录表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface MemberCoinRecordMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/member/mapper/MemberLevelMapper.java b/src/main/java/cn/sliyun/api/member/mapper/MemberLevelMapper.java new file mode 100644 index 0000000..c833259 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/mapper/MemberLevelMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.mapper; + +import cn.sliyun.api.member.entity.MemberLevel; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 会员等级表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface MemberLevelMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/member/mapper/MemberLoginLogMapper.java b/src/main/java/cn/sliyun/api/member/mapper/MemberLoginLogMapper.java new file mode 100644 index 0000000..dcca76e --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/mapper/MemberLoginLogMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.mapper; + +import cn.sliyun.api.member.entity.MemberLoginLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 会员登录记录 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface MemberLoginLogMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/member/mapper/MemberMapper.java b/src/main/java/cn/sliyun/api/member/mapper/MemberMapper.java new file mode 100644 index 0000000..efec93c --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/mapper/MemberMapper.java @@ -0,0 +1,26 @@ +package cn.sliyun.api.member.mapper; + +import cn.sliyun.api.member.entity.Member; +import cn.sliyun.api.wallet.entity.Address; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * 会员表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface MemberMapper extends BaseMapper { + + /** + * @return + */ + @Select(" SELECT * FROM sly_member WHERE YEARWEEK(DATE_FORMAT(create_time,'%Y-%m-%d')) = YEARWEEK(NOW());") + List
getWeekList(); + +} diff --git a/src/main/java/cn/sliyun/api/member/mapper/MemberStatisticsInfoMapper.java b/src/main/java/cn/sliyun/api/member/mapper/MemberStatisticsInfoMapper.java new file mode 100644 index 0000000..1b8ffa0 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/mapper/MemberStatisticsInfoMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.mapper; + +import cn.sliyun.api.member.entity.MemberStatisticsInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 会员统计信息 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface MemberStatisticsInfoMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/IMemberCoinAddressService.java b/src/main/java/cn/sliyun/api/member/service/IMemberCoinAddressService.java new file mode 100644 index 0000000..dbe8820 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/IMemberCoinAddressService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.service; + +import cn.sliyun.api.member.entity.MemberCoinAddress; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 会员货币地址表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IMemberCoinAddressService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/IMemberCoinRecordService.java b/src/main/java/cn/sliyun/api/member/service/IMemberCoinRecordService.java new file mode 100644 index 0000000..2d2eadc --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/IMemberCoinRecordService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.service; + +import cn.sliyun.api.member.entity.MemberCoinRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 会员挖矿记录表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IMemberCoinRecordService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/IMemberLevelService.java b/src/main/java/cn/sliyun/api/member/service/IMemberLevelService.java new file mode 100644 index 0000000..cec71c1 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/IMemberLevelService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.service; + +import cn.sliyun.api.member.entity.MemberLevel; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 会员等级表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IMemberLevelService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/IMemberLoginLogService.java b/src/main/java/cn/sliyun/api/member/service/IMemberLoginLogService.java new file mode 100644 index 0000000..1cf96a0 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/IMemberLoginLogService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.service; + +import cn.sliyun.api.member.entity.MemberLoginLog; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 会员登录记录 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IMemberLoginLogService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/IMemberService.java b/src/main/java/cn/sliyun/api/member/service/IMemberService.java new file mode 100644 index 0000000..3bc5b10 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/IMemberService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.service; + +import cn.sliyun.api.member.entity.Member; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 会员表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IMemberService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/IMemberStatisticsInfoService.java b/src/main/java/cn/sliyun/api/member/service/IMemberStatisticsInfoService.java new file mode 100644 index 0000000..bb64b1e --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/IMemberStatisticsInfoService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.member.service; + +import cn.sliyun.api.member.entity.MemberStatisticsInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 会员统计信息 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IMemberStatisticsInfoService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/impl/MemberCoinAddressServiceImpl.java b/src/main/java/cn/sliyun/api/member/service/impl/MemberCoinAddressServiceImpl.java new file mode 100644 index 0000000..def7c8b --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/impl/MemberCoinAddressServiceImpl.java @@ -0,0 +1,31 @@ +package cn.sliyun.api.member.service.impl; + +import cn.sliyun.api.member.entity.MemberCoinAddress; +import cn.sliyun.api.member.mapper.MemberCoinAddressMapper; +import cn.sliyun.api.member.service.IMemberCoinAddressService; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 会员货币地址表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class MemberCoinAddressServiceImpl extends ServiceImpl implements IMemberCoinAddressService { + public Result getList() { + return ResultGenerator.genSuccessResult(baseMapper.getAddressList()); + } + + + public Result delete(Integer id) { + removeById(id); + return ResultGenerator.genSuccessResult(); + + } +} diff --git a/src/main/java/cn/sliyun/api/member/service/impl/MemberCoinRecordServiceImpl.java b/src/main/java/cn/sliyun/api/member/service/impl/MemberCoinRecordServiceImpl.java new file mode 100644 index 0000000..93aaacd --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/impl/MemberCoinRecordServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.member.service.impl; + +import cn.sliyun.api.member.entity.MemberCoinRecord; +import cn.sliyun.api.member.mapper.MemberCoinRecordMapper; +import cn.sliyun.api.member.service.IMemberCoinRecordService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 会员挖矿记录表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class MemberCoinRecordServiceImpl extends ServiceImpl implements IMemberCoinRecordService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/impl/MemberLevelServiceImpl.java b/src/main/java/cn/sliyun/api/member/service/impl/MemberLevelServiceImpl.java new file mode 100644 index 0000000..d18bab3 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/impl/MemberLevelServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.member.service.impl; + +import cn.sliyun.api.member.entity.MemberLevel; +import cn.sliyun.api.member.mapper.MemberLevelMapper; +import cn.sliyun.api.member.service.IMemberLevelService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 会员等级表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class MemberLevelServiceImpl extends ServiceImpl implements IMemberLevelService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/impl/MemberLoginLogServiceImpl.java b/src/main/java/cn/sliyun/api/member/service/impl/MemberLoginLogServiceImpl.java new file mode 100644 index 0000000..706bb60 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/impl/MemberLoginLogServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.member.service.impl; + +import cn.sliyun.api.member.entity.MemberLoginLog; +import cn.sliyun.api.member.mapper.MemberLoginLogMapper; +import cn.sliyun.api.member.service.IMemberLoginLogService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 会员登录记录 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class MemberLoginLogServiceImpl extends ServiceImpl implements IMemberLoginLogService { + +} diff --git a/src/main/java/cn/sliyun/api/member/service/impl/MemberServiceImpl.java b/src/main/java/cn/sliyun/api/member/service/impl/MemberServiceImpl.java new file mode 100644 index 0000000..fb4d2ca --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/impl/MemberServiceImpl.java @@ -0,0 +1,149 @@ +package cn.sliyun.api.member.service.impl; + +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.IdUtil; +import cn.sliyun.common.utils.RegUtil; +import cn.sliyun.api.member.entity.Member; +import cn.sliyun.api.member.mapper.MemberMapper; +import cn.sliyun.api.member.service.IMemberService; +import cn.sliyun.api.user.entity.UpdateUserEntity; +import cn.sliyun.api.user.entity.UserActionBean; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * 会员表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class MemberServiceImpl extends ServiceImpl implements IMemberService { + + + public Result register(UserActionBean userRegister) { + if (!RegUtil.checkMobile(userRegister.getPhone())) { + throw new AppException("手机号不正确"); + } + System.out.println("phone:" + userRegister.getPhone()); + Member user = baseMapper.selectOne(new QueryWrapper().eq("phone", userRegister.getPhone())); + if (user != null) { + System.out.println("phone:" + user.getUsername() + "/" + user.getPhone()); + throw new AppException("手机号已经注册"); + } + + Member member = new Member(); + member.setMemberSn("" + IdUtil.create()); + member.setNickname(StringUtils.isEmpty(userRegister.getName()) ? IdUtil.genNickname() : userRegister.getName() + ""); + member.setUsername(StringUtils.isEmpty(userRegister.getName()) ? IdUtil.genNickname() : userRegister.getName() + ""); + + if (StringUtils.isEmpty(userRegister.getOssFile())) { + member.setAvatarOssFile(Constants.IMG_DEFAULT_USER_AVATAR); + } else { + member.setAvatarOssFile(userRegister.getOssFile()); + } + member.setPhone(userRegister.getPhone()); + + member.setPassword(userRegister.getPassword()); + member.setCreateTime(LocalDateTime.now()); + member.setUpdateTime(LocalDateTime.now()); + member.setSourceType(1); + int id = baseMapper.insert(member); + return ResultGenerator.genSuccessResult(id); + } + + public Result edit(String token, UpdateUserEntity updateUser) { + Member user = baseMapper.selectOne(new QueryWrapper().ge("token", token)); + if (user == null) { + return ResultGenerator.genFailResult("用户不存在"); + } + BeanUtils.copyProperties(updateUser, user); + baseMapper.update(user, new UpdateWrapper<>()); + return ResultGenerator.genSuccessResult(); + } + + public Result getInfo(String token) { + Member user = baseMapper.selectOne(new QueryWrapper().eq("token", token)); + if (user == null) { + throw new AppException("用户不存在"); + } + return ResultGenerator.genSuccessResult(user); + } + + + public Result updatePassword(UserActionBean updateUser) { + Member user = baseMapper.selectOne(new QueryWrapper().eq("phone", updateUser.getPhone())); + if (user == null) { + throw new AppException("用户不存在"); + } + user.setPassword(updateUser.getPassword()); + baseMapper.update(user, new UpdateWrapper<>()); + return ResultGenerator.genSuccessResult(user); + } + + public Result getList(Integer pageIndex, Integer size) { + System.out.println(pageIndex + "/" + size); + Page page = new Page<>(pageIndex, size); + QueryWrapper queryWrapper = new QueryWrapper(); + queryWrapper.eq("is_delete", 0); + Page userMyPage = baseMapper.selectPage(page, queryWrapper); + Map map = new HashMap(); + map.put("totalCount", userMyPage.getTotal()); + map.put("totalPage", userMyPage.getPages()); + map.put("pageNo", userMyPage.getCurrent()); + map.put("pageSize", size); + map.put("data", userMyPage.getRecords()); + return ResultGenerator.genSuccessResult(map); + } + + + public Result updateStatus(Map params) { + Member user = baseMapper.selectOne(new QueryWrapper().eq("id", params.get("id"))); + if (user == null) { + throw new AppException("用户不存在"); + } + user.setStatus((Integer) params.get("status")); + baseMapper.updateById(user); + return ResultGenerator.genSuccessResult(); + } + + public Result onDelete(Map params) { + Member user = baseMapper.selectOne(new QueryWrapper().eq("id", params.get("id"))); + if (user == null) { + throw new AppException("用户不存在"); + } + user.setIsDelete(1); + baseMapper.updateById(user); + return ResultGenerator.genSuccessResult(); + } + + + public Member getLoginUserInfo(String token) { + Member member = baseMapper.selectOne(new QueryWrapper().eq("token", token)); + if (member == null) { + throw new AppException("请先登录"); + } + + return member; + } + + public long getCount() { + return count(); + } + + +} diff --git a/src/main/java/cn/sliyun/api/member/service/impl/MemberStatisticsInfoServiceImpl.java b/src/main/java/cn/sliyun/api/member/service/impl/MemberStatisticsInfoServiceImpl.java new file mode 100644 index 0000000..cb52344 --- /dev/null +++ b/src/main/java/cn/sliyun/api/member/service/impl/MemberStatisticsInfoServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.member.service.impl; + +import cn.sliyun.api.member.entity.MemberStatisticsInfo; +import cn.sliyun.api.member.mapper.MemberStatisticsInfoMapper; +import cn.sliyun.api.member.service.IMemberStatisticsInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 会员统计信息 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class MemberStatisticsInfoServiceImpl extends ServiceImpl implements IMemberStatisticsInfoService { + +} diff --git a/src/main/java/cn/sliyun/api/order/controller/OrderController.java b/src/main/java/cn/sliyun/api/order/controller/OrderController.java new file mode 100644 index 0000000..3540d71 --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/controller/OrderController.java @@ -0,0 +1,58 @@ +package cn.sliyun.api.order.controller; + + +import cn.sliyun.api.member.service.impl.MemberCoinAddressServiceImpl; +import cn.sliyun.api.order.entity.Order; +import cn.sliyun.api.order.service.impl.OrderServiceImpl; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.springframework.web.bind.annotation.*; + +import org.springframework.stereotype.Controller; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * 订单表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/order") +public class OrderController { + @Resource + private OrderServiceImpl orderService; + + @GetMapping("/list") + public Result list(@RequestParam(defaultValue = "1",required = false) int pageNo, @RequestParam(defaultValue = "20" ,required = false) int pageSize) { + Page page = new Page<>(pageNo,pageSize); + orderService.page(page); + Map map = new HashMap(); + map.put("totalCount", page.getTotal()); + map.put("totalPage", page.getPages()); + map.put("pageNo", page.getCurrent()); + map.put("pageSize", page); + map.put("data", page.getRecords()); + return ResultGenerator.genSuccessResult(map); + } + + + @PostMapping("/confirmPayment") + public Result confirmPayment(@RequestBody Map params) { + return orderService.confirmPayment(params.get("orderSn")); + } + + + @PostMapping("/updatePayPrice") + public Result updatePayPrice(@RequestBody Map params) { + return orderService.updatePayPrice(params); + } + + +} diff --git a/src/main/java/cn/sliyun/api/order/controller/OrderOperateHistoryController.java b/src/main/java/cn/sliyun/api/order/controller/OrderOperateHistoryController.java new file mode 100644 index 0000000..194e3b0 --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/controller/OrderOperateHistoryController.java @@ -0,0 +1,21 @@ +package cn.sliyun.api.order.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 订单操作历史记录 前端控制器 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@RestController +@RequestMapping("/order/order-operate-history") +public class OrderOperateHistoryController { + +} diff --git a/src/main/java/cn/sliyun/api/order/entity/Order.java b/src/main/java/cn/sliyun/api/order/entity/Order.java new file mode 100644 index 0000000..bd0f41d --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/entity/Order.java @@ -0,0 +1,423 @@ +package cn.sliyun.api.order.entity; + +import java.math.BigDecimal; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 订单表 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_order") +public class Order implements Serializable { + + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Integer memberId; + + + /** + * 订单编号 + */ + private String orderSn; + + /** + * 用户帐号 + */ + private String memberSn; + + /** + * 订单总金额 + */ + private BigDecimal totalAmount; + + /** + * 应付金额(实际支付金额) + */ + private BigDecimal payAmount; + + /** + * 管理员后台调整订单使用的折扣金额 + */ + @JsonIgnore + private BigDecimal discountAmount; + + /** + * 支付方式:0->未支付;1->支付宝;2->微信 + */ + private Integer payType=0; + + @TableField(exist = false) + private String payTypeName; + + /** + * 订单来源:0->PC订单;1->app订单; 2> web 订单 + */ + private Integer sourceType; + + @TableField(exist = false) + private String sourceTypeName; + + /** + * 订单状态:0->待付款;1->待进行;2->进行中;3->已完成;4->已关闭;5->无效订单 + */ + private Integer status; + + + @TableField(exist = false) + private String statusName; + + /** + * 订单类型:0->正常订单; + */ + private Integer orderType; + + + /** + * 货币ID + */ + private Integer coinId; + + /** + * 钱包地址 + */ + private Long coinAddressId; + + /** + * 订单图片 + */ + @JsonIgnore + private String ossImg; + + /** + * 购买时长 + */ + private long duration; + + /** + * 规格包 + */ + private Integer sukId; + + /** + * 租赁状态(0 待进行 1 进行中 2 已完成 ) + */ + private String leaseStatus; + + /** + * 租用开始时间 + */ + private LocalDateTime leaseStartTime; + + /** + * 租用结束时间 + */ + private LocalDateTime leaseEndTime; + + /** + * 支付时间 + */ + private LocalDateTime paymentTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * remarks + */ + private String remarks; + + + @TableField(exist = false) + public String icon; + + + public String getStatusName() { + if (status == 0) { + return "待付款"; + } else if (status == 1) { + return "待进行"; + } else if (status == 2) { + return "进行中"; + } else if (status == 3) { + return "已完成"; + } else if (status == 4) { + return "已关闭"; + } else { + return "无效订单"; + } + } + + public String getPayTypeName() { + if (payType == 0) { + return "未支付"; + } else if (payType == 1) { + return "支付宝"; + } else if (payType == 2) { + return "微信"; + } else if (payType == 3) { + return "后台确认"; + } else { + return "未支付"; + } + } + + public String getSourceTypeName() { + if (orderType == 0) { + return "PC"; + } else if (status == 1) { + return "APP"; + } else if (status == 2) { + return "H5"; + } + return "未知来源"; + } + + public String getIcon() { + return AliyunOSSUtil.getInstance().getFileUrl(ossImg); + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Integer getMemberId() { + return memberId; + } + + public void setMemberId(Integer memberId) { + this.memberId = memberId; + } + + public String getOrderSn() { + return orderSn; + } + + public void setOrderSn(String orderSn) { + this.orderSn = orderSn; + } + + + public String getMemberSn() { + return memberSn; + } + + public void setMemberSn(String memberSn) { + this.memberSn = memberSn; + } + + public BigDecimal getTotalAmount() { + return totalAmount; + } + + public void setTotalAmount(BigDecimal totalAmount) { + this.totalAmount = totalAmount; + } + + public BigDecimal getPayAmount() { + return payAmount; + } + + public void setPayAmount(BigDecimal payAmount) { + this.payAmount = payAmount; + } + + public BigDecimal getDiscountAmount() { + return discountAmount; + } + + public void setDiscountAmount(BigDecimal discountAmount) { + this.discountAmount = discountAmount; + } + + public Integer getPayType() { + return payType; + } + + public void setPayType(Integer payType) { + this.payType = payType; + } + + public Integer getSourceType() { + return sourceType; + } + + public void setSourceType(Integer sourceType) { + this.sourceType = sourceType; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getOrderType() { + return orderType; + } + + public void setOrderType(Integer orderType) { + this.orderType = orderType; + } + + public Integer getCoinId() { + return coinId; + } + + public void setCoinId(Integer coinId) { + this.coinId = coinId; + } + + public Long getCoinAddressId() { + return coinAddressId; + } + + public void setCoinAddressId(Long coinAddressId) { + this.coinAddressId = coinAddressId; + } + + public String getOssImg() { + return ossImg; + } + + public void setOssImg(String ossImg) { + this.ossImg = ossImg; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public Integer getSukId() { + return sukId; + } + + public void setSukId(Integer suk) { + this.sukId = suk; + } + + public String getLeaseStatus() { + return leaseStatus; + } + + public void setLeaseStatus(String leaseStatus) { + this.leaseStatus = leaseStatus; + } + + public LocalDateTime getLeaseStartTime() { + return leaseStartTime; + } + + public void setLeaseStartTime(LocalDateTime leaseStartTime) { + this.leaseStartTime = leaseStartTime; + } + + public LocalDateTime getLeaseEndTime() { + return leaseEndTime; + } + + public void setLeaseEndTime(LocalDateTime leaseEndTime) { + this.leaseEndTime = leaseEndTime; + } + + public LocalDateTime getPaymentTime() { + return paymentTime; + } + + public void setPaymentTime(LocalDateTime paymentTime) { + this.paymentTime = paymentTime; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + public String getRemarks() { + return remarks; + } + + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + @Override + public String toString() { + return "Order{" + + "id=" + id + + ", memberId=" + memberId + + ", orderSn=" + orderSn + + ", memberSn=" + memberSn + + ", totalAmount=" + totalAmount + + ", payAmount=" + payAmount + + ", discountAmount=" + discountAmount + + ", payType=" + payType + + ", sourceType=" + sourceType + + ", status=" + status + + ", orderType=" + orderType + + ", coinId=" + coinId + + ", coinAddress=" + coinAddressId + + ", ossImg=" + ossImg + + ", duration=" + duration + + ", sukId=" + sukId + + ", leaseStatus=" + leaseStatus + + ", leaseStartTime=" + leaseStartTime + + ", leaseEndTime=" + leaseEndTime + + ", paymentTime=" + paymentTime + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + ", remarks=" + remarks + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/order/entity/OrderOperateHistory.java b/src/main/java/cn/sliyun/api/order/entity/OrderOperateHistory.java new file mode 100644 index 0000000..515b72e --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/entity/OrderOperateHistory.java @@ -0,0 +1,117 @@ +package cn.sliyun.api.order.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 订单操作历史记录 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@TableName("sly_order_operate_history") +public class OrderOperateHistory implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 订单id + */ + private Long orderId; + + /** + * 操作人:用户;系统;后台管理员 + */ + private String operateMan; + + /** + * 订单状态:0->待付款;1->待进行;2->进行中;3->已完成;4->已关闭;5->无效订单 + */ + private Integer orderStatus; + + /** + * 备注 + */ + private String note; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 操作时间 + */ + private LocalDateTime updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public Long getOrderId() { + return orderId; + } + + public void setOrderId(Long orderId) { + this.orderId = orderId; + } + public String getOperateMan() { + return operateMan; + } + + public void setOperateMan(String operateMan) { + this.operateMan = operateMan; + } + public Integer getOrderStatus() { + return orderStatus; + } + + public void setOrderStatus(Integer orderStatus) { + this.orderStatus = orderStatus; + } + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "OrderOperateHistory{" + + "id=" + id + + ", orderId=" + orderId + + ", operateMan=" + operateMan + + ", orderStatus=" + orderStatus + + ", note=" + note + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/order/mapper/OrderMapper.java b/src/main/java/cn/sliyun/api/order/mapper/OrderMapper.java new file mode 100644 index 0000000..c230a08 --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/mapper/OrderMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.order.mapper; + +import cn.sliyun.api.order.entity.Order; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface OrderMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/order/mapper/OrderOperateHistoryMapper.java b/src/main/java/cn/sliyun/api/order/mapper/OrderOperateHistoryMapper.java new file mode 100644 index 0000000..7b1ec2d --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/mapper/OrderOperateHistoryMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.order.mapper; + +import cn.sliyun.api.order.entity.OrderOperateHistory; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单操作历史记录 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface OrderOperateHistoryMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/order/service/IOrderOperateHistoryService.java b/src/main/java/cn/sliyun/api/order/service/IOrderOperateHistoryService.java new file mode 100644 index 0000000..899ceb0 --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/service/IOrderOperateHistoryService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.order.service; + +import cn.sliyun.api.order.entity.OrderOperateHistory; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 订单操作历史记录 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IOrderOperateHistoryService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/order/service/IOrderService.java b/src/main/java/cn/sliyun/api/order/service/IOrderService.java new file mode 100644 index 0000000..3a5a442 --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/service/IOrderService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.order.service; + +import cn.sliyun.api.order.entity.Order; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 订单表 服务类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +public interface IOrderService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/order/service/impl/OrderOperateHistoryServiceImpl.java b/src/main/java/cn/sliyun/api/order/service/impl/OrderOperateHistoryServiceImpl.java new file mode 100644 index 0000000..a4211a9 --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/service/impl/OrderOperateHistoryServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.order.service.impl; + +import cn.sliyun.api.order.entity.OrderOperateHistory; +import cn.sliyun.api.order.mapper.OrderOperateHistoryMapper; +import cn.sliyun.api.order.service.IOrderOperateHistoryService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单操作历史记录 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class OrderOperateHistoryServiceImpl extends ServiceImpl implements IOrderOperateHistoryService { + +} diff --git a/src/main/java/cn/sliyun/api/order/service/impl/OrderServiceImpl.java b/src/main/java/cn/sliyun/api/order/service/impl/OrderServiceImpl.java new file mode 100644 index 0000000..d7799de --- /dev/null +++ b/src/main/java/cn/sliyun/api/order/service/impl/OrderServiceImpl.java @@ -0,0 +1,60 @@ +package cn.sliyun.api.order.service.impl; + +import cn.sliyun.api.order.entity.Order; +import cn.sliyun.api.order.mapper.OrderMapper; +import cn.sliyun.api.order.service.IOrderService; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.StringUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.Map; + +/** + *

+ * 订单表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-02-24 + */ +@Service +public class OrderServiceImpl extends ServiceImpl implements IOrderService { + + + public Result confirmPayment(String orderSn) { + System.out.println("orderSn:" + orderSn); + Order order = baseMapper.selectOne(new QueryWrapper().eq("order_sn", orderSn)); + if (order == null) { + throw new AppException("订单不存在"); + } + order.setPayType(3); + order.setStatus(1); + order.setRemarks("后台确认支付"); + updateById(order); + return ResultGenerator.genSuccessResult(); + } + + + + public Result updatePayPrice(Map params) { + String orderSn = params.get("orderSn"); + Order order = baseMapper.selectOne(new QueryWrapper().eq("order_sn", orderSn)); + if (order == null) { + throw new AppException("订单不存在"); + } + BigDecimal price = new BigDecimal(params.get("price")); + order.setPayAmount(price); + if (StringUtils.isEmpty(order.getRemarks())){ + order.setRemarks(params.get("remarks")); + }else { + order.setRemarks(order.getRemarks()+"|"+params.get("remarks")); + } + updateById(order); + return ResultGenerator.genSuccessResult(); + } +} diff --git a/src/main/java/cn/sliyun/api/user/controller/BeamUserController.java b/src/main/java/cn/sliyun/api/user/controller/BeamUserController.java new file mode 100644 index 0000000..9e651fe --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/controller/BeamUserController.java @@ -0,0 +1,62 @@ +package cn.sliyun.api.user.controller; + + +import cn.sliyun.api.user.entity.UpdateUserEntity; +import cn.sliyun.api.user.service.impl.BeamUserServiceImpl; +import cn.sliyun.api.user.entity.UserActionBean; +import cn.sliyun.common.core.Result; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import java.util.Map; + +/** + *

+ * 用户表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-01-28 + */ +@RestController +@RequestMapping("/sys/user") +public class BeamUserController { + + @Autowired + BeamUserServiceImpl beamUserService; + + @PostMapping("/register") + public Result register(@RequestBody @Valid UserActionBean register) { + return beamUserService.register(register); + } + + @PostMapping("/edit") + public Result edit(@RequestHeader @NotBlank String token, @RequestBody @Valid UpdateUserEntity user) { + return beamUserService.edit(token, user); + } + + @PostMapping("/updateStatus") + public Result edit(@RequestBody Map params) { + return beamUserService.updateStatus(params); + } + + + + @GetMapping("/info") + public Result getInfo(@RequestHeader @NotBlank String token) { + return beamUserService.getInfo(token); + } + + @PostMapping("/updatePassword") + public Result updatePassword(@RequestBody @Valid UserActionBean actionBean) { + return beamUserService.updatePassword(actionBean); + } + + @GetMapping("/list") + public Result list(@RequestParam(defaultValue = "1") int pageNo,@RequestParam(defaultValue = "20") int pageSize) { + return beamUserService.getList(pageNo, pageSize); + } + +} diff --git a/src/main/java/cn/sliyun/api/user/entity/BeamUser.java b/src/main/java/cn/sliyun/api/user/entity/BeamUser.java new file mode 100644 index 0000000..f09ac9a --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/entity/BeamUser.java @@ -0,0 +1,278 @@ +package cn.sliyun.api.user.entity; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.commons.lang.StringUtils; + +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + *

+ * 用户表 + *

+ * + * @author Enoch + * @since 2021-01-28 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class BeamUser implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + /** + * 头像 + */ + private String avatar="img_coin_1612004588012.png"; + + /** + * 账号 + */ + private String account; + + /** + * 密码 + */ + private String password; + + /** + * md5密码盐 + */ + @JsonIgnore + private String salt; + + /** + * 名字 + */ + private String name; + + /** + * 生日 + */ + private LocalDateTime birthday; + + /** + * 性别(1:男 2:女) + */ + private String sex; + + /** + * 电子邮件 + */ + private String mail; + + /** + * 电话 + */ + private String phone; + + /** + * 状态(1:启用 2:冻结 3:删除) + */ + private String status; + + /** + * 创建人 + */ + @JsonIgnore + private String createdBy; + + /** + * 创建时间 + */ + @JsonIgnore + private LocalDateTime createdTime; + + /** + * 创建时间 + */ + @TableField(exist=false) + private String registerTime; + + + /** + * 更新人 + */ + @JsonIgnore + private String updateBy; + + /** + * 更新时间 + */ + @JsonIgnore + private LocalDateTime updateTime; + + /** + * Token + */ + private String token; + + /** + * 保留字段 + */ + @JsonIgnore + private Integer version; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getRegisterTime() { + DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return dtf2.format(createdTime); + } + + public void setRegisterTime(String registerTime) { + this.registerTime = registerTime; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getAvatar() { + return AliyunOSSUtil.getInstance().getFileUrl(avatar); + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getSalt() { + return salt; + } + + public void setSalt(String salt) { + this.salt = salt; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public LocalDateTime getBirthday() { + return birthday; + } + + public void setBirthday(LocalDateTime birthday) { + this.birthday = birthday; + } + + public String getSex() { + return sex; + } + + public void setSex(String sex) { + this.sex = sex; + } + + public String getMail() { + return mail; + } + + public void setMail(String mail) { + this.mail = mail; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + + public String getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public LocalDateTime getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(LocalDateTime createdTime) { + this.createdTime = createdTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } +} diff --git a/src/main/java/cn/sliyun/api/user/entity/SysUser.java b/src/main/java/cn/sliyun/api/user/entity/SysUser.java new file mode 100644 index 0000000..d06af50 --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/entity/SysUser.java @@ -0,0 +1,24 @@ +package cn.sliyun.api.user.entity; + +public class SysUser extends BeamUser{ + + private int count; + private int page; + + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public int getPage() { + return page; + } + + public void setPage(int page) { + this.page = page; + } +} diff --git a/src/main/java/cn/sliyun/api/user/entity/UpdateUserEntity.java b/src/main/java/cn/sliyun/api/user/entity/UpdateUserEntity.java new file mode 100644 index 0000000..57509e8 --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/entity/UpdateUserEntity.java @@ -0,0 +1,112 @@ +package cn.sliyun.api.user.entity; + +import java.time.LocalDateTime; + +public class UpdateUserEntity { + + /** + * 头像 + */ + private String avatar; + + /** + * 账号 + */ + private String account; + + /** + * 密码 + */ + private String password; + + + /** + * 名字 + */ + private String name; + + /** + * 生日 + */ + private LocalDateTime birthday; + + /** + * 性别(1:男 2:女) + */ + private String sex; + + /** + * 电子邮件 + */ + private String mail; + + /** + * 电话 + */ + private String phone; + + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public LocalDateTime getBirthday() { + return birthday; + } + + public void setBirthday(LocalDateTime birthday) { + this.birthday = birthday; + } + + public String getSex() { + return sex; + } + + public void setSex(String sex) { + this.sex = sex; + } + + public String getMail() { + return mail; + } + + public void setMail(String mail) { + this.mail = mail; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/src/main/java/cn/sliyun/api/user/entity/UserActionBean.java b/src/main/java/cn/sliyun/api/user/entity/UserActionBean.java new file mode 100644 index 0000000..9d4912c --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/entity/UserActionBean.java @@ -0,0 +1,62 @@ +package cn.sliyun.api.user.entity; + + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Valid +public class UserActionBean { + + + @NotBlank(message = "手机号不能为空") + private String phone; + @Size(max = 20, min = 6 ,message = "密码长度最低为6位") + private String password; + private String code=""; + private String name; + private String ossFile; + + public String getOssFile() { + return ossFile; + } + + public void setOssFile(String ossFile) { + this.ossFile = ossFile; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/cn/sliyun/api/user/entity/UserPasswordBean.java b/src/main/java/cn/sliyun/api/user/entity/UserPasswordBean.java new file mode 100644 index 0000000..b1e3921 --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/entity/UserPasswordBean.java @@ -0,0 +1,25 @@ +package cn.sliyun.api.user.entity; + +import javax.validation.Valid; +import javax.validation.constraints.Size; + +@Valid +public class UserPasswordBean { + + /** + * 密码 + */ + @Size(min = 6, max = 25) + private String password; + + + + + public void setPassword(String password) { + this.password = password; + } + + public String getPassword() { + return password; + } +} diff --git a/src/main/java/cn/sliyun/api/user/mapper/BeamUserMapper.java b/src/main/java/cn/sliyun/api/user/mapper/BeamUserMapper.java new file mode 100644 index 0000000..0f222cd --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/mapper/BeamUserMapper.java @@ -0,0 +1,23 @@ +package cn.sliyun.api.user.mapper; + +import cn.sliyun.api.user.entity.BeamUser; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 用户表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-01-28 + */ +@Mapper +public interface BeamUserMapper extends BaseMapper { + + + IPage selectPageVo(Page page, Integer state); + +} diff --git a/src/main/java/cn/sliyun/api/user/service/IBeamUserService.java b/src/main/java/cn/sliyun/api/user/service/IBeamUserService.java new file mode 100644 index 0000000..94099cd --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/service/IBeamUserService.java @@ -0,0 +1,17 @@ +package cn.sliyun.api.user.service; + +import cn.sliyun.api.user.entity.BeamUser; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 用户表 服务类 + *

+ * + * @author Enoch + * @since 2021-01-28 + */ +public interface IBeamUserService extends IService { + + +} diff --git a/src/main/java/cn/sliyun/api/user/service/impl/BeamUserServiceImpl.java b/src/main/java/cn/sliyun/api/user/service/impl/BeamUserServiceImpl.java new file mode 100644 index 0000000..fb946f7 --- /dev/null +++ b/src/main/java/cn/sliyun/api/user/service/impl/BeamUserServiceImpl.java @@ -0,0 +1,119 @@ +package cn.sliyun.api.user.service.impl; + +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.IdUtil; +import cn.sliyun.common.utils.RegUtil; +import com.alibaba.fastjson.JSON; +import cn.sliyun.api.user.entity.BeamUser; +import cn.sliyun.api.user.entity.UpdateUserEntity; +import cn.sliyun.api.user.entity.UserActionBean; +import cn.sliyun.api.user.mapper.BeamUserMapper; +import cn.sliyun.api.user.service.IBeamUserService; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * 用户表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-01-28 + */ +@Service +public class BeamUserServiceImpl extends ServiceImpl implements IBeamUserService { + + + public Result register(UserActionBean userRegister) { + if (!RegUtil.checkMobile(userRegister.getPhone())) { + throw new AppException("手机号不正确"); + } + System.out.println("phone:"+userRegister.getPhone()); + BeamUser user = baseMapper.selectOne(new QueryWrapper().eq("phone", userRegister.getPhone())); + if (user != null) { + System.out.println("phone:"+user.getName()+"/"+user.getPhone()); + throw new AppException("手机号已经注册"); + } + + BeamUser beamUser = new BeamUser(); + beamUser.setAccount("" + IdUtil.create()); + beamUser.setName(StringUtils.isEmpty(userRegister.getName()) ? "会员" + IdUtil.genNickname() : userRegister.getName() + ""); + beamUser.setAvatar(Constants.IMG_DEFAULT_USER_AVATAR); + beamUser.setPhone(userRegister.getPhone()); + beamUser.setSalt(userRegister.getPhone()); + beamUser.setPassword(userRegister.getPassword()); + beamUser.setCreatedTime(LocalDateTime.now()); + beamUser.setCreatedBy(userRegister.getPhone()); + beamUser.setUpdateTime(LocalDateTime.now()); + beamUser.setUpdateBy(userRegister.getPhone()); + int id = baseMapper.insert(beamUser); + return ResultGenerator.genSuccessResult(id); + } + + public Result edit(String token, UpdateUserEntity updateUser) { + BeamUser user = baseMapper.selectOne(new QueryWrapper().ge("token", token)); + if (user == null) { + return ResultGenerator.genFailResult("用户不存在"); + } + BeanUtils.copyProperties(updateUser, user); + baseMapper.update(user, new UpdateWrapper<>()); + return ResultGenerator.genSuccessResult(); + } + + public Result getInfo(String token) { + BeamUser user = baseMapper.selectOne(new QueryWrapper().eq("token", token)); + if (user == null) { + throw new AppException("用户不存在"); + } + return ResultGenerator.genSuccessResult(user); + } + + + public Result updatePassword(UserActionBean updateUser) { + BeamUser user = baseMapper.selectOne(new QueryWrapper().eq("phone", updateUser.getPhone())); + if (user == null) { + throw new AppException("用户不存在"); + } + user.setPassword(updateUser.getPassword()); + baseMapper.update(user, new UpdateWrapper<>()); + return ResultGenerator.genSuccessResult(user); + } + + public Result getList(Integer pageIndex, Integer size) { + System.out.println(pageIndex + "/" + size); + Page page = new Page<>(pageIndex, size); + Page userMyPage = baseMapper.selectPage(page, new QueryWrapper<>()); + System.out.println("" + JSON.toJSONString(userMyPage)); + Map map = new HashMap(); + map.put("totalCount", userMyPage.getTotal()); + map.put("totalPage", userMyPage.getPages()); + map.put("pageNo", userMyPage.getCurrent()); + map.put("pageSize", size); + map.put("data", userMyPage.getRecords()); + return ResultGenerator.genSuccessResult(map); + } + + + public Result updateStatus(Map params) { + BeamUser user = baseMapper.selectOne(new QueryWrapper().eq("id", params.get("id"))); + if (user == null) { + throw new AppException("用户不存在"); + } + user.setStatus(params.get("status").toString()); + baseMapper.updateById(user); + return ResultGenerator.genSuccessResult(); + } +} diff --git a/src/main/java/cn/sliyun/api/wallet/controller/AddressController.java b/src/main/java/cn/sliyun/api/wallet/controller/AddressController.java new file mode 100644 index 0000000..24b160d --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/controller/AddressController.java @@ -0,0 +1,40 @@ +package cn.sliyun.api.wallet.controller; + + +import cn.sliyun.api.wallet.service.impl.AddressServiceImpl; +import cn.sliyun.common.core.Result; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.HashMap; + +/** + *

+ * 钱包地址表 前端控制器 + *

+ * + * @author Enoch + * @since 2021-01-29 + */ +@RestController +@RequestMapping("/sys/wallet/address") +public class AddressController { + + + @Resource + private AddressServiceImpl service; + + + @GetMapping("/list") + public Result getList() { + return service.getList(); + } + + + @PostMapping("/delete") + public Result create(@RequestBody HashMap map) { + return service.delete((Integer) map.get("id")); + } + + +} diff --git a/src/main/java/cn/sliyun/api/wallet/controller/OrderPayRecordsController.java b/src/main/java/cn/sliyun/api/wallet/controller/OrderPayRecordsController.java new file mode 100644 index 0000000..08da03a --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/controller/OrderPayRecordsController.java @@ -0,0 +1,53 @@ +package cn.sliyun.api.wallet.controller; + + +import cn.sliyun.api.order.entity.Order; +import cn.sliyun.api.order.service.impl.OrderServiceImpl; +import cn.sliyun.api.wallet.entity.OrderPayRecords; +import cn.sliyun.api.wallet.service.impl.AddressServiceImpl; +import cn.sliyun.api.wallet.service.impl.OrderPayRecordsServiceImpl; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * 订单支付记录 前端控制器 + *

+ * + * @author Enoch + * @since 2021-03-16 + */ +@RestController +@RequestMapping("/wallet/payment") +public class OrderPayRecordsController { + + + @Resource + private OrderPayRecordsServiceImpl service; + + + @GetMapping("/list") + public Result list(@RequestParam(defaultValue = "1", required = false) int pageNo + , @RequestParam(defaultValue = "20", required = false) int pageSize) { + Page page = new Page<>(pageNo, pageSize); + service.page(page); + Map map = new HashMap(); + map.put("totalCount", page.getTotal()); + map.put("totalPage", page.getPages()); + map.put("pageNo", page.getCurrent()); + map.put("pageSize", page); + map.put("data", page.getRecords()); + return ResultGenerator.genSuccessResult(map); + } + +} diff --git a/src/main/java/cn/sliyun/api/wallet/entity/Address.java b/src/main/java/cn/sliyun/api/wallet/entity/Address.java new file mode 100644 index 0000000..65738bb --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/entity/Address.java @@ -0,0 +1,213 @@ +package cn.sliyun.api.wallet.entity; + +import cn.sliyun.common.utils.AliyunOSSUtil; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + *

+ * 钱包地址表 + *

+ * + * @author Enoch + * @since 2021-01-29 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("wallet_address") +public class Address implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 货币ID + */ + private Integer coinId; + + /** + * 用户ID + */ + private Integer userId; + + /** + * 钱包地址 + */ + private String address; + + /** + * coin 描述 + */ + private String description; + + /** + * 创建人 + */ + @JsonIgnore + private String createBy; + + /** + * 创建时间 + */ + @JsonIgnore + private LocalDateTime createTime; + + /** + * 更新人 + */ + @JsonIgnore + private String updateBy; + + /** + * 更新时间 + */ + @JsonIgnore + private LocalDateTime updateTime; + + @TableField(exist = false) + @JsonIgnore + private String ossFileName; + + @TableField(exist = false) + private String coinIcon; + + @TableField(exist = false) + private String coinEnName; + + @TableField(exist = false) + private String coinCnName; + + @TableField(exist = false) + private String time ; + + public void setTime(String time) { + this.time = time; + } + + public String getTime() { + DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return dtf2.format(createTime); + } + + public String getOssFileName() { + return ossFileName; + } + + public void setOssFileName(String ossFileName) { + this.ossFileName = ossFileName; + } + + public String getCoinIcon() { + return AliyunOSSUtil.getInstance().getFileUrl(ossFileName); + } + + public void setCoinIcon(String coinIcon) { + this.coinIcon = coinIcon; + } + + public String getCoinEnName() { + return coinEnName; + } + + public void setCoinEnName(String coinEnName) { + this.coinEnName = coinEnName; + } + + public String getCoinCnName() { + return coinCnName; + } + + public void setCoinCnName(String coinCnName) { + this.coinCnName = coinCnName; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getCoinId() { + return coinId; + } + + public void setCoinId(Integer coinId) { + this.coinId = coinId; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } +} diff --git a/src/main/java/cn/sliyun/api/wallet/entity/OrderPayRecords.java b/src/main/java/cn/sliyun/api/wallet/entity/OrderPayRecords.java new file mode 100644 index 0000000..0161e89 --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/entity/OrderPayRecords.java @@ -0,0 +1,277 @@ +package cn.sliyun.api.wallet.entity; + +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; + +import java.time.LocalDateTime; +import java.io.Serializable; + +/** + *

+ * 订单支付记录 + *

+ * + * @author Enoch + * @since 2021-03-16 + */ +@TableName("sly_order_pay_records") +public class OrderPayRecords implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 预支付订单号 + */ + private String prepayid; + + /** + * 订单id + */ + private Long orderId; + + /** + * 订单号 + */ + private String orderSn; + + /** + * 支付状态: 0->未支付 1-> 已支付 2 -> 已过期 + */ + private Integer status; + + /** + * 支付方式:0->未支付;1->支付宝;2->微信 + */ + private Integer paymentChannel; + + /** + * 支付标题 + */ + private String paymentSubject; + + /** + * 应付金额(实际支付金额) + */ + private BigDecimal paymentAmount; + + /** + * 扩展字段 + */ + private String extendsParam; + + /** + * 交易开始时间 + */ + private LocalDateTime prepayStartTime; + + /** + * 交易结束时间 + */ + private LocalDateTime prepayExpire; + + /** + * 交易备注 + */ + private String remarks; + + /** + * 支付时间 + */ + private LocalDateTime paymentTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 操作时间 + */ + private LocalDateTime updateTime; + + + @TableField(exist = false) + private String statusName; + + @TableField(exist = false) + private String paymentChannelName; + + + public String getStatusName() { + if (status == 0) { + return "未支付"; + } else if (status == 1) { + return "已支付"; + } + return "未知"; + } + + public String getPaymentChannelName() { + if (paymentChannel == 1) { + return "支付宝"; + } else if (paymentChannel == 1) { + return "微信"; + } else if (paymentChannel == 1) { + return "QQ"; + } else if (paymentChannel == 1) { + return ""; + } + return "未知"; + } + + + public String getRemarks() { + StringBuffer string = new StringBuffer(); + string.append("支付标题:"+paymentSubject); + string.append("\n"); + string.append("创建时间:"+getCreateTime()); + string.append("\n"); + string.append("自定义参数:"+extendsParam); + return string.toString(); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getPrepayid() { + return prepayid; + } + + public void setPrepayid(String prepayid) { + this.prepayid = prepayid; + } + + public Long getOrderId() { + return orderId; + } + + public void setOrderId(Long orderId) { + this.orderId = orderId; + } + + public String getOrderSn() { + return orderSn; + } + + public void setOrderSn(String orderSn) { + this.orderSn = orderSn; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getPaymentChannel() { + return paymentChannel; + } + + public void setPaymentChannel(Integer paymentChannel) { + this.paymentChannel = paymentChannel; + } + + public String getPaymentSubject() { + return paymentSubject; + } + + public void setPaymentSubject(String paymentSubject) { + this.paymentSubject = paymentSubject; + } + + public BigDecimal getPaymentAmount() { + return paymentAmount; + } + + public void setPaymentAmount(BigDecimal paymentAmount) { + this.paymentAmount = paymentAmount; + } + + public String getExtendsParam() { + return extendsParam; + } + + public void setExtendsParam(String extendsParam) { + this.extendsParam = extendsParam; + } + + public LocalDateTime getPrepayStartTime() { + return prepayStartTime; + } + + public void setPrepayStartTime(LocalDateTime prepayStartTime) { + this.prepayStartTime = prepayStartTime; + } + + public LocalDateTime getPrepayExpire() { + return prepayExpire; + } + + public void setPrepayExpire(LocalDateTime prepayExpire) { + this.prepayExpire = prepayExpire; + } + + + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + public LocalDateTime getPaymentTime() { + return paymentTime; + } + + public void setPaymentTime(LocalDateTime paymentTime) { + this.paymentTime = paymentTime; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "OrderPayRecords{" + + "id=" + id + + ", prepayid=" + prepayid + + ", orderId=" + orderId + + ", orderSn=" + orderSn + + ", status=" + status + + ", paymentChannel=" + paymentChannel + + ", paymentSubject=" + paymentSubject + + ", paymentAmount=" + paymentAmount + + ", extendsParam=" + extendsParam + + ", prepayStartTime=" + prepayStartTime + + ", prepayExpire=" + prepayExpire + + ", remarks=" + remarks + + ", paymentTime=" + paymentTime + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + "}"; + } +} diff --git a/src/main/java/cn/sliyun/api/wallet/mapper/AddressMapper.java b/src/main/java/cn/sliyun/api/wallet/mapper/AddressMapper.java new file mode 100644 index 0000000..c01d709 --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/mapper/AddressMapper.java @@ -0,0 +1,25 @@ +package cn.sliyun.api.wallet.mapper; + +import cn.sliyun.api.wallet.entity.Address; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * 钱包地址表 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-01-29 + */ +public interface AddressMapper extends BaseMapper
{ + /** + * @return + */ + @Select("SELECT wallet_address.*,wallet_coin.`name` AS coinCnName ,wallet_coin.`description` AS coinEnName ,wallet_coin.`img_id`,beam_img.`oss_file_name` AS ossFileName FROM wallet_address, wallet_coin,beam_img WHERE wallet_address.coin_id=wallet_coin.id AND wallet_coin.img_id=beam_img.id") + List
getAddressList(); + + +} diff --git a/src/main/java/cn/sliyun/api/wallet/mapper/OrderPayRecordsMapper.java b/src/main/java/cn/sliyun/api/wallet/mapper/OrderPayRecordsMapper.java new file mode 100644 index 0000000..e44170d --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/mapper/OrderPayRecordsMapper.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.wallet.mapper; + +import cn.sliyun.api.wallet.entity.OrderPayRecords; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单支付记录 Mapper 接口 + *

+ * + * @author Enoch + * @since 2021-03-16 + */ +public interface OrderPayRecordsMapper extends BaseMapper { + +} diff --git a/src/main/java/cn/sliyun/api/wallet/service/IAddressService.java b/src/main/java/cn/sliyun/api/wallet/service/IAddressService.java new file mode 100644 index 0000000..7cf8427 --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/service/IAddressService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.wallet.service; + +import cn.sliyun.api.wallet.entity.Address; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 钱包地址表 服务类 + *

+ * + * @author Enoch + * @since 2021-01-29 + */ +public interface IAddressService extends IService
{ + +} diff --git a/src/main/java/cn/sliyun/api/wallet/service/IOrderPayRecordsService.java b/src/main/java/cn/sliyun/api/wallet/service/IOrderPayRecordsService.java new file mode 100644 index 0000000..6c09af4 --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/service/IOrderPayRecordsService.java @@ -0,0 +1,16 @@ +package cn.sliyun.api.wallet.service; + +import cn.sliyun.api.wallet.entity.OrderPayRecords; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 订单支付记录 服务类 + *

+ * + * @author Enoch + * @since 2021-03-16 + */ +public interface IOrderPayRecordsService extends IService { + +} diff --git a/src/main/java/cn/sliyun/api/wallet/service/impl/AddressServiceImpl.java b/src/main/java/cn/sliyun/api/wallet/service/impl/AddressServiceImpl.java new file mode 100644 index 0000000..ef3ea7e --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/service/impl/AddressServiceImpl.java @@ -0,0 +1,32 @@ +package cn.sliyun.api.wallet.service.impl; + +import cn.sliyun.api.wallet.entity.Address; +import cn.sliyun.api.wallet.mapper.AddressMapper; +import cn.sliyun.api.wallet.service.IAddressService; +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 钱包地址表 服务实现类 + *

+ * + * @author Enoch + * @since 2021-01-29 + */ +@Service +public class AddressServiceImpl extends ServiceImpl implements IAddressService { + + public Result getList() { + return ResultGenerator.genSuccessResult(baseMapper.getAddressList()); + } + + + public Result delete(Integer id) { + removeById(id); + return ResultGenerator.genSuccessResult(); + + } +} diff --git a/src/main/java/cn/sliyun/api/wallet/service/impl/OrderPayRecordsServiceImpl.java b/src/main/java/cn/sliyun/api/wallet/service/impl/OrderPayRecordsServiceImpl.java new file mode 100644 index 0000000..3f80a60 --- /dev/null +++ b/src/main/java/cn/sliyun/api/wallet/service/impl/OrderPayRecordsServiceImpl.java @@ -0,0 +1,20 @@ +package cn.sliyun.api.wallet.service.impl; + +import cn.sliyun.api.wallet.entity.OrderPayRecords; +import cn.sliyun.api.wallet.mapper.OrderPayRecordsMapper; +import cn.sliyun.api.wallet.service.IOrderPayRecordsService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单支付记录 服务实现类 + *

+ * + * @author Enoch + * @since 2021-03-16 + */ +@Service +public class OrderPayRecordsServiceImpl extends ServiceImpl implements IOrderPayRecordsService { + +} diff --git a/src/main/java/cn/sliyun/common/constant/Constants.java b/src/main/java/cn/sliyun/common/constant/Constants.java new file mode 100644 index 0000000..752204a --- /dev/null +++ b/src/main/java/cn/sliyun/common/constant/Constants.java @@ -0,0 +1,137 @@ +package cn.sliyun.common.constant; + +import io.jsonwebtoken.Claims; + +/** + * 通用常量信息 + * + * @author ruoyi + */ +public class Constants +{ + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 登录用户 redis key + */ + public static final String LOGIN_TOKEN_KEY = "login_tokens:"; + + /** + * 防重提交 redis key + */ + public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; + + /** + * 验证码有效期(分钟) + */ + public static final Integer CAPTCHA_EXPIRATION = 2; + + /** + * 令牌 + */ + public static final String TOKEN = "token"; + + /** + * 令牌前缀 + */ + public static final String TOKEN_PREFIX = "Bearer "; + + /** + * 令牌前缀 + */ + public static final String LOGIN_USER_KEY = "login_user_key"; + + /** + * 用户ID + */ + public static final String JWT_USERID = "userid"; + + /** + * 用户名称 + */ + public static final String JWT_USERNAME = Claims.SUBJECT; + + /** + * 用户头像 + */ + public static final String JWT_AVATAR = "avatar"; + + /** + * 创建时间 + */ + public static final String JWT_CREATED = "created"; + + /** + * 用户权限 + */ + public static final String JWT_AUTHORITIES = "authorities"; + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 资源映射路径 前缀 + */ + public static final String RESOURCE_PREFIX = "/profile"; + + + public static final String IMG_DEFAULT_USER_AVATAR = "icon_default_user.png"; + + public final static String UPLOAD_PATH_PREFIX = "static/images/"; + +} diff --git a/src/main/java/cn/sliyun/common/constant/GenConstants.java b/src/main/java/cn/sliyun/common/constant/GenConstants.java new file mode 100644 index 0000000..5569539 --- /dev/null +++ b/src/main/java/cn/sliyun/common/constant/GenConstants.java @@ -0,0 +1,114 @@ +package cn.sliyun.common.constant; + +/** + * 代码生成通用常量 + * + * @author ruoyi + */ +public class GenConstants +{ + /** 单表(增删改查) */ + public static final String TPL_CRUD = "crud"; + + /** 树表(增删改查) */ + public static final String TPL_TREE = "tree"; + + /** 主子表(增删改查) */ + public static final String TPL_SUB = "sub"; + + /** 树编码字段 */ + public static final String TREE_CODE = "treeCode"; + + /** 树父编码字段 */ + public static final String TREE_PARENT_CODE = "treeParentCode"; + + /** 树名称字段 */ + public static final String TREE_NAME = "treeName"; + + /** 上级菜单ID字段 */ + public static final String PARENT_MENU_ID = "parentMenuId"; + + /** 上级菜单名称字段 */ + public static final String PARENT_MENU_NAME = "parentMenuName"; + + /** 数据库字符串类型 */ + public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" }; + + /** 数据库文本类型 */ + public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" }; + + /** 数据库时间类型 */ + public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; + + /** 数据库数字类型 */ + public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", + "bit", "bigint", "float", "double", "decimal" }; + + /** 页面不需要编辑字段 */ + public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; + + /** 页面不需要显示的列表字段 */ + public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by", + "update_time" }; + + /** 页面不需要查询字段 */ + public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by", + "update_time", "remark" }; + + /** Entity基类字段 */ + public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; + + /** Tree基类字段 */ + public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" }; + + /** 文本框 */ + public static final String HTML_INPUT = "input"; + + /** 文本域 */ + public static final String HTML_TEXTAREA = "textarea"; + + /** 下拉框 */ + public static final String HTML_SELECT = "select"; + + /** 单选框 */ + public static final String HTML_RADIO = "radio"; + + /** 复选框 */ + public static final String HTML_CHECKBOX = "checkbox"; + + /** 日期控件 */ + public static final String HTML_DATETIME = "datetime"; + + /** 图片上传控件 */ + public static final String HTML_IMAGE_UPLOAD = "imageUpload"; + + /** 文件上传控件 */ + public static final String HTML_FILE_UPLOAD = "fileUpload"; + + /** 富文本控件 */ + public static final String HTML_EDITOR = "editor"; + + /** 字符串类型 */ + public static final String TYPE_STRING = "String"; + + /** 整型 */ + public static final String TYPE_INTEGER = "Integer"; + + /** 长整型 */ + public static final String TYPE_LONG = "Long"; + + /** 浮点型 */ + public static final String TYPE_DOUBLE = "Double"; + + /** 高精度计算类型 */ + public static final String TYPE_BIGDECIMAL = "BigDecimal"; + + /** 时间类型 */ + public static final String TYPE_DATE = "Date"; + + /** 模糊查询 */ + public static final String QUERY_LIKE = "LIKE"; + + /** 需要 */ + public static final String REQUIRE = "1"; +} diff --git a/src/main/java/cn/sliyun/common/constant/HttpStatus.java b/src/main/java/cn/sliyun/common/constant/HttpStatus.java new file mode 100644 index 0000000..e8349bb --- /dev/null +++ b/src/main/java/cn/sliyun/common/constant/HttpStatus.java @@ -0,0 +1,89 @@ +package cn.sliyun.common.constant; + +/** + * 返回状态码 + * + * @author ruoyi + */ +public class HttpStatus +{ + /** + * 操作成功 + */ + public static final int SUCCESS = 200; + + /** + * 对象创建成功 + */ + public static final int CREATED = 201; + + /** + * 请求已经被接受 + */ + public static final int ACCEPTED = 202; + + /** + * 操作已经执行成功,但是没有返回数据 + */ + public static final int NO_CONTENT = 204; + + /** + * 资源已被移除 + */ + public static final int MOVED_PERM = 301; + + /** + * 重定向 + */ + public static final int SEE_OTHER = 303; + + /** + * 资源没有被修改 + */ + public static final int NOT_MODIFIED = 304; + + /** + * 参数列表错误(缺少,格式不匹配) + */ + public static final int BAD_REQUEST = 400; + + /** + * 未授权 + */ + public static final int UNAUTHORIZED = 401; + + /** + * 访问受限,授权过期 + */ + public static final int FORBIDDEN = 403; + + /** + * 资源,服务未找到 + */ + public static final int NOT_FOUND = 404; + + /** + * 不允许的http方法 + */ + public static final int BAD_METHOD = 405; + + /** + * 资源冲突,或者资源被锁 + */ + public static final int CONFLICT = 409; + + /** + * 不支持的数据,媒体类型 + */ + public static final int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + public static final int ERROR = 500; + + /** + * 接口未实现 + */ + public static final int NOT_IMPLEMENTED = 501; +} diff --git a/src/main/java/cn/sliyun/common/constant/ScheduleConstants.java b/src/main/java/cn/sliyun/common/constant/ScheduleConstants.java new file mode 100644 index 0000000..35c197c --- /dev/null +++ b/src/main/java/cn/sliyun/common/constant/ScheduleConstants.java @@ -0,0 +1,50 @@ +package cn.sliyun.common.constant; + +/** + * 任务调度通用常量 + * + * @author ruoyi + */ +public class ScheduleConstants +{ + public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; + + /** 执行目标key */ + public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; + + /** 默认 */ + public static final String MISFIRE_DEFAULT = "0"; + + /** 立即触发执行 */ + public static final String MISFIRE_IGNORE_MISFIRES = "1"; + + /** 触发一次执行 */ + public static final String MISFIRE_FIRE_AND_PROCEED = "2"; + + /** 不触发立即执行 */ + public static final String MISFIRE_DO_NOTHING = "3"; + + public enum Status + { + /** + * 正常 + */ + NORMAL("0"), + /** + * 暂停 + */ + PAUSE("1"); + + private String value; + + private Status(String value) + { + this.value = value; + } + + public String getValue() + { + return value; + } + } +} diff --git a/src/main/java/cn/sliyun/common/constant/UserConstants.java b/src/main/java/cn/sliyun/common/constant/UserConstants.java new file mode 100644 index 0000000..6807a8f --- /dev/null +++ b/src/main/java/cn/sliyun/common/constant/UserConstants.java @@ -0,0 +1,63 @@ +package cn.sliyun.common.constant; + +/** + * 用户常量信息 + * + * @author ruoyi + */ +public class UserConstants +{ + /** + * 平台内系统用户的唯一标志 + */ + public static final String SYS_USER = "SYS_USER"; + + /** 正常状态 */ + public static final String NORMAL = "0"; + + /** 异常状态 */ + public static final String EXCEPTION = "1"; + + /** 用户封禁状态 */ + public static final String USER_DISABLE = "1"; + + /** 角色封禁状态 */ + public static final String ROLE_DISABLE = "1"; + + /** 部门正常状态 */ + public static final String DEPT_NORMAL = "0"; + + /** 部门停用状态 */ + public static final String DEPT_DISABLE = "1"; + + /** 字典正常状态 */ + public static final String DICT_NORMAL = "0"; + + /** 是否为系统默认(是) */ + public static final String YES = "Y"; + + /** 是否菜单外链(是) */ + public static final String YES_FRAME = "0"; + + /** 是否菜单外链(否) */ + public static final String NO_FRAME = "1"; + + /** 菜单类型(目录) */ + public static final String TYPE_DIR = "M"; + + /** 菜单类型(菜单) */ + public static final String TYPE_MENU = "C"; + + /** 菜单类型(按钮) */ + public static final String TYPE_BUTTON = "F"; + + /** Layout组件标识 */ + public final static String LAYOUT = "Layout"; + + /** ParentView组件标识 */ + public final static String PARENT_VIEW = "ParentView"; + + /** 校验返回结果码 */ + public final static String UNIQUE = "0"; + public final static String NOT_UNIQUE = "1"; +} diff --git a/src/main/java/cn/sliyun/common/core/Result.java b/src/main/java/cn/sliyun/common/core/Result.java new file mode 100644 index 0000000..4f706b2 --- /dev/null +++ b/src/main/java/cn/sliyun/common/core/Result.java @@ -0,0 +1,47 @@ +package cn.sliyun.common.core; + +public class Result { + private int code; + private String msg; + private long timestamp; + private T data; + + public Result setCode(ResultCode resultCode) { + this.code = resultCode.code(); + return this; + } + public Result setCode(int resultCode) { + this.code = resultCode; + return this; + } + + public int getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + public long getTimestamp() { + return timestamp; + } + + public Result setMsg(String msg) { + this.msg = msg; + this.timestamp = System.currentTimeMillis(); + return this; + } + + public T getData() { + return data; + } + + + public Result setData(T data) { + this.data = data; + this.timestamp = System.currentTimeMillis(); + return this; + } + +} diff --git a/src/main/java/cn/sliyun/common/core/ResultCode.java b/src/main/java/cn/sliyun/common/core/ResultCode.java new file mode 100644 index 0000000..10559d3 --- /dev/null +++ b/src/main/java/cn/sliyun/common/core/ResultCode.java @@ -0,0 +1,22 @@ +package cn.sliyun.common.core; + +/** + * 响应码枚举,参考HTTP状态码的语义 + */ +public enum ResultCode { + SUCCESS(200),//成功 + FAIL(400),//失败 + UNAUTHORIZED(401),//未认证(签名错误) + NOT_FOUND(404),//接口不存在 + INTERNAL_SERVER_ERROR(500);//服务器内部错误 + + private final int code; + + ResultCode(int code) { + this.code = code; + } + + public int code() { + return code; + } +} diff --git a/src/main/java/cn/sliyun/common/core/ResultGenerator.java b/src/main/java/cn/sliyun/common/core/ResultGenerator.java new file mode 100644 index 0000000..370083f --- /dev/null +++ b/src/main/java/cn/sliyun/common/core/ResultGenerator.java @@ -0,0 +1,39 @@ +package cn.sliyun.common.core; + +public class ResultGenerator { + private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS"; + + private String format = "json"; + + public static Result genSuccessResult() { + return new Result() + .setCode(ResultCode.SUCCESS) + .setMsg(DEFAULT_SUCCESS_MESSAGE); + } + + public static Result genSuccessResult(T data) { + return new Result() + .setCode(ResultCode.SUCCESS) + .setMsg(DEFAULT_SUCCESS_MESSAGE) + .setData(data); + } + + public static Result genFailResult(String message) { + return new Result() + .setCode(ResultCode.FAIL) + .setMsg(message); + } + + public static Result genFailResult(ResultCode code, String message) { + return new Result() + .setCode(code) + .setMsg(message); + } + + public static Result genFailResult(int code, String message) { + return new Result() + .setCode(code) + .setMsg(message); + } +} + diff --git a/src/main/java/cn/sliyun/common/core/lang/UUID.java b/src/main/java/cn/sliyun/common/core/lang/UUID.java new file mode 100644 index 0000000..db16fd5 --- /dev/null +++ b/src/main/java/cn/sliyun/common/core/lang/UUID.java @@ -0,0 +1,484 @@ +package cn.sliyun.common.core.lang; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import cn.sliyun.common.exception.UtilException; + +/** + * 提供通用唯一识别码(universally unique identifier)(UUID)实现 + * + * @author ruoyi + */ +public final class UUID implements java.io.Serializable, Comparable +{ + private static final long serialVersionUID = -1185015143654744140L; + + /** + * SecureRandom 的单例 + * + */ + private static class Holder + { + static final SecureRandom numberGenerator = getSecureRandom(); + } + + /** 此UUID的最高64有效位 */ + private final long mostSigBits; + + /** 此UUID的最低64有效位 */ + private final long leastSigBits; + + /** + * 私有构造 + * + * @param data 数据 + */ + private UUID(byte[] data) + { + long msb = 0; + long lsb = 0; + assert data.length == 16 : "data must be 16 bytes in length"; + for (int i = 0; i < 8; i++) + { + msb = (msb << 8) | (data[i] & 0xff); + } + for (int i = 8; i < 16; i++) + { + lsb = (lsb << 8) | (data[i] & 0xff); + } + this.mostSigBits = msb; + this.leastSigBits = lsb; + } + + /** + * 使用指定的数据构造新的 UUID。 + * + * @param mostSigBits 用于 {@code UUID} 的最高有效 64 位 + * @param leastSigBits 用于 {@code UUID} 的最低有效 64 位 + */ + public UUID(long mostSigBits, long leastSigBits) + { + this.mostSigBits = mostSigBits; + this.leastSigBits = leastSigBits; + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。 + * + * @return 随机生成的 {@code UUID} + */ + public static UUID fastUUID() + { + return randomUUID(false); + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 + * + * @return 随机生成的 {@code UUID} + */ + public static UUID randomUUID() + { + return randomUUID(true); + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 + * + * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能 + * @return 随机生成的 {@code UUID} + */ + public static UUID randomUUID(boolean isSecure) + { + final Random ng = isSecure ? Holder.numberGenerator : getRandom(); + + byte[] randomBytes = new byte[16]; + ng.nextBytes(randomBytes); + randomBytes[6] &= 0x0f; /* clear version */ + randomBytes[6] |= 0x40; /* set to version 4 */ + randomBytes[8] &= 0x3f; /* clear variant */ + randomBytes[8] |= 0x80; /* set to IETF variant */ + return new UUID(randomBytes); + } + + /** + * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。 + * + * @param name 用于构造 UUID 的字节数组。 + * + * @return 根据指定数组生成的 {@code UUID} + */ + public static UUID nameUUIDFromBytes(byte[] name) + { + MessageDigest md; + try + { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException nsae) + { + throw new InternalError("MD5 not supported"); + } + byte[] md5Bytes = md.digest(name); + md5Bytes[6] &= 0x0f; /* clear version */ + md5Bytes[6] |= 0x30; /* set to version 3 */ + md5Bytes[8] &= 0x3f; /* clear variant */ + md5Bytes[8] |= 0x80; /* set to IETF variant */ + return new UUID(md5Bytes); + } + + /** + * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。 + * + * @param name 指定 {@code UUID} 字符串 + * @return 具有指定值的 {@code UUID} + * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常 + * + */ + public static UUID fromString(String name) + { + String[] components = name.split("-"); + if (components.length != 5) + { + throw new IllegalArgumentException("Invalid UUID string: " + name); + } + for (int i = 0; i < 5; i++) + { + components[i] = "0x" + components[i]; + } + + long mostSigBits = Long.decode(components[0]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[1]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[2]).longValue(); + + long leastSigBits = Long.decode(components[3]).longValue(); + leastSigBits <<= 48; + leastSigBits |= Long.decode(components[4]).longValue(); + + return new UUID(mostSigBits, leastSigBits); + } + + /** + * 返回此 UUID 的 128 位值中的最低有效 64 位。 + * + * @return 此 UUID 的 128 位值中的最低有效 64 位。 + */ + public long getLeastSignificantBits() + { + return leastSigBits; + } + + /** + * 返回此 UUID 的 128 位值中的最高有效 64 位。 + * + * @return 此 UUID 的 128 位值中最高有效 64 位。 + */ + public long getMostSignificantBits() + { + return mostSigBits; + } + + /** + * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。 + *

+ * 版本号具有以下含意: + *

    + *
  • 1 基于时间的 UUID + *
  • 2 DCE 安全 UUID + *
  • 3 基于名称的 UUID + *
  • 4 随机生成的 UUID + *
+ * + * @return 此 {@code UUID} 的版本号 + */ + public int version() + { + // Version is bits masked by 0x000000000000F000 in MS long + return (int) ((mostSigBits >> 12) & 0x0f); + } + + /** + * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。 + *

+ * 变体号具有以下含意: + *

    + *
  • 0 为 NCS 向后兼容保留 + *
  • 2 IETF RFC 4122(Leach-Salz), 用于此类 + *
  • 6 保留,微软向后兼容 + *
  • 7 保留供以后定义使用 + *
+ * + * @return 此 {@code UUID} 相关联的变体号 + */ + public int variant() + { + // This field is composed of a varying number of bits. + // 0 - - Reserved for NCS backward compatibility + // 1 0 - The IETF aka Leach-Salz variant (used by this class) + // 1 1 0 Reserved, Microsoft backward compatibility + // 1 1 1 Reserved for future definition. + return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); + } + + /** + * 与此 UUID 相关联的时间戳值。 + * + *

+ * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。
+ * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。 + * + *

+ * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。
+ * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 + * + * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。 + */ + public long timestamp() throws UnsupportedOperationException + { + checkTimeBase(); + return (mostSigBits & 0x0FFFL) << 48// + | ((mostSigBits >> 16) & 0x0FFFFL) << 32// + | mostSigBits >>> 32; + } + + /** + * 与此 UUID 相关联的时钟序列值。 + * + *

+ * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。 + *

+ * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出 + * UnsupportedOperationException。 + * + * @return 此 {@code UUID} 的时钟序列 + * + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 + */ + public int clockSequence() throws UnsupportedOperationException + { + checkTimeBase(); + return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); + } + + /** + * 与此 UUID 相关的节点值。 + * + *

+ * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。 + *

+ * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。
+ * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 + * + * @return 此 {@code UUID} 的节点值 + * + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 + */ + public long node() throws UnsupportedOperationException + { + checkTimeBase(); + return leastSigBits & 0x0000FFFFFFFFFFFFL; + } + + /** + * 返回此{@code UUID} 的字符串表现形式。 + * + *

+ * UUID 的字符串表示形式由此 BNF 描述: + * + *

+     * {@code
+     * UUID                   = ----
+     * time_low               = 4*
+     * time_mid               = 2*
+     * time_high_and_version  = 2*
+     * variant_and_sequence   = 2*
+     * node                   = 6*
+     * hexOctet               = 
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * 
+ * + * + * + * @return 此{@code UUID} 的字符串表现形式 + * @see #toString(boolean) + */ + @Override + public String toString() + { + return toString(false); + } + + /** + * 返回此{@code UUID} 的字符串表现形式。 + * + *

+ * UUID 的字符串表示形式由此 BNF 描述: + * + *

+     * {@code
+     * UUID                   = ----
+     * time_low               = 4*
+     * time_mid               = 2*
+     * time_high_and_version  = 2*
+     * variant_and_sequence   = 2*
+     * node                   = 6*
+     * hexOctet               = 
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * 
+ * + * + * + * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串 + * @return 此{@code UUID} 的字符串表现形式 + */ + public String toString(boolean isSimple) + { + final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); + // time_low + builder.append(digits(mostSigBits >> 32, 8)); + if (false == isSimple) + { + builder.append('-'); + } + // time_mid + builder.append(digits(mostSigBits >> 16, 4)); + if (false == isSimple) + { + builder.append('-'); + } + // time_high_and_version + builder.append(digits(mostSigBits, 4)); + if (false == isSimple) + { + builder.append('-'); + } + // variant_and_sequence + builder.append(digits(leastSigBits >> 48, 4)); + if (false == isSimple) + { + builder.append('-'); + } + // node + builder.append(digits(leastSigBits, 12)); + + return builder.toString(); + } + + /** + * 返回此 UUID 的哈希码。 + * + * @return UUID 的哈希码值。 + */ + @Override + public int hashCode() + { + long hilo = mostSigBits ^ leastSigBits; + return ((int) (hilo >> 32)) ^ (int) hilo; + } + + /** + * 将此对象与指定对象比较。 + *

+ * 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。 + * + * @param obj 要与之比较的对象 + * + * @return 如果对象相同,则返回 {@code true};否则返回 {@code false} + */ + @Override + public boolean equals(Object obj) + { + if ((null == obj) || (obj.getClass() != UUID.class)) + { + return false; + } + UUID id = (UUID) obj; + return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); + } + + // Comparison Operations + + /** + * 将此 UUID 与指定的 UUID 比较。 + * + *

+ * 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。 + * + * @param val 与此 UUID 比较的 UUID + * + * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。 + * + */ + @Override + public int compareTo(UUID val) + { + // The ordering is intentionally set up so that the UUIDs + // can simply be numerically compared as two numbers + return (this.mostSigBits < val.mostSigBits ? -1 : // + (this.mostSigBits > val.mostSigBits ? 1 : // + (this.leastSigBits < val.leastSigBits ? -1 : // + (this.leastSigBits > val.leastSigBits ? 1 : // + 0)))); + } + + // ------------------------------------------------------------------------------------------------------------------- + // Private method start + /** + * 返回指定数字对应的hex值 + * + * @param val 值 + * @param digits 位 + * @return 值 + */ + private static String digits(long val, int digits) + { + long hi = 1L << (digits * 4); + return Long.toHexString(hi | (val & (hi - 1))).substring(1); + } + + /** + * 检查是否为time-based版本UUID + */ + private void checkTimeBase() + { + if (version() != 1) + { + throw new UnsupportedOperationException("Not a time-based UUID"); + } + } + + /** + * 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG) + * + * @return {@link SecureRandom} + */ + public static SecureRandom getSecureRandom() + { + try + { + return SecureRandom.getInstance("SHA1PRNG"); + } + catch (NoSuchAlgorithmException e) + { + throw new UtilException(e); + } + } + + /** + * 获取随机数生成器对象
+ * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。 + * + * @return {@link ThreadLocalRandom} + */ + public static ThreadLocalRandom getRandom() + { + return ThreadLocalRandom.current(); + } +} diff --git a/src/main/java/cn/sliyun/common/core/text/CharsetKit.java b/src/main/java/cn/sliyun/common/core/text/CharsetKit.java new file mode 100644 index 0000000..84e9e79 --- /dev/null +++ b/src/main/java/cn/sliyun/common/core/text/CharsetKit.java @@ -0,0 +1,86 @@ +package cn.sliyun.common.core.text; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import cn.sliyun.common.utils.StringUtils; + +/** + * 字符集工具类 + * + * @author ruoyi + */ +public class CharsetKit +{ + /** ISO-8859-1 */ + public static final String ISO_8859_1 = "ISO-8859-1"; + /** UTF-8 */ + public static final String UTF_8 = "UTF-8"; + /** GBK */ + public static final String GBK = "GBK"; + + /** ISO-8859-1 */ + public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); + /** UTF-8 */ + public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); + /** GBK */ + public static final Charset CHARSET_GBK = Charset.forName(GBK); + + /** + * 转换为Charset对象 + * + * @param charset 字符集,为空则返回默认字符集 + * @return Charset + */ + public static Charset charset(String charset) + { + return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, String srcCharset, String destCharset) + { + return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, Charset srcCharset, Charset destCharset) + { + if (null == srcCharset) + { + srcCharset = StandardCharsets.ISO_8859_1; + } + + if (null == destCharset) + { + destCharset = StandardCharsets.UTF_8; + } + + if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) + { + return source; + } + return new String(source.getBytes(srcCharset), destCharset); + } + + /** + * @return 系统字符集编码 + */ + public static String systemCharset() + { + return Charset.defaultCharset().name(); + } +} diff --git a/src/main/java/cn/sliyun/common/core/text/Convert.java b/src/main/java/cn/sliyun/common/core/text/Convert.java new file mode 100644 index 0000000..b22b236 --- /dev/null +++ b/src/main/java/cn/sliyun/common/core/text/Convert.java @@ -0,0 +1,1000 @@ +package cn.sliyun.common.core.text; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; + +import cn.sliyun.common.utils.StringUtils; + +/** + * 类型转换器 + * + * @author ruoyi + */ +public class Convert +{ + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static String toStr(Object value, String defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof String) + { + return (String) value; + } + return value.toString(); + } + + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static String toStr(Object value) + { + return toStr(value, null); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Character toChar(Object value, Character defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof Character) + { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Character toChar(Object value) + { + return toChar(value, null); + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Byte toByte(Object value, Byte defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Byte) + { + return (Byte) value; + } + if (value instanceof Number) + { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Byte.parseByte(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Byte toByte(Object value) + { + return toByte(value, null); + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Short toShort(Object value, Short defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Short) + { + return (Short) value; + } + if (value instanceof Number) + { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Short.parseShort(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Short toShort(Object value) + { + return toShort(value, null); + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Number toNumber(Object value, Number defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Number) + { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return NumberFormat.getInstance().parse(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Number toNumber(Object value) + { + return toNumber(value, null); + } + + /** + * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Integer toInt(Object value, Integer defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Integer) + { + return (Integer) value; + } + if (value instanceof Number) + { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Integer.parseInt(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为int
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Integer toInt(Object value) + { + return toInt(value, null); + } + + /** + * 转换为Integer数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) + { + return toIntArray(",", str); + } + + /** + * 转换为Long数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String str) + { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Integer[] {}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转换为Long数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Long[] {}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转换为String数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String str) + { + return toStrArray(",", str); + } + + /** + * 转换为String数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) + { + return str.split(split); + } + + /** + * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Long) + { + return (Long) value; + } + if (value instanceof Number) + { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为long
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) + { + return toLong(value, null); + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Double) + { + return (Double) value; + } + if (value instanceof Number) + { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) + { + return toDouble(value, null); + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Float) + { + return (Float) value; + } + if (value instanceof Number) + { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Float.parseFloat(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) + { + return toFloat(value, null); + } + + /** + * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Boolean toBool(Object value, Boolean defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Boolean) + { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) + { + case "true": + return true; + case "false": + return false; + case "yes": + return true; + case "ok": + return true; + case "no": + return false; + case "1": + return true; + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Boolean toBool(Object value) + { + return toBool(value, null); + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) + { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Enum.valueOf(clazz, valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) + { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigInteger) + { + return (BigInteger) value; + } + if (value instanceof Long) + { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigInteger(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) + { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigDecimal) + { + return (BigDecimal) value; + } + if (value instanceof Long) + { + return new BigDecimal((Long) value); + } + if (value instanceof Double) + { + return new BigDecimal((Double) value); + } + if (value instanceof Integer) + { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigDecimal(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) + { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) + { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) + { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) + { + if (null == obj) + { + return null; + } + + if (obj instanceof String) + { + return (String) obj; + } + else if (obj instanceof byte[] || obj instanceof Byte[]) + { + return str((Byte[]) obj, charset); + } + else if (obj instanceof ByteBuffer) + { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) + { + return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String str(byte[] data, Charset charset) + { + if (data == null) + { + return null; + } + + if (null == charset) + { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) + { + if (data == null) + { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) + { + if (null == charset) + { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角半角转换 + /** + * 半角转全角 + * + * @param input String. + * @return 全角字符串. + */ + public static String toSBC(String input) + { + return toSBC(input, null); + } + + /** + * 半角转全角 + * + * @param input String + * @param notConvertSet 不替换的字符集合 + * @return 全角字符串. + */ + public static String toSBC(String input, Set notConvertSet) + { + char c[] = input.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == ' ') + { + c[i] = '\u3000'; + } + else if (c[i] < '\177') + { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转半角 + * + * @param input String. + * @return 半角字符串 + */ + public static String toDBC(String input) + { + return toDBC(input, null); + } + + /** + * 替换全角为半角 + * + * @param text 文本 + * @param notConvertSet 不替换的字符集合 + * @return 替换后的字符 + */ + public static String toDBC(String text, Set notConvertSet) + { + char c[] = text.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == '\u3000') + { + c[i] = ' '; + } + else if (c[i] > '\uFF00' && c[i] < '\uFF5F') + { + c[i] = (char) (c[i] - 65248); + } + } + String returnString = new String(c); + + return returnString; + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @param n 数字 + * @return 中文大写数字 + */ + public static String digitUppercase(double n) + { + String[] fraction = { "角", "分" }; + String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; + String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } }; + + String head = n < 0 ? "负" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0; i < fraction.length; i++) + { + s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); + } + if (s.length() < 1) + { + s = "整"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0; i < unit[0].length && integerPart > 0; i++) + { + String p = ""; + for (int j = 0; j < unit[1].length && n > 0; j++) + { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; + } + return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); + } +} diff --git a/src/main/java/cn/sliyun/common/core/text/StrFormatter.java b/src/main/java/cn/sliyun/common/core/text/StrFormatter.java new file mode 100644 index 0000000..5d42ec7 --- /dev/null +++ b/src/main/java/cn/sliyun/common/core/text/StrFormatter.java @@ -0,0 +1,92 @@ +package cn.sliyun.common.core.text; + +import cn.sliyun.common.utils.StringUtils; + +/** + * 字符串格式化 + * + * @author ruoyi + */ +public class StrFormatter +{ + public static final String EMPTY_JSON = "{}"; + public static final char C_BACKSLASH = '\\'; + public static final char C_DELIM_START = '{'; + public static final char C_DELIM_END = '}'; + + /** + * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param strPattern 字符串模板 + * @param argArray 参数列表 + * @return 结果 + */ + public static String format(final String strPattern, final Object... argArray) + { + if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) + { + return strPattern; + } + final int strPatternLength = strPattern.length(); + + // 初始化定义好的长度以获得更好的性能 + StringBuilder sbuf = new StringBuilder(strPatternLength + 50); + + int handledPosition = 0; + int delimIndex;// 占位符所在位置 + for (int argIndex = 0; argIndex < argArray.length; argIndex++) + { + delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); + if (delimIndex == -1) + { + if (handledPosition == 0) + { + return strPattern; + } + else + { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 + sbuf.append(strPattern, handledPosition, strPatternLength); + return sbuf.toString(); + } + } + else + { + if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) + { + if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) + { + // 转义符之前还有一个转义符,占位符依旧有效 + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + else + { + // 占位符被转义 + argIndex--; + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(C_DELIM_START); + handledPosition = delimIndex + 1; + } + } + else + { + // 正常占位符 + sbuf.append(strPattern, handledPosition, delimIndex); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + } + } + // 加入最后一个占位符后所有的字符 + sbuf.append(strPattern, handledPosition, strPattern.length()); + + return sbuf.toString(); + } +} diff --git a/src/main/java/cn/sliyun/common/enums/HttpMethod.java b/src/main/java/cn/sliyun/common/enums/HttpMethod.java new file mode 100644 index 0000000..b2f811c --- /dev/null +++ b/src/main/java/cn/sliyun/common/enums/HttpMethod.java @@ -0,0 +1,36 @@ +package cn.sliyun.common.enums; + +import java.util.HashMap; +import java.util.Map; +import org.springframework.lang.Nullable; + +/** + * 请求方式 + * + * @author ruoyi + */ +public enum HttpMethod +{ + GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; + + private static final Map mappings = new HashMap<>(16); + + static + { + for (HttpMethod httpMethod : values()) + { + mappings.put(httpMethod.name(), httpMethod); + } + } + + @Nullable + public static HttpMethod resolve(@Nullable String method) + { + return (method != null ? mappings.get(method) : null); + } + + public boolean matches(String method) + { + return (this == resolve(method)); + } +} diff --git a/src/main/java/cn/sliyun/common/enums/UserStatus.java b/src/main/java/cn/sliyun/common/enums/UserStatus.java new file mode 100644 index 0000000..a06ac08 --- /dev/null +++ b/src/main/java/cn/sliyun/common/enums/UserStatus.java @@ -0,0 +1,30 @@ +package cn.sliyun.common.enums; + +/** + * 用户状态 + * + * @author ruoyi + */ +public enum UserStatus +{ + OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除"); + + private final String code; + private final String info; + + UserStatus(String code, String info) + { + this.code = code; + this.info = info; + } + + public String getCode() + { + return code; + } + + public String getInfo() + { + return info; + } +} diff --git a/src/main/java/cn/sliyun/common/exception/AppException.java b/src/main/java/cn/sliyun/common/exception/AppException.java new file mode 100644 index 0000000..78cf2e4 --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/AppException.java @@ -0,0 +1,62 @@ +package cn.sliyun.common.exception; + +/** + * 自定义异常 + * + * @author ruoyi + */ +public class AppException extends RuntimeException { + private static final long serialVersionUID = 1L; + + + private int code; //异常状态码 + private String message; //异常信息 + private String error; //描述 + + + public AppException(String message) { + this.message = message; + } + + /** + * @param code 状态 + * @param message 信息 + * @param error 错误,描述! + */ + public AppException(int code, String message, String error) { + this.code = code; + this.message = message; + this.error = error; + } + + public AppException(String message, Integer code) { + this.message = message; + this.code = code; + } + + public AppException(String message, Throwable e) { + super(message, e); + this.message = message; + } + + @Override + public String getMessage() { + return message; + } + + public Integer getCode() { + return code; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } +} diff --git a/src/main/java/cn/sliyun/common/exception/BaseException.java b/src/main/java/cn/sliyun/common/exception/BaseException.java new file mode 100644 index 0000000..a763f70 --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/BaseException.java @@ -0,0 +1,97 @@ +package cn.sliyun.common.exception; + +import cn.sliyun.common.utils.MessageUtils; +import cn.sliyun.common.utils.StringUtils; + +/** + * 基础异常 + * + * @author ruoyi + */ +public class BaseException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * 所属模块 + */ + private String module; + + /** + * 错误码 + */ + private String code; + + /** + * 错误码对应的参数 + */ + private Object[] args; + + /** + * 错误消息 + */ + private String defaultMessage; + + public BaseException(String module, String code, Object[] args, String defaultMessage) + { + this.module = module; + this.code = code; + this.args = args; + this.defaultMessage = defaultMessage; + } + + public BaseException(String module, String code, Object[] args) + { + this(module, code, args, null); + } + + public BaseException(String module, String defaultMessage) + { + this(module, null, null, defaultMessage); + } + + public BaseException(String code, Object[] args) + { + this(null, code, args, null); + } + + public BaseException(String defaultMessage) + { + this(null, null, null, defaultMessage); + } + + @Override + public String getMessage() + { + String message = null; + if (!StringUtils.isEmpty(code)) + { + message = MessageUtils.message(code, args); + } + if (message == null) + { + message = defaultMessage; + } + return message; + } + + public String getModule() + { + return module; + } + + public String getCode() + { + return code; + } + + public Object[] getArgs() + { + return args; + } + + public String getDefaultMessage() + { + return defaultMessage; + } +} diff --git a/src/main/java/cn/sliyun/common/exception/DemoModeException.java b/src/main/java/cn/sliyun/common/exception/DemoModeException.java new file mode 100644 index 0000000..5e7375d --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/DemoModeException.java @@ -0,0 +1,15 @@ +package cn.sliyun.common.exception; + +/** + * 演示模式异常 + * + * @author ruoyi + */ +public class DemoModeException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public DemoModeException() + { + } +} diff --git a/src/main/java/cn/sliyun/common/exception/UtilException.java b/src/main/java/cn/sliyun/common/exception/UtilException.java new file mode 100644 index 0000000..9074d92 --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/UtilException.java @@ -0,0 +1,26 @@ +package cn.sliyun.common.exception; + +/** + * 工具类异常 + * + * @author ruoyi + */ +public class UtilException extends RuntimeException +{ + private static final long serialVersionUID = 8247610319171014183L; + + public UtilException(Throwable e) + { + super(e.getMessage(), e); + } + + public UtilException(String message) + { + super(message); + } + + public UtilException(String message, Throwable throwable) + { + super(message, throwable); + } +} diff --git a/src/main/java/cn/sliyun/common/exception/file/FileException.java b/src/main/java/cn/sliyun/common/exception/file/FileException.java new file mode 100644 index 0000000..a748bdc --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/file/FileException.java @@ -0,0 +1,19 @@ +package cn.sliyun.common.exception.file; + +import cn.sliyun.common.exception.BaseException; + +/** + * 文件信息异常类 + * + * @author ruoyi + */ +public class FileException extends BaseException +{ + private static final long serialVersionUID = 1L; + + public FileException(String code, Object[] args) + { + super("file", code, args, null); + } + +} diff --git a/src/main/java/cn/sliyun/common/exception/file/FileNameLengthLimitExceededException.java b/src/main/java/cn/sliyun/common/exception/file/FileNameLengthLimitExceededException.java new file mode 100644 index 0000000..7a26525 --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/file/FileNameLengthLimitExceededException.java @@ -0,0 +1,16 @@ +package cn.sliyun.common.exception.file; + +/** + * 文件名称超长限制异常类 + * + * @author ruoyi + */ +public class FileNameLengthLimitExceededException extends FileException +{ + private static final long serialVersionUID = 1L; + + public FileNameLengthLimitExceededException(int defaultFileNameLength) + { + super("上传的文件名最长{0}个字符", new Object[] { defaultFileNameLength }); + } +} diff --git a/src/main/java/cn/sliyun/common/exception/file/FileSizeLimitExceededException.java b/src/main/java/cn/sliyun/common/exception/file/FileSizeLimitExceededException.java new file mode 100644 index 0000000..33e3224 --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/file/FileSizeLimitExceededException.java @@ -0,0 +1,16 @@ +package cn.sliyun.common.exception.file; + +/** + * 文件名大小限制异常类 + * + * @author ruoyi + */ +public class FileSizeLimitExceededException extends FileException +{ + private static final long serialVersionUID = 1L; + + public FileSizeLimitExceededException(long defaultMaxSize) + { + super("上传的文件大小超出限制的文件大小!
允许的文件最大大小是:{0}MB!", new Object[] { defaultMaxSize }); + } +} diff --git a/src/main/java/cn/sliyun/common/exception/file/InvalidExtensionException.java b/src/main/java/cn/sliyun/common/exception/file/InvalidExtensionException.java new file mode 100644 index 0000000..8c2918c --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/file/InvalidExtensionException.java @@ -0,0 +1,71 @@ +package cn.sliyun.common.exception.file; + +import java.util.Arrays; +import org.apache.commons.fileupload.FileUploadException; + +/** + * 文件上传 误异常类 + * + * @author ruoyi + */ +public class InvalidExtensionException extends FileUploadException +{ + private static final long serialVersionUID = 1L; + + private String[] allowedExtension; + private String extension; + private String filename; + + public InvalidExtensionException(String[] allowedExtension, String extension, String filename) + { + super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]"); + this.allowedExtension = allowedExtension; + this.extension = extension; + this.filename = filename; + } + + public String[] getAllowedExtension() + { + return allowedExtension; + } + + public String getExtension() + { + return extension; + } + + public String getFilename() + { + return filename; + } + + public static class InvalidImageExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidFlashExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidMediaExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } +} diff --git a/src/main/java/cn/sliyun/common/exception/job/TaskException.java b/src/main/java/cn/sliyun/common/exception/job/TaskException.java new file mode 100644 index 0000000..1ddce81 --- /dev/null +++ b/src/main/java/cn/sliyun/common/exception/job/TaskException.java @@ -0,0 +1,34 @@ +package cn.sliyun.common.exception.job; + +/** + * 计划策略异常 + * + * @author ruoyi + */ +public class TaskException extends Exception +{ + private static final long serialVersionUID = 1L; + + private Code code; + + public TaskException(String msg, Code code) + { + this(msg, code, null); + } + + public TaskException(String msg, Code code, Exception nestedEx) + { + super(msg, nestedEx); + this.code = code; + } + + public Code getCode() + { + return code; + } + + public enum Code + { + TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/filter/RepeatableFilter.java b/src/main/java/cn/sliyun/common/filter/RepeatableFilter.java new file mode 100644 index 0000000..7a7d132 --- /dev/null +++ b/src/main/java/cn/sliyun/common/filter/RepeatableFilter.java @@ -0,0 +1,53 @@ +package cn.sliyun.common.filter; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import cn.sliyun.common.utils.StringUtils; +import org.springframework.http.MediaType; + +/** + * Repeatable 过滤器 + * + * @author ruoyi + */ +public class RepeatableFilter implements Filter +{ + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + ServletRequest requestWrapper = null; + if (request instanceof HttpServletRequest + && StringUtils.equalsAnyIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) + { + requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); + } + if (null == requestWrapper) + { + chain.doFilter(request, response); + } + else + { + chain.doFilter(requestWrapper, response); + } + } + + @Override + public void destroy() + { + + } +} diff --git a/src/main/java/cn/sliyun/common/filter/RepeatedlyRequestWrapper.java b/src/main/java/cn/sliyun/common/filter/RepeatedlyRequestWrapper.java new file mode 100644 index 0000000..8c998dd --- /dev/null +++ b/src/main/java/cn/sliyun/common/filter/RepeatedlyRequestWrapper.java @@ -0,0 +1,73 @@ +package cn.sliyun.common.filter; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import cn.sliyun.common.utils.http.HttpHelper; + +/** + * 构建可重复读取inputStream的request + * + * @author ruoyi + */ +public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper +{ + private final byte[] body; + + public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException + { + super(request); + request.setCharacterEncoding("UTF-8"); + response.setCharacterEncoding("UTF-8"); + + body = HttpHelper.getBodyString(request).getBytes("UTF-8"); + } + + @Override + public BufferedReader getReader() throws IOException + { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + + final ByteArrayInputStream bais = new ByteArrayInputStream(body); + + return new ServletInputStream() + { + + @Override + public int read() throws IOException + { + return bais.read(); + } + + @Override + public boolean isFinished() + { + return false; + } + + @Override + public boolean isReady() + { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) + { + + } + }; + } +} diff --git a/src/main/java/cn/sliyun/common/filter/XssFilter.java b/src/main/java/cn/sliyun/common/filter/XssFilter.java new file mode 100644 index 0000000..1fd485c --- /dev/null +++ b/src/main/java/cn/sliyun/common/filter/XssFilter.java @@ -0,0 +1,98 @@ +package cn.sliyun.common.filter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.sliyun.common.utils.StringUtils; + +/** + * 防止XSS攻击的过滤器 + * + * @author ruoyi + */ +public class XssFilter implements Filter +{ + /** + * 排除链接 + */ + public List excludes = new ArrayList<>(); + + /** + * xss过滤开关 + */ + public boolean enabled = false; + + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + String tempExcludes = filterConfig.getInitParameter("excludes"); + String tempEnabled = filterConfig.getInitParameter("enabled"); + if (StringUtils.isNotEmpty(tempExcludes)) + { + String[] url = tempExcludes.split(","); + for (int i = 0; url != null && i < url.length; i++) + { + excludes.add(url[i]); + } + } + if (StringUtils.isNotEmpty(tempEnabled)) + { + enabled = Boolean.valueOf(tempEnabled); + } + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + if (handleExcludeURL(req, resp)) + { + chain.doFilter(request, response); + return; + } + XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); + chain.doFilter(xssRequest, response); + } + + private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) + { + if (!enabled) + { + return true; + } + if (excludes == null || excludes.isEmpty()) + { + return false; + } + String url = request.getServletPath(); + for (String pattern : excludes) + { + Pattern p = Pattern.compile("^" + pattern); + Matcher m = p.matcher(url); + if (m.find()) + { + return true; + } + } + return false; + } + + @Override + public void destroy() + { + + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/filter/XssHttpServletRequestWrapper.java b/src/main/java/cn/sliyun/common/filter/XssHttpServletRequestWrapper.java new file mode 100644 index 0000000..d210db2 --- /dev/null +++ b/src/main/java/cn/sliyun/common/filter/XssHttpServletRequestWrapper.java @@ -0,0 +1,105 @@ +package cn.sliyun.common.filter; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.html.EscapeUtil; +import org.apache.commons.io.IOUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +/** + * XSS过滤处理 + * + * @author ruoyi + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper +{ + /** + * @param request + */ + public XssHttpServletRequestWrapper(HttpServletRequest request) + { + super(request); + } + + @Override + public String[] getParameterValues(String name) + { + String[] values = super.getParameterValues(name); + if (values != null) + { + int length = values.length; + String[] escapseValues = new String[length]; + for (int i = 0; i < length; i++) + { + // 防xss攻击和过滤前后空格 + escapseValues[i] = EscapeUtil.clean(values[i]).trim(); + } + return escapseValues; + } + return super.getParameterValues(name); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + // 非json类型,直接返回 + if (!isJsonRequest()) + { + return super.getInputStream(); + } + + // 为空,直接返回 + String json = IOUtils.toString(super.getInputStream(), "utf-8"); + if (StringUtils.isEmpty(json)) + { + return super.getInputStream(); + } + + // xss过滤 + json = EscapeUtil.clean(json).trim(); + final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8")); + return new ServletInputStream() + { + @Override + public boolean isFinished() + { + return true; + } + + @Override + public boolean isReady() + { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) + { + } + + @Override + public int read() throws IOException + { + return bis.read(); + } + }; + } + + /** + * 是否是Json请求 + * + * @param request + */ + public boolean isJsonRequest() + { + String header = super.getHeader(HttpHeaders.CONTENT_TYPE); + return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/AliyunOSSUtil.java b/src/main/java/cn/sliyun/common/utils/AliyunOSSUtil.java new file mode 100644 index 0000000..9520d14 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/AliyunOSSUtil.java @@ -0,0 +1,168 @@ +package cn.sliyun.common.utils; + +import cn.sliyun.framework.config.OSSConfig; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClient; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.OSSException; +import com.aliyun.oss.model.CannedAccessControlList; +import com.aliyun.oss.model.CreateBucketRequest; +import com.aliyun.oss.model.PutObjectRequest; +import com.aliyun.oss.model.PutObjectResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +public class AliyunOSSUtil { + + private static AliyunOSSUtil instance = null; + + + public static AliyunOSSUtil getInstance() { + if (null == instance) { + instance = new AliyunOSSUtil(); + } + return instance; + } + + public AliyunOSSUtil() { + init(); + } + + public static String upload(File file) { + return upload(file, OSSConfig.OSS_FILE_HOST); + } + + + public static String uploadApk(File file) { + return upload(file, OSSConfig.OSS_FILE_HOST); + } + + public static String uploadImg(File file) { + return upload(file, "img"); + } + + public static String upload(File file, String path) { + Logger logger = LoggerFactory.getLogger(AliyunOSSUtil.class); + String endpoint = OSSConfig.OSS_END_POINT; + String accessKeyId = OSSConfig.OSS_ACCESS_KEY_ID; + String accessKeySecret = OSSConfig.OSS_ACCESS_KEY_SECRET; + String bucketName = OSSConfig.OSS_BUCKET_NAME; + String fileHost = path; + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + String dateStr = format.format(new Date()); + if (null == file) { + return null; + } + OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); + try { + //容器不存在,就创建 + if (!ossClient.doesBucketExist(bucketName)) { + ossClient.createBucket(bucketName); + CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); + createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); + ossClient.createBucket(createBucketRequest); + } + + //创建文件路径 + String fileUrl = fileHost + "/" + (dateStr + "/" + UUID.randomUUID().toString().replace("-", "") + "-"); + + String fileName = URLDecoder.decode(file.getName().toString(), "UTF-8").replaceAll(" ", ""); + + fileUrl = fileUrl + fileName; + //上传文件 + PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, file)); + //设置权限 这里是公开读 + ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead); + if (null != result) { + + return "https://" + bucketName + "." + endpoint + "/" + fileUrl; + } + } catch (OSSException | UnsupportedEncodingException oe) { + logger.error(oe.toString()); + } finally { + logger.error("ossClient finally"); + //关闭 + ossClient.shutdown(); + } + return null; + } + + + + public String uploadImage(MultipartFile file) { + Logger logger = LoggerFactory.getLogger(AliyunOSSUtil.class); + String endpoint = OSSConfig.OSS_END_POINT; + String accessKeyId = OSSConfig.OSS_ACCESS_KEY_ID; + String accessKeySecret = OSSConfig.OSS_ACCESS_KEY_SECRET; + String bucketName = OSSConfig.OSS_BUCKET_NAME; + String fileHost = "img"; + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + String dateStr = format.format(new Date()); + if (null == file) { + return null; + } + OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); + try { + //容器不存在,就创建 + if (!ossClient.doesBucketExist(bucketName)) { + ossClient.createBucket(bucketName); + CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); + createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); + ossClient.createBucket(createBucketRequest); + } + + String fileUrl = fileHost + "/"; + String oldName = file.getOriginalFilename(); + System.out.println("-----------文件原始的名字【" + oldName + "】-----------"); + String newName = "img_coin_" + System.currentTimeMillis() + oldName.substring(oldName.lastIndexOf(".")); + System.out.println("-----------文件要保存后的新名字【" + newName + "】-----------"); + String fileName = URLDecoder.decode(newName, "UTF-8").replaceAll(" ", ""); + + fileUrl = fileUrl + fileName; + //上传文件 + InputStream multipartFileInputStream = file.getInputStream(); + + PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, multipartFileInputStream)); + //设置权限 这里是公开读 + ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead); + if (null != result) { + return newName; + } + } catch (OSSException | UnsupportedEncodingException oe) { + logger.error(oe.toString()); + } catch (IOException e) { + e.printStackTrace(); + } finally { + logger.error("ossClient finally"); + //关闭 + ossClient.shutdown(); + } + return null; + } + + + OSS ossClient; + + private void init() { + ossClient = new OSSClientBuilder().build(OSSConfig.OSS_END_POINT, OSSConfig.OSS_ACCESS_KEY_ID, OSSConfig.OSS_ACCESS_KEY_SECRET); + + } + + + public String getFileUrl(String objectName) { + objectName = OSSConfig.OSS_IMG_PATH + objectName; + return OSSConfig.OSS_DOMAIN + objectName; } + +} diff --git a/src/main/java/cn/sliyun/common/utils/Arith.java b/src/main/java/cn/sliyun/common/utils/Arith.java new file mode 100644 index 0000000..d3bb2dd --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/Arith.java @@ -0,0 +1,114 @@ +package cn.sliyun.common.utils; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 精确的浮点数运算 + * + * @author ruoyi + */ +public class Arith +{ + + /** 默认除法运算精度 */ + private static final int DEF_DIV_SCALE = 10; + + /** 这个类不能实例化 */ + private Arith() + { + } + + /** + * 提供精确的加法运算。 + * @param v1 被加数 + * @param v2 加数 + * @return 两个参数的和 + */ + public static double add(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.add(b2).doubleValue(); + } + + /** + * 提供精确的减法运算。 + * @param v1 被减数 + * @param v2 减数 + * @return 两个参数的差 + */ + public static double sub(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.subtract(b2).doubleValue(); + } + + /** + * 提供精确的乘法运算。 + * @param v1 被乘数 + * @param v2 乘数 + * @return 两个参数的积 + */ + public static double mul(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.multiply(b2).doubleValue(); + } + + /** + * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 + * 小数点以后10位,以后的数字四舍五入。 + * @param v1 被除数 + * @param v2 除数 + * @return 两个参数的商 + */ + public static double div(double v1, double v2) + { + return div(v1, v2, DEF_DIV_SCALE); + } + + /** + * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 + * 定精度,以后的数字四舍五入。 + * @param v1 被除数 + * @param v2 除数 + * @param scale 表示表示需要精确到小数点以后几位。 + * @return 两个参数的商 + */ + public static double div(double v1, double v2, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + if (b1.compareTo(BigDecimal.ZERO) == 0) + { + return BigDecimal.ZERO.doubleValue(); + } + return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); + } + + /** + * 提供精确的小数位四舍五入处理。 + * @param v 需要四舍五入的数字 + * @param scale 小数点后保留几位 + * @return 四舍五入后的结果 + */ + public static double round(double v, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b = new BigDecimal(Double.toString(v)); + BigDecimal one = new BigDecimal("1"); + return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); + } +} diff --git a/src/main/java/cn/sliyun/common/utils/DateUtils.java b/src/main/java/cn/sliyun/common/utils/DateUtils.java new file mode 100644 index 0000000..3e29fe8 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/DateUtils.java @@ -0,0 +1,155 @@ +package cn.sliyun.common.utils; + +import java.lang.management.ManagementFactory; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import org.apache.commons.lang3.time.DateFormatUtils; + +/** + * 时间工具类 + * + * @author ruoyi + */ +public class DateUtils extends org.apache.commons.lang3.time.DateUtils +{ + public static String YYYY = "yyyy"; + + public static String YYYY_MM = "yyyy-MM"; + + public static String YYYY_MM_DD = "yyyy-MM-dd"; + + public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + + private static String[] parsePatterns = { + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + + /** + * 获取当前Date型日期 + * + * @return Date() 当前日期 + */ + public static Date getNowDate() + { + return new Date(); + } + + /** + * 获取当前日期, 默认格式为yyyy-MM-dd + * + * @return String + */ + public static String getDate() + { + return dateTimeNow(YYYY_MM_DD); + } + + public static final String getTime() + { + return dateTimeNow(YYYY_MM_DD_HH_MM_SS); + } + + public static final String dateTimeNow() + { + return dateTimeNow(YYYYMMDDHHMMSS); + } + + public static final String dateTimeNow(final String format) + { + return parseDateToStr(format, new Date()); + } + + public static final String dateTime(final Date date) + { + return parseDateToStr(YYYY_MM_DD, date); + } + + public static final String parseDateToStr(final String format, final Date date) + { + return new SimpleDateFormat(format).format(date); + } + + public static final Date dateTime(final String format, final String ts) + { + try + { + return new SimpleDateFormat(format).parse(ts); + } + catch (ParseException e) + { + throw new RuntimeException(e); + } + } + + /** + * 日期路径 即年/月/日 如2018/08/08 + */ + public static final String datePath() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyy/MM/dd"); + } + + /** + * 日期路径 即年/月/日 如20180808 + */ + public static final String dateTime() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyyMMdd"); + } + + /** + * 日期型字符串转化为日期 格式 + */ + public static Date parseDate(Object str) + { + if (str == null) + { + return null; + } + try + { + return parseDate(str.toString(), parsePatterns); + } + catch (ParseException e) + { + return null; + } + } + + /** + * 获取服务器启动时间 + */ + public static Date getServerStartDate() + { + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + return new Date(time); + } + + /** + * 计算两个时间差 + */ + public static String getDatePoor(Date endDate, Date nowDate) + { + long nd = 1000 * 24 * 60 * 60; + long nh = 1000 * 60 * 60; + long nm = 1000 * 60; + // long ns = 1000; + // 获得两个时间的毫秒时间差异 + long diff = endDate.getTime() - nowDate.getTime(); + // 计算差多少天 + long day = diff / nd; + // 计算差多少小时 + long hour = diff % nd / nh; + // 计算差多少分钟 + long min = diff % nd % nh / nm; + // 计算差多少秒//输出结果 + // long sec = diff % nd % nh % nm / ns; + return day + "天" + hour + "小时" + min + "分钟"; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/DictUtils.java b/src/main/java/cn/sliyun/common/utils/DictUtils.java new file mode 100644 index 0000000..34465ca --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/DictUtils.java @@ -0,0 +1,168 @@ +package cn.sliyun.common.utils; + +import java.util.List; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.project.system.domain.SysDictData; + +/** + * 字典工具类 + * + * @author ruoyi + */ +public class DictUtils +{ + /** + * 分隔符 + */ + public static final String SEPARATOR = ","; + + /** + * 设置字典缓存 + * + * @param key 参数键 + * @param dictDatas 字典数据列表 + */ + public static void setDictCache(String key, List dictDatas) + { +// SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas); + } + + /** + * 获取字典缓存 + * + * @param key 参数键 + * @return dictDatas 字典数据列表 + */ + public static List getDictCache(String key) + { +// Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); +// if (StringUtils.isNotNull(cacheObj)) +// { +// List dictDatas = StringUtils.cast(cacheObj); +// return dictDatas; +// } + return null; + } + + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @return 字典标签 + */ + public static String getDictLabel(String dictType, String dictValue) + { + return getDictLabel(dictType, dictValue, SEPARATOR); + } + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @return 字典值 + */ + public static String getDictValue(String dictType, String dictLabel) + { + return getDictValue(dictType, dictLabel, SEPARATOR); + } + + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String getDictLabel(String dictType, String dictValue, String separator) + { + StringBuilder propertyString = new StringBuilder(); + List datas = getDictCache(dictType); + + if (StringUtils.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas)) + { + for (SysDictData dict : datas) + { + for (String value : dictValue.split(separator)) + { + if (value.equals(dict.getDictValue())) + { + propertyString.append(dict.getDictLabel() + separator); + break; + } + } + } + } + else + { + for (SysDictData dict : datas) + { + if (dictValue.equals(dict.getDictValue())) + { + return dict.getDictLabel(); + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @param separator 分隔符 + * @return 字典值 + */ + public static String getDictValue(String dictType, String dictLabel, String separator) + { + StringBuilder propertyString = new StringBuilder(); + List datas = getDictCache(dictType); + + if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas)) + { + for (SysDictData dict : datas) + { + for (String label : dictLabel.split(separator)) + { + if (label.equals(dict.getDictLabel())) + { + propertyString.append(dict.getDictValue() + separator); + break; + } + } + } + } + else + { + for (SysDictData dict : datas) + { + if (dictLabel.equals(dict.getDictLabel())) + { + return dict.getDictValue(); + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 清空字典缓存 + */ + public static void clearDictCache() + { + } + + /** + * 设置cache key + * + * @param configKey 参数键 + * @return 缓存键key + */ + public static String getCacheKey(String configKey) + { + return Constants.SYS_DICT_KEY + configKey; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/ExceptionUtil.java b/src/main/java/cn/sliyun/common/utils/ExceptionUtil.java new file mode 100644 index 0000000..d348339 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/ExceptionUtil.java @@ -0,0 +1,40 @@ +package cn.sliyun.common.utils; + +import java.io.PrintWriter; +import java.io.StringWriter; +import org.apache.commons.lang3.exception.ExceptionUtils; + +/** + * 错误信息处理类。 + * + * @author ruoyi + */ +public class ExceptionUtil +{ + /** + * 获取exception的详细错误信息。 + */ + public static String getExceptionMessage(Throwable e) + { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw, true)); + String str = sw.toString(); + return str; + } + + public static String getRootErrorMseeage(Exception e) + { + Throwable root = ExceptionUtils.getRootCause(e); + root = (root == null ? e : root); + if (root == null) + { + return ""; + } + String msg = root.getMessage(); + if (msg == null) + { + return "null"; + } + return StringUtils.defaultString(msg); + } +} diff --git a/src/main/java/cn/sliyun/common/utils/IdUtil.java b/src/main/java/cn/sliyun/common/utils/IdUtil.java new file mode 100644 index 0000000..57b534d --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/IdUtil.java @@ -0,0 +1,54 @@ +package cn.sliyun.common.utils; + +import org.apache.commons.lang.StringUtils; + +import java.math.BigInteger; +import java.util.Random; + +public class IdUtil { + private static final long EPOCH = 1479533469598L; //开始时间,固定一个小于当前时间的毫秒数 + private static final int max12bit = 4095; + private static final long max41bit= 1099511627775L; + private static String machineId = "" ; // 机器ID + + /** + * + * 创建ID + * + * @return + * + */ + public static String create(){ + + long time = System.currentTimeMillis() - EPOCH + max41bit; + // 二进制的 毫秒级时间戳 + String base = Long.toBinaryString(time); + + // 序列数 + String randomStr = StringUtils.leftPad(Integer.toBinaryString(new Random().nextInt(max12bit)),12,'0'); + if(StringUtils.isNotEmpty(machineId)){ + machineId = StringUtils.leftPad(machineId, 10, '0'); + } + + //拼接 + String appendStr = base + machineId + randomStr; + // 转化为十进制 返回 + BigInteger bi = new BigInteger(appendStr, 2); + + return Long.valueOf(bi.toString())+""; + } + + /** + * + * 创建ID + * + * @return + * + */ + public static String genNickname(){ + + long time = System.currentTimeMillis() - EPOCH + max41bit; + // 二进制的 毫秒级时间戳 + String base = Long.toBinaryString(time); + return "算力云会员"+ base.substring(base.length()-6,base.length());} +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/IdUtils.java b/src/main/java/cn/sliyun/common/utils/IdUtils.java new file mode 100644 index 0000000..50f01d7 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/IdUtils.java @@ -0,0 +1,54 @@ +package cn.sliyun.common.utils; + +import cn.sliyun.common.core.lang.UUID; + +/** + * ID生成器工具类 + * + * @author ruoyi + */ +public class IdUtils +{ + /** + * 获取随机UUID + * + * @return 随机UUID + */ + public static String randomUUID() + { + return UUID.randomUUID().toString(); + } + + /** + * 简化的UUID,去掉了横线 + * + * @return 简化的UUID,去掉了横线 + */ + public static String simpleUUID() + { + return UUID.randomUUID().toString(true); + } + + /** + * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID + * + * @return 随机UUID + */ + public static String fastUUID() + { + return UUID.fastUUID().toString(); + } + + /** + * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID + * + * @return 简化的UUID,去掉了横线 + */ + public static String fastSimpleUUID() + { + return UUID.fastUUID().toString(true); + } + + + +} diff --git a/src/main/java/cn/sliyun/common/utils/LogUtils.java b/src/main/java/cn/sliyun/common/utils/LogUtils.java new file mode 100644 index 0000000..326b516 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/LogUtils.java @@ -0,0 +1,18 @@ +package cn.sliyun.common.utils; + +/** + * 处理并记录日志文件 + * + * @author ruoyi + */ +public class LogUtils +{ + public static String getBlock(Object msg) + { + if (msg == null) + { + msg = ""; + } + return "[" + msg.toString() + "]"; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/MessageUtils.java b/src/main/java/cn/sliyun/common/utils/MessageUtils.java new file mode 100644 index 0000000..be8ec26 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/MessageUtils.java @@ -0,0 +1,21 @@ +package cn.sliyun.common.utils; + +/** + * 获取i18n资源文件 + * + * @author ruoyi + */ +public class MessageUtils +{ + /** + * 根据消息键和参数 获取消息 委托给spring messageSource + * + * @param code 消息键 + * @param args 参数 + * @return 获取国际化翻译值 + */ + public static String message(String code, Object... args) + { + return code; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/RegUtil.java b/src/main/java/cn/sliyun/common/utils/RegUtil.java new file mode 100644 index 0000000..25b7c15 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/RegUtil.java @@ -0,0 +1,282 @@ +package cn.sliyun.common.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RegUtil { + /** + * 验证身份证号码 + * + * @param idCard 居民身份证号码15位或18位,最后一位可能是数字或字母 + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkIdCard(String idCard) { + String regex = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}"; + return Pattern.matches(regex, idCard); + } + + /** + * 验证手机号码(支持国际格式,+86135xxxx...(中国内地),+00852137xxxx...(中国香港)) + * + * @param mobile 移动、联通、电信运营商的号码段 + *

移动的号段:134(0-8)、135、136、137、138、139、147(预计用于TD上网卡) + * 、150、151、152、157(TD专用)、158、159、187(未启用)、188(TD专用)

+ *

联通的号段:130、131、132、155、156(世界风专用)、185(未启用)、186(3g)

+ *

电信的号段:133、153、180(未启用)、189

+ * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkMobile(String mobile) { + String regex = "(\\+\\d+)?1[23456789]\\d{9}$"; + return Pattern.matches(regex, mobile); + } + + /** + * 验证固定电话号码 + * + * @param phone 电话号码,格式:国家(地区)电话代码 + 区号(城市代码) + 电话号码,如:+8602085588447 + *

国家(地区) 代码 :标识电话号码的国家(地区)的标准国家(地区)代码。它包含从 0 到 9 的一位或多位数字, + * 数字之后是空格分隔的国家(地区)代码。

+ *

区号(城市代码):这可能包含一个或多个从 0 到 9 的数字,地区或城市代码放在圆括号—— + * 对不使用地区或城市代码的国家(地区),则省略该组件。

+ *

电话号码:这包含从 0 到 9 的一个或多个数字

+ * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkPhone(String phone) { + String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$"; + return Pattern.matches(regex, phone); + } + + /** + * 验证整数(正整数和负整数) + * + * @param digit 一位或多位0-9之间的整数 + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkDigit(String digit) { + String regex = "\\-?[1-9]\\d+"; + return Pattern.matches(regex, digit); + } + + /** + * 验证整数和浮点数(正负整数和正负浮点数) + * + * @param decimals 一位或多位0-9之间的浮点数,如:1.23,233.30 + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkDecimals(String decimals) { + String regex = "\\-?[1-9]\\d+(\\.\\d+)?"; + return Pattern.matches(regex, decimals); + } + + /** + * 验证空白字符 + * + * @param blankSpace 空白字符,包括:空格、\t、\n、\r、\f、\x0B + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkBlankSpace(String blankSpace) { + String regex = "\\s+"; + return Pattern.matches(regex, blankSpace); + } + + /** + * 验证中文 + * + * @param chinese 中文字符 + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkChinese(String chinese) { + String regex = "^[\u4E00-\u9FA5]+$"; + return Pattern.matches(regex, chinese); + } + + /** + * 验证日期(年月日) + * + * @param birthday 日期,格式:1992-09-03,或1992.09.03 + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkBirthday(String birthday) { + String regex = "[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}"; + return Pattern.matches(regex, birthday); + } + + /** + * 验证URL地址 + * + * @param url 格式:http://blog.csdn.net:80/xyang81/article/details/7705960? 或 http://www.csdn.net:80 + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkURL(String url) { + String regex = "(http|https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?"; + return Pattern.matches(regex, url); + } + + /** + * 匹配中国邮政编码 + * + * @param postcode 邮政编码 + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkPostcode(String postcode) { + String regex = "[1-9]\\d{5}"; + return Pattern.matches(regex, postcode); + } + + /** + * 匹配IP地址(简单匹配,格式,如:192.168.1.1,127.0.0.1,没有匹配IP段的大小) + * + * @param ipAddress IPv4标准地址 + * @return 验证成功返回true,验证失败返回false + */ + public static boolean checkIpAddress(String ipAddress) { + String regex = "[1-9](\\d{1,2})?\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))"; + return Pattern.matches(regex, ipAddress); + } + private static Pattern numericPattern = Pattern.compile("^[0-9\\-]+$"); + private static Pattern numericStringPattern = Pattern.compile("^[0-9\\-\\-]+$"); + private static Pattern floatNumericPattern = Pattern.compile("^[0-9\\-\\.]+$"); + private static Pattern abcPattern = Pattern.compile("^[a-z|A-Z]+$"); + + + public static final String splitStrPattern = ",|,|;|;|、|\\.|。|-|_|\\(|\\)|\\[|\\]|\\{|\\}|\\\\|/| | |\""; + /** + * 判断是否数字表示 + * + * @param src 源字符串 + * @return 是否数字的标志 + */ + public static boolean isNumeric(String src) { + boolean return_value = false; + if (src != null && src.length() > 0) { + Matcher m = numericPattern.matcher(src); + if (m.find()) { + return_value = true; + } + } + return return_value; + } + + /** + * 判断是否纯字母组合 + * + * @param src 源字符串 + * @return 是否纯字母组合的标志 + */ + public static boolean isABC(String src) { + boolean return_value = false; + if (src != null && src.length() > 0) { + Matcher m = abcPattern.matcher(src); + if (m.find()) { + return_value = true; + } + } + return return_value; + } + + /** + * 判断是否数字表示 + * + * @param src 源字符串 + * @return 是否数字的标志 + */ + public static boolean isNumericString(String src) { + boolean return_value = false; + if (src != null && src.length() > 0) { + Matcher m = numericStringPattern.matcher(src); + if (m.find()) { + return_value = true; + } + } + return return_value; + } + /** + * 判断是否浮点数字表示 + * + * @param src 源字符串 + * @return 是否数字的标志 + */ + public static boolean isFloatNumeric(String src) { + boolean return_value = false; + if (src != null && src.length() > 0) { + Matcher m = floatNumericPattern.matcher(src); + if (m.find()) { + return_value = true; + } + } + return return_value; + } + + /** + * 判断字符串str是否符合正则表达式reg + * @param str + * @param reg + * @return + */ + public static boolean isMatche(String str,String reg){ + Pattern pattern = Pattern.compile(reg); + Matcher isNum = pattern.matcher(str); + if( !isNum.matches() ){ + return false; + } + return true; + } + + /** + * 获取符合reg正则表达式的字符串在String中出现的次数 + * + * @param str + * @param reg + * @return + */ + public static int countSubStrReg(String str, String reg) { + Pattern p = Pattern.compile(reg); + Matcher m = p.matcher(str); + int i = 0; + while (m.find()) { + String temp = m.group(0); + i += temp.length(); + } + return i; + } + + /** + * @param str + * @return + * @Method:判断是否是整数 + */ + public static boolean isInteger(String str) { + String reg = "^[-\\+]?[\\d]+$"; + Pattern pattern = Pattern.compile(reg); + return pattern.matcher(str).matches(); + } + + + /** + * @param email + * @return + * @Method:判断是否是符合邮箱 + */ + public static boolean isEmail(String email) { + if (email == null || email.length() < 1 || email.length() > 256) { + return false; + } + String reg = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; + Pattern pattern = Pattern + .compile(reg); + return pattern.matcher(email).matches(); + } + + /** + * is url + * + * @return + */ + public static boolean isUrl(String url) { + String reg ="^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+$"; + Pattern pattern = Pattern.compile(reg); + return pattern.matcher(url).matches(); + } + +} + diff --git a/src/main/java/cn/sliyun/common/utils/SecurityUtils.java b/src/main/java/cn/sliyun/common/utils/SecurityUtils.java new file mode 100644 index 0000000..f4a704e --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/SecurityUtils.java @@ -0,0 +1,90 @@ +package cn.sliyun.common.utils; + +import cn.sliyun.framework.security.LoginUser; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import cn.sliyun.common.constant.HttpStatus; +import cn.sliyun.common.exception.AppException; + +/** + * 安全服务工具类 + * + * @author ruoyi + */ +public class SecurityUtils +{ + /** + * 获取用户账户 + **/ + public static String getUsername() + { + try + { + return getLoginUser().getUsername(); + } + catch (Exception e) + { + throw new AppException("获取用户账户异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获取用户 + **/ + public static LoginUser getLoginUser() + { + try + { + return (LoginUser) getAuthentication().getPrincipal(); + } + catch (Exception e) + { + throw new AppException("获取用户信息异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获取Authentication + */ + public static Authentication getAuthentication() + { + return SecurityContextHolder.getContext().getAuthentication(); + } + + /** + * 生成BCryptPasswordEncoder密码 + * + * @param password 密码 + * @return 加密字符串 + */ + public static String encryptPassword(String password) + { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(password); + } + + /** + * 判断密码是否相同 + * + * @param rawPassword 真实密码 + * @param encodedPassword 加密后字符 + * @return 结果 + */ + public static boolean matchesPassword(String rawPassword, String encodedPassword) + { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + /** + * 是否为管理员 + * + * @param userId 用户ID + * @return 结果 + */ + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/ServletUtils.java b/src/main/java/cn/sliyun/common/utils/ServletUtils.java new file mode 100644 index 0000000..2f06ee4 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/ServletUtils.java @@ -0,0 +1,137 @@ +package cn.sliyun.common.utils; + +import java.io.IOException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import cn.sliyun.common.core.text.Convert; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +/** + * 客户端工具类 + * + * @author ruoyi + */ +public class ServletUtils +{ + /** + * 获取String参数 + */ + public static String getParameter(String name) + { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getParameter(String name, String defaultValue) + { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name) + { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name, Integer defaultValue) + { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() + { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() + { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() + { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() + { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + * @return null + */ + public static String renderString(HttpServletResponse response, String string) + { + try + { + response.setStatus(200); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().print(string); + } + catch (IOException e) + { + e.printStackTrace(); + } + return null; + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) + { + String accept = request.getHeader("accept"); + if (accept != null && accept.indexOf("application/json") != -1) + { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) + { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) + { + return true; + } + + String ajax = request.getParameter("__ajax"); + if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) + { + return true; + } + return false; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/StringUtils.java b/src/main/java/cn/sliyun/common/utils/StringUtils.java new file mode 100644 index 0000000..e4ef6ad --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/StringUtils.java @@ -0,0 +1,460 @@ +package cn.sliyun.common.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import cn.sliyun.common.core.text.StrFormatter; + +/** + * 字符串工具类 + * + * @author ruoyi + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils +{ + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** 下划线 */ + private static final char SEPARATOR = '_'; + + /** + * 获取参数不为空值 + * + * @param value defaultValue 要判断的value + * @return value 返回值 + */ + public static T nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Collection coll) + { + return !isEmpty(coll); + } + + /** + * * 判断一个对象数组是否为空 + * + * @param objects 要判断的对象数组 + ** @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * * 判断一个对象数组是否非空 + * + * @param objects 要判断的对象数组 + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Object[] objects) + { + return !isEmpty(objects); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Map map) + { + return isNull(map) || map.isEmpty(); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Map map) + { + return !isEmpty(map); + } + + /** + * * 判断一个字符串是否为空串 + * + * @param str String + * @return true:为空 false:非空 + */ + public static boolean isEmpty(String str) + { + return isNull(str) || NULLSTR.equals(str.trim()); + } + + /** + * * 判断一个字符串是否为非空串 + * + * @param str String + * @return true:非空串 false:空串 + */ + public static boolean isNotEmpty(String str) + { + return !isEmpty(str); + } + + /** + * * 判断一个对象是否为空 + * + * @param object Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) + { + return object == null; + } + + /** + * * 判断一个对象是否非空 + * + * @param object Object + * @return true:非空 false:空 + */ + public static boolean isNotNull(Object object) + { + return !isNull(object); + } + + /** + * * 判断一个对象是否是数组类型(Java基本型别的数组) + * + * @param object 对象 + * @return true:是数组 false:不是数组 + */ + public static boolean isArray(Object object) + { + return isNotNull(object) && object.getClass().isArray(); + } + + /** + * 去空格 + */ + public static String trim(String str) + { + return (str == null ? "" : str.trim()); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @return 结果 + */ + public static String substring(final String str, int start) + { + if (str == null) + { + return NULLSTR; + } + + if (start < 0) + { + start = str.length() + start; + } + + if (start < 0) + { + start = 0; + } + if (start > str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param params 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... params) + { + if (isEmpty(params) || isEmpty(template)) + { + return template; + } + return StrFormatter.format(template, params); + } + + /** + * 字符串转set + * + * @param str 字符串 + * @param sep 分隔符 + * @return set集合 + */ + public static final Set str2Set(String str, String sep) + { + return new HashSet(str2List(str, sep, true, false)); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @param filterBlank 过滤纯空白 + * @param trim 去掉首尾空白 + * @return list集合 + */ + public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) + { + List list = new ArrayList(); + if (StringUtils.isEmpty(str)) + { + return list; + } + + // 过滤空白字符串 + if (filterBlank && StringUtils.isBlank(str)) + { + return list; + } + String[] split = str.split(sep); + for (String string : split) + { + if (filterBlank && StringUtils.isBlank(string)) + { + continue; + } + if (trim) + { + string = string.trim(); + } + list.add(string); + } + + return list; + } + + /** + * 下划线转驼峰命名 + */ + public static String toUnderScoreCase(String str) + { + if (str == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + // 前置字符是否大写 + boolean preCharIsUpperCase = true; + // 当前字符是否大写 + boolean curreCharIsUpperCase = true; + // 下一字符是否大写 + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (i > 0) + { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } + else + { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) + { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) + { + sb.append(SEPARATOR); + } + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) + { + sb.append(SEPARATOR); + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains("_")) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 驼峰式命名法 例如:user_name->userName + */ + public static String toCamelCase(String s) + { + if (s == null) + { + return null; + } + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + if (c == SEPARATOR) + { + upperCase = true; + } + else if (upperCase) + { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + @SuppressWarnings("unchecked") + public static T cast(Object obj) + { + return (T) obj; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/Threads.java b/src/main/java/cn/sliyun/common/utils/Threads.java new file mode 100644 index 0000000..193f854 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/Threads.java @@ -0,0 +1,99 @@ +package cn.sliyun.common.utils; + +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 线程相关工具类. + * + * @author ruoyi + */ +public class Threads +{ + private static final Logger logger = LoggerFactory.getLogger(Threads.class); + + /** + * sleep等待,单位为毫秒 + */ + public static void sleep(long milliseconds) + { + try + { + Thread.sleep(milliseconds); + } + catch (InterruptedException e) + { + return; + } + } + + /** + * 停止线程池 + * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. + * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数. + * 如果仍人超時,則強制退出. + * 另对在shutdown时线程本身被调用中断做了处理. + */ + public static void shutdownAndAwaitTermination(ExecutorService pool) + { + if (pool != null && !pool.isShutdown()) + { + pool.shutdown(); + try + { + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) + { + pool.shutdownNow(); + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) + { + logger.info("Pool did not terminate"); + } + } + } + catch (InterruptedException ie) + { + pool.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + } + + /** + * 打印线程异常信息 + */ + public static void printException(Runnable r, Throwable t) + { + if (t == null && r instanceof Future) + { + try + { + Future future = (Future) r; + if (future.isDone()) + { + future.get(); + } + } + catch (CancellationException ce) + { + t = ce; + } + catch (ExecutionException ee) + { + t = ee.getCause(); + } + catch (InterruptedException ie) + { + Thread.currentThread().interrupt(); + } + } + if (t != null) + { + logger.error(t.getMessage(), t); + } + } +} diff --git a/src/main/java/cn/sliyun/common/utils/bean/BeanUtils.java b/src/main/java/cn/sliyun/common/utils/bean/BeanUtils.java new file mode 100644 index 0000000..36d8a34 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/bean/BeanUtils.java @@ -0,0 +1,110 @@ +package cn.sliyun.common.utils.bean; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Bean 工具类 + * + * @author ruoyi + */ +public class BeanUtils extends org.springframework.beans.BeanUtils +{ + /** Bean方法名中属性名开始的下标 */ + private static final int BEAN_METHOD_PROP_INDEX = 3; + + /** * 匹配getter方法的正则表达式 */ + private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); + + /** * 匹配setter方法的正则表达式 */ + private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); + + /** + * Bean属性复制工具方法。 + * + * @param dest 目标对象 + * @param src 源对象 + */ + public static void copyBeanProp(Object dest, Object src) + { + try + { + copyProperties(src, dest); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * 获取对象的setter方法。 + * + * @param obj 对象 + * @return 对象的setter方法列表 + */ + public static List getSetterMethods(Object obj) + { + // setter方法列表 + List setterMethods = new ArrayList(); + + // 获取所有方法 + Method[] methods = obj.getClass().getMethods(); + + // 查找setter方法 + + for (Method method : methods) + { + Matcher m = SET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 1)) + { + setterMethods.add(method); + } + } + // 返回setter方法列表 + return setterMethods; + } + + /** + * 获取对象的getter方法。 + * + * @param obj 对象 + * @return 对象的getter方法列表 + */ + + public static List getGetterMethods(Object obj) + { + // getter方法列表 + List getterMethods = new ArrayList(); + // 获取所有方法 + Method[] methods = obj.getClass().getMethods(); + // 查找getter方法 + for (Method method : methods) + { + Matcher m = GET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 0)) + { + getterMethods.add(method); + } + } + // 返回getter方法列表 + return getterMethods; + } + + /** + * 检查Bean方法名中的属性名是否相等。
+ * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 + * + * @param m1 方法名1 + * @param m2 方法名2 + * @return 属性名一样返回true,否则返回false + */ + + public static boolean isMethodPropEquals(String m1, String m2) + { + return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); + } +} diff --git a/src/main/java/cn/sliyun/common/utils/file/FileTypeUtils.java b/src/main/java/cn/sliyun/common/utils/file/FileTypeUtils.java new file mode 100644 index 0000000..4b8edfe --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/file/FileTypeUtils.java @@ -0,0 +1,76 @@ +package cn.sliyun.common.utils.file; + +import java.io.File; +import org.apache.commons.lang3.StringUtils; + +/** + * 文件类型工具类 + * + * @author ruoyi + */ +public class FileTypeUtils +{ + /** + * 获取文件类型 + *

+ * 例如: ruoyi.txt, 返回: txt + * + * @param file 文件名 + * @return 后缀(不含".") + */ + public static String getFileType(File file) + { + if (null == file) + { + return StringUtils.EMPTY; + } + return getFileType(file.getName()); + } + + /** + * 获取文件类型 + *

+ * 例如: ruoyi.txt, 返回: txt + * + * @param fileName 文件名 + * @return 后缀(不含".") + */ + public static String getFileType(String fileName) + { + int separatorIndex = fileName.lastIndexOf("."); + if (separatorIndex < 0) + { + return ""; + } + return fileName.substring(separatorIndex + 1).toLowerCase(); + } + + /** + * 获取文件类型 + * + * @param photoByte 文件字节码 + * @return 后缀(不含".") + */ + public static String getFileExtendName(byte[] photoByte) + { + String strFileExtendName = "JPG"; + if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) + { + strFileExtendName = "GIF"; + } + else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) + { + strFileExtendName = "JPG"; + } + else if ((photoByte[0] == 66) && (photoByte[1] == 77)) + { + strFileExtendName = "BMP"; + } + else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) + { + strFileExtendName = "PNG"; + } + return strFileExtendName; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/file/FileUploadUtils.java b/src/main/java/cn/sliyun/common/utils/file/FileUploadUtils.java new file mode 100644 index 0000000..b387b1e --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/file/FileUploadUtils.java @@ -0,0 +1,232 @@ +package cn.sliyun.common.utils.file; + +import java.io.File; +import java.io.IOException; + +import cn.sliyun.common.exception.file.FileNameLengthLimitExceededException; +import cn.sliyun.common.exception.file.FileSizeLimitExceededException; +import cn.sliyun.common.exception.file.InvalidExtensionException; +import cn.sliyun.common.utils.DateUtils; +import cn.sliyun.common.utils.IdUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.config.RuoYiConfig; +import org.apache.commons.io.FilenameUtils; +import org.springframework.web.multipart.MultipartFile; +import cn.sliyun.common.constant.Constants; + +/** + * 文件上传工具类 + * + * @author ruoyi + */ +public class FileUploadUtils +{ + /** + * 默认大小 50M + */ + public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; + + /** + * 默认的文件名最大长度 100 + */ + public static final int DEFAULT_FILE_NAME_LENGTH = 100; + + /** + * 默认上传的地址 + */ + private static String defaultBaseDir = RuoYiConfig.getProfile(); + + public static void setDefaultBaseDir(String defaultBaseDir) + { + FileUploadUtils.defaultBaseDir = defaultBaseDir; + } + + public static String getDefaultBaseDir() + { + return defaultBaseDir; + } + + /** + * 以默认配置进行文件上传 + * + * @param file 上传的文件 + * @return 文件名称 + * @throws Exception + */ + public static final String upload(MultipartFile file) throws IOException + { + try + { + return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } + catch (Exception e) + { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 根据文件路径上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @return 文件名称 + * @throws IOException + */ + public static final String upload(String baseDir, MultipartFile file) throws IOException + { + try + { + return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } + catch (Exception e) + { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 文件上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @param extension 上传文件类型 + * @return 返回上传成功的文件名 + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws FileNameLengthLimitExceededException 文件名太长 + * @throws IOException 比如读写文件出错时 + * @throws InvalidExtensionException 文件校验异常 + */ + public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, + InvalidExtensionException + { + int fileNamelength = file.getOriginalFilename().length(); + if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) + { + throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); + } + + assertAllowed(file, allowedExtension); + + String fileName = extractFilename(file); + + File desc = getAbsoluteFile(baseDir, fileName); + file.transferTo(desc); + String pathFileName = getPathFileName(baseDir, fileName); + return pathFileName; + } + + /** + * 编码文件名 + */ + public static final String extractFilename(MultipartFile file) + { + String fileName = file.getOriginalFilename(); + String extension = getExtension(file); + fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; + return fileName; + } + + private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException + { + File desc = new File(uploadDir + File.separator + fileName); + + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + if (!desc.exists()) + { + desc.createNewFile(); + } + return desc; + } + + private static final String getPathFileName(String uploadDir, String fileName) throws IOException + { + int dirLastIndex = RuoYiConfig.getProfile().length() + 1; + String currentDir = StringUtils.substring(uploadDir, dirLastIndex); + String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; + return pathFileName; + } + + /** + * 文件大小校验 + * + * @param file 上传的文件 + * @return + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws InvalidExtensionException + */ + public static final void assertAllowed(MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, InvalidExtensionException + { + long size = file.getSize(); + if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE) + { + throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); + } + + String fileName = file.getOriginalFilename(); + String extension = getExtension(file); + if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) + { + if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) + { + throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) + { + throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) + { + throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, + fileName); + } + else + { + throw new InvalidExtensionException(allowedExtension, extension, fileName); + } + } + + } + + /** + * 判断MIME类型是否是允许的MIME类型 + * + * @param extension + * @param allowedExtension + * @return + */ + public static final boolean isAllowedExtension(String extension, String[] allowedExtension) + { + for (String str : allowedExtension) + { + if (str.equalsIgnoreCase(extension)) + { + return true; + } + } + return false; + } + + /** + * 获取文件名的后缀 + * + * @param file 表单文件 + * @return 后缀名 + */ + public static final String getExtension(MultipartFile file) + { + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + if (StringUtils.isEmpty(extension)) + { + extension = MimeTypeUtils.getExtension(file.getContentType()); + } + return extension; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/file/FileUtils.java b/src/main/java/cn/sliyun/common/utils/file/FileUtils.java new file mode 100644 index 0000000..5387671 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/file/FileUtils.java @@ -0,0 +1,204 @@ +package cn.sliyun.common.utils.file; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.sliyun.common.utils.StringUtils; +import org.apache.commons.lang3.ArrayUtils; + +/** + * 文件处理工具类 + * + * @author ruoyi + */ +public class FileUtils extends org.apache.commons.io.FileUtils +{ + public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; + + /** + * 输出指定文件的byte数组 + * + * @param filePath 文件路径 + * @param os 输出流 + * @return + */ + public static void writeBytes(String filePath, OutputStream os) throws IOException + { + FileInputStream fis = null; + try + { + File file = new File(filePath); + if (!file.exists()) + { + throw new FileNotFoundException(filePath); + } + fis = new FileInputStream(file); + byte[] b = new byte[1024]; + int length; + while ((length = fis.read(b)) > 0) + { + os.write(b, 0, length); + } + } + catch (IOException e) + { + throw e; + } + finally + { + if (os != null) + { + try + { + os.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + if (fis != null) + { + try + { + fis.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + } + } + + /** + * 删除文件 + * + * @param filePath 文件 + * @return + */ + public static boolean deleteFile(String filePath) + { + boolean flag = false; + File file = new File(filePath); + // 路径为文件且不为空则进行删除 + if (file.isFile() && file.exists()) + { + file.delete(); + flag = true; + } + return flag; + } + + /** + * 文件名称验证 + * + * @param filename 文件名称 + * @return true 正常 false 非法 + */ + public static boolean isValidFilename(String filename) + { + return filename.matches(FILENAME_PATTERN); + } + + /** + * 检查文件是否可下载 + * + * @param resource 需要下载的文件 + * @return true 正常 false 非法 + */ + public static boolean checkAllowDownload(String resource) + { + // 禁止目录上跳级别 + if (StringUtils.contains(resource, "..")) + { + return false; + } + + // 检查允许下载的文件规则 + if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) + { + return true; + } + + // 不在允许下载的文件规则 + return false; + } + + /** + * 下载文件名重新编码 + * + * @param request 请求对象 + * @param fileName 文件名 + * @return 编码后的文件名 + */ + public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException + { + final String agent = request.getHeader("USER-AGENT"); + String filename = fileName; + if (agent.contains("MSIE")) + { + // IE浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + filename = filename.replace("+", " "); + } + else if (agent.contains("Firefox")) + { + // 火狐浏览器 + filename = new String(fileName.getBytes(), "ISO8859-1"); + } + else if (agent.contains("Chrome")) + { + // google浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + } + else + { + // 其它浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + } + return filename; + } + + /** + * 下载文件名重新编码 + * + * @param response 响应对象 + * @param realFileName 真实文件名 + * @return + */ + public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException + { + String percentEncodedFileName = percentEncode(realFileName); + + StringBuilder contentDispositionValue = new StringBuilder(); + contentDispositionValue.append("attachment; filename=") + .append(percentEncodedFileName) + .append(";") + .append("filename*=") + .append("utf-8''") + .append(percentEncodedFileName); + + response.setHeader("Content-disposition", contentDispositionValue.toString()); + } + + /** + * 百分号编码工具方法 + * + * @param s 需要百分号编码的字符串 + * @return 百分号编码后的字符串 + */ + public static String percentEncode(String s) throws UnsupportedEncodingException + { + String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); + return encode.replaceAll("\\+", "%20"); + } +} diff --git a/src/main/java/cn/sliyun/common/utils/file/ImageUtils.java b/src/main/java/cn/sliyun/common/utils/file/ImageUtils.java new file mode 100644 index 0000000..5f81759 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/file/ImageUtils.java @@ -0,0 +1,101 @@ +package cn.sliyun.common.utils.file; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.config.RuoYiConfig; +import org.apache.poi.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import cn.sliyun.common.constant.Constants; + +/** + * 图片处理工具类 + * + * @author ruoyi + */ +public class ImageUtils +{ + private static final Logger log = LoggerFactory.getLogger(ImageUtils.class); + + public static byte[] getImage(String imagePath) + { + InputStream is = getFile(imagePath); + try + { + return IOUtils.toByteArray(is); + } + catch (Exception e) + { + log.error("图片加载异常 {}", e); + return null; + } + finally + { + IOUtils.closeQuietly(is); + } + } + + public static InputStream getFile(String imagePath) + { + try + { + byte[] result = readFile(imagePath); + result = Arrays.copyOf(result, result.length); + return new ByteArrayInputStream(result); + } + catch (Exception e) + { + log.error("获取图片异常 {}", e); + } + return null; + } + + /** + * 读取文件为字节数据 + * + * @param key 地址 + * @return 字节数据 + */ + public static byte[] readFile(String url) + { + InputStream in = null; + ByteArrayOutputStream baos = null; + try + { + if (url.startsWith("http")) + { + // 网络地址 + URL urlObj = new URL(url); + URLConnection urlConnection = urlObj.openConnection(); + urlConnection.setConnectTimeout(30 * 1000); + urlConnection.setReadTimeout(60 * 1000); + urlConnection.setDoInput(true); + in = urlConnection.getInputStream(); + } + else + { + // 本机地址 + String localPath = RuoYiConfig.getProfile(); + String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX); + in = new FileInputStream(downloadPath); + } + return IOUtils.toByteArray(in); + } + catch (Exception e) + { + log.error("获取文件路径异常 {}", e); + return null; + } + finally + { + IOUtils.closeQuietly(baos); + } + } +} diff --git a/src/main/java/cn/sliyun/common/utils/file/MimeTypeUtils.java b/src/main/java/cn/sliyun/common/utils/file/MimeTypeUtils.java new file mode 100644 index 0000000..24f42db --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/file/MimeTypeUtils.java @@ -0,0 +1,55 @@ +package cn.sliyun.common.utils.file; + +/** + * 媒体类型工具类 + * + * @author ruoyi + */ +public class MimeTypeUtils +{ + public static final String IMAGE_PNG = "image/png"; + + public static final String IMAGE_JPG = "image/jpg"; + + public static final String IMAGE_JPEG = "image/jpeg"; + + public static final String IMAGE_BMP = "image/bmp"; + + public static final String IMAGE_GIF = "image/gif"; + + public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; + + public static final String[] FLASH_EXTENSION = { "swf", "flv" }; + + public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", + "asf", "rm", "rmvb" }; + + public static final String[] DEFAULT_ALLOWED_EXTENSION = { + // 图片 + "bmp", "gif", "jpg", "jpeg", "png", + // word excel powerpoint + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", + // 压缩文件 + "rar", "zip", "gz", "bz2", + // pdf + "pdf" }; + + public static String getExtension(String prefix) + { + switch (prefix) + { + case IMAGE_PNG: + return "png"; + case IMAGE_JPG: + return "jpg"; + case IMAGE_JPEG: + return "jpeg"; + case IMAGE_BMP: + return "bmp"; + case IMAGE_GIF: + return "gif"; + default: + return ""; + } + } +} diff --git a/src/main/java/cn/sliyun/common/utils/html/EscapeUtil.java b/src/main/java/cn/sliyun/common/utils/html/EscapeUtil.java new file mode 100644 index 0000000..dda9571 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/html/EscapeUtil.java @@ -0,0 +1,155 @@ +package cn.sliyun.common.utils.html; + +import cn.sliyun.common.utils.StringUtils; + +/** + * 转义和反转义工具类 + * + * @author ruoyi + */ +public class EscapeUtil +{ + public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; + + private static final char[][] TEXT = new char[64][]; + + static + { + for (int i = 0; i < 64; i++) + { + TEXT[i] = new char[] { (char) i }; + } + + // special HTML characters + TEXT['\''] = "'".toCharArray(); // 单引号 + TEXT['"'] = """.toCharArray(); // 单引号 + TEXT['&'] = "&".toCharArray(); // &符 + TEXT['<'] = "<".toCharArray(); // 小于号 + TEXT['>'] = ">".toCharArray(); // 大于号 + } + + /** + * 转义文本中的HTML字符为安全的字符 + * + * @param text 被转义的文本 + * @return 转义后的文本 + */ + public static String escape(String text) + { + return encode(text); + } + + /** + * 还原被转义的HTML特殊字符 + * + * @param content 包含转义符的HTML内容 + * @return 转换后的字符串 + */ + public static String unescape(String content) + { + return decode(content); + } + + /** + * 清除所有HTML标签,但是不删除标签内的内容 + * + * @param content 文本 + * @return 清除标签后的文本 + */ + public static String clean(String content) + { + return new HTMLFilter().filter(content); + } + + /** + * Escape编码 + * + * @param text 被编码的文本 + * @return 编码后的字符 + */ + private static String encode(String text) + { + int len; + if ((text == null) || ((len = text.length()) == 0)) + { + return StringUtils.EMPTY; + } + StringBuilder buffer = new StringBuilder(len + (len >> 2)); + char c; + for (int i = 0; i < len; i++) + { + c = text.charAt(i); + if (c < 64) + { + buffer.append(TEXT[c]); + } + else + { + buffer.append(c); + } + } + return buffer.toString(); + } + + /** + * Escape解码 + * + * @param content 被转义的内容 + * @return 解码后的字符串 + */ + public static String decode(String content) + { + if (StringUtils.isEmpty(content)) + { + return content; + } + + StringBuilder tmp = new StringBuilder(content.length()); + int lastPos = 0, pos = 0; + char ch; + while (lastPos < content.length()) + { + pos = content.indexOf("%", lastPos); + if (pos == lastPos) + { + if (content.charAt(pos + 1) == 'u') + { + ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); + tmp.append(ch); + lastPos = pos + 6; + } + else + { + ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); + tmp.append(ch); + lastPos = pos + 3; + } + } + else + { + if (pos == -1) + { + tmp.append(content.substring(lastPos)); + lastPos = content.length(); + } + else + { + tmp.append(content.substring(lastPos, pos)); + lastPos = pos; + } + } + } + return tmp.toString(); + } + + public static void main(String[] args) + { + String html = ""; + // String html = "ipt>alert(\"XSS\")ipt>"; + // String html = "<123"; + // String html = "123>"; + System.out.println(EscapeUtil.clean(html)); + System.out.println(EscapeUtil.escape(html)); + System.out.println(EscapeUtil.unescape(html)); + } +} diff --git a/src/main/java/cn/sliyun/common/utils/html/HTMLFilter.java b/src/main/java/cn/sliyun/common/utils/html/HTMLFilter.java new file mode 100644 index 0000000..b7a985c --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/html/HTMLFilter.java @@ -0,0 +1,570 @@ +package cn.sliyun.common.utils.html; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * HTML过滤器,用于去除XSS漏洞隐患。 + * + * @author ruoyi + */ +public final class HTMLFilter +{ + /** + * regex flag union representing /si modifiers in php + **/ + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + + // @xxx could grow large... maybe use sesat's ReferenceMap + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); + + /** + * set of allowed html elements, along with allowed attributes for each element + **/ + private final Map> vAllowed; + /** + * counts of open tags for each (allowable) html element + **/ + private final Map vTagCounts = new HashMap<>(); + + /** + * html elements which must always be self-closing (e.g. "") + **/ + private final String[] vSelfClosingTags; + /** + * html elements which must always have separate opening and closing tags (e.g. "") + **/ + private final String[] vNeedClosingTags; + /** + * set of disallowed html elements + **/ + private final String[] vDisallowed; + /** + * attributes which should be checked for valid protocols + **/ + private final String[] vProtocolAtts; + /** + * allowed protocols + **/ + private final String[] vAllowedProtocols; + /** + * tags which should be removed if they contain no content (e.g. "" or "") + **/ + private final String[] vRemoveBlanks; + /** + * entities allowed within html markup + **/ + private final String[] vAllowedEntities; + /** + * flag determining whether comments are allowed in input String. + */ + private final boolean stripComment; + private final boolean encodeQuotes; + /** + * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "" + * becomes " text "). If set to false, unbalanced angle brackets will be html escaped. + */ + private final boolean alwaysMakeTags; + + /** + * Default constructor. + */ + public HTMLFilter() + { + vAllowed = new HashMap<>(); + + final ArrayList a_atts = new ArrayList<>(); + a_atts.add("href"); + a_atts.add("target"); + vAllowed.put("a", a_atts); + + final ArrayList img_atts = new ArrayList<>(); + img_atts.add("src"); + img_atts.add("width"); + img_atts.add("height"); + img_atts.add("alt"); + vAllowed.put("img", img_atts); + + final ArrayList no_atts = new ArrayList<>(); + vAllowed.put("b", no_atts); + vAllowed.put("strong", no_atts); + vAllowed.put("i", no_atts); + vAllowed.put("em", no_atts); + + vSelfClosingTags = new String[] { "img" }; + vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; + vDisallowed = new String[] {}; + vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. + vProtocolAtts = new String[] { "src", "href" }; + vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; + vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = false; + } + + /** + * Map-parameter configurable constructor. + * + * @param conf map containing configuration. keys match field names. + */ + @SuppressWarnings("unchecked") + public HTMLFilter(final Map conf) + { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + private void reset() + { + vTagCounts.clear(); + } + + // --------------------------------------------------------------- + // my versions of some PHP library functions + public static String chr(final int decimal) + { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) + { + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + // --------------------------------------------------------------- + + /** + * given a user submitted input String, filter out any invalid or restricted html. + * + * @param input text (i.e. submitted by a user) than may contain html + * @return "clean" version of input, with only valid, whitelisted html elements allowed + */ + public String filter(final String input) + { + reset(); + String s = input; + + s = escapeComments(s); + + s = balanceHTML(s); + + s = checkTags(s); + + s = processRemoveBlanks(s); + + // s = validateEntities(s); + + return s; + } + + public boolean isAlwaysMakeTags() + { + return alwaysMakeTags; + } + + public boolean isStripComments() + { + return stripComment; + } + + private String escapeComments(final String s) + { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) + { + final String match = m.group(1); // (.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) + { + if (alwaysMakeTags) + { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + // 不追加结束标签 + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } + else + { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) + { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) + { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + final StringBuilder sBuilder = new StringBuilder(buf.toString()); + for (String key : vTagCounts.keySet()) + { + for (int ii = 0; ii < vTagCounts.get(key); ii++) + { + sBuilder.append(""); + } + } + s = sBuilder.toString(); + + return s; + } + + private String processRemoveBlanks(final String s) + { + String result = s; + for (String tag : vRemoveBlanks) + { + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) + { + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) + { + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) + { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) + { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) + { + if (false == inArray(name, vSelfClosingTags)) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + // starting tags + m = P_START_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); + if (allowed(name)) + { + final StringBuilder params = new StringBuilder(); + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList<>(); + final List paramValues = new ArrayList<>(); + while (m2.find()) + { + paramNames.add(m2.group(1)); // ([a-z0-9]+) + paramValues.add(m2.group(3)); // (.*?) + } + while (m3.find()) + { + paramNames.add(m3.group(1)); // ([a-z0-9]+) + paramValues.add(m3.group(3)); // ([^\"\\s']+) + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) + { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + + // debug( "paramName='" + paramName + "'" ); + // debug( "paramValue='" + paramValue + "'" ); + // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); + + if (allowedAttribute(name, paramName)) + { + if (inArray(paramName, vProtocolAtts)) + { + paramValue = processParamProtocol(paramValue); + } + params.append(' ').append(paramName).append("=\"").append(paramValue).append("\""); + } + } + + if (inArray(name, vSelfClosingTags)) + { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) + { + ending = ""; + } + + if (ending == null || ending.length() < 1) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } + else + { + vTagCounts.put(name, 1); + } + } + else + { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } + else + { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) + { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) + { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) + { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) + { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1); + if (s.startsWith("#//")) + { + s = "#" + s.substring(3); + } + } + } + + return s; + } + + private String decodeEntities(String s) + { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.decode(match).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) + { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // ([^&;]*) + final String two = m.group(2); // (?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s) + { + if (encodeQuotes) + { + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // (>|^) + final String two = m.group(2); // ([^<]+?) + final String three = m.group(3); // (<|$) + // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); + } + m.appendTail(buf); + return buf.toString(); + } + else + { + return s; + } + } + + private String checkEntity(final String preamble, final String term) + { + + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; + } + + private boolean isValidEntity(final String entity) + { + return inArray(entity, vAllowedEntities); + } + + private static boolean inArray(final String s, final String[] array) + { + for (String item : array) + { + if (item != null && item.equals(s)) + { + return true; + } + } + return false; + } + + private boolean allowed(final String name) + { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) + { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/http/HttpHelper.java b/src/main/java/cn/sliyun/common/utils/http/HttpHelper.java new file mode 100644 index 0000000..bf037bc --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/http/HttpHelper.java @@ -0,0 +1,55 @@ +package cn.sliyun.common.utils.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import javax.servlet.ServletRequest; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 通用http工具封装 + * + * @author ruoyi + */ +public class HttpHelper +{ + private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); + + public static String getBodyString(ServletRequest request) + { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try (InputStream inputStream = request.getInputStream()) + { + reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); + String line = ""; + while ((line = reader.readLine()) != null) + { + sb.append(line); + } + } + catch (IOException e) + { + LOGGER.warn("getBodyString出现问题!"); + } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + LOGGER.error(ExceptionUtils.getFullStackTrace(e)); + } + } + } + return sb.toString(); + } +} diff --git a/src/main/java/cn/sliyun/common/utils/http/HttpUtils.java b/src/main/java/cn/sliyun/common/utils/http/HttpUtils.java new file mode 100644 index 0000000..317e7b6 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/http/HttpUtils.java @@ -0,0 +1,262 @@ +package cn.sliyun.common.utils.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import cn.sliyun.common.constant.Constants; + +/** + * 通用http发送方法 + * + * @author ruoyi + */ +public class HttpUtils +{ + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) + { + return sendGet(url, param, Constants.UTF8); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType) + { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try + { + String urlNameString = url + "?" + param; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (in != null) + { + in.close(); + } + } + catch (Exception ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) + { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try + { + String urlNameString = url; + log.info("sendPost - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (out != null) + { + out.close(); + } + if (in != null) + { + in.close(); + } + } + catch (IOException ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSSLPost(String url, String param) + { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try + { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) + { + if (ret != null && !"".equals(ret.trim())) + { + result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8")); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static class TrustAnyTrustManager implements X509TrustManager + { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return new X509Certificate[] {}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier + { + @Override + public boolean verify(String hostname, SSLSession session) + { + return true; + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/ip/AddressUtils.java b/src/main/java/cn/sliyun/common/utils/ip/AddressUtils.java new file mode 100644 index 0000000..c179ed7 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/ip/AddressUtils.java @@ -0,0 +1,56 @@ +package cn.sliyun.common.utils.ip; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.config.RuoYiConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.alibaba.fastjson.JSONObject; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.utils.http.HttpUtils; + +/** + * 获取地址类 + * + * @author ruoyi + */ +public class AddressUtils +{ + private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); + + // IP地址查询 + public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; + + // 未知地址 + public static final String UNKNOWN = "XX XX"; + + public static String getRealAddressByIP(String ip) + { + String address = UNKNOWN; + // 内网不查询 + if (IpUtils.internalIp(ip)) + { + return "内网IP"; + } + if (RuoYiConfig.isAddressEnabled()) + { + try + { + String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); + if (StringUtils.isEmpty(rspStr)) + { + log.error("获取地理位置异常 {}", ip); + return UNKNOWN; + } + JSONObject obj = JSONObject.parseObject(rspStr); + String region = obj.getString("pro"); + String city = obj.getString("city"); + return String.format("%s %s", region, city); + } + catch (Exception e) + { + log.error("获取地理位置异常 {}", ip); + } + } + return address; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/ip/IpUtils.java b/src/main/java/cn/sliyun/common/utils/ip/IpUtils.java new file mode 100644 index 0000000..453a74e --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/ip/IpUtils.java @@ -0,0 +1,196 @@ +package cn.sliyun.common.utils.ip; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import javax.servlet.http.HttpServletRequest; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.html.EscapeUtil; + +/** + * 获取IP方法 + * + * @author ruoyi + */ +public class IpUtils +{ + public static String getIpAddr(HttpServletRequest request) + { + if (request == null) + { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Real-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getRemoteAddr(); + } + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : EscapeUtil.clean(ip); + } + + public static boolean internalIp(String ip) + { + byte[] addr = textToNumericFormatV4(ip); + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + private static boolean internalIp(byte[] addr) + { + if (StringUtils.isNull(addr) || addr.length < 2) + { + return true; + } + final byte b0 = addr[0]; + final byte b1 = addr[1]; + // 10.x.x.x/8 + final byte SECTION_1 = 0x0A; + // 172.16.x.x/12 + final byte SECTION_2 = (byte) 0xAC; + final byte SECTION_3 = (byte) 0x10; + final byte SECTION_4 = (byte) 0x1F; + // 192.168.x.x/16 + final byte SECTION_5 = (byte) 0xC0; + final byte SECTION_6 = (byte) 0xA8; + switch (b0) + { + case SECTION_1: + return true; + case SECTION_2: + if (b1 >= SECTION_3 && b1 <= SECTION_4) + { + return true; + } + case SECTION_5: + switch (b1) + { + case SECTION_6: + return true; + } + default: + return false; + } + } + + /** + * 将IPv4地址转换成字节 + * + * @param text IPv4地址 + * @return byte 字节 + */ + public static byte[] textToNumericFormatV4(String text) + { + if (text.length() == 0) + { + return null; + } + + byte[] bytes = new byte[4]; + String[] elements = text.split("\\.", -1); + try + { + long l; + int i; + switch (elements.length) + { + case 1: + l = Long.parseLong(elements[0]); + if ((l < 0L) || (l > 4294967295L)) { + return null; + } + bytes[0] = (byte) (int) (l >> 24 & 0xFF); + bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 2: + l = Integer.parseInt(elements[0]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[0] = (byte) (int) (l & 0xFF); + l = Integer.parseInt(elements[1]); + if ((l < 0L) || (l > 16777215L)) { + return null; + } + bytes[1] = (byte) (int) (l >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 3: + for (i = 0; i < 2; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + l = Integer.parseInt(elements[2]); + if ((l < 0L) || (l > 65535L)) { + return null; + } + bytes[2] = (byte) (int) (l >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 4: + for (i = 0; i < 4; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + break; + default: + return null; + } + } + catch (NumberFormatException e) + { + return null; + } + return bytes; + } + + public static String getHostIp() + { + try + { + return InetAddress.getLocalHost().getHostAddress(); + } + catch (UnknownHostException e) + { + } + return "127.0.0.1"; + } + + public static String getHostName() + { + try + { + return InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException e) + { + } + return "未知"; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/poi/ExcelUtil.java b/src/main/java/cn/sliyun/common/utils/poi/ExcelUtil.java new file mode 100644 index 0000000..68e4f64 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/poi/ExcelUtil.java @@ -0,0 +1,1092 @@ +package cn.sliyun.common.utils.poi; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +import cn.sliyun.common.core.text.Convert; +import cn.sliyun.common.utils.DateUtils; +import cn.sliyun.common.utils.DictUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.aspectj.lang.annotation.Excels; +import cn.sliyun.framework.config.RuoYiConfig; +import cn.sliyun.framework.web.domain.AjaxResult; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.file.FileTypeUtils; +import cn.sliyun.common.utils.file.ImageUtils; +import cn.sliyun.common.utils.reflect.ReflectUtils; + +/** + * Excel相关处理 + * + * @author ruoyi + */ +public class ExcelUtil +{ + private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + + /** + * Excel sheet最大行数,默认65536 + */ + public static final int sheetSize = 65536; + + /** + * 工作表名称 + */ + private String sheetName; + + /** + * 导出类型(EXPORT:导出数据;IMPORT:导入模板) + */ + private Excel.Type type; + + /** + * 工作薄对象 + */ + private Workbook wb; + + /** + * 工作表对象 + */ + private Sheet sheet; + + /** + * 样式列表 + */ + private Map styles; + + /** + * 导入导出数据列表 + */ + private List list; + + /** + * 注解列表 + */ + private List fields; + + /** + * 最大高度 + */ + private short maxHeight; + + /** + * 统计列表 + */ + private Map statistics = new HashMap(); + + /** + * 数字格式 + */ + private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + + /** + * 实体对象 + */ + public Class clazz; + + public ExcelUtil(Class clazz) + { + this.clazz = clazz; + } + + public void init(List list, String sheetName, Excel.Type type) + { + if (list == null) + { + list = new ArrayList(); + } + this.list = list; + this.sheetName = sheetName; + this.type = type; + createExcelField(); + createWorkbook(); + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(InputStream is) throws Exception + { + return importExcel(StringUtils.EMPTY, is); + } + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(String sheetName, InputStream is) throws Exception + { + this.type = Excel.Type.IMPORT; + this.wb = WorkbookFactory.create(is); + List list = new ArrayList(); + Sheet sheet = null; + if (StringUtils.isNotEmpty(sheetName)) + { + // 如果指定sheet名,则取指定sheet中的内容. + sheet = wb.getSheet(sheetName); + } + else + { + // 如果传入的sheet名不存在则默认指向第1个sheet. + sheet = wb.getSheetAt(0); + } + + if (sheet == null) + { + throw new IOException("文件sheet不存在"); + } + + int rows = sheet.getPhysicalNumberOfRows(); + + if (rows > 0) + { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + Row heard = sheet.getRow(0); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) + { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) + { + String value = this.getCellValue(heard, i).toString(); + cellMap.put(value, i); + } + else + { + cellMap.put(null, i); + } + } + // 有数据时才处理 得到类的所有field. + Field[] allFields = clazz.getDeclaredFields(); + // 定义一个map用于存放列的序号和field. + Map fieldsMap = new HashMap(); + for (int col = 0; col < allFields.length; col++) + { + Field field = allFields[col]; + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type)) + { + // 设置类的私有字段属性可访问. + field.setAccessible(true); + Integer column = cellMap.get(attr.name()); + if (column != null) + { + fieldsMap.put(column, field); + } + } + } + for (int i = 1; i < rows; i++) + { + // 从第2行开始取数据,默认第一行是表头. + Row row = sheet.getRow(i); + T entity = null; + for (Map.Entry entry : fieldsMap.entrySet()) + { + Object val = this.getCellValue(row, entry.getKey()); + + // 如果不存在实例则新建. + entity = (entity == null ? clazz.newInstance() : entity); + // 从map中得到对应列的field. + Field field = fieldsMap.get(entry.getKey()); + // 取得类型,并根据对象类型设置值. + Class fieldType = field.getType(); + if (String.class == fieldType) + { + String s = Convert.toStr(val); + if (StringUtils.endsWith(s, ".0")) + { + val = StringUtils.substringBefore(s, ".0"); + } + else + { + String dateFormat = field.getAnnotation(Excel.class).dateFormat(); + if (StringUtils.isNotEmpty(dateFormat)) + { + val = DateUtils.parseDateToStr(dateFormat, (Date) val); + } + else + { + val = Convert.toStr(val); + } + } + } + else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toInt(val); + } + else if (Long.TYPE == fieldType || Long.class == fieldType) + { + val = Convert.toLong(val); + } + else if (Double.TYPE == fieldType || Double.class == fieldType) + { + val = Convert.toDouble(val); + } + else if (Float.TYPE == fieldType || Float.class == fieldType) + { + val = Convert.toFloat(val); + } + else if (BigDecimal.class == fieldType) + { + val = Convert.toBigDecimal(val); + } + else if (Date.class == fieldType) + { + if (val instanceof String) + { + val = DateUtils.parseDate(val); + } + else if (val instanceof Double) + { + val = DateUtil.getJavaDate((Double) val); + } + } + else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) + { + val = Convert.toBool(val, false); + } + if (StringUtils.isNotNull(fieldType)) + { + Excel attr = field.getAnnotation(Excel.class); + String propertyName = field.getName(); + if (StringUtils.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (StringUtils.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); + } + else if (StringUtils.isNotEmpty(attr.dictType())) + { + val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + } + ReflectUtils.invokeSetter(entity, propertyName, val); + } + } + list.add(entity); + } + } + return list; + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult exportExcel(List list, String sheetName) + { + this.init(list, sheetName, Excel.Type.EXPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName) + { + this.init(null, sheetName, Excel.Type.IMPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @return 结果 + */ + public AjaxResult exportExcel() + { + OutputStream out = null; + try + { + // 取出一共有多少个sheet. + double sheetNo = Math.ceil(list.size() / sheetSize); + for (int index = 0; index <= sheetNo; index++) + { + createSheet(sheetNo, index); + + // 产生一行 + Row row = sheet.createRow(0); + int column = 0; + // 写入各个字段的列头名称 + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + this.createCell(excel, row, column++); + } + if (Excel.Type.EXPORT.equals(type)) + { + fillExcelData(index, row); + addStatisticsRow(); + } + } + String filename = encodingFilename(sheetName); + out = new FileOutputStream(getAbsoluteFile(filename)); + wb.write(out); + return AjaxResult.success(filename); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + throw new AppException("导出Excel失败,请联系网站管理员!"); + } + finally + { + if (wb != null) + { + try + { + wb.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + if (out != null) + { + try + { + out.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + } + } + + /** + * 填充excel数据 + * + * @param index 序号 + * @param row 单元格行 + */ + public void fillExcelData(int index, Row row) + { + int startNo = index * sheetSize; + int endNo = Math.min(startNo + sheetSize, list.size()); + for (int i = startNo; i < endNo; i++) + { + row = sheet.createRow(i + 1 - startNo); + // 得到导出对象. + T vo = (T) list.get(i); + int column = 0; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + // 设置实体类私有属性可访问 + field.setAccessible(true); + this.addCell(excel, row, vo, field, column++); + } + } + } + + /** + * 创建表格样式 + * + * @param wb 工作薄对象 + * @return 样式列表 + */ + private Map createStyles(Workbook wb) + { + // 写入各条记录,每条记录对应excel表中的一行 + Map styles = new HashMap(); + CellStyle style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + style.setFont(dataFont); + styles.put("data", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + Font headerFont = wb.createFont(); + headerFont.setFontName("Arial"); + headerFont.setFontHeightInPoints((short) 10); + headerFont.setBold(true); + headerFont.setColor(IndexedColors.WHITE.getIndex()); + style.setFont(headerFont); + styles.put("header", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font totalFont = wb.createFont(); + totalFont.setFontName("Arial"); + totalFont.setFontHeightInPoints((short) 10); + style.setFont(totalFont); + styles.put("total", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.LEFT); + styles.put("data1", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + styles.put("data2", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.RIGHT); + styles.put("data3", style); + + return styles; + } + + /** + * 创建单元格 + */ + public Cell createCell(Excel attr, Row row, int column) + { + // 创建列 + Cell cell = row.createCell(column); + // 写入列信息 + cell.setCellValue(attr.name()); + setDataValidation(attr, row, column); + cell.setCellStyle(styles.get("header")); + return cell; + } + + /** + * 设置单元格信息 + * + * @param value 单元格值 + * @param attr 注解相关 + * @param cell 单元格信息 + */ + public void setCellVo(Object value, Excel attr, Cell cell) + { + if (Excel.ColumnType.STRING == attr.cellType()) + { + cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix()); + } + else if (Excel.ColumnType.NUMERIC == attr.cellType()) + { + cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); + } + else if (Excel.ColumnType.IMAGE == attr.cellType()) + { + ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), + cell.getRow().getRowNum() + 1); + String imagePath = Convert.toStr(value); + if (StringUtils.isNotEmpty(imagePath)) + { + byte[] data = ImageUtils.getImage(imagePath); + getDrawingPatriarch(cell.getSheet()).createPicture(anchor, + cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); + } + } + } + + /** + * 获取画布 + */ + public static Drawing getDrawingPatriarch(Sheet sheet) + { + if (sheet.getDrawingPatriarch() == null) + { + sheet.createDrawingPatriarch(); + } + return sheet.getDrawingPatriarch(); + } + + /** + * 获取图片类型,设置图片插入类型 + */ + public int getImageType(byte[] value) + { + String type = FileTypeUtils.getFileExtendName(value); + if ("JPG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_JPEG; + } + else if ("PNG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_PNG; + } + return Workbook.PICTURE_TYPE_JPEG; + } + + /** + * 创建表格样式 + */ + public void setDataValidation(Excel attr, Row row, int column) + { + if (attr.name().indexOf("注:") >= 0) + { + sheet.setColumnWidth(column, 6000); + } + else + { + // 设置列宽 + sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); + } + // 如果设置了提示信息则鼠标放上去提示. + if (StringUtils.isNotEmpty(attr.prompt())) + { + // 这里默认设了2-101列提示. + setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); + } + // 如果设置了combo属性则本列只能选择不能输入 + if (attr.combo().length > 0) + { + // 这里默认设了2-101列只能选择不能输入. + setXSSFValidation(sheet, attr.combo(), 1, 100, column, column); + } + } + + /** + * 添加单元格 + */ + public Cell addCell(Excel attr, Row row, T vo, Field field, int column) + { + Cell cell = null; + try + { + // 设置行高 + row.setHeight(maxHeight); + // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. + if (attr.isExport()) + { + // 创建cell + cell = row.createCell(column); + int align = attr.align().value(); + cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : ""))); + + // 用于读取对象中的属性 + Object value = getTargetValue(vo, field, attr); + String dateFormat = attr.dateFormat(); + String readConverterExp = attr.readConverterExp(); + String separator = attr.separator(); + String dictType = attr.dictType(); + if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) + { + cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); + } + else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); + } + else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator)); + } + else if (value instanceof BigDecimal && -1 != attr.scale()) + { + cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString()); + } + else + { + // 设置列类型 + setCellVo(value, attr, cell); + } + addStatisticsData(column, Convert.toStr(value), attr); + } + } + catch (Exception e) + { + log.error("导出Excel失败{}", e); + } + return cell; + } + + /** + * 设置 POI XSSFSheet 单元格提示 + * + * @param sheet 表单 + * @param promptTitle 提示标题 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, + int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + DataValidation dataValidation = helper.createValidation(constraint, regions); + dataValidation.createPromptBox(promptTitle, promptContent); + dataValidation.setShowPromptBox(true); + sheet.addValidationData(dataValidation); + } + + /** + * 设置某些列的值只能输入预制的数据,显示下拉框. + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + * @return 设置好的sheet. + */ + public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 加载下拉列表内容 + DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // 数据有效性对象 + DataValidation dataValidation = helper.createValidation(constraint, regions); + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + + sheet.addValidationData(dataValidation); + } + + /** + * 解析导出值 0=男,1=女,2=未知 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String convertByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(separator, propertyValue)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[0].equals(value)) + { + propertyString.append(itemArray[1] + separator); + break; + } + } + } + else + { + if (itemArray[0].equals(propertyValue)) + { + return itemArray[1]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 反向解析值 男=0,女=1,未知=2 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String reverseByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(separator, propertyValue)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[1].equals(value)) + { + propertyString.append(itemArray[0] + separator); + break; + } + } + } + else + { + if (itemArray[1].equals(propertyValue)) + { + return itemArray[0]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 解析字典值 + * + * @param dictValue 字典值 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String convertDictByExp(String dictValue, String dictType, String separator) + { + return DictUtils.getDictLabel(dictType, dictValue, separator); + } + + /** + * 反向解析值字典值 + * + * @param dictLabel 字典标签 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典值 + */ + public static String reverseDictByExp(String dictLabel, String dictType, String separator) + { + return DictUtils.getDictValue(dictType, dictLabel, separator); + } + + /** + * 合计统计信息 + */ + private void addStatisticsData(Integer index, String text, Excel entity) + { + if (entity != null && entity.isStatistics()) + { + Double temp = 0D; + if (!statistics.containsKey(index)) + { + statistics.put(index, temp); + } + try + { + temp = Double.valueOf(text); + } + catch (NumberFormatException e) + { + } + statistics.put(index, statistics.get(index) + temp); + } + } + + /** + * 创建统计行 + */ + public void addStatisticsRow() + { + if (statistics.size() > 0) + { + Cell cell = null; + Row row = sheet.createRow(sheet.getLastRowNum() + 1); + Set keys = statistics.keySet(); + cell = row.createCell(0); + cell.setCellStyle(styles.get("total")); + cell.setCellValue("合计"); + + for (Integer key : keys) + { + cell = row.createCell(key); + cell.setCellStyle(styles.get("total")); + cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); + } + statistics.clear(); + } + } + + /** + * 编码文件名 + */ + public String encodingFilename(String filename) + { + filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx"; + return filename; + } + + /** + * 获取下载路径 + * + * @param filename 文件名称 + */ + public String getAbsoluteFile(String filename) + { + String downloadPath = RuoYiConfig.getDownloadPath() + filename; + File desc = new File(downloadPath); + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + return downloadPath; + } + + /** + * 获取bean中的属性值 + * + * @param vo 实体对象 + * @param field 字段 + * @param excel 注解 + * @return 最终的属性值 + * @throws Exception + */ + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception + { + Object o = field.get(vo); + if (StringUtils.isNotEmpty(excel.targetAttr())) + { + String target = excel.targetAttr(); + if (target.indexOf(".") > -1) + { + String[] targets = target.split("[.]"); + for (String name : targets) + { + o = getValue(o, name); + } + } + else + { + o = getValue(o, target); + } + } + return o; + } + + /** + * 以类的属性的get方法方法形式获取值 + * + * @param o + * @param name + * @return value + * @throws Exception + */ + private Object getValue(Object o, String name) throws Exception + { + if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) + { + Class clazz = o.getClass(); + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + o = field.get(o); + } + return o; + } + + /** + * 得到所有定义字段 + */ + private void createExcelField() + { + this.fields = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + putToField(field, field.getAnnotation(Excel.class)); + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel excel : excels) + { + putToField(field, excel); + } + } + } + this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); + this.maxHeight = getRowHeight(); + } + + /** + * 根据注解获取最大行高 + */ + public short getRowHeight() + { + double maxHeight = 0; + for (Object[] os : this.fields) + { + Excel excel = (Excel) os[1]; + maxHeight = maxHeight > excel.height() ? maxHeight : excel.height(); + } + return (short) (maxHeight * 20); + } + + /** + * 放到字段集合中 + */ + private void putToField(Field field, Excel attr) + { + if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type)) + { + this.fields.add(new Object[] { field, attr }); + } + } + + /** + * 创建一个工作簿 + */ + public void createWorkbook() + { + this.wb = new SXSSFWorkbook(500); + } + + /** + * 创建工作表 + * + * @param sheetNo sheet数量 + * @param index 序号 + */ + public void createSheet(double sheetNo, int index) + { + this.sheet = wb.createSheet(); + this.styles = createStyles(wb); + // 设置工作表的名称. + if (sheetNo == 0) + { + wb.setSheetName(index, sheetName); + } + else + { + wb.setSheetName(index, sheetName + index); + } + } + + /** + * 获取单元格值 + * + * @param row 获取的行 + * @param column 获取单元格列号 + * @return 单元格值 + */ + public Object getCellValue(Row row, int column) + { + if (row == null) + { + return row; + } + Object val = ""; + try + { + Cell cell = row.getCell(column); + if (StringUtils.isNotNull(cell)) + { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) + { + val = cell.getNumericCellValue(); + if (DateUtil.isCellDateFormatted(cell)) + { + val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 + } + else + { + if ((Double) val % 1 != 0) + { + val = new BigDecimal(val.toString()); + } + else + { + val = new DecimalFormat("0").format(val); + } + } + } + else if (cell.getCellType() == CellType.STRING) + { + val = cell.getStringCellValue(); + } + else if (cell.getCellType() == CellType.BOOLEAN) + { + val = cell.getBooleanCellValue(); + } + else if (cell.getCellType() == CellType.ERROR) + { + val = cell.getErrorCellValue(); + } + + } + } + catch (Exception e) + { + return val; + } + return val; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/common/utils/reflect/ReflectUtils.java b/src/main/java/cn/sliyun/common/utils/reflect/ReflectUtils.java new file mode 100644 index 0000000..25dbe8d --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/reflect/ReflectUtils.java @@ -0,0 +1,411 @@ +package cn.sliyun.common.utils.reflect; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Date; + +import cn.sliyun.common.core.text.Convert; +import cn.sliyun.common.utils.DateUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; +import org.apache.poi.ss.usermodel.DateUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. + * + * @author ruoyi + */ +@SuppressWarnings("rawtypes") +public class ReflectUtils +{ + private static final String SETTER_PREFIX = "set"; + + private static final String GETTER_PREFIX = "get"; + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); + + /** + * 调用Getter方法. + * 支持多级,如:对象名.对象名.方法 + */ + @SuppressWarnings("unchecked") + public static E invokeGetter(Object obj, String propertyName) + { + Object object = obj; + for (String name : StringUtils.split(propertyName, ".")) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + return (E) object; + } + + /** + * 调用Setter方法, 仅匹配方法名。 + * 支持多级,如:对象名.对象名.方法 + */ + public static void invokeSetter(Object obj, String propertyName, E value) + { + Object object = obj; + String[] names = StringUtils.split(propertyName, "."); + for (int i = 0; i < names.length; i++) + { + if (i < names.length - 1) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + else + { + String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); + invokeMethodByName(object, setterMethodName, new Object[] { value }); + } + } + } + + /** + * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. + */ + @SuppressWarnings("unchecked") + public static E getFieldValue(final Object obj, final String fieldName) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return null; + } + E result = null; + try + { + result = (E) field.get(obj); + } + catch (IllegalAccessException e) + { + logger.error("不可能抛出的异常{}", e.getMessage()); + } + return result; + } + + /** + * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. + */ + public static void setFieldValue(final Object obj, final String fieldName, final E value) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return; + } + try + { + field.set(obj, value); + } + catch (IllegalAccessException e) + { + logger.error("不可能抛出的异常: {}", e.getMessage()); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符. + * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. + * 同时匹配方法名+参数类型, + */ + @SuppressWarnings("unchecked") + public static E invokeMethod(final Object obj, final String methodName, final Class[] parameterTypes, + final Object[] args) + { + if (obj == null || methodName == null) + { + return null; + } + Method method = getAccessibleMethod(obj, methodName, parameterTypes); + if (method == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符, + * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. + * 只匹配函数名,如果有多个同名函数调用第一个。 + */ + @SuppressWarnings("unchecked") + public static E invokeMethodByName(final Object obj, final String methodName, final Object[] args) + { + Method method = getAccessibleMethodByName(obj, methodName, args.length); + if (method == null) + { + // 如果为空不报错,直接返回空。 + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + // 类型转换(将参数数据类型转换为目标方法参数类型) + Class[] cs = method.getParameterTypes(); + for (int i = 0; i < cs.length; i++) + { + if (args[i] != null && !args[i].getClass().equals(cs[i])) + { + if (cs[i] == String.class) + { + args[i] = Convert.toStr(args[i]); + if (StringUtils.endsWith((String) args[i], ".0")) + { + args[i] = StringUtils.substringBefore((String) args[i], ".0"); + } + } + else if (cs[i] == Integer.class) + { + args[i] = Convert.toInt(args[i]); + } + else if (cs[i] == Long.class) + { + args[i] = Convert.toLong(args[i]); + } + else if (cs[i] == Double.class) + { + args[i] = Convert.toDouble(args[i]); + } + else if (cs[i] == Float.class) + { + args[i] = Convert.toFloat(args[i]); + } + else if (cs[i] == Date.class) + { + if (args[i] instanceof String) + { + args[i] = DateUtils.parseDate(args[i]); + } + else + { + args[i] = DateUtil.getJavaDate((Double) args[i]); + } + } + else if (cs[i] == boolean.class || cs[i] == Boolean.class) + { + args[i] = Convert.toBool(args[i]); + } + } + } + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + */ + public static Field getAccessibleField(final Object obj, final String fieldName) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(fieldName, "fieldName can't be blank"); + for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) + { + try + { + Field field = superClass.getDeclaredField(fieldName); + makeAccessible(field); + return field; + } + catch (NoSuchFieldException e) + { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 匹配函数名+参数类型。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethod(final Object obj, final String methodName, + final Class... parameterTypes) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + try + { + Method method = searchType.getDeclaredMethod(methodName, parameterTypes); + makeAccessible(method); + return method; + } + catch (NoSuchMethodException e) + { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 只匹配函数名。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + Method[] methods = searchType.getDeclaredMethods(); + for (Method method : methods) + { + if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) + { + makeAccessible(method); + return method; + } + } + } + return null; + } + + /** + * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Method method) + { + if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) + && !method.isAccessible()) + { + method.setAccessible(true); + } + } + + /** + * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Field field) + { + if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) + || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) + { + field.setAccessible(true); + } + } + + /** + * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 + * 如无法找到, 返回Object.class. + */ + @SuppressWarnings("unchecked") + public static Class getClassGenricType(final Class clazz) + { + return getClassGenricType(clazz, 0); + } + + /** + * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. + * 如无法找到, 返回Object.class. + */ + public static Class getClassGenricType(final Class clazz, final int index) + { + Type genType = clazz.getGenericSuperclass(); + + if (!(genType instanceof ParameterizedType)) + { + logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); + return Object.class; + } + + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + + if (index >= params.length || index < 0) + { + logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + + params.length); + return Object.class; + } + if (!(params[index] instanceof Class)) + { + logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); + return Object.class; + } + + return (Class) params[index]; + } + + public static Class getUserClass(Object instance) + { + if (instance == null) + { + throw new RuntimeException("Instance must not be null"); + } + Class clazz = instance.getClass(); + if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) + { + Class superClass = clazz.getSuperclass(); + if (superClass != null && !Object.class.equals(superClass)) + { + return superClass; + } + } + return clazz; + + } + + /** + * 将反射时的checked exception转换为unchecked exception. + */ + public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) + { + if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException + || e instanceof NoSuchMethodException) + { + return new IllegalArgumentException(msg, e); + } + else if (e instanceof InvocationTargetException) + { + return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); + } + return new RuntimeException(msg, e); + } +} diff --git a/src/main/java/cn/sliyun/common/utils/sign/Base64.java b/src/main/java/cn/sliyun/common/utils/sign/Base64.java new file mode 100644 index 0000000..793d8a9 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/sign/Base64.java @@ -0,0 +1,291 @@ +package cn.sliyun.common.utils.sign; + +/** + * Base64工具类 + * + * @author ruoyi + */ +public final class Base64 +{ + static private final int BASELENGTH = 128; + static private final int LOOKUPLENGTH = 64; + static private final int TWENTYFOURBITGROUP = 24; + static private final int EIGHTBIT = 8; + static private final int SIXTEENBIT = 16; + static private final int FOURBYTE = 4; + static private final int SIGN = -128; + static private final char PAD = '='; + static final private byte[] base64Alphabet = new byte[BASELENGTH]; + static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; + + static + { + for (int i = 0; i < BASELENGTH; ++i) + { + base64Alphabet[i] = -1; + } + for (int i = 'Z'; i >= 'A'; i--) + { + base64Alphabet[i] = (byte) (i - 'A'); + } + for (int i = 'z'; i >= 'a'; i--) + { + base64Alphabet[i] = (byte) (i - 'a' + 26); + } + + for (int i = '9'; i >= '0'; i--) + { + base64Alphabet[i] = (byte) (i - '0' + 52); + } + + base64Alphabet['+'] = 62; + base64Alphabet['/'] = 63; + + for (int i = 0; i <= 25; i++) + { + lookUpBase64Alphabet[i] = (char) ('A' + i); + } + + for (int i = 26, j = 0; i <= 51; i++, j++) + { + lookUpBase64Alphabet[i] = (char) ('a' + j); + } + + for (int i = 52, j = 0; i <= 61; i++, j++) + { + lookUpBase64Alphabet[i] = (char) ('0' + j); + } + lookUpBase64Alphabet[62] = (char) '+'; + lookUpBase64Alphabet[63] = (char) '/'; + } + + private static boolean isWhiteSpace(char octect) + { + return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); + } + + private static boolean isPad(char octect) + { + return (octect == PAD); + } + + private static boolean isData(char octect) + { + return (octect < BASELENGTH && base64Alphabet[octect] != -1); + } + + /** + * Encodes hex octects into Base64 + * + * @param binaryData Array containing binaryData + * @return Encoded Base64 array + */ + public static String encode(byte[] binaryData) + { + if (binaryData == null) + { + return null; + } + + int lengthDataBits = binaryData.length * EIGHTBIT; + if (lengthDataBits == 0) + { + return ""; + } + + int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; + int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; + int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; + char encodedData[] = null; + + encodedData = new char[numberQuartet * 4]; + + byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; + + int encodedIndex = 0; + int dataIndex = 0; + + for (int i = 0; i < numberTriplets; i++) + { + b1 = binaryData[dataIndex++]; + b2 = binaryData[dataIndex++]; + b3 = binaryData[dataIndex++]; + + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); + byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; + } + + // form integral number of 6-bit groups + if (fewerThan24bits == EIGHTBIT) + { + b1 = binaryData[dataIndex]; + k = (byte) (b1 & 0x03); + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; + encodedData[encodedIndex++] = PAD; + encodedData[encodedIndex++] = PAD; + } + else if (fewerThan24bits == SIXTEENBIT) + { + b1 = binaryData[dataIndex]; + b2 = binaryData[dataIndex + 1]; + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; + encodedData[encodedIndex++] = PAD; + } + return new String(encodedData); + } + + /** + * Decodes Base64 data into octects + * + * @param encoded string containing Base64 data + * @return Array containind decoded data. + */ + public static byte[] decode(String encoded) + { + if (encoded == null) + { + return null; + } + + char[] base64Data = encoded.toCharArray(); + // remove white spaces + int len = removeWhiteSpace(base64Data); + + if (len % FOURBYTE != 0) + { + return null;// should be divisible by four + } + + int numberQuadruple = (len / FOURBYTE); + + if (numberQuadruple == 0) + { + return new byte[0]; + } + + byte decodedData[] = null; + byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; + char d1 = 0, d2 = 0, d3 = 0, d4 = 0; + + int i = 0; + int encodedIndex = 0; + int dataIndex = 0; + decodedData = new byte[(numberQuadruple) * 3]; + + for (; i < numberQuadruple - 1; i++) + { + + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])) + || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) + { + return null; + } // if found "no data" just return null + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + } + + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) + { + return null;// if found "no data" just return null + } + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + + d3 = base64Data[dataIndex++]; + d4 = base64Data[dataIndex++]; + if (!isData((d3)) || !isData((d4))) + {// Check if they are PAD characters + if (isPad(d3) && isPad(d4)) + { + if ((b2 & 0xf) != 0)// last 4 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 1]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); + return tmp; + } + else if (!isPad(d3) && isPad(d4)) + { + b3 = base64Alphabet[d3]; + if ((b3 & 0x3) != 0)// last 2 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 2]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + return tmp; + } + else + { + return null; + } + } + else + { // No PAD e.g 3cQl + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + + } + return decodedData; + } + + /** + * remove WhiteSpace from MIME containing encoded Base64 data. + * + * @param data the byte array of base64 data (with WS) + * @return the new length + */ + private static int removeWhiteSpace(char[] data) + { + if (data == null) + { + return 0; + } + + // count characters that's not whitespace + int newSize = 0; + int len = data.length; + for (int i = 0; i < len; i++) + { + if (!isWhiteSpace(data[i])) + { + data[newSize++] = data[i]; + } + } + return newSize; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/sign/Md5Utils.java b/src/main/java/cn/sliyun/common/utils/sign/Md5Utils.java new file mode 100644 index 0000000..dad3f3c --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/sign/Md5Utils.java @@ -0,0 +1,113 @@ +package cn.sliyun.common.utils.sign; + +import java.security.MessageDigest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Md5加密方法 + * + * @author ruoyi + */ +public class Md5Utils +{ + private static final Logger log = LoggerFactory.getLogger(Md5Utils.class); + + private static byte[] md5(String s) + { + MessageDigest algorithm; + try + { + algorithm = MessageDigest.getInstance("MD5"); + algorithm.reset(); + algorithm.update(s.getBytes("UTF-8")); + byte[] messageDigest = algorithm.digest(); + return messageDigest; + } + catch (Exception e) + { + log.error("MD5 Error...", e); + } + return null; + } + + private static final String toHex(byte hash[]) + { + if (hash == null) + { + return null; + } + StringBuffer buf = new StringBuffer(hash.length * 2); + int i; + + for (i = 0; i < hash.length; i++) + { + if ((hash[i] & 0xff) < 0x10) + { + buf.append("0"); + } + buf.append(Long.toString(hash[i] & 0xff, 16)); + } + return buf.toString(); + } + + public static String hash(String s) + { + try + { + return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8"); + } + catch (Exception e) + { + log.error("not supported charset...{}", e); + return s; + } + } + + public final static String encrypt(String s) { + char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' }; + try { + byte[] btInput = s.getBytes(); + // 获得MD5摘要算法的 MessageDigest 对象 + MessageDigest mdInst = MessageDigest.getInstance("MD5"); + // 使用指定的字节更新摘要 + mdInst.update(btInput); + // 获得密文 + byte[] md = mdInst.digest(); + // 把密文转换成十六进制的字符串形式 + int j = md.length; + char str[] = new char[j * 2]; + int k = 0; + for (int i = 0; i < j; i++) { + byte byte0 = md[i]; + str[k++] = hexDigits[byte0 >>> 4 & 0xf]; + str[k++] = hexDigits[byte0 & 0xf]; + } + return new String(str).toLowerCase(); + } catch (Exception e) { + return null; + } + } + + public final static String getMessageDigest(byte[] buffer) { + char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + try { + MessageDigest mdTemp = MessageDigest.getInstance("MD5"); + mdTemp.update(buffer); + byte[] md = mdTemp.digest(); + int j = md.length; + char str[] = new char[j * 2]; + int k = 0; + for (int i = 0; i < j; i++) { + byte byte0 = md[i]; + str[k++] = hexDigits[byte0 >>> 4 & 0xf]; + str[k++] = hexDigits[byte0 & 0xf]; + } + return new String(str); + } catch (Exception e) { + return null; + } + } +} + diff --git a/src/main/java/cn/sliyun/common/utils/spring/SpringUtils.java b/src/main/java/cn/sliyun/common/utils/spring/SpringUtils.java new file mode 100644 index 0000000..da33e83 --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/spring/SpringUtils.java @@ -0,0 +1,146 @@ +package cn.sliyun.common.utils.spring; + +import cn.sliyun.common.utils.StringUtils; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * spring工具类 方便在非spring管理环境中获取bean + * + * @author ruoyi + */ +@Component +public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware +{ + /** Spring应用上下文环境 */ + private static ConfigurableListableBeanFactory beanFactory; + + private static ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + SpringUtils.beanFactory = beanFactory; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + SpringUtils.applicationContext = applicationContext; + } + + /** + * 获取对象 + * + * @param name + * @return Object 一个以所给名字注册的bean的实例 + * @throws org.springframework.beans.BeansException + * + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws org.springframework.beans.BeansException + * + */ + public static T getBean(Class clz) throws BeansException + { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) + { + return beanFactory.containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + * @return + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) + { + return (T) AopContext.currentProxy(); + } + + /** + * 获取当前的环境配置,无配置返回null + * + * @return 当前的环境配置 + */ + public static String[] getActiveProfiles() + { + return applicationContext.getEnvironment().getActiveProfiles(); + } + + /** + * 获取当前的环境配置,当有多个环境配置时,只获取第一个 + * + * @return 当前的环境配置 + */ + public static String getActiveProfile() + { + final String[] activeProfiles = getActiveProfiles(); + return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; + } +} diff --git a/src/main/java/cn/sliyun/common/utils/sql/SqlUtil.java b/src/main/java/cn/sliyun/common/utils/sql/SqlUtil.java new file mode 100644 index 0000000..9646d1d --- /dev/null +++ b/src/main/java/cn/sliyun/common/utils/sql/SqlUtil.java @@ -0,0 +1,37 @@ +package cn.sliyun.common.utils.sql; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.exception.BaseException; + +/** + * sql操作工具类 + * + * @author ruoyi + */ +public class SqlUtil +{ + /** + * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) + */ + public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; + + /** + * 检查字符,防止注入绕过 + */ + public static String escapeOrderBySql(String value) + { + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) + { + throw new BaseException("参数不符合规范,不能进行查询"); + } + return value; + } + + /** + * 验证 order by 语法是否符合规范 + */ + public static boolean isValidOrderBySql(String value) + { + return value.matches(SQL_PATTERN); + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/BSVTransaction.java b/src/main/java/cn/sliyun/dotwallet/BSVTransaction.java new file mode 100644 index 0000000..a70f39a --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/BSVTransaction.java @@ -0,0 +1,166 @@ +package cn.sliyun.dotwallet; + +import cn.sliyun.dotwallet.entity.response.data.SignParam; +import cn.sliyun.dotwallet.util.Util; +import com.subgraph.orchid.encoders.Hex; +import org.bitcoinj.core.*; +import org.bitcoinj.crypto.ChildNumber; +import org.bitcoinj.crypto.DeterministicKey; +import org.bitcoinj.crypto.HDKeyDerivation; +import org.bitcoinj.script.Script; +import org.bitcoinj.script.ScriptBuilder; + +import java.util.ArrayList; +import java.util.List; + +public class BSVTransaction extends Transaction { + public static final byte ForkID = 0x40; + public BSVTransaction(NetworkParameters params, byte[] payloadBytes) throws ProtocolException { + super(params, payloadBytes); + } + + public BSVTransaction(NetworkParameters params, String rawTx) throws ProtocolException { + super(params, Hex.decode(rawTx)); + } + + private int appendVarInt(ArrayList byteArray, byte[] connectedScript) { + long len = connectedScript.length; + int scriptLen = 0; + if (len < 0xfd) { + scriptLen += appendBytes(byteArray, Util.byteToBytesLittle((byte) len)); + return scriptLen; + } + + if (len <= Short.MAX_VALUE) { + scriptLen += appendBytes(byteArray, Util.byteToBytesLittle((byte) 0xfd)); + scriptLen += appendBytes(byteArray, Util.shortToBytesLittle((short) len)); + return scriptLen; + } + + if (len <= Integer.MAX_VALUE) { + scriptLen += appendBytes(byteArray, Util.byteToBytesLittle((byte) 0xfe)); + scriptLen += appendBytes(byteArray, Util.intToBytesLittle((int) len)); + return scriptLen; + } + + scriptLen += appendBytes(byteArray, Util.byteToBytesLittle((byte) 0xff)); + scriptLen += appendBytes(byteArray, Util.longToBytesLittle(len)); + return scriptLen; + } + + private int appendBytes(ArrayList byteArray, byte[] newByte) { + byteArray.add(newByte); + return newByte.length; + } + + private byte[] getFinalBytes(ArrayList byteArray, int totalLen) { + byte[] finalBytes = new byte[totalLen]; + int off = 0; + for (byte[] tmpBytes : byteArray) { + System.arraycopy(tmpBytes, 0, finalBytes, off, tmpBytes.length); + off += tmpBytes.length; + } + return finalBytes; + } + + private Sha256Hash hashForSignature(int inputIndex, byte[] connectedScript, long value, byte sigHashType) { + ArrayList byteArray = new ArrayList<>(); + byte sigHashMask = 0x1f; + int totalLen = 0; + + if (inputIndex > getInputs().size() - 1) { + throw new RuntimeException("inputIndex out of range"); + } + + totalLen += appendBytes(byteArray, Util.intToBytesLittle((int) getVersion())); + + if ((sigHashType & SigHash.ANYONECANPAY.value) == 0) { + ArrayList byteArrayTmp = new ArrayList(); + int tmplen = 0; + for (TransactionInput tmpInput : getInputs()) { + tmplen += appendBytes(byteArrayTmp, tmpInput.getOutpoint().bitcoinSerialize()); + } + byte[] tmpBufferBytes = getFinalBytes(byteArrayTmp, tmplen); + Sha256Hash tmpHash = Sha256Hash.twiceOf(tmpBufferBytes); + totalLen += appendBytes(byteArray, tmpHash.getBytes()); + } else { + totalLen += appendBytes(byteArray, Sha256Hash.ZERO_HASH.getBytes()); + } + + if ((sigHashType & SigHash.ANYONECANPAY.value) == 0 && + (sigHashType & sigHashMask) != SigHash.SINGLE.value && + (sigHashType & sigHashMask) != SigHash.NONE.value) { + ArrayList byteArrayTmp = new ArrayList<>(); + int tmplen = 0; + for (TransactionInput tmpInput : getInputs()) { + tmplen += appendBytes(byteArrayTmp, Util.intToBytesLittle((int) tmpInput.getSequenceNumber())); + } + + byte[] tmpBufferBytes = getFinalBytes(byteArrayTmp, tmplen); + Sha256Hash tmpHash = Sha256Hash.twiceOf(tmpBufferBytes); + totalLen += appendBytes(byteArray, tmpHash.getBytes()); + } else { + totalLen += appendBytes(byteArray, Sha256Hash.ZERO_HASH.getBytes()); + } + + totalLen += appendBytes(byteArray, getInput(inputIndex).getOutpoint().bitcoinSerialize()); + totalLen += appendVarInt(byteArray, connectedScript); + totalLen += appendBytes(byteArray, connectedScript); + totalLen += appendBytes(byteArray, Util.longToBytesLittle(value)); + totalLen += appendBytes(byteArray, Util.intToBytesLittle((int) getInput(inputIndex).getSequenceNumber())); + + if ((sigHashType & SigHash.SINGLE.value) != SigHash.SINGLE.value && + (sigHashType & SigHash.NONE.value) != SigHash.NONE.value) { + ArrayList byteArrayTmp = new ArrayList(); + int tmplen = 0; + for (TransactionOutput tmpOutput : getOutputs()) { + tmplen += appendBytes(byteArrayTmp, tmpOutput.bitcoinSerialize()); + } + byte[] tmpBufferBytes = getFinalBytes(byteArrayTmp, tmplen); + Sha256Hash tmpHash = Sha256Hash.twiceOf(tmpBufferBytes); + totalLen += appendBytes(byteArray, tmpHash.getBytes()); + } else if ((sigHashType & sigHashMask) == SigHash.SINGLE.value && + inputIndex < getOutputs().size()) { + byte[] tmpBytes = getOutput(inputIndex).bitcoinSerialize(); + Sha256Hash tmpHash = Sha256Hash.twiceOf(tmpBytes); + totalLen += appendBytes(byteArray, tmpHash.getBytes()); + } else { + totalLen += appendBytes(byteArray, Sha256Hash.ZERO_HASH.getBytes()); + } + + totalLen += appendBytes(byteArray, Util.intToBytesLittle((int) getLockTime())); + totalLen += appendBytes(byteArray, Util.intToBytesLittle(sigHashType | ForkID)); + byte[] finalBytes = getFinalBytes(byteArray, totalLen); + return Sha256Hash.twiceOf(finalBytes); + } + + private Script createVinScript(int inputIndex, ECKey key, byte[] connectedScript, long value, SigHash hashType) { + byte trueSigHashByte = (byte) (hashType.byteValue() | ForkID); + Sha256Hash hash = this.hashForSignature(inputIndex, connectedScript, value, trueSigHashByte); + ECKey.ECDSASignature ecdsaSignature = key.sign(hash); + byte[] ecdsaSignatureByte = ecdsaSignature.encodeToDER(); + byte[] trueSignResult = new byte[ecdsaSignatureByte.length + 1]; + System.arraycopy(ecdsaSignatureByte, 0, trueSignResult, 0, ecdsaSignatureByte.length); + trueSignResult[trueSignResult.length - 1] = trueSigHashByte; + return new ScriptBuilder().data(trueSignResult).data(key.getPubKey()).build(); + } + + public String signBSVTransaction(DeterministicKey key, List signParams) throws Exception { + List inputs = this.getInputs(); + if (inputs.size() != signParams.size()) { + throw new Exception(String.format("transactionInputs size %d , but signParams size %d", inputs.size(), signParams.size())); + } + for (int i = 0; i < signParams.size(); i++) { + int changeStep = 0; + if (signParams.get(i).isChange()) { + changeStep = 1; + } + DeterministicKey step4 = HDKeyDerivation.deriveChildKey(key, new ChildNumber(changeStep, false)); + DeterministicKey privateKey = HDKeyDerivation.deriveChildKey(step4, new ChildNumber(signParams.get(i).getAddressIndex(), false)); + byte[] preScript = Hex.decode(signParams.get(i).getScriptHex().getBytes()); + Script inputScript = this.createVinScript(i, privateKey, preScript, signParams.get(i).getAmount(), SigHash.ALL); + this.getInput(i).setScriptSig(inputScript); + } + return new String(Hex.encode(this.bitcoinSerialize())); + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/DotApiConstants.java b/src/main/java/cn/sliyun/dotwallet/DotApiConstants.java new file mode 100644 index 0000000..cd2da40 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/DotApiConstants.java @@ -0,0 +1,11 @@ +package cn.sliyun.dotwallet; + +public interface DotApiConstants { + + + String getSubUserList = "/v1/mempool/getSubUserList"; + String setMiningType = "/v1/mempool/setMiningType"; + String getBlockList = "/v1/mempool/getBlockList"; + String getShareAccept = "/v1/mempool/getShareAccept"; + +} diff --git a/src/main/java/cn/sliyun/dotwallet/DotWalletClient.java b/src/main/java/cn/sliyun/dotwallet/DotWalletClient.java new file mode 100644 index 0000000..17253d9 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/DotWalletClient.java @@ -0,0 +1,252 @@ +package cn.sliyun.dotwallet; + +import cn.sliyun.dotwallet.entity.DotBaseResponse; +import cn.sliyun.dotwallet.entity.PKIRequest; +import cn.sliyun.dotwallet.entity.Vout; +import cn.sliyun.dotwallet.entity.response.BaseResponse; +import cn.sliyun.dotwallet.entity.response.BroadcastTransactionResponse; +import cn.sliyun.dotwallet.entity.response.BuildTransactionResponse; +import cn.sliyun.dotwallet.entity.response.GetMerkleProofResponse; +import cn.sliyun.dotwallet.util.HttpUtil; +import cn.sliyun.http.OkHttpUtils; +import com.alibaba.fastjson.JSON; +import okhttp3.MediaType; +import okhttp3.Response; +import org.bitcoinj.core.ECKey; +import org.bitcoinj.core.Sha256Hash; +import org.bitcoinj.crypto.ChildNumber; +import org.bitcoinj.crypto.DeterministicKey; +import org.bitcoinj.crypto.HDKeyDerivation; +import org.bitcoinj.crypto.MnemonicCode; +import org.bitcoinj.params.AbstractBitcoinNetParams; +import org.bitcoinj.params.MainNetParams; +import org.spongycastle.util.encoders.Hex; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class DotWalletClient { + private static final String DotWalletHost = "https://api.ddpurse.com"; + public static final AbstractBitcoinNetParams BSVNetParams = MainNetParams.get(); + private DeterministicKey masterKey; + + /** + * 打点HD钱包使用路径为:m/44'/0'/0' + * + * @param masterKey main HDKey + */ + private DotWalletClient(DeterministicKey masterKey) { + //path:m/44' + DeterministicKey step1 = HDKeyDerivation.deriveChildKey(masterKey, new ChildNumber(44, true)); + //path:m/44'/0' + DeterministicKey step2 = HDKeyDerivation.deriveChildKey(step1, new ChildNumber(0, true)); + //path:m/44'/0'/0' + DeterministicKey step3 = HDKeyDerivation.deriveChildKey(step2, new ChildNumber(0, true)); + this.masterKey = step3; + } + + /** + * @param mnemonicWords 助记词 + * @return + * @throws Exception + */ + public static DotWalletClient newInstance(List mnemonicWords) throws Exception { + if (mnemonicWords == null || mnemonicWords.size() == 0) { + throw new Exception("mnemonic words empty"); + } + byte[] seed = MnemonicCode.toSeed(mnemonicWords, ""); + return new DotWalletClient(HDKeyDerivation.createMasterPrivateKey(seed)); + } + + /** + * 注册xPub + * + * @param userIndex 该xpub与用户的关联,不可重复,不可为0,需要记住该数字 + * @param xPub 公钥 + * @return + * @throws Exception + */ + public BaseResponse registerXPub(Integer userIndex, String xPub) throws Exception { + Map params = new HashMap<>(); + params.put("appid", "test_bsv_coin_regular"); + params.put("user_index", userIndex); + params.put("xpub", xPub); + params.put("seed", xPub); + return doPKIRequest("/v1/bsv/register_xpub", params, BaseResponse.class); + } + + /** + * 构建未签名交易 + * + * @param userIndex 注册公钥时填写的userIndex + * @param vouts 交易输出 + * @param feeByte 交易手续费费率,最终以feesatoshi/feebyte计算,表示每字节多少聪,建议值`2` + * @param feeSatoshi 交易手续费费率,最终以feesatoshi/feebyte计算,表示每字节多少聪,建议值`2` + * @return + * @throws Exception + */ + public BuildTransactionResponse buildTransaction(Integer userIndex, List vouts, Integer feeByte, Integer feeSatoshi) throws Exception { + Map sender = new HashMap<>(); + sender.put("appid", "test_bsv_coin_regular"); + sender.put("user_index", userIndex); + Map params = new HashMap<>(); + params.put("sender", sender); + params.put("vouts", vouts); + params.put("feebyte", feeByte); + params.put("feesatoshi", feeSatoshi); + params.put("sign", false); + params.put("send", false); + return doPKIRequest("/v1/bsv/send_to_script", params, BuildTransactionResponse.class); + } + + /** + * 广播交易 + * + * @param rawtx 十六进制已签名的原始交易 + * @param unlimited 是否突破链式交易上线 + * @return + * @throws Exception + */ + public BroadcastTransactionResponse broadcastTransaction(String rawtx, Boolean unlimited) throws Exception { + Map params = new HashMap<>(); + params.put("rawtx", rawtx); + params.put("unlimit", unlimited); + return doPKIRequest("/v1/bsv/broadcast_transaction", params, BroadcastTransactionResponse.class); + } + + /** + * 获取默克尔证明 + * + * @param txid 交易txid + * @return + * @throws Exception + */ + public GetMerkleProofResponse getMerkleProof(String txid) throws Exception { + Map params = new HashMap<>(); + params.put("txid", txid); + return doPKIRequest("/v1/bsvchain/get_merkleproof", params, GetMerkleProofResponse.class); + } + + public GetMerkleProofResponse getSubUser() throws Exception { + Map params = new HashMap<>(); + return doPKIRequest(DotApiConstants.getSubUserList, params, GetMerkleProofResponse.class); + } + + + public DotBaseResponse getSubUserList() { + Map params = new HashMap<>(); + return doRequest(DotApiConstants.getSubUserList,params); + } + + + public DotBaseResponse startSolo(int puid, String address) { + Map params = new HashMap<>(); + params.put("puid", puid); + params.put("is_solo", 1); + params.put("address", address); + return doRequest(DotApiConstants.setMiningType,params); + } + + public DotBaseResponse stopSolo(int puid, String address) { + Map params = new HashMap<>(); + params.put("puid", puid); + params.put("is_solo", 0); + params.put("address", address); + return doRequest(DotApiConstants.setMiningType,params); + } + + + public DotBaseResponse getBlockList(long startTime, long endTime) { + Map params = new HashMap<>(); + params.put("start_time", startTime); + params.put("end_time", endTime); + return doRequest(DotApiConstants.getBlockList,params); + } + + + public DotBaseResponse getShareAccept(long startTime, long endTime) { + Map params = new HashMap<>(); + params.put("start_time", startTime); + params.put("end_time", endTime); + return doRequest(DotApiConstants.getShareAccept,params); + } + + + private DotBaseResponse doRequest(String requestURL, Map params) { + String payload = JSON.toJSONString(params); + //path:m/44'/0'/0'/0 + DeterministicKey step4 = HDKeyDerivation.deriveChildKey(this.masterKey, new ChildNumber(0, false)); + //path:m/44'/0'/0'/0/0 + DeterministicKey PKIKey = HDKeyDerivation.deriveChildKey(step4, new ChildNumber(0, false)); + Sha256Hash hashToSign = Sha256Hash.of(payload.getBytes()); + ECKey.ECDSASignature ecdsaSignature = PKIKey.sign(hashToSign); + PKIRequest request = new PKIRequest(); + request.setPayload(payload); + request.setSignature(Hex.toHexString(ecdsaSignature.encodeToDER())); + request.setPubkey(Hex.toHexString(PKIKey.getPubKey())); + String json = JSON.toJSONString(request); + System.out.println("doRequest json :"+json); + Response response = null; + try { + response = + OkHttpUtils + .postString() + .url(DotWalletHost+requestURL) + .content(json) + .mediaType(MediaType.parse("application/json; charset=utf-8")) + .build() + .execute(); + String re = response.body().string(); + System.out.println("response:" + re); + DotBaseResponse baseResponse = JSON.parseObject(re, DotBaseResponse.class); + return baseResponse; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + private T + doPKIRequest(String requestURL, Map params, Class tClass) throws Exception { + String payload = JSON.toJSONString(params); + //path:m/44'/0'/0'/0 + DeterministicKey step4 = HDKeyDerivation.deriveChildKey(this.masterKey, new ChildNumber(0, false)); + //path:m/44'/0'/0'/0/0 + DeterministicKey PKIKey = HDKeyDerivation.deriveChildKey(step4, new ChildNumber(0, false)); + Sha256Hash hashToSign = Sha256Hash.of(payload.getBytes()); + ECKey.ECDSASignature ecdsaSignature = PKIKey.sign(hashToSign); + PKIRequest request = new PKIRequest(); + request.setPayload(payload); + request.setSignature(Hex.toHexString(ecdsaSignature.encodeToDER())); + request.setPubkey(Hex.toHexString(PKIKey.getPubKey())); + String json = JSON.toJSONString(request); + System.out.println("doPKIRequest json :"+json); + + String result = HttpUtil.httpPostWithJson(DotWalletHost+requestURL, json); + T response; + try { + if (result.equals("")) { + throw new RuntimeException("empty http result"); + } + response = JSON.parseObject(result, tClass); + return response; + } catch (Exception e) { + try { + response = tClass.newInstance(); + Field code = tClass.getSuperclass().getDeclaredField("code"); + code.setAccessible(true); + code.set(response, -1); + Field msg = tClass.getSuperclass().getDeclaredField("msg"); + msg.setAccessible(true); + msg.set(response, result); + return response; + } catch (Exception e1) { + throw new RuntimeException(e1); + } + } + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/DotWalletManager.java b/src/main/java/cn/sliyun/dotwallet/DotWalletManager.java new file mode 100644 index 0000000..11bae67 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/DotWalletManager.java @@ -0,0 +1,89 @@ +package cn.sliyun.dotwallet; + +import cn.sliyun.dotwallet.entity.DotBaseResponse; +import com.alibaba.fastjson.JSON; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class DotWalletManager { + + + public static void main(String[] args) { + long s = System.currentTimeMillis()/1000-86400 ; + long e= System.currentTimeMillis()/1000; + getInstance().getBlockList(s,e); + } + + private DotWalletClient client; + public static DotWalletManager dotWalletManager; + public String[] mnemonicWordArray = new String[]{"world", "ramp", "coil", "awesome", "loud", "warrior", "equip", "panic", "shield", "away", "desert", "find"}; + + public static DotWalletManager getInstance() { + if (dotWalletManager == null) { + dotWalletManager = new DotWalletManager(); + } + return dotWalletManager; + } + + + public DotWalletManager() { + //获取PKI接口能力 + //从打点钱包web版(www.ddpurse.com)导出BSV助记词 + List mnemonicWords = Arrays.asList(mnemonicWordArray); + System.out.println("BSV助记词:" + JSON.toJSONString(mnemonicWords)); + //初始化DotWalletClient + try { + //使用该助记词生成的私钥进行接口调用签名 + client = DotWalletClient.newInstance(mnemonicWords); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + public void getSubUserList() { + try { +// GetMerkleProofResponse response= client.getSubUser(); +// System.out.println("response:"+response.toString()); +// DotBaseResponse broadcastTransactionResponse= client.getSubUserList(); +// System.out.println("getSubUserList:"+ JSON.toJSONString(broadcastTransactionResponse)); + Object startSolo = client.startSolo(7990, "123"); + System.out.println("startSolo:" + JSON.toJSONString(startSolo)); + +// DotBaseResponse startSolo= client.startSolo("1","add"); +// System.out.println("startSolo:"+startSolo.toString()); +// DotBaseResponse stopSolo= client.stopSolo("1","asd"); +// System.out.println("stopSolo:"+stopSolo.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public boolean startSolo(String address) { + DotBaseResponse startSolo = client.startSolo(7990, address); + if (startSolo.getCode() == 0) { + return true; + } + return false; + } + + public boolean stopSolo(String address) { + DotBaseResponse startSolo = client.startSolo(7990, address); + if (startSolo.getCode() == 0) { + return true; + } + return false; + } + + + public List getBlockList(long startTime, long endTime) { + DotBaseResponse startSolo = client.getBlockList(startTime, endTime); + if (startSolo.getCode() == 0) { + return startSolo.getData(); + } + return new ArrayList(); + } + +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/BlockBean.java b/src/main/java/cn/sliyun/dotwallet/entity/BlockBean.java new file mode 100644 index 0000000..b0f8135 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/BlockBean.java @@ -0,0 +1,78 @@ +package cn.sliyun.dotwallet.entity; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class BlockBean { + + /** + * puid : 145 + * worker_full_name : h555.cpu + * height : 24492 + * hash : 5f9ac746b83bb33c6ff2ba79715057a9b8b6d5df0763d33a51eee2ded306d8ff + * rewards : 0 + * created_at : 1591828601 + */ + + @JsonProperty("puid") + private Integer puid; + @JsonProperty("worker_full_name") + private String workerFullName; + @JsonProperty("height") + private Integer height; + @JsonProperty("hash") + private String hash; + @JsonProperty("rewards") + private int rewards; + @JsonProperty("created_at") + private long createdAt; + + public Integer getPuid() { + return puid; + } + + public void setPuid(Integer puid) { + this.puid = puid; + } + + public String getWorkerFullName() { + return workerFullName; + } + + public void setWorkerFullName(String workerFullName) { + this.workerFullName = workerFullName; + } + + public Integer getHeight() { + return height; + } + + public void setHeight(Integer height) { + this.height = height; + } + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } + + public Integer getRewards() { + return rewards; + } + + public void setRewards(Integer rewards) { + this.rewards = rewards; + } + + public long getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(long createdAt) { + this.createdAt = createdAt; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/DotBaseResponse.java b/src/main/java/cn/sliyun/dotwallet/entity/DotBaseResponse.java new file mode 100644 index 0000000..0cef7b6 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/DotBaseResponse.java @@ -0,0 +1,55 @@ +package cn.sliyun.dotwallet.entity; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class DotBaseResponse { + + /** + * code : 0 + * msg : MSG_act_success + * data : [{"puid":5024,"user_name":"loan_system","is_solo":0,"address":"","created_at":1589446708}] + */ + + @JsonProperty("code") + private Integer code; + @JsonProperty("msg") + private String msg; + @JsonProperty("data") + private T t; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return t; + } + + public void setData(T data) { + this.t = data; + } + + @Override + public String toString() { + return "DotBaseResponse{" + + "code=" + code + + ", msg='" + msg + '\'' + + ", t=" + t + + '}'; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/PKIRequest.java b/src/main/java/cn/sliyun/dotwallet/entity/PKIRequest.java new file mode 100644 index 0000000..dc240bb --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/PKIRequest.java @@ -0,0 +1,45 @@ +package cn.sliyun.dotwallet.entity; + +import com.alibaba.fastjson.annotation.JSONField; + +public class PKIRequest { + @JSONField(name = "payload") + private String payload; + @JSONField(name = "signature") + private String signature; + @JSONField(name = "pubkey") + private String pubkey; + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public String getPubkey() { + return pubkey; + } + + public void setPubkey(String pubkey) { + this.pubkey = pubkey; + } + + @Override + public String toString() { + return "PKIRequest{" + + "payload='" + payload + '\'' + + ", signature='" + signature + '\'' + + ", pubkey='" + pubkey + '\'' + + '}'; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/Vin.java b/src/main/java/cn/sliyun/dotwallet/entity/Vin.java new file mode 100644 index 0000000..d8110ae --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/Vin.java @@ -0,0 +1,32 @@ +package cn.sliyun.dotwallet.entity; + + +import com.alibaba.fastjson.annotation.JSONField; + +public class Vin { + @JSONField(name = "txid") + private String txid; + @JSONField(name = "index") + private int index; + + public Vin(String txid, int index) { + this.txid = txid; + this.index = index; + } + + public String getTxid() { + return txid; + } + + public void setTxid(String txid) { + this.txid = txid; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/Vout.java b/src/main/java/cn/sliyun/dotwallet/entity/Vout.java new file mode 100644 index 0000000..e8748ce --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/Vout.java @@ -0,0 +1,32 @@ +package cn.sliyun.dotwallet.entity; + + +import com.alibaba.fastjson.annotation.JSONField; + +public class Vout { + @JSONField(name="amount") + private long amount; + @JSONField(name="hexscript") + private String hexScript; + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + public String getHexScript() { + return hexScript; + } + + public void setHexScript(String hexScript) { + this.hexScript = hexScript; + } + + public Vout(long amount, String hexScript) { + this.amount = amount; + this.hexScript = hexScript; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/response/BaseResponse.java b/src/main/java/cn/sliyun/dotwallet/entity/response/BaseResponse.java new file mode 100644 index 0000000..9137650 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/response/BaseResponse.java @@ -0,0 +1,48 @@ +package cn.sliyun.dotwallet.entity.response; + +import com.alibaba.fastjson.annotation.JSONField; + +/** + * 响应基类 + */ +public class BaseResponse { + public static final Integer SuccessCode = 0; + /** + * 状态码 + */ + @JSONField(name = "code") + private Integer code; + /** + * 信息 + */ + @JSONField(name = "msg") + private String msg; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public boolean isSuccess() { + return this.code == SuccessCode; + } + + @Override + public String toString() { + return "BaseResponse{" + + "code=" + code + + ", msg='" + msg + '\'' + + '}'; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/response/BroadcastTransactionResponse.java b/src/main/java/cn/sliyun/dotwallet/entity/response/BroadcastTransactionResponse.java new file mode 100644 index 0000000..29d53ec --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/response/BroadcastTransactionResponse.java @@ -0,0 +1,14 @@ +package cn.sliyun.dotwallet.entity.response; + +public class BroadcastTransactionResponse extends BaseResponse { + //txid + private String data; + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/response/BuildTransactionResponse.java b/src/main/java/cn/sliyun/dotwallet/entity/response/BuildTransactionResponse.java new file mode 100644 index 0000000..2b3392e --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/response/BuildTransactionResponse.java @@ -0,0 +1,24 @@ +package cn.sliyun.dotwallet.entity.response; + + +import cn.sliyun.dotwallet.entity.response.data.BuildTransactionData; + +public class BuildTransactionResponse extends BaseResponse { + + private BuildTransactionData data; + + public BuildTransactionData getData() { + return data; + } + + public void setData(BuildTransactionData data) { + this.data = data; + } + + @Override + public String toString() { + return "BuildTransactionResponse{" + + "data=" + data + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/dotwallet/entity/response/GetMerkleProofResponse.java b/src/main/java/cn/sliyun/dotwallet/entity/response/GetMerkleProofResponse.java new file mode 100644 index 0000000..34e238f --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/response/GetMerkleProofResponse.java @@ -0,0 +1,23 @@ +package cn.sliyun.dotwallet.entity.response; + + +import cn.sliyun.dotwallet.entity.response.data.MerkleProofData; + +public class GetMerkleProofResponse extends BaseResponse { + private MerkleProofData data; + + public MerkleProofData getData() { + return data; + } + + public void setData(MerkleProofData data) { + this.data = data; + } + + @Override + public String toString() { + return "GetMerkleProofResponse{" + + "data=" + data + + '}'; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/entity/response/data/BuildTransactionData.java b/src/main/java/cn/sliyun/dotwallet/entity/response/data/BuildTransactionData.java new file mode 100644 index 0000000..77881d5 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/response/data/BuildTransactionData.java @@ -0,0 +1,49 @@ +package cn.sliyun.dotwallet.entity.response.data; + +import com.alibaba.fastjson.annotation.JSONField; + +import java.util.List; + +public class BuildTransactionData { + @JSONField(name = "txid") + private String txid; + @JSONField(name = "fee") + private long fee; + @JSONField(name = "rawtx") + private String rawtx; + @JSONField(name = "params") + private List params; + + public String getTxid() { + return txid; + } + + public void setTxid(String txid) { + this.txid = txid; + } + + public long getFee() { + return fee; + } + + public void setFee(long fee) { + this.fee = fee; + } + + public String getRawtx() { + return rawtx; + } + + public void setRawtx(String rawtx) { + this.rawtx = rawtx; + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } +} + diff --git a/src/main/java/cn/sliyun/dotwallet/entity/response/data/MerkleProofData.java b/src/main/java/cn/sliyun/dotwallet/entity/response/data/MerkleProofData.java new file mode 100644 index 0000000..affebec --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/response/data/MerkleProofData.java @@ -0,0 +1,56 @@ +package cn.sliyun.dotwallet.entity.response.data; + +import com.alibaba.fastjson.annotation.JSONField; + +public class MerkleProofData { + @JSONField(name = "flags") + private Integer flags; + @JSONField(name = "index") + private Integer index; + @JSONField(name = "txOrId") + private String TxOrId; + @JSONField(name = "target") + private MerkleProofTarget Target; + @JSONField(name = "nodes") + private String[] nodes; + + public Integer getFlags() { + return flags; + } + + public void setFlags(Integer flags) { + this.flags = flags; + } + + public Integer getIndex() { + return index; + } + + public void setIndex(Integer index) { + this.index = index; + } + + public String getTxOrId() { + return TxOrId; + } + + public void setTxOrId(String txOrId) { + TxOrId = txOrId; + } + + public MerkleProofTarget getTarget() { + return Target; + } + + public void setTarget(MerkleProofTarget target) { + Target = target; + } + + public String[] getNodes() { + return nodes; + } + + public void setNodes(String[] nodes) { + this.nodes = nodes; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/dotwallet/entity/response/data/MerkleProofTarget.java b/src/main/java/cn/sliyun/dotwallet/entity/response/data/MerkleProofTarget.java new file mode 100644 index 0000000..9874c20 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/response/data/MerkleProofTarget.java @@ -0,0 +1,171 @@ +package cn.sliyun.dotwallet.entity.response.data; + +import com.alibaba.fastjson.annotation.JSONField; + +// Hash string `json:"hash"` +// Confirmations int64 `json:"confirmations"` +// Height int64 `json:"height"` +// Version int64 `json:"version"` +// VersionHex string `json:"versionHex"` +// Merkleroot string `json:"merkleroot"` +// NumTx int64 `json:"num_tx"` +// Time int64 `json:"time"` +// Mediantime int64 `json:"mediantime"` +// Nonce int64 `json:"nonce"` +// Bits string `json:"bits"` +// Difficulty float64 `json:"difficulty"` +// Chainwork string `json:"chainwork"` +// Previousblockhash string `json:"previousblockhash"` +// Nextblockhash string `json:"nextblockhash"` +public class MerkleProofTarget { + @JSONField(name = "hash") + private String hash; + @JSONField(name = "confirmations") + private Integer confirmations; + @JSONField(name = "height") + private Integer height; + @JSONField(name = "version") + private Integer version; + @JSONField(name = "versionHex") + private String versionHex; + @JSONField(name = "merkleroot") + private String merkleRoot; + @JSONField(name = "num_tx") + private Integer numTx; + @JSONField(name = "time") + private Integer time; + @JSONField(name = "mediantime") + private Integer mediantime; + @JSONField(name = "nonce") + private Integer nonce; + @JSONField(name = "bits") + private String bits; + @JSONField(name = "difficulty") + private Float difficulty; + @JSONField(name = "chainwork") + private String chainWork; + @JSONField(name = "previousblockhash") + private String PreviousBlockHash; + @JSONField(name = "nextblockhash") + private String nextBlockHash; + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } + + public Integer getConfirmations() { + return confirmations; + } + + public void setConfirmations(Integer confirmations) { + this.confirmations = confirmations; + } + + public Integer getHeight() { + return height; + } + + public void setHeight(Integer height) { + this.height = height; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getVersionHex() { + return versionHex; + } + + public void setVersionHex(String versionHex) { + this.versionHex = versionHex; + } + + public String getMerkleRoot() { + return merkleRoot; + } + + public void setMerkleRoot(String merkleRoot) { + this.merkleRoot = merkleRoot; + } + + public Integer getNumTx() { + return numTx; + } + + public void setNumTx(Integer numTx) { + this.numTx = numTx; + } + + public Integer getTime() { + return time; + } + + public void setTime(Integer time) { + this.time = time; + } + + public Integer getMediantime() { + return mediantime; + } + + public void setMediantime(Integer mediantime) { + this.mediantime = mediantime; + } + + public Integer getNonce() { + return nonce; + } + + public void setNonce(Integer nonce) { + this.nonce = nonce; + } + + public String getBits() { + return bits; + } + + public void setBits(String bits) { + this.bits = bits; + } + + public Float getDifficulty() { + return difficulty; + } + + public void setDifficulty(Float difficulty) { + this.difficulty = difficulty; + } + + public String getChainWork() { + return chainWork; + } + + public void setChainWork(String chainWork) { + this.chainWork = chainWork; + } + + public String getPreviousBlockHash() { + return PreviousBlockHash; + } + + public void setPreviousBlockHash(String previousBlockHash) { + PreviousBlockHash = previousBlockHash; + } + + public String getNextBlockHash() { + return nextBlockHash; + } + + public void setNextBlockHash(String nextBlockHash) { + this.nextBlockHash = nextBlockHash; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/dotwallet/entity/response/data/SignParam.java b/src/main/java/cn/sliyun/dotwallet/entity/response/data/SignParam.java new file mode 100644 index 0000000..a29143b --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/entity/response/data/SignParam.java @@ -0,0 +1,50 @@ +package cn.sliyun.dotwallet.entity.response.data; + + +import com.alibaba.fastjson.annotation.JSONField; + +public class SignParam { + @JSONField(name = "address_index") + private int addressIndex; + + @JSONField(name = "is_change") + private boolean isChange; + + @JSONField(name = "script_hex") + private String scriptHex; + + @JSONField(name = "amount") + private long amount; + + public int getAddressIndex() { + return addressIndex; + } + + public void setAddressIndex(int addressIndex) { + this.addressIndex = addressIndex; + } + + public boolean isChange() { + return isChange; + } + + public void setChange(boolean change) { + isChange = change; + } + + public String getScriptHex() { + return scriptHex; + } + + public void setScriptHex(String scriptHex) { + this.scriptHex = scriptHex; + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } +} diff --git a/src/main/java/cn/sliyun/dotwallet/util/HttpUtil.java b/src/main/java/cn/sliyun/dotwallet/util/HttpUtil.java new file mode 100644 index 0000000..620484d --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/util/HttpUtil.java @@ -0,0 +1,217 @@ +package cn.sliyun.dotwallet.util; + +import org.apache.http.HttpEntity; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.util.Map; + +/** + * Http操作工具类 + * + * @author + */ +public class HttpUtil { + /** + * 发送POST请求,参数为JSON格式 + * + * @param url 请求地址 + * @param json JSON格式参数 + * @return + */ + public static String httpPostWithJson(String url, String json) throws Exception{ + String returnValue = ""; + CloseableHttpClient httpClient = HttpClients.createDefault(); + try { + HttpPost httpPost = new HttpPost(url); + StringEntity requestEntity = new StringEntity(json, "utf-8"); + httpPost.setConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()); + httpPost.setHeader("Content-Type", "application/json"); + httpPost.setEntity(requestEntity); + CloseableHttpResponse resp = httpClient.execute(httpPost); + returnValue = EntityUtils.toString(resp.getEntity()); + } catch (Exception e) { + throw e; + } finally { + try { + httpClient.close(); + } catch (IOException e) { + throw e; + } + } + return returnValue; + } + + /** + * 发送POST请求,body参数为JSON格式,自定义添加header参数 + * + * @param url 请求地址 + * @param json JSON格式参数 + * @param paramHeadMap header参数 + * @return + */ + public static String httpPostWithJson(String url, String json, Map paramHeadMap) { + String returnValue = ""; + CloseableHttpClient httpClient = HttpClients.createDefault(); + try { + HttpPost httpPost = new HttpPost(url); + StringEntity requestEntity = new StringEntity(json, "utf-8"); + + httpPost.setConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()); + httpPost.setHeader("Content-Type", "application/json"); + for (Map.Entry entry : paramHeadMap.entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue()); + } + httpPost.setEntity(requestEntity); + + CloseableHttpResponse resp = httpClient.execute(httpPost); + returnValue = EntityUtils.toString(resp.getEntity()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + httpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return returnValue; + } + + /** + * 发送普通get请求 + * + * @param url 地址 + * @return + */ + public static String httpGet(String url) { + CloseableHttpClient client = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet(url); + CloseableHttpResponse response = null; + try { + response = client.execute(httpGet); + HttpEntity entity = response.getEntity(); + return EntityUtils.toString(entity, "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (response != null) { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + client.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + + /** + * 发送普通get请求 + * + * @param url 地址 + * @param paramMap 参数 + * @return + */ + public static String httpGet(String url, Map paramMap) { + if (paramMap != null && !paramMap.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : paramMap.entrySet()) { + sb.append(entry.getKey()); + sb.append("="); + sb.append(entry.getValue()); + sb.append("&"); + } + url = url + "?" + sb.toString(); + } + CloseableHttpClient client = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet(url); + CloseableHttpResponse response = null; + try { + response = client.execute(httpGet); + HttpEntity entity = response.getEntity(); + return EntityUtils.toString(entity, "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (response != null) { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + client.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + + /** + * 发送普通get请求 + * + * @param url 地址 + * @param paramMap 参数 + * @param headerMap header + * @return + */ + public static String httpGet(String url, Map paramMap, Map headerMap) { + if (paramMap != null && !paramMap.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : paramMap.entrySet()) { + sb.append(entry.getKey()); + sb.append("="); + sb.append(entry.getValue()); + sb.append("&"); + } + url = url + "?" + sb.toString(); + } + CloseableHttpClient client = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet(url); + httpGet.setConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()); + if (headerMap != null && !headerMap.isEmpty()) { + for (Map.Entry entry : headerMap.entrySet()) { + httpGet.setHeader(entry.getKey(), (String)entry.getValue()); + } + } + CloseableHttpResponse response = null; + try { + response = client.execute(httpGet); + HttpEntity entity = response.getEntity(); + return EntityUtils.toString(entity, "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (response != null) { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + client.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + +} diff --git a/src/main/java/cn/sliyun/dotwallet/util/Util.java b/src/main/java/cn/sliyun/dotwallet/util/Util.java new file mode 100644 index 0000000..f0d1708 --- /dev/null +++ b/src/main/java/cn/sliyun/dotwallet/util/Util.java @@ -0,0 +1,38 @@ +package cn.sliyun.dotwallet.util; + +public class Util { + public static byte[] longToBytesLittle(long n) { + byte[] b = new byte[8]; + b[0] = (byte) (n & 0xff); + b[1] = (byte) (n >> 8 & 0xff); + b[2] = (byte) (n >> 16 & 0xff); + b[3] = (byte) (n >> 24 & 0xff); + b[4] = (byte) (n >> 32 & 0xff); + b[5] = (byte) (n >> 40 & 0xff); + b[6] = (byte) (n >> 48 & 0xff); + b[7] = (byte) (n >> 56 & 0xff); + return b; + } + + public static byte[] intToBytesLittle(int n) { + byte[] b = new byte[4]; + b[0] = (byte) (n & 0xff); + b[1] = (byte) (n >> 8 & 0xff); + b[2] = (byte) (n >> 16 & 0xff); + b[3] = (byte) (n >> 24 & 0xff); + return b; + } + + public static byte[] shortToBytesLittle(short n) { + byte[] b = new byte[2]; + b[0] = (byte) (n & 0xff); + b[1] = (byte) (n >> 8 & 0xff); + return b; + } + + public static byte[] byteToBytesLittle(byte n) { + byte[] b = new byte[1]; + b[0] = (byte) (n & 0xff); + return b; + } +} diff --git a/src/main/java/cn/sliyun/framework/annotion/LoginRequired.java b/src/main/java/cn/sliyun/framework/annotion/LoginRequired.java new file mode 100644 index 0000000..040957a --- /dev/null +++ b/src/main/java/cn/sliyun/framework/annotion/LoginRequired.java @@ -0,0 +1,16 @@ +package cn.sliyun.framework.annotion; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginRequired { + /** + * 是否需要登录 + */ + boolean required() default true; + +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/annotion/Permission.java b/src/main/java/cn/sliyun/framework/annotion/Permission.java new file mode 100644 index 0000000..5ae441c --- /dev/null +++ b/src/main/java/cn/sliyun/framework/annotion/Permission.java @@ -0,0 +1,24 @@ +package cn.sliyun.framework.annotion; + + +import java.lang.annotation.*; + +/** + * 权限注解 用于检查权限 规定访问权限 + * + * @example @Permission({role1,role2}) + * @example @Permission + */ +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface Permission { + + /** + *

角色英文名称

+ *

使用注解时加上这个值表示限制只有某个角色的才可以访问对应的资源

+ *

常用在某些资源限制只有超级管理员角色才可访问

+ */ + String[] value() default {}; +} + diff --git a/src/main/java/cn/sliyun/framework/aspectj/DataScopeAspect.java b/src/main/java/cn/sliyun/framework/aspectj/DataScopeAspect.java new file mode 100644 index 0000000..87539fa --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/DataScopeAspect.java @@ -0,0 +1,170 @@ +package cn.sliyun.framework.aspectj; + +import java.lang.reflect.Method; + +import cn.sliyun.framework.web.domain.BaseEntity; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.spring.SpringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.DataScope; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.TokenService; +import cn.sliyun.project.system.domain.SysRole; +import cn.sliyun.project.system.domain.SysUser; + +/** + * 数据过滤处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class DataScopeAspect +{ + /** + * 全部数据权限 + */ + public static final String DATA_SCOPE_ALL = "1"; + + /** + * 自定数据权限 + */ + public static final String DATA_SCOPE_CUSTOM = "2"; + + /** + * 部门数据权限 + */ + public static final String DATA_SCOPE_DEPT = "3"; + + /** + * 部门及以下数据权限 + */ + public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; + + /** + * 仅本人数据权限 + */ + public static final String DATA_SCOPE_SELF = "5"; + + /** + * 数据权限过滤关键字 + */ + public static final String DATA_SCOPE = "dataScope"; + + // 配置织入点 + @Pointcut("@annotation(cn.sliyun.framework.aspectj.lang.annotation.DataScope)") + public void dataScopePointCut() + { + } + + @Before("dataScopePointCut()") + public void doBefore(JoinPoint point) throws Throwable + { + handleDataScope(point); + } + + protected void handleDataScope(final JoinPoint joinPoint) + { + // 获得注解 + DataScope controllerDataScope = getAnnotationLog(joinPoint); + if (controllerDataScope == null) + { + return; + } + // 获取当前的用户 + LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNotNull(loginUser)) + { + SysUser currentUser = loginUser.getUser(); + // 如果是超级管理员,则不过滤数据 + if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) + { + dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), + controllerDataScope.userAlias()); + } + } + } + + /** + * 数据范围过滤 + * + * @param joinPoint 切点 + * @param user 用户 + * @param alias 别名 + */ + public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) + { + StringBuilder sqlString = new StringBuilder(); + + for (SysRole role : user.getRoles()) + { + String dataScope = role.getDataScope(); + if (DATA_SCOPE_ALL.equals(dataScope)) + { + sqlString = new StringBuilder(); + break; + } + else if (DATA_SCOPE_CUSTOM.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, + role.getRoleId())); + } + else if (DATA_SCOPE_DEPT.equals(dataScope)) + { + sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); + } + else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", + deptAlias, user.getDeptId(), user.getDeptId())); + } + else if (DATA_SCOPE_SELF.equals(dataScope)) + { + if (StringUtils.isNotBlank(userAlias)) + { + sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); + } + else + { + // 数据权限为仅本人且没有userAlias别名不查询任何数据 + sqlString.append(" OR 1=0 "); + } + } + } + + if (StringUtils.isNotBlank(sqlString.toString())) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); + } + } + } + + /** + * 是否存在注解,如果存在就获取 + */ + private DataScope getAnnotationLog(JoinPoint joinPoint) + { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + + if (method != null) + { + return method.getAnnotation(DataScope.class); + } + return null; + } +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/DataSourceAspect.java b/src/main/java/cn/sliyun/framework/aspectj/DataSourceAspect.java new file mode 100644 index 0000000..ed3ca74 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/DataSourceAspect.java @@ -0,0 +1,73 @@ +package cn.sliyun.framework.aspectj; + +import java.util.Objects; + +import cn.sliyun.framework.aspectj.lang.annotation.DataSource; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.datasource.DynamicDataSourceContextHolder; + +/** + * 多数据源处理 + * + * @author ruoyi + */ +@Aspect +@Order(1) +@Component +public class DataSourceAspect +{ + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Pointcut("@annotation(cn.sliyun.framework.aspectj.lang.annotation.DataSource)" + + "|| @within(cn.sliyun.framework.aspectj.lang.annotation.DataSource)") + public void dsPointCut() + { + + } + + @Around("dsPointCut()") + public Object around(ProceedingJoinPoint point) throws Throwable + { + DataSource dataSource = getDataSource(point); + + if (StringUtils.isNotNull(dataSource)) + { + DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); + } + + try + { + return point.proceed(); + } + finally + { + // 销毁数据源 在执行方法之后 + DynamicDataSourceContextHolder.clearDataSourceType(); + } + } + + /** + * 获取需要切换的数据源 + */ + public DataSource getDataSource(ProceedingJoinPoint point) + { + MethodSignature signature = (MethodSignature) point.getSignature(); + DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); + if (Objects.nonNull(dataSource)) + { + return dataSource; + } + + return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); + } +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/LogAspect.java b/src/main/java/cn/sliyun/framework/aspectj/LogAspect.java new file mode 100644 index 0000000..30799ce --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/LogAspect.java @@ -0,0 +1,242 @@ +package cn.sliyun.framework.aspectj; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.HandlerMapping; +import com.alibaba.fastjson.JSON; +import cn.sliyun.common.enums.HttpMethod; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.ip.IpUtils; +import cn.sliyun.common.utils.spring.SpringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessStatus; +import cn.sliyun.framework.manager.AsyncManager; +import cn.sliyun.framework.manager.factory.AsyncFactory; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.TokenService; +import cn.sliyun.project.monitor.domain.SysOperLog; + +/** + * 操作日志记录处理 + * + * @author ruoyi + */ +@Aspect +@Component +public class LogAspect +{ + private static final Logger log = LoggerFactory.getLogger(LogAspect.class); + + // 配置织入点 + @Pointcut("@annotation(cn.sliyun.framework.aspectj.lang.annotation.Log)") + public void logPointCut() + { + } + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) + { + handleLog(joinPoint, null, jsonResult); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "logPointCut()", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Exception e) + { + handleLog(joinPoint, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) + { + try + { + // 获得注解 + Log controllerLog = getAnnotationLog(joinPoint); + if (controllerLog == null) + { + return; + } + + // 获取当前的用户 + LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest()); + + // *========数据库日志=========*// + SysOperLog operLog = new SysOperLog(); + operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + // 请求的地址 + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + operLog.setOperIp(ip); + // 返回参数 + operLog.setJsonResult(JSON.toJSONString(jsonResult)); + + operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); + if (loginUser != null) + { + operLog.setOperName(loginUser.getUsername()); + } + + if (e != null) + { + operLog.setStatus(BusinessStatus.FAIL.ordinal()); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); + } + // 设置方法名称 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setMethod(className + "." + methodName + "()"); + // 设置请求方式 + operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog); + // 保存数据库 + AsyncManager.me().execute(AsyncFactory.recordOper(operLog)); + } + catch (Exception exp) + { + // 记录本地异常日志 + log.error("==前置通知异常=="); + log.error("异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + } + + /** + * 获取注解中对方法的描述信息 用于Controller层注解 + * + * @param log 日志 + * @param operLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception + { + // 设置action动作 + operLog.setBusinessType(log.businessType().ordinal()); + // 设置标题 + operLog.setTitle(log.title()); + // 设置操作人类别 + operLog.setOperatorType(log.operatorType().ordinal()); + // 是否需要保存request,参数和值 + if (log.isSaveRequestData()) + { + // 获取参数的信息,传入到数据库中。 + setRequestValue(joinPoint, operLog); + } + } + + /** + * 获取请求的参数,放到log中 + * + * @param operLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception + { + String requestMethod = operLog.getRequestMethod(); + if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) + { + String params = argsArrayToString(joinPoint.getArgs()); + operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + } + else + { + Map paramsMap = (Map) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000)); + } + } + + /** + * 是否存在注解,如果存在就获取 + */ + private Log getAnnotationLog(JoinPoint joinPoint) throws Exception + { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + + if (method != null) + { + return method.getAnnotation(Log.class); + } + return null; + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) + { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) + { + for (int i = 0; i < paramsArray.length; i++) + { + if (!isFilterObject(paramsArray[i])) + { + Object jsonObj = JSON.toJSON(paramsArray[i]); + params += jsonObj.toString() + " "; + } + } + } + return params.trim(); + } + + /** + * 判断是否需要过滤的对象。 + * + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) + { + Class clazz = o.getClass(); + if (clazz.isArray()) + { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } + else if (Collection.class.isAssignableFrom(clazz)) + { + Collection collection = (Collection) o; + for (Iterator iter = collection.iterator(); iter.hasNext();) + { + return iter.next() instanceof MultipartFile; + } + } + else if (Map.class.isAssignableFrom(clazz)) + { + Map map = (Map) o; + for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) + { + Map.Entry entry = (Map.Entry) iter.next(); + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse; + } +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/DataScope.java b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/DataScope.java new file mode 100644 index 0000000..d6af79f --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/DataScope.java @@ -0,0 +1,28 @@ +package cn.sliyun.framework.aspectj.lang.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 数据权限过滤注解 + * + * @author ruoyi + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataScope +{ + /** + * 部门表的别名 + */ + public String deptAlias() default ""; + + /** + * 用户表的别名 + */ + public String userAlias() default ""; +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/DataSource.java b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/DataSource.java new file mode 100644 index 0000000..4b61c8b --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/DataSource.java @@ -0,0 +1,28 @@ +package cn.sliyun.framework.aspectj.lang.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import cn.sliyun.framework.aspectj.lang.enums.DataSourceType; + +/** + * 自定义多数据源切换注解 + * + * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 + * + * @author ruoyi + */ +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface DataSource +{ + /** + * 切换数据源名称 + */ + public DataSourceType value() default DataSourceType.MASTER; +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Excel.java b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Excel.java new file mode 100644 index 0000000..55323bf --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Excel.java @@ -0,0 +1,165 @@ +package cn.sliyun.framework.aspectj.lang.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.math.BigDecimal; + +/** + * 自定义导出Excel数据注解 + * + * @author ruoyi + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Excel +{ + /** + * 导出时在excel中排序 + */ + public int sort() default Integer.MAX_VALUE; + + /** + * 导出到Excel中的名字. + */ + public String name() default ""; + + /** + * 日期格式, 如: yyyy-MM-dd + */ + public String dateFormat() default ""; + + /** + * 如果是字典类型,请设置字典的type值 (如: sys_user_sex) + */ + public String dictType() default ""; + + /** + * 读取内容转表达式 (如: 0=男,1=女,2=未知) + */ + public String readConverterExp() default ""; + + /** + * 分隔符,读取字符串组内容 + */ + public String separator() default ","; + + /** + * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化) + */ + public int scale() default -1; + + /** + * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN + */ + public int roundingMode() default BigDecimal.ROUND_HALF_EVEN; + + /** + * 导出类型(0数字 1字符串) + */ + public ColumnType cellType() default ColumnType.STRING; + + /** + * 导出时在excel中每个列的高度 单位为字符 + */ + public double height() default 14; + + /** + * 导出时在excel中每个列的宽 单位为字符 + */ + public double width() default 16; + + /** + * 文字后缀,如% 90 变成90% + */ + public String suffix() default ""; + + /** + * 当值为空时,字段的默认值 + */ + public String defaultValue() default ""; + + /** + * 提示信息 + */ + public String prompt() default ""; + + /** + * 设置只能选择不能输入的列内容. + */ + public String[] combo() default {}; + + /** + * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. + */ + public boolean isExport() default true; + + /** + * 另一个类中的属性名称,支持多级获取,以小数点隔开 + */ + public String targetAttr() default ""; + + /** + * 是否自动统计数据,在最后追加一行统计数据总和 + */ + public boolean isStatistics() default false; + + /** + * 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右) + */ + Align align() default Align.AUTO; + + public enum Align + { + AUTO(0), LEFT(1), CENTER(2), RIGHT(3); + private final int value; + + Align(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } + + /** + * 字段类型(0:导出导入;1:仅导出;2:仅导入) + */ + Type type() default Type.ALL; + + public enum Type + { + ALL(0), EXPORT(1), IMPORT(2); + private final int value; + + Type(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } + + public enum ColumnType + { + NUMERIC(0), STRING(1), IMAGE(2); + private final int value; + + ColumnType(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Excels.java b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Excels.java new file mode 100644 index 0000000..83c8ae5 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Excels.java @@ -0,0 +1,18 @@ +package cn.sliyun.framework.aspectj.lang.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Excel注解集 + * + * @author ruoyi + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Excels +{ + Excel[] value(); +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Log.java b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Log.java new file mode 100644 index 0000000..caa127d --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/annotation/Log.java @@ -0,0 +1,42 @@ +package cn.sliyun.framework.aspectj.lang.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.aspectj.lang.enums.OperatorType; + +/** + * 自定义操作日志记录注解 + * + * @author ruoyi + * + */ +@Target({ ElementType.PARAMETER, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log +{ + /** + * 模块 + */ + public String title() default ""; + + /** + * 功能 + */ + public BusinessType businessType() default BusinessType.OTHER; + + /** + * 操作人类别 + */ + public OperatorType operatorType() default OperatorType.MANAGE; + + /** + * 是否保存请求的参数 + */ + public boolean isSaveRequestData() default true; +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/enums/BusinessStatus.java b/src/main/java/cn/sliyun/framework/aspectj/lang/enums/BusinessStatus.java new file mode 100644 index 0000000..d8e3295 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/enums/BusinessStatus.java @@ -0,0 +1,20 @@ +package cn.sliyun.framework.aspectj.lang.enums; + +/** + * 操作状态 + * + * @author ruoyi + * + */ +public enum BusinessStatus +{ + /** + * 成功 + */ + SUCCESS, + + /** + * 失败 + */ + FAIL, +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/enums/BusinessType.java b/src/main/java/cn/sliyun/framework/aspectj/lang/enums/BusinessType.java new file mode 100644 index 0000000..6b639c6 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/enums/BusinessType.java @@ -0,0 +1,59 @@ +package cn.sliyun.framework.aspectj.lang.enums; + +/** + * 业务操作类型 + * + * @author ruoyi + */ +public enum BusinessType +{ + /** + * 其它 + */ + OTHER, + + /** + * 新增 + */ + INSERT, + + /** + * 修改 + */ + UPDATE, + + /** + * 删除 + */ + DELETE, + + /** + * 授权 + */ + GRANT, + + /** + * 导出 + */ + EXPORT, + + /** + * 导入 + */ + IMPORT, + + /** + * 强退 + */ + FORCE, + + /** + * 生成代码 + */ + GENCODE, + + /** + * 清空数据 + */ + CLEAN, +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/enums/DataSourceType.java b/src/main/java/cn/sliyun/framework/aspectj/lang/enums/DataSourceType.java new file mode 100644 index 0000000..7231bed --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/enums/DataSourceType.java @@ -0,0 +1,19 @@ +package cn.sliyun.framework.aspectj.lang.enums; + +/** + * 数据源 + * + * @author ruoyi + */ +public enum DataSourceType +{ + /** + * 主库 + */ + MASTER, + + /** + * 从库 + */ + SLAVE +} diff --git a/src/main/java/cn/sliyun/framework/aspectj/lang/enums/OperatorType.java b/src/main/java/cn/sliyun/framework/aspectj/lang/enums/OperatorType.java new file mode 100644 index 0000000..fbf3bc5 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/aspectj/lang/enums/OperatorType.java @@ -0,0 +1,24 @@ +package cn.sliyun.framework.aspectj.lang.enums; + +/** + * 操作人类别 + * + * @author ruoyi + */ +public enum OperatorType +{ + /** + * 其它 + */ + OTHER, + + /** + * 后台用户 + */ + MANAGE, + + /** + * 手机端用户 + */ + MOBILE +} diff --git a/src/main/java/cn/sliyun/framework/config/ApplicationConfig.java b/src/main/java/cn/sliyun/framework/config/ApplicationConfig.java new file mode 100644 index 0000000..d913221 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/ApplicationConfig.java @@ -0,0 +1,30 @@ +package cn.sliyun.framework.config; + +import java.util.TimeZone; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +/** + * 程序注解配置 + * + * @author ruoyi + */ +@Configuration +// 表示通过aop框架暴露该代理对象,AopContext能够访问 +@EnableAspectJAutoProxy(exposeProxy = true) +// 指定要扫描的Mapper类的包的路径 +@MapperScan(basePackages={"cn.sliyun.project.**.mapper","cn.sliyun.api.**.mapper"}) +public class ApplicationConfig +{ + /** + * 时区配置 + */ + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() + { + return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()); + } +} diff --git a/src/main/java/cn/sliyun/framework/config/CaptchaConfig.java b/src/main/java/cn/sliyun/framework/config/CaptchaConfig.java new file mode 100644 index 0000000..8bc0463 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/CaptchaConfig.java @@ -0,0 +1,83 @@ +package cn.sliyun.framework.config; + +import java.util.Properties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import static com.google.code.kaptcha.Constants.*; + +/** + * 验证码配置 + * + * @author ruoyi + */ +@Configuration +public class CaptchaConfig +{ + @Bean(name = "captchaProducer") + public DefaultKaptcha getKaptchaBean() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 是否有边框 默认为true 我们可以自己设置yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 验证码文本字符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); + // 验证码图片宽度 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验证码图片高度 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验证码文本字符大小 默认为40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); + // 验证码文本字符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); + // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + @Bean(name = "captchaProducerMath") + public DefaultKaptcha getKaptchaBeanMath() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 是否有边框 默认为true 我们可以自己设置yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 边框颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); + // 验证码文本字符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); + // 验证码图片宽度 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验证码图片高度 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验证码文本字符大小 默认为40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); + // 验证码文本生成器 + properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "cn.sliyun.framework.config.KaptchaTextCreator"); + // 验证码文本字符间距 默认为2 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); + // 验证码文本字符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); + // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 验证码噪点颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); + // 干扰实现类 + properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); + // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } +} diff --git a/src/main/java/cn/sliyun/framework/config/FilterConfig.java b/src/main/java/cn/sliyun/framework/config/FilterConfig.java new file mode 100644 index 0000000..5115441 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/FilterConfig.java @@ -0,0 +1,60 @@ +package cn.sliyun.framework.config; + +import java.util.HashMap; +import java.util.Map; +import javax.servlet.DispatcherType; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import cn.sliyun.common.filter.RepeatableFilter; +import cn.sliyun.common.filter.XssFilter; +import cn.sliyun.common.utils.StringUtils; + +/** + * Filter配置 + * + * @author ruoyi + */ +@Configuration +public class FilterConfig +{ + @Value("${xss.enabled}") + private String enabled; + + @Value("${xss.excludes}") + private String excludes; + + @Value("${xss.urlPatterns}") + private String urlPatterns; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + public FilterRegistrationBean xssFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setDispatcherTypes(DispatcherType.REQUEST); + registration.setFilter(new XssFilter()); + registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); + registration.setName("xssFilter"); + registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); + Map initParameters = new HashMap(); + initParameters.put("excludes", excludes); + initParameters.put("enabled", enabled); + registration.setInitParameters(initParameters); + return registration; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + public FilterRegistrationBean someFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new RepeatableFilter()); + registration.addUrlPatterns("/*"); + registration.setName("repeatableFilter"); + registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE); + return registration; + } + +} diff --git a/src/main/java/cn/sliyun/framework/config/GenConfig.java b/src/main/java/cn/sliyun/framework/config/GenConfig.java new file mode 100644 index 0000000..d39da4f --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/GenConfig.java @@ -0,0 +1,66 @@ +package cn.sliyun.framework.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 读取代码生成相关配置 + * + * @author ruoyi + */ +@Component +@ConfigurationProperties(prefix = "gen") +public class GenConfig +{ + /** 作者 */ + public static String author; + + /** 生成包路径 */ + public static String packageName; + + /** 自动去除表前缀,默认是true */ + public static boolean autoRemovePre; + + /** 表前缀(类名不会包含表前缀) */ + public static String tablePrefix; + + public static String getAuthor() + { + return author; + } + + public void setAuthor(String author) + { + GenConfig.author = author; + } + + public static String getPackageName() + { + return packageName; + } + + public void setPackageName(String packageName) + { + GenConfig.packageName = packageName; + } + + public static boolean getAutoRemovePre() + { + return autoRemovePre; + } + + public void setAutoRemovePre(boolean autoRemovePre) + { + GenConfig.autoRemovePre = autoRemovePre; + } + + public static String getTablePrefix() + { + return tablePrefix; + } + + public void setTablePrefix(String tablePrefix) + { + GenConfig.tablePrefix = tablePrefix; + } +} diff --git a/src/main/java/cn/sliyun/framework/config/KaptchaTextCreator.java b/src/main/java/cn/sliyun/framework/config/KaptchaTextCreator.java new file mode 100644 index 0000000..8c690a1 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/KaptchaTextCreator.java @@ -0,0 +1,75 @@ +package cn.sliyun.framework.config; + +import java.util.Random; +import com.google.code.kaptcha.text.impl.DefaultTextCreator; + +/** + * 验证码文本生成器 + * + * @author ruoyi + */ +public class KaptchaTextCreator extends DefaultTextCreator +{ + private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); + + @Override + public String getText() + { + Integer result = 0; + Random random = new Random(); + int x = random.nextInt(10); + int y = random.nextInt(10); + StringBuilder suChinese = new StringBuilder(); + int randomoperands = (int) Math.round(Math.random() * 2); + if (randomoperands == 0) + { + result = x * y; + suChinese.append(CNUMBERS[x]); + suChinese.append("*"); + suChinese.append(CNUMBERS[y]); + } + else if (randomoperands == 1) + { + if (!(x == 0) && y % x == 0) + { + result = y / x; + suChinese.append(CNUMBERS[y]); + suChinese.append("/"); + suChinese.append(CNUMBERS[x]); + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + } + else if (randomoperands == 2) + { + if (x >= y) + { + result = x - y; + suChinese.append(CNUMBERS[x]); + suChinese.append("-"); + suChinese.append(CNUMBERS[y]); + } + else + { + result = y - x; + suChinese.append(CNUMBERS[y]); + suChinese.append("-"); + suChinese.append(CNUMBERS[x]); + } + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + suChinese.append("=?@" + result); + return suChinese.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/config/MvcConfig.java b/src/main/java/cn/sliyun/framework/config/MvcConfig.java new file mode 100644 index 0000000..80f21f2 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/MvcConfig.java @@ -0,0 +1,23 @@ +package cn.sliyun.framework.config; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Component +public class MvcConfig implements WebMvcConfigurer { + + @Bean + public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){ + + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + ObjectMapper objectMapper = new ObjectMapper(); + //添加此配置 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + converter.setObjectMapper(objectMapper); + return converter; + } +} diff --git a/src/main/java/cn/sliyun/framework/config/MyBatisConfig.java b/src/main/java/cn/sliyun/framework/config/MyBatisConfig.java new file mode 100644 index 0000000..75888ac --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/MyBatisConfig.java @@ -0,0 +1,115 @@ +package cn.sliyun.framework.config; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import javax.sql.DataSource; + +import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; +import org.apache.ibatis.io.VFS; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.boot.autoconfigure.SpringBootVFS; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.util.ClassUtils; +import cn.sliyun.common.utils.StringUtils; + +/** + * Mybatis支持*匹配扫描包 + * + * @author ruoyi + */ +@Configuration +public class MyBatisConfig { + @Autowired + private Environment env; + + static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; + + public static String setTypeAliasesPackage(String typeAliasesPackage) { + ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver(); + MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver); + List allResult = new ArrayList(); + try { + for (String aliasesPackage : typeAliasesPackage.split(",")) { + List result = new ArrayList(); + aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN; + Resource[] resources = resolver.getResources(aliasesPackage); + if (resources != null && resources.length > 0) { + MetadataReader metadataReader = null; + for (Resource resource : resources) { + if (resource.isReadable()) { + metadataReader = metadataReaderFactory.getMetadataReader(resource); + try { + result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + } + } + if (result.size() > 0) { + HashSet hashResult = new HashSet(result); + allResult.addAll(hashResult); + } + } + if (allResult.size() > 0) { + typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0])); + } else { + throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包"); + } + } catch (IOException e) { + e.printStackTrace(); + } + return typeAliasesPackage; + } + + public Resource[] resolveMapperLocations(String[] mapperLocations) { + ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); + List resources = new ArrayList(); + if (mapperLocations != null) { + for (String mapperLocation : mapperLocations) { + try { + Resource[] mappers = resourceResolver.getResources(mapperLocation); + resources.addAll(Arrays.asList(mappers)); + } catch (IOException e) { + // ignore + } + } + } + return resources.toArray(new Resource[resources.size()]); + } + + @Bean + public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { + String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage"); + String mapperLocations = env.getProperty("mybatis.mapperLocations"); + String configLocation = env.getProperty("mybatis.configLocation"); + typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage); + VFS.addImplClass(SpringBootVFS.class); + + /** + * SqlSessionFactoryBean 更换为 MybatisSqlSessionFactoryBean 可解决mybatis,mybatis-plus共存 + */ +// final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); + MybatisSqlSessionFactoryBean sessionFactory=new MybatisSqlSessionFactoryBean(); + sessionFactory.setDataSource(dataSource); + sessionFactory.setTypeAliasesPackage(typeAliasesPackage); + sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ","))); + sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation)); + return sessionFactory.getObject(); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/config/MybatisPlusConfig.java b/src/main/java/cn/sliyun/framework/config/MybatisPlusConfig.java new file mode 100644 index 0000000..70f4f00 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/MybatisPlusConfig.java @@ -0,0 +1,26 @@ +package cn.sliyun.framework.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MybatisPlusConfig { + /** + * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); + return interceptor; + } + + @Bean + public ConfigurationCustomizer configurationCustomizer() { + return configuration -> configuration.setUseDeprecatedExecutor(false); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/config/OSSConfig.java b/src/main/java/cn/sliyun/framework/config/OSSConfig.java new file mode 100644 index 0000000..2ed36e6 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/OSSConfig.java @@ -0,0 +1,57 @@ +package cn.sliyun.framework.config; + + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class OSSConfig implements InitializingBean { + @Value("${oss.file.endpoint}") + private String oss_file_endpoint; + + @Value("${oss.file.keyid}") + private String oss_file_keyid; + + @Value("${oss.file.keysecret}") + private String oss_file_keysecret; + + @Value("${oss.file.filehost}") + private String oss_file_filehost; + + @Value("${oss.file.bucketname}") + private String oss_file_bucketname; + public static String OSS_END_POINT; + public static String OSS_ACCESS_KEY_ID; + public static String OSS_ACCESS_KEY_SECRET; + public static String OSS_BUCKET_NAME; + public static String OSS_FILE_HOST; + + public static String OSS_DOMAIN="http://oss.mxzhe.cn/"; + + + public static String OSS_IMG_PATH="img/"; + + + + + + + private String accessKeyId; + private String accessKeySecret; + private String securityToken; + private String expiration; + private String bucketName; + private String endpoint; + + + + @Override + public void afterPropertiesSet() throws Exception { + OSS_END_POINT=oss_file_endpoint; + OSS_ACCESS_KEY_ID=oss_file_keyid; + OSS_ACCESS_KEY_SECRET=oss_file_keysecret; + OSS_BUCKET_NAME=oss_file_bucketname; + OSS_FILE_HOST=oss_file_filehost; + } +} diff --git a/src/main/java/cn/sliyun/framework/config/ResourcesConfig.java b/src/main/java/cn/sliyun/framework/config/ResourcesConfig.java new file mode 100644 index 0000000..f336ec6 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/ResourcesConfig.java @@ -0,0 +1,65 @@ +package cn.sliyun.framework.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.framework.interceptor.RepeatSubmitInterceptor; + +/** + * 通用配置 + * + * @author ruoyi + */ +@Configuration +public class ResourcesConfig implements WebMvcConfigurer +{ + @Autowired + private RepeatSubmitInterceptor repeatSubmitInterceptor; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) + { + /** 本地文件上传路径 */ + registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/"); + + /** swagger配置 */ + registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); + } + + /** + * 自定义拦截规则 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) + { + registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); + } + + /** + * 跨域配置 + */ + @Bean + public CorsFilter corsFilter() + { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + // 设置访问源地址 + config.addAllowedOrigin("*"); + // 设置访问源请求头 + config.addAllowedHeader("*"); + // 设置访问源请求方法 + config.addAllowedMethod("*"); + // 对接口配置跨域设置 + source.registerCorsConfiguration("/**", config); + return new CorsFilter(source); + } +} diff --git a/src/main/java/cn/sliyun/framework/config/RuoYiConfig.java b/src/main/java/cn/sliyun/framework/config/RuoYiConfig.java new file mode 100644 index 0000000..e7c6027 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/RuoYiConfig.java @@ -0,0 +1,116 @@ +package cn.sliyun.framework.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 读取项目相关配置 + * + * @author ruoyi + */ +@Component +@ConfigurationProperties(prefix = "ruoyi") +public class RuoYiConfig +{ + /** 项目名称 */ + private String name; + + /** 版本 */ + private String version; + + /** 版权年份 */ + private String copyrightYear; + + /** 实例演示开关 */ + private boolean demoEnabled; + + /** 上传路径 */ + private static String profile; + + /** 获取地址开关 */ + private static boolean addressEnabled; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public String getCopyrightYear() + { + return copyrightYear; + } + + public void setCopyrightYear(String copyrightYear) + { + this.copyrightYear = copyrightYear; + } + + public boolean isDemoEnabled() + { + return demoEnabled; + } + + public void setDemoEnabled(boolean demoEnabled) + { + this.demoEnabled = demoEnabled; + } + + public static String getProfile() + { + return profile; + } + + public void setProfile(String profile) + { + RuoYiConfig.profile = profile; + } + + public static boolean isAddressEnabled() + { + return addressEnabled; + } + + public void setAddressEnabled(boolean addressEnabled) + { + RuoYiConfig.addressEnabled = addressEnabled; + } + + /** + * 获取头像上传路径 + */ + public static String getAvatarPath() + { + return getProfile() + "/avatar"; + } + + /** + * 获取下载路径 + */ + public static String getDownloadPath() + { + return getProfile() + "/download/"; + } + + /** + * 获取上传路径 + */ + public static String getUploadPath() + { + return getProfile() + "/upload"; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/config/SecurityConfig.java b/src/main/java/cn/sliyun/framework/config/SecurityConfig.java new file mode 100644 index 0000000..079d7a8 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/SecurityConfig.java @@ -0,0 +1,145 @@ +package cn.sliyun.framework.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.logout.LogoutFilter; +import org.springframework.web.filter.CorsFilter; +import cn.sliyun.framework.security.filter.JwtAuthenticationTokenFilter; +import cn.sliyun.framework.security.handle.AuthenticationEntryPointImpl; +import cn.sliyun.framework.security.handle.LogoutSuccessHandlerImpl; + +/** + * spring security配置 + * + * @author ruoyi + */ +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter +{ + /** + * 自定义用户认证逻辑 + */ + @Autowired + private UserDetailsService userDetailsService; + + /** + * 认证失败处理类 + */ + @Autowired + private AuthenticationEntryPointImpl unauthorizedHandler; + + /** + * 退出处理类 + */ + @Autowired + private LogoutSuccessHandlerImpl logoutSuccessHandler; + + /** + * token认证过滤器 + */ + @Autowired + private JwtAuthenticationTokenFilter authenticationTokenFilter; + + /** + * 跨域过滤器 + */ + @Autowired + private CorsFilter corsFilter; + + /** + * 解决 无法直接注入 AuthenticationManager + * + * @return + * @throws Exception + */ + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception + { + return super.authenticationManagerBean(); + } + + /** + * anyRequest | 匹配所有请求路径 + * access | SpringEl表达式结果为true时可以访问 + * anonymous | 匿名可以访问 + * denyAll | 用户不能访问 + * fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录) + * hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问 + * hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问 + * hasAuthority | 如果有参数,参数表示权限,则其权限可以访问 + * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 + * hasRole | 如果有参数,参数表示角色,则其角色可以访问 + * permitAll | 用户可以任意访问 + * rememberMe | 允许通过remember-me登录的用户访问 + * authenticated | 用户登录后可访问 + */ + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception + { + httpSecurity + // CSRF禁用,因为不使用session + .csrf().disable() + // 认证失败处理类 + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() + // 基于token,所以不需要session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + // 过滤请求 + .authorizeRequests() + // 对于登录login 验证码captchaImage 允许匿名访问 + .antMatchers("/login", "/captchaImage").anonymous() + .antMatchers( + HttpMethod.GET, + "/*.html", + "/**/*.html", + "/**/*.css", + "/**/*.js" + ).permitAll() + .antMatchers("/profile/**").anonymous() + .antMatchers("/common/download**").anonymous() + .antMatchers("/common/download/resource**").anonymous() + .antMatchers("/swagger-ui.html").anonymous() + .antMatchers("/swagger-resources/**").anonymous() + .antMatchers("/webjars/**").anonymous() + .antMatchers("/*/api-docs").anonymous() + .antMatchers("/druid/**").anonymous() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated() + .and() + .headers().frameOptions().disable(); + httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); + // 添加JWT filter + httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + // 添加CORS filter + httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class); + httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); + } + + /** + * 强散列哈希加密实现 + */ + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() + { + return new BCryptPasswordEncoder(); + } + + /** + * 身份认证接口 + */ + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception + { + auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); + } +} diff --git a/src/main/java/cn/sliyun/framework/config/ServerConfig.java b/src/main/java/cn/sliyun/framework/config/ServerConfig.java new file mode 100644 index 0000000..0775509 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/ServerConfig.java @@ -0,0 +1,32 @@ +package cn.sliyun.framework.config; + +import javax.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; +import cn.sliyun.common.utils.ServletUtils; + +/** + * 服务相关配置 + * + * @author ruoyi + */ +@Component +public class ServerConfig +{ + /** + * 获取完整的请求路径,包括:域名,端口,上下文访问路径 + * + * @return 服务地址 + */ + public String getUrl() + { + HttpServletRequest request = ServletUtils.getRequest(); + return getDomain(request); + } + + public static String getDomain(HttpServletRequest request) + { + StringBuffer url = request.getRequestURL(); + String contextPath = request.getServletContext().getContextPath(); + return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString(); + } +} diff --git a/src/main/java/cn/sliyun/framework/config/SwaggerConfig.java b/src/main/java/cn/sliyun/framework/config/SwaggerConfig.java new file mode 100644 index 0000000..08da38c --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/SwaggerConfig.java @@ -0,0 +1,123 @@ +package cn.sliyun.framework.config; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import io.swagger.annotations.ApiOperation; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.Contact; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * Swagger2的接口配置 + * + * @author ruoyi + */ +@Configuration +@EnableSwagger2 +public class SwaggerConfig +{ + /** 系统基础配置 */ + @Autowired + private RuoYiConfig ruoyiConfig; + + /** 是否开启swagger */ + @Value("${swagger.enabled}") + private boolean enabled; + + /** 设置请求的统一前缀 */ + @Value("${swagger.pathMapping}") + private String pathMapping; + + /** + * 创建API + */ + @Bean + public Docket createRestApi() + { + return new Docket(DocumentationType.SWAGGER_2) + // 是否启用Swagger + .enable(enabled) + // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息) + .apiInfo(apiInfo()) + // 设置哪些接口暴露给Swagger展示 + .select() + // 扫描所有有注解的api,用这种方式更灵活 + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) + // 扫描指定包中的swagger注解 + // 扫描所有 .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build() + /* 设置安全模式,swagger可以设置访问token */ + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()) + .pathMapping(pathMapping); + } + + /** + * 安全模式,这里指定token通过Authorization头请求头传递 + */ + private List securitySchemes() + { + List apiKeyList = new ArrayList(); + apiKeyList.add(new ApiKey("Authorization", "Authorization", "header")); + return apiKeyList; + } + + /** + * 安全上下文 + */ + private List securityContexts() + { + List securityContexts = new ArrayList<>(); + securityContexts.add( + SecurityContext.builder() + .securityReferences(defaultAuth()) + .forPaths(PathSelectors.regex("^(?!auth).*$")) + .build()); + return securityContexts; + } + + /** + * 默认的安全上引用 + */ + private List defaultAuth() + { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + List securityReferences = new ArrayList<>(); + securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); + return securityReferences; + } + + /** + * 添加摘要信息 + */ + private ApiInfo apiInfo() + { + // 用ApiInfoBuilder进行定制 + return new ApiInfoBuilder() + // 设置标题 + .title("标题:若依管理系统_接口文档") + // 描述 + .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...") + // 作者信息 + .contact(new Contact(ruoyiConfig.getName(), null, null)) + // 版本 + .version("版本号:" + ruoyiConfig.getVersion()) + .build(); + } +} diff --git a/src/main/java/cn/sliyun/framework/config/ThreadPoolConfig.java b/src/main/java/cn/sliyun/framework/config/ThreadPoolConfig.java new file mode 100644 index 0000000..244c1dd --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/ThreadPoolConfig.java @@ -0,0 +1,62 @@ +package cn.sliyun.framework.config; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import cn.sliyun.common.utils.Threads; + +/** + * 线程池配置 + * + * @author ruoyi + **/ +@Configuration +public class ThreadPoolConfig +{ + // 核心线程池大小 + private int corePoolSize = 50; + + // 最大可创建的线程数 + private int maxPoolSize = 200; + + // 队列最大长度 + private int queueCapacity = 1000; + + // 线程池维护线程所允许的空闲时间 + private int keepAliveSeconds = 300; + + @Bean(name = "threadPoolTaskExecutor") + public ThreadPoolTaskExecutor threadPoolTaskExecutor() + { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setMaxPoolSize(maxPoolSize); + executor.setCorePoolSize(corePoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setKeepAliveSeconds(keepAliveSeconds); + // 线程池对拒绝任务(无线程可用)的处理策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } + + /** + * 执行周期性或定时任务 + */ + @Bean(name = "scheduledExecutorService") + protected ScheduledExecutorService scheduledExecutorService() + { + return new ScheduledThreadPoolExecutor(corePoolSize, + new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) + { + @Override + protected void afterExecute(Runnable r, Throwable t) + { + super.afterExecute(r, t); + Threads.printException(r, t); + } + }; + } +} diff --git a/src/main/java/cn/sliyun/framework/config/properties/DruidProperties.java b/src/main/java/cn/sliyun/framework/config/properties/DruidProperties.java new file mode 100644 index 0000000..f992d07 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/config/properties/DruidProperties.java @@ -0,0 +1,80 @@ +package cn.sliyun.framework.config.properties; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import com.alibaba.druid.pool.DruidDataSource; + +/** + * druid 配置属性 + * + * @author ruoyi + */ +@Configuration +//@ConfigurationProperties(prefix = “ai”,locations=”classpath:config/ai.properties”) +@ConfigurationProperties(prefix = "application-druid") +public class DruidProperties +{ + @Value("${spring.datasource.druid.initialSize}") + private int initialSize; + + @Value("${spring.datasource.druid.minIdle}") + private int minIdle; + + @Value("${spring.datasource.druid.maxActive}") + private int maxActive; + + @Value("${spring.datasource.druid.maxWait}") + private int maxWait; + + @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}") + private int timeBetweenEvictionRunsMillis; + + @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}") + private int minEvictableIdleTimeMillis; + + @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}") + private int maxEvictableIdleTimeMillis; + + @Value("${spring.datasource.druid.validationQuery}") + private String validationQuery; + + @Value("${spring.datasource.druid.testWhileIdle}") + private boolean testWhileIdle; + + @Value("${spring.datasource.druid.testOnBorrow}") + private boolean testOnBorrow; + + @Value("${spring.datasource.druid.testOnReturn}") + private boolean testOnReturn; + + public DruidDataSource dataSource(DruidDataSource datasource) + { + /** 配置初始化大小、最小、最大 */ + datasource.setInitialSize(initialSize); + datasource.setMaxActive(maxActive); + datasource.setMinIdle(minIdle); + + /** 配置获取连接等待超时的时间 */ + datasource.setMaxWait(maxWait); + + /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */ + datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + + /** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */ + datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis); + + /** + * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 + */ + datasource.setValidationQuery(validationQuery); + /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */ + datasource.setTestWhileIdle(testWhileIdle); + /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ + datasource.setTestOnBorrow(testOnBorrow); + /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ + datasource.setTestOnReturn(testOnReturn); + return datasource; + } +} diff --git a/src/main/java/cn/sliyun/framework/datasource/DynamicDataSource.java b/src/main/java/cn/sliyun/framework/datasource/DynamicDataSource.java new file mode 100644 index 0000000..62a5e5f --- /dev/null +++ b/src/main/java/cn/sliyun/framework/datasource/DynamicDataSource.java @@ -0,0 +1,26 @@ +package cn.sliyun.framework.datasource; + +import java.util.Map; +import javax.sql.DataSource; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +/** + * 动态数据源 + * + * @author ruoyi + */ +public class DynamicDataSource extends AbstractRoutingDataSource +{ + public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) + { + super.setDefaultTargetDataSource(defaultTargetDataSource); + super.setTargetDataSources(targetDataSources); + super.afterPropertiesSet(); + } + + @Override + protected Object determineCurrentLookupKey() + { + return DynamicDataSourceContextHolder.getDataSourceType(); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/datasource/DynamicDataSourceContextHolder.java b/src/main/java/cn/sliyun/framework/datasource/DynamicDataSourceContextHolder.java new file mode 100644 index 0000000..ac59e56 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/datasource/DynamicDataSourceContextHolder.java @@ -0,0 +1,45 @@ +package cn.sliyun.framework.datasource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 数据源切换处理 + * + * @author ruoyi + */ +public class DynamicDataSourceContextHolder +{ + public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class); + + /** + * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本, + * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 + */ + private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); + + /** + * 设置数据源的变量 + */ + public static void setDataSourceType(String dsType) + { + log.info("切换到{}数据源", dsType); + CONTEXT_HOLDER.set(dsType); + } + + /** + * 获得数据源的变量 + */ + public static String getDataSourceType() + { + return CONTEXT_HOLDER.get(); + } + + /** + * 清空数据源变量 + */ + public static void clearDataSourceType() + { + CONTEXT_HOLDER.remove(); + } +} diff --git a/src/main/java/cn/sliyun/framework/delay/DelayQueueManager.java b/src/main/java/cn/sliyun/framework/delay/DelayQueueManager.java new file mode 100644 index 0000000..b438b24 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/delay/DelayQueueManager.java @@ -0,0 +1,90 @@ +package cn.sliyun.framework.delay; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Executors; + +@Component +public class DelayQueueManager implements CommandLineRunner , InitializingBean { + private final Logger logger = LoggerFactory.getLogger(DelayQueueManager.class); + private DelayQueue delayQueue = new DelayQueue<>(); + + /** + * 加入到延时队列中 + * @param task + */ + public void put(DelayTask task) { + logger.info("加入延时任务:{}", task); + delayQueue.put(task); + logger.info("延时任务SIZE:{}", delayQueue.size()); + } + + + + + /** + * 取消延时任务 + * @param task + * @return + */ + public boolean remove(DelayTask task) { + logger.info("取消延时任务:{}", task); + return delayQueue.remove(task); + } + + /** + * 取消延时任务 + * @param taskId + * @return + */ + public boolean remove(int taskId) { + return remove(new DelayTask((taskId),"", 0)); + } + + + @Override + public void run(String... args) { + logger.info("初始化延时队列"); + Executors.newSingleThreadExecutor().execute((this::executeThread)); + } + + /** + * 延时任务执行线程 + */ + private void executeThread() { + while (true) { + try { + DelayTask task = delayQueue.take(); + processTask(task); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.error("执行延时任务ERROR:{}", e.getMessage()); + } + } + } + + /** + * 内部执行延时任务 + * @param task + */ + private void processTask(DelayTask task) { + logger.info("执行延时任务:{}", task); + //根据task中的data自定义数据来处理相关逻辑,例 if (task.getData() instanceof XXX) {} + } + + private static DelayQueueManager queueManager; + + public static DelayQueueManager getQueueManager() { + return queueManager; + } + + @Override + public void afterPropertiesSet() throws Exception { + queueManager = this; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/delay/DelayTask.java b/src/main/java/cn/sliyun/framework/delay/DelayTask.java new file mode 100644 index 0000000..dc160a9 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/delay/DelayTask.java @@ -0,0 +1,69 @@ +package cn.sliyun.framework.delay; + + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +public class DelayTask implements Delayed { + final private T data; + final private long expire; + private int identifier; + + /** + * 构造延时任务 + * + * @param id id + * @param data 业务数据 + * @param expire 任务延时时间(ms) + */ + public DelayTask(int id, T data, long expire) { + super(); + this.identifier = id; + this.data = data; + this.expire = expire + System.currentTimeMillis(); + + } + + public T getData() { + return data; + } + + public long getExpire() { + return expire; + } + + public int getId() { + return identifier; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DelayTask) { + return this.getId()==getId(); + } + return false; + } + + @Override + public String toString() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return "{" + "data:" + data.toString() + "," + "expire:" + dateFormat.format(new Date(expire)) + "}"; + } + + @Override + public long getDelay(TimeUnit unit) { + // //下面用到unit.convert()方法,其实在这个小场景不需要用到,只是学习一下如何使用罢了 + long e= this.expire-System.currentTimeMillis(); + System.out.println("delay:"+e); + return unit.convert(e, TimeUnit.MILLISECONDS); + } + + @Override + public int compareTo(Delayed o) { + // //这里根据取消时间来比较,如果取消时间小的,就会优先被队列提取出来 + long delta = getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS); + return (int) delta; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/global/AppContextHolder.java b/src/main/java/cn/sliyun/framework/global/AppContextHolder.java new file mode 100644 index 0000000..00bf943 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/global/AppContextHolder.java @@ -0,0 +1,32 @@ +package cn.sliyun.framework.global; + + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class AppContextHolder implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException { + AppContextHolder.applicationContext = context; + } + + public static ApplicationContext getContext() { + return applicationContext; + } + + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException { + return (T)applicationContext.getBean(name); + } + + public static T getBean(Class clz) throws BeansException { + return (T)applicationContext.getBean(clz); + } + +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/global/LocalDateTimeSerializerConfig.java b/src/main/java/cn/sliyun/framework/global/LocalDateTimeSerializerConfig.java new file mode 100644 index 0000000..91293f6 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/global/LocalDateTimeSerializerConfig.java @@ -0,0 +1,49 @@ +package cn.sliyun.framework.global; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +@Configuration +public class LocalDateTimeSerializerConfig { + + @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}") + private String pattern; + + // 方案三 + @Bean + @Primary + public ObjectMapper serializingObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer()); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer()); + objectMapper.registerModule(javaTimeModule); + return objectMapper; + } + + public class LocalDateTimeSerializer extends JsonSerializer { + @Override + public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) + throws IOException { + gen.writeString(value.format(DateTimeFormatter.ofPattern(pattern))); + } + } + + public class LocalDateTimeDeserializer extends JsonDeserializer { + @Override + public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) + throws IOException { + return LocalDateTime.parse(p.getValueAsString(), DateTimeFormatter.ofPattern(pattern)); + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/global/RequestHandler.java b/src/main/java/cn/sliyun/framework/global/RequestHandler.java new file mode 100644 index 0000000..b286edb --- /dev/null +++ b/src/main/java/cn/sliyun/framework/global/RequestHandler.java @@ -0,0 +1,31 @@ +package cn.sliyun.framework.global; + +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; + +import java.io.IOException; +import java.lang.reflect.Type; + +public class RequestHandler implements RequestBodyAdvice { + @Override + public boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) { + return false; + } + + @Override + public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) throws IOException { + return null; + } + + @Override + public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { + return null; + } + + @Override + public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { + return null; + } +} diff --git a/src/main/java/cn/sliyun/framework/global/ResponseHandler.java b/src/main/java/cn/sliyun/framework/global/ResponseHandler.java new file mode 100644 index 0000000..f08c57f --- /dev/null +++ b/src/main/java/cn/sliyun/framework/global/ResponseHandler.java @@ -0,0 +1,60 @@ +package cn.sliyun.framework.global; + +import com.alibaba.fastjson.JSON; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +import java.util.HashMap; +import java.util.Map; + + +@ControllerAdvice +public class ResponseHandler implements ResponseBodyAdvice { + + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + @Override + public boolean supports(MethodParameter returnType, Class> converterType) { + return true; + } + + + @Override + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { + + + //获得所有头信息的name + HttpHeaders header = request.getHeaders(); + //输出所有的头信息的名字 + Map headers = new HashMap(); + for (String key : header.keySet()) { + headers.put(key, header.get(key)); + } + + Map param = new HashMap(); + Map params = new HashMap(); + params.put("header", headers); + params.put("query", request.getURI().getQuery()); + params.put("params", request.getURI().getScheme()); + //当前时间 + long currentTime = System.currentTimeMillis(); + //请求开始时间 +// long time = Long.valueOf(request.getAttribute(LOGGER_SEND_TIME).toString()); + + + + log.info("Method:{} ", request.getMethod().name()); + log.info("接口:{} 入参:{} 返回:{}", request.getURI().getPath(), JSON.toJSON(params), JSON.toJSON(body)); + return body; + } + + +} diff --git a/src/main/java/cn/sliyun/framework/interceptor/ApiSignInterceptor.java b/src/main/java/cn/sliyun/framework/interceptor/ApiSignInterceptor.java new file mode 100644 index 0000000..4fdc1d8 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/interceptor/ApiSignInterceptor.java @@ -0,0 +1,55 @@ +package cn.sliyun.framework.interceptor; + +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +@Component +public class ApiSignInterceptor implements HandlerInterceptor { + + /** + * 请求前 + * + * @param request + * @param response + * @param handler controllerHandler 对象 + * @return + * @throws Exception + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + return false; + } + + /** + * 请求后 , 无抛出异常时 + * + * @param request + * @param response + * @param handler + * @param modelAndView + * @throws Exception + */ + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + + } + /** + * 请求后,无论是否抛出异常 , 均执行 + * 注意: controlleradvice的执行是在该方法之前的.对exception进行处理过. 该方法接收不到该异常 + * 会拦截所有的controller,包括spring提供的controller , 如baseerrorcontroller 异常处理handler + * @param request + * @param response + * @param handler + * @param ex + * @throws Exception + */ + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + + } +} diff --git a/src/main/java/cn/sliyun/framework/interceptor/RepeatSubmitInterceptor.java b/src/main/java/cn/sliyun/framework/interceptor/RepeatSubmitInterceptor.java new file mode 100644 index 0000000..f44f347 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/interceptor/RepeatSubmitInterceptor.java @@ -0,0 +1,56 @@ +package cn.sliyun.framework.interceptor; + +import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.sliyun.framework.web.domain.AjaxResult; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import com.alibaba.fastjson.JSONObject; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.framework.interceptor.annotation.RepeatSubmit; + +/** + * 防止重复提交拦截器 + * + * @author ruoyi + */ +@Component +public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter +{ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception + { + if (handler instanceof HandlerMethod) + { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); + if (annotation != null) + { + if (this.isRepeatSubmit(request)) + { + AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试"); + ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult)); + return false; + } + } + return true; + } + else + { + return super.preHandle(request, response, handler); + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * + * @param httpServletRequest + * @return + * @throws Exception + */ + public abstract boolean isRepeatSubmit(HttpServletRequest request); +} diff --git a/src/main/java/cn/sliyun/framework/interceptor/UserLoginInterceptor.java b/src/main/java/cn/sliyun/framework/interceptor/UserLoginInterceptor.java new file mode 100644 index 0000000..b2d464b --- /dev/null +++ b/src/main/java/cn/sliyun/framework/interceptor/UserLoginInterceptor.java @@ -0,0 +1,97 @@ +package cn.sliyun.framework.interceptor; + +import cn.sliyun.common.core.Result; +import cn.sliyun.common.exception.AppException; +import cn.sliyun.framework.annotion.LoginRequired; +import cn.sliyun.project.system.service.impl.SysUserServiceImpl; +import com.alibaba.fastjson.JSON; +import org.apache.commons.lang.StringUtils; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Method; + + +//@Component +public class UserLoginInterceptor implements HandlerInterceptor { + + @Resource + private SysUserServiceImpl userService; + public static UserLoginInterceptor articlesReceiver; //关键2 + + @PostConstruct //关键3 + public void init() { + articlesReceiver = this; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + String token = ""; + if (StringUtils.isBlank(token)) { + // 2.从headers中获取 + token = request.getHeader("token"); + } + if (StringUtils.isBlank(token)) { + // 3.从请求参数获取 + token = request.getParameter("token"); + } + if (!(handler instanceof HandlerMethod)) { + return true; + } + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + if (method.isAnnotationPresent(LoginRequired.class)) { + if (!StringUtils.isEmpty(token)) { +// SysUser user = articlesReceiver.userService.(token); +// if (user == null || !user.getToken().equals(token)) { +// throw new CustomException("token 无效"); +//// result(response, ResultGenerator.genFailResult("token 无效")); +//// return false; +// } else { +// return true; +// } + } + throw new AppException("token 无效"); + } + return true; + } + + + private void result(HttpServletResponse response, Result result) { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json; charset=utf-8"); + response.setStatus(200); + PrintWriter out = null; + try { + out = response.getWriter(); + out.append(JSON.toJSONString(result)); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (out != null) + out.close(); + } + } + + private String getTokenFromCookie(HttpServletRequest request) { + String token = null; + Cookie[] cookies = request.getCookies(); + int len = null == cookies ? 0 : cookies.length; + if (len > 0) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("token")) { + token = cookie.getValue(); + break; + } + } + } + return token; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/interceptor/annotation/RepeatSubmit.java b/src/main/java/cn/sliyun/framework/interceptor/annotation/RepeatSubmit.java new file mode 100644 index 0000000..05f825a --- /dev/null +++ b/src/main/java/cn/sliyun/framework/interceptor/annotation/RepeatSubmit.java @@ -0,0 +1,23 @@ +package cn.sliyun.framework.interceptor.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义注解防止表单重复提交 + * + * @author ruoyi + * + */ +@Inherited +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RepeatSubmit +{ + +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/interceptor/impl/SameUrlDataInterceptor.java b/src/main/java/cn/sliyun/framework/interceptor/impl/SameUrlDataInterceptor.java new file mode 100644 index 0000000..0ae45ec --- /dev/null +++ b/src/main/java/cn/sliyun/framework/interceptor/impl/SameUrlDataInterceptor.java @@ -0,0 +1,121 @@ +package cn.sliyun.framework.interceptor.impl; + +import java.util.HashMap; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.interceptor.RepeatSubmitInterceptor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson.JSONObject; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.filter.RepeatedlyRequestWrapper; +import cn.sliyun.common.utils.http.HttpHelper; + +/** + * 判断请求url和数据是否和上一次相同, + * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。 + * + * @author ruoyi + */ +@Component +public class SameUrlDataInterceptor extends RepeatSubmitInterceptor +{ + public final String REPEAT_PARAMS = "repeatParams"; + + public final String REPEAT_TIME = "repeatTime"; + + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + + /** + * 间隔时间,单位:秒 默认10秒 + * + * 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据 + */ + private int intervalTime = 10; + + public void setIntervalTime(int intervalTime) + { + this.intervalTime = intervalTime; + } + + @SuppressWarnings("unchecked") + @Override + public boolean isRepeatSubmit(HttpServletRequest request) + { + String nowParams = ""; + if (request instanceof RepeatedlyRequestWrapper) + { + RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; + nowParams = HttpHelper.getBodyString(repeatedlyRequest); + } + + // body参数为空,获取Parameter的数据 + if (StringUtils.isEmpty(nowParams)) + { + nowParams = JSONObject.toJSONString(request.getParameterMap()); + } + Map nowDataMap = new HashMap(); + nowDataMap.put(REPEAT_PARAMS, nowParams); + nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); + + // 请求地址(作为存放cache的key值) + String url = request.getRequestURI(); + + // 唯一值(没有消息头则使用请求地址) + String submitKey = request.getHeader(header); + if (StringUtils.isEmpty(submitKey)) + { + submitKey = url; + } + + // 唯一标识(指定key + 消息头) + String cache_repeat_key = Constants.REPEAT_SUBMIT_KEY + submitKey; + + Object sessionObj =null;// redisCache.getCacheObject(cache_repeat_key); + if (sessionObj != null) + { + Map sessionMap = (Map) sessionObj; + if (sessionMap.containsKey(url)) + { + Map preDataMap = (Map) sessionMap.get(url); + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)) + { + return true; + } + } + } + Map cacheMap = new HashMap(); + cacheMap.put(url, nowDataMap); +// redisCache.setCacheObject(cache_repeat_key, cacheMap, intervalTime, TimeUnit.SECONDS); + return false; + } + + /** + * 判断参数是否相同 + */ + private boolean compareParams(Map nowMap, Map preMap) + { + String nowParams = (String) nowMap.get(REPEAT_PARAMS); + String preParams = (String) preMap.get(REPEAT_PARAMS); + return nowParams.equals(preParams); + } + + /** + * 判断两次间隔时间 + */ + private boolean compareTime(Map nowMap, Map preMap) + { + long time1 = (Long) nowMap.get(REPEAT_TIME); + long time2 = (Long) preMap.get(REPEAT_TIME); + if ((time1 - time2) < (this.intervalTime * 1000)) + { + return true; + } + return false; + } +} diff --git a/src/main/java/cn/sliyun/framework/manager/AsyncManager.java b/src/main/java/cn/sliyun/framework/manager/AsyncManager.java new file mode 100644 index 0000000..d47380e --- /dev/null +++ b/src/main/java/cn/sliyun/framework/manager/AsyncManager.java @@ -0,0 +1,55 @@ +package cn.sliyun.framework.manager; + +import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import cn.sliyun.common.utils.Threads; +import cn.sliyun.common.utils.spring.SpringUtils; + +/** + * 异步任务管理器 + * + * @author ruoyi + */ +public class AsyncManager +{ + /** + * 操作延迟10毫秒 + */ + private final int OPERATE_DELAY_TIME = 10; + + /** + * 异步操作任务调度线程池 + */ + private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); + + /** + * 单例模式 + */ + private AsyncManager(){} + + private static AsyncManager me = new AsyncManager(); + + public static AsyncManager me() + { + return me; + } + + /** + * 执行任务 + * + * @param task 任务 + */ + public void execute(TimerTask task) + { + executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); + } + + /** + * 停止任务线程池 + */ + public void shutdown() + { + Threads.shutdownAndAwaitTermination(executor); + } +} diff --git a/src/main/java/cn/sliyun/framework/manager/ShutdownManager.java b/src/main/java/cn/sliyun/framework/manager/ShutdownManager.java new file mode 100644 index 0000000..cd95ad0 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/manager/ShutdownManager.java @@ -0,0 +1,39 @@ +package cn.sliyun.framework.manager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import javax.annotation.PreDestroy; + +/** + * 确保应用退出时能关闭后台线程 + * + * @author ruoyi + */ +@Component +public class ShutdownManager +{ + private static final Logger logger = LoggerFactory.getLogger("sys-user"); + + @PreDestroy + public void destroy() + { + shutdownAsyncManager(); + } + + /** + * 停止异步执行任务 + */ + private void shutdownAsyncManager() + { + try + { + logger.info("====关闭后台任务任务线程池===="); + AsyncManager.me().shutdown(); + } + catch (Exception e) + { + logger.error(e.getMessage(), e); + } + } +} diff --git a/src/main/java/cn/sliyun/framework/manager/factory/AsyncFactory.java b/src/main/java/cn/sliyun/framework/manager/factory/AsyncFactory.java new file mode 100644 index 0000000..2977f3d --- /dev/null +++ b/src/main/java/cn/sliyun/framework/manager/factory/AsyncFactory.java @@ -0,0 +1,101 @@ +package cn.sliyun.framework.manager.factory; + +import java.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.utils.LogUtils; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.ip.AddressUtils; +import cn.sliyun.common.utils.ip.IpUtils; +import cn.sliyun.common.utils.spring.SpringUtils; +import cn.sliyun.project.monitor.domain.SysLogininfor; +import cn.sliyun.project.monitor.domain.SysOperLog; +import cn.sliyun.project.monitor.service.ISysLogininforService; +import cn.sliyun.project.monitor.service.ISysOperLogService; +import eu.bitwalker.useragentutils.UserAgent; + +/** + * 异步工厂(产生任务用) + * + * @author ruoyi + */ +public class AsyncFactory +{ + private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user"); + + /** + * 记录登录信息 + * + * @param username 用户名 + * @param status 状态 + * @param message 消息 + * @param args 列表 + * @return 任务task + */ + public static TimerTask recordLogininfor(final String username, final String status, final String message, + final Object... args) + { + final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + final String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + return new TimerTask() + { + @Override + public void run() + { + String address = AddressUtils.getRealAddressByIP(ip); + StringBuilder s = new StringBuilder(); + s.append(LogUtils.getBlock(ip)); + s.append(address); + s.append(LogUtils.getBlock(username)); + s.append(LogUtils.getBlock(status)); + s.append(LogUtils.getBlock(message)); + // 打印信息到日志 + sys_user_logger.info(s.toString(), args); + // 获取客户端操作系统 + String os = userAgent.getOperatingSystem().getName(); + // 获取客户端浏览器 + String browser = userAgent.getBrowser().getName(); + // 封装对象 + SysLogininfor logininfor = new SysLogininfor(); + logininfor.setUserName(username); + logininfor.setIpaddr(ip); + logininfor.setLoginLocation(address); + logininfor.setBrowser(browser); + logininfor.setOs(os); + logininfor.setMsg(message); + // 日志状态 + if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) + { + logininfor.setStatus(Constants.SUCCESS); + } + else if (Constants.LOGIN_FAIL.equals(status)) + { + logininfor.setStatus(Constants.FAIL); + } + // 插入数据 + SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor); + } + }; + } + + /** + * 操作日志记录 + * + * @param operLog 操作日志信息 + * @return 任务task + */ + public static TimerTask recordOper(final SysOperLog operLog) + { + return new TimerTask() + { + @Override + public void run() + { + // 远程查询操作地点 + operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); + SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog); + } + }; + } +} diff --git a/src/main/java/cn/sliyun/framework/security/LoginBody.java b/src/main/java/cn/sliyun/framework/security/LoginBody.java new file mode 100644 index 0000000..cab73fd --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/LoginBody.java @@ -0,0 +1,69 @@ +package cn.sliyun.framework.security; + +/** + * 用户登录对象 + * + * @author ruoyi + */ +public class LoginBody +{ + /** + * 用户名 + */ + private String username; + + /** + * 用户密码 + */ + private String password; + + /** + * 验证码 + */ + private String code; + + /** + * 唯一标识 + */ + private String uuid = ""; + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getCode() + { + return code; + } + + public void setCode(String code) + { + this.code = code; + } + + public String getUuid() + { + return uuid; + } + + public void setUuid(String uuid) + { + this.uuid = uuid; + } +} diff --git a/src/main/java/cn/sliyun/framework/security/LoginUser.java b/src/main/java/cn/sliyun/framework/security/LoginUser.java new file mode 100644 index 0000000..129868f --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/LoginUser.java @@ -0,0 +1,228 @@ +package cn.sliyun.framework.security; + +import java.util.Collection; +import java.util.Set; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import com.fasterxml.jackson.annotation.JsonIgnore; +import cn.sliyun.project.system.domain.SysUser; + +/** + * 登录用户身份权限 + * + * @author ruoyi + */ +public class LoginUser implements UserDetails +{ + private static final long serialVersionUID = 1L; + + /** + * 用户唯一标识 + */ + private String token; + + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 权限列表 + */ + private Set permissions; + + /** + * 用户信息 + */ + private SysUser user; + + public String getToken() + { + return token; + } + + public void setToken(String token) + { + this.token = token; + } + + public LoginUser() + { + } + + public LoginUser(SysUser user, Set permissions) + { + this.user = user; + this.permissions = permissions; + } + + @JsonIgnore + @Override + public String getPassword() + { + return user.getPassword(); + } + + @Override + public String getUsername() + { + return user.getUserName(); + } + + /** + * 账户是否未过期,过期无法验证 + */ + @JsonIgnore + @Override + public boolean isAccountNonExpired() + { + return true; + } + + /** + * 指定用户是否解锁,锁定的用户无法进行身份验证 + * + * @return + */ + @JsonIgnore + @Override + public boolean isAccountNonLocked() + { + return true; + } + + /** + * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证 + * + * @return + */ + @JsonIgnore + @Override + public boolean isCredentialsNonExpired() + { + return true; + } + + /** + * 是否可用 ,禁用的用户不能身份验证 + * + * @return + */ + @JsonIgnore + @Override + public boolean isEnabled() + { + return true; + } + + public Long getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Long loginTime) + { + this.loginTime = loginTime; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public Long getExpireTime() + { + return expireTime; + } + + public void setExpireTime(Long expireTime) + { + this.expireTime = expireTime; + } + + public Set getPermissions() + { + return permissions; + } + + public void setPermissions(Set permissions) + { + this.permissions = permissions; + } + + public SysUser getUser() + { + return user; + } + + public void setUser(SysUser user) + { + this.user = user; + } + + @Override + public Collection getAuthorities() + { + return null; + } +} diff --git a/src/main/java/cn/sliyun/framework/security/filter/JwtAuthenticationTokenFilter.java b/src/main/java/cn/sliyun/framework/security/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..f1bfd4a --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,44 @@ +package cn.sliyun.framework.security.filter; + +import java.io.IOException; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.TokenService; + +/** + * token过滤器 验证token有效性 + * + * @author ruoyi + */ +@Component +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter +{ + @Autowired + private TokenService tokenService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException + { + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) + { + tokenService.verifyToken(loginUser); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } + chain.doFilter(request, response); + } +} diff --git a/src/main/java/cn/sliyun/framework/security/handle/AuthenticationEntryPointImpl.java b/src/main/java/cn/sliyun/framework/security/handle/AuthenticationEntryPointImpl.java new file mode 100644 index 0000000..02d3288 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/handle/AuthenticationEntryPointImpl.java @@ -0,0 +1,35 @@ +package cn.sliyun.framework.security.handle; + +import java.io.IOException; +import java.io.Serializable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.sliyun.framework.web.domain.AjaxResult; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson.JSON; +import cn.sliyun.common.constant.HttpStatus; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.StringUtils; + +/** + * 认证失败处理类 返回未授权 + * + * @author ruoyi + */ +@Component +public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable +{ + private static final long serialVersionUID = -8970718410437077606L; + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) + throws IOException + { + int code = HttpStatus.UNAUTHORIZED; + String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI()); + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); + } +} diff --git a/src/main/java/cn/sliyun/framework/security/handle/LogoutSuccessHandlerImpl.java b/src/main/java/cn/sliyun/framework/security/handle/LogoutSuccessHandlerImpl.java new file mode 100644 index 0000000..302de37 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/handle/LogoutSuccessHandlerImpl.java @@ -0,0 +1,54 @@ +package cn.sliyun.framework.security.handle; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.sliyun.framework.manager.AsyncManager; +import cn.sliyun.framework.manager.factory.AsyncFactory; +import cn.sliyun.framework.web.domain.AjaxResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import com.alibaba.fastjson.JSON; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.constant.HttpStatus; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.TokenService; + +/** + * 自定义退出处理类 返回成功 + * + * @author ruoyi + */ +@Configuration +public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler +{ + @Autowired + private TokenService tokenService; + + /** + * 退出处理 + * + * @return + */ + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException, ServletException + { + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser)) + { + String userName = loginUser.getUsername(); + // 删除用户缓存记录 + tokenService.delLoginUser(loginUser.getToken()); + // 记录用户退出日志 + AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功")); + } + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(HttpStatus.SUCCESS, "退出成功"))); + } +} diff --git a/src/main/java/cn/sliyun/framework/security/service/PermissionService.java b/src/main/java/cn/sliyun/framework/security/service/PermissionService.java new file mode 100644 index 0000000..ac6132a --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/service/PermissionService.java @@ -0,0 +1,170 @@ +package cn.sliyun.framework.security.service; + +import java.util.Set; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.security.LoginUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.project.system.domain.SysRole; + +/** + * RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母 + * + * @author ruoyi + */ +@Service("ss") +public class PermissionService +{ + /** 所有权限标识 */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** 管理员角色权限标识 */ + private static final String SUPER_ADMIN = "admin"; + + private static final String ROLE_DELIMETER = ","; + + private static final String PERMISSION_DELIMETER = ","; + + @Autowired + private TokenService tokenService; + + /** + * 验证用户是否具备某权限 + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(String permission) + { + if (StringUtils.isEmpty(permission)) + { + return false; + } + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) + { + return false; + } + return hasPermissions(loginUser.getPermissions(), permission); + } + + /** + * 验证用户是否不具备某权限,与 hasPermi逻辑相反 + * + * @param permission 权限字符串 + * @return 用户是否不具备某权限 + */ + public boolean lacksPermi(String permission) + { + return hasPermi(permission) != true; + } + + /** + * 验证用户是否具有以下任意一个权限 + * + * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表 + * @return 用户是否具有以下任意一个权限 + */ + public boolean hasAnyPermi(String permissions) + { + if (StringUtils.isEmpty(permissions)) + { + return false; + } + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) + { + return false; + } + Set authorities = loginUser.getPermissions(); + for (String permission : permissions.split(PERMISSION_DELIMETER)) + { + if (permission != null && hasPermissions(authorities, permission)) + { + return true; + } + } + return false; + } + + /** + * 判断用户是否拥有某个角色 + * + * @param role 角色字符串 + * @return 用户是否具备某角色 + */ + public boolean hasRole(String role) + { + if (StringUtils.isEmpty(role)) + { + return false; + } + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) + { + return false; + } + for (SysRole sysRole : loginUser.getUser().getRoles()) + { + String roleKey = sysRole.getRoleKey(); + if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) + { + return true; + } + } + return false; + } + + /** + * 验证用户是否不具备某角色,与 isRole逻辑相反。 + * + * @param role 角色名称 + * @return 用户是否不具备某角色 + */ + public boolean lacksRole(String role) + { + return hasRole(role) != true; + } + + /** + * 验证用户是否具有以下任意一个角色 + * + * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表 + * @return 用户是否具有以下任意一个角色 + */ + public boolean hasAnyRoles(String roles) + { + if (StringUtils.isEmpty(roles)) + { + return false; + } + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) + { + return false; + } + for (String role : roles.split(ROLE_DELIMETER)) + { + if (hasRole(role)) + { + return true; + } + } + return false; + } + + /** + * 判断是否包含权限 + * + * @param permissions 权限列表 + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + private boolean hasPermissions(Set permissions, String permission) + { + return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission)); + } +} diff --git a/src/main/java/cn/sliyun/framework/security/service/SysLoginService.java b/src/main/java/cn/sliyun/framework/security/service/SysLoginService.java new file mode 100644 index 0000000..d869ad9 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/service/SysLoginService.java @@ -0,0 +1,84 @@ +package cn.sliyun.framework.security.service; + +import javax.annotation.Resource; + +import cn.sliyun.common.utils.MessageUtils; +import cn.sliyun.framework.manager.AsyncManager; +import cn.sliyun.framework.manager.factory.AsyncFactory; +import cn.sliyun.framework.security.LoginUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.exception.AppException; + +import java.util.HashMap; +import java.util.Map; + +/** + * 登录校验方法 + * + * @author ruoyi + */ +@Component +public class SysLoginService { + @Autowired + private TokenService tokenService; + + @Resource + private AuthenticationManager authenticationManager; + + private Map verifyMap = new HashMap<>(); + + + public void putVerifyMapCode(String verifyKey, String captcha) { + verifyMap.put(verifyKey, captcha); + } + + + /** + * 登录验证 + * + * @param username 用户名 + * @param password 密码 + * @param code 验证码 + * @param uuid 唯一标识 + * @return 结果 + */ + public String login(String username, String password, String code, String uuid) { + System.out.println("UUID:" + code); + String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; + String captcha = verifyMap.get(verifyKey); + verifyMap.clear(); + if (code == null) { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("验证码已失效"))); + throw new AppException("验证码已失效"); + } + if (!code.equalsIgnoreCase(captcha)) { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); + throw new AppException("验证码错误"); + } + // 用户验证 + Authentication authentication = null; + try { + // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername + authentication = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken(username, password)); + } catch (Exception e) { + if (e instanceof BadCredentialsException) { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("用户不存在/密码错误"))); + throw new AppException("用户不存在/密码错误"); + } else { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); + throw new AppException(e.getMessage()); + } + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("登录成功"))); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + // 生成token + return tokenService.createToken(loginUser); + } +} diff --git a/src/main/java/cn/sliyun/framework/security/service/SysPermissionService.java b/src/main/java/cn/sliyun/framework/security/service/SysPermissionService.java new file mode 100644 index 0000000..60f1195 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/service/SysPermissionService.java @@ -0,0 +1,66 @@ +package cn.sliyun.framework.security.service; + +import java.util.HashSet; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import cn.sliyun.project.system.domain.SysUser; +import cn.sliyun.project.system.service.ISysMenuService; +import cn.sliyun.project.system.service.ISysRoleService; + +/** + * 用户权限处理 + * + * @author ruoyi + */ +@Component +public class SysPermissionService +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysMenuService menuService; + + /** + * 获取角色数据权限 + * + * @param user 用户信息 + * @return 角色权限信息 + */ + public Set getRolePermission(SysUser user) + { + Set roles = new HashSet(); + // 管理员拥有所有权限 + if (user.isAdmin()) + { + roles.add("admin"); + } + else + { + roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId())); + } + return roles; + } + + /** + * 获取菜单数据权限 + * + * @param user 用户信息 + * @return 菜单权限信息 + */ + public Set getMenuPermission(SysUser user) + { + Set perms = new HashSet(); + // 管理员拥有所有权限 + if (user.isAdmin()) + { + perms.add("*:*:*"); + } + else + { + perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); + } + return perms; + } +} diff --git a/src/main/java/cn/sliyun/framework/security/service/TokenService.java b/src/main/java/cn/sliyun/framework/security/service/TokenService.java new file mode 100644 index 0000000..a9db463 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/service/TokenService.java @@ -0,0 +1,199 @@ +package cn.sliyun.framework.security.service; + +import java.util.HashMap; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.security.LoginUser; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.utils.IdUtils; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.ip.AddressUtils; +import cn.sliyun.common.utils.ip.IpUtils; +import eu.bitwalker.useragentutils.UserAgent; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +/** + * token验证处理 + * + * @author ruoyi + */ +@Component +public class TokenService { + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + // 令牌秘钥 + @Value("${token.secret}") + private String secret; + + // 令牌有效期(默认30分钟) + @Value("${token.expireTime}") + private int expireTime; + + protected static final long MILLIS_SECOND = 1000; + + protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; + + private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; + private Map mCache = new HashMap(); + + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUser(HttpServletRequest request) { + // 获取请求携带的令牌 + String token = getToken(request); + if (StringUtils.isNotEmpty(token)) { + Claims claims = parseToken(token); + // 解析对应的权限以及用户信息 + String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); + String userKey = getTokenKey(uuid); + return (LoginUser) mCache.get(userKey); +// LoginUser user = redisCache.getCacheObject(userKey); + } + return null; + } + + /** + * 设置用户身份信息 + */ + public void setLoginUser(LoginUser loginUser) { + if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) { + refreshToken(loginUser); + } + } + + /** + * 删除用户身份信息 + */ + + public void delLoginUser(String token) { + if (StringUtils.isNotEmpty(token)) { + String userKey = getTokenKey(token); + mCache.remove(userKey); + } + } + + /** + * 创建令牌 + * + * @param loginUser 用户信息 + * @return 令牌 + */ + public String createToken(LoginUser loginUser) { + String token = IdUtils.fastUUID(); + loginUser.setToken(token); + setUserAgent(loginUser); + refreshToken(loginUser); + + Map claims = new HashMap<>(); + claims.put(Constants.LOGIN_USER_KEY, token); + return createToken(claims); + } + + /** + * 验证令牌有效期,相差不足20分钟,自动刷新缓存 + * + * @param loginUser 令牌 + * @return 令牌 + */ + public void verifyToken(LoginUser loginUser) { + long expireTime = loginUser.getExpireTime(); + long currentTime = System.currentTimeMillis(); + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { + refreshToken(loginUser); + } + } + + /** + * 刷新令牌有效期 + * + * @param loginUser 登录信息 + */ + public void refreshToken(LoginUser loginUser) { + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); + // 根据uuid将loginUser缓存 + String userKey = getTokenKey(loginUser.getToken()); + mCache.put(userKey, loginUser); + } + + /** + * 设置用户代理信息 + * + * @param loginUser 登录信息 + */ + public void setUserAgent(LoginUser loginUser) { + UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + loginUser.setIpaddr(ip); + loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + loginUser.setBrowser(userAgent.getBrowser().getName()); + loginUser.setOs(userAgent.getOperatingSystem().getName()); + } + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + private String createToken(Map claims) { + String token = Jwts.builder() + .setClaims(claims) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + private Claims parseToken(String token) { + return Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + } + + /** + * 从令牌中获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public String getUsernameFromToken(String token) { + Claims claims = parseToken(token); + return claims.getSubject(); + } + + /** + * 获取请求token + * + * @param request + * @return token + */ + private String getToken(HttpServletRequest request) { + String token = request.getHeader(header); + if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { + token = token.replace(Constants.TOKEN_PREFIX, ""); + } + return token; + } + + private String getTokenKey(String uuid) { + return Constants.LOGIN_TOKEN_KEY + uuid; + } +} diff --git a/src/main/java/cn/sliyun/framework/security/service/UserDetailsServiceImpl.java b/src/main/java/cn/sliyun/framework/security/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..c017bdd --- /dev/null +++ b/src/main/java/cn/sliyun/framework/security/service/UserDetailsServiceImpl.java @@ -0,0 +1,60 @@ +package cn.sliyun.framework.security.service; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.security.LoginUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import cn.sliyun.common.enums.UserStatus; +import cn.sliyun.common.exception.BaseException; +import cn.sliyun.project.system.domain.SysUser; +import cn.sliyun.project.system.service.ISysUserService; + +/** + * 用户验证处理 + * + * @author ruoyi + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService +{ + private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); + + @Autowired + private ISysUserService userService; + + @Autowired + private SysPermissionService permissionService; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException + { + SysUser user = userService.selectUserByUserName(username); + if (StringUtils.isNull(user)) + { + log.info("登录用户:{} 不存在.", username); + throw new UsernameNotFoundException("登录用户:" + username + " 不存在"); + } + else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + log.info("登录用户:{} 已被删除.", username); + throw new BaseException("对不起,您的账号:" + username + " 已被删除"); + } + else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + log.info("登录用户:{} 已被停用.", username); + throw new BaseException("对不起,您的账号:" + username + " 已停用"); + } + + return createLoginUser(user); + } + + public UserDetails createLoginUser(SysUser user) + { + return new LoginUser(user, permissionService.getMenuPermission(user)); + } +} diff --git a/src/main/java/cn/sliyun/framework/web/controller/BaseController.java b/src/main/java/cn/sliyun/framework/web/controller/BaseController.java new file mode 100644 index 0000000..3cc08d0 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/controller/BaseController.java @@ -0,0 +1,87 @@ +package cn.sliyun.framework.web.controller; + +import java.beans.PropertyEditorSupport; +import java.util.Date; +import java.util.List; + +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.PageDomain; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.framework.web.page.TableSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import cn.sliyun.common.constant.HttpStatus; +import cn.sliyun.common.utils.DateUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.sql.SqlUtil; + +/** + * web层通用数据处理 + * + * @author ruoyi + */ +public class BaseController +{ + protected final Logger logger = LoggerFactory.getLogger(BaseController.class); + + /** + * 将前台传递过来的日期格式的字符串,自动转化为Date类型 + */ + @InitBinder + public void initBinder(WebDataBinder binder) + { + // Date 类型转换 + binder.registerCustomEditor(Date.class, new PropertyEditorSupport() + { + @Override + public void setAsText(String text) + { + setValue(DateUtils.parseDate(text)); + } + }); + } + + /** + * 设置请求分页数据 + */ + protected void startPage() + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + Integer pageNum = pageDomain.getPageNum(); + Integer pageSize = pageDomain.getPageSize(); + if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) + { + String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); + PageHelper.startPage(pageNum, pageSize, orderBy); + } + } + + /** + * 响应请求分页数据 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected TableDataInfo getDataTable(List list) + { + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(HttpStatus.SUCCESS); + rspData.setMsg("查询成功"); + rspData.setRows(list); + rspData.setTotal(new PageInfo(list).getTotal()); + return rspData; + } + + /** + * 响应返回结果 + * + * @param rows 影响行数 + * @return 操作结果 + */ + protected AjaxResult toAjax(int rows) + { + return rows > 0 ? AjaxResult.success() : AjaxResult.error(); + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/AjaxResult.java b/src/main/java/cn/sliyun/framework/web/domain/AjaxResult.java new file mode 100644 index 0000000..9c13198 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/AjaxResult.java @@ -0,0 +1,148 @@ +package cn.sliyun.framework.web.domain; + +import java.util.HashMap; +import cn.sliyun.common.constant.HttpStatus; +import cn.sliyun.common.utils.StringUtils; + +/** + * 操作消息提醒 + * + * @author ruoyi + */ +public class AjaxResult extends HashMap +{ + private static final long serialVersionUID = 1L; + + /** 状态码 */ + public static final String CODE_TAG = "code"; + + /** 返回内容 */ + public static final String MSG_TAG = "msg"; + + /** 数据对象 */ + public static final String DATA_TAG = "data"; + + /** + * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 + */ + public AjaxResult() + { + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + */ + public AjaxResult(int code, String msg) + { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + * @param data 数据对象 + */ + public AjaxResult(int code, String msg, Object data) + { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + if (StringUtils.isNotNull(data)) + { + super.put(DATA_TAG, data); + } + } + + /** + * 返回成功消息 + * + * @return 成功消息 + */ + public static AjaxResult success() + { + return AjaxResult.success("操作成功"); + } + + /** + * 返回成功数据 + * + * @return 成功消息 + */ + public static AjaxResult success(Object data) + { + return AjaxResult.success("操作成功", data); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @return 成功消息 + */ + public static AjaxResult success(String msg) + { + return AjaxResult.success(msg, null); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 成功消息 + */ + public static AjaxResult success(String msg, Object data) + { + return new AjaxResult(HttpStatus.SUCCESS, msg, data); + } + + /** + * 返回错误消息 + * + * @return + */ + public static AjaxResult error() + { + return AjaxResult.error("操作失败"); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @return 警告消息 + */ + public static AjaxResult error(String msg) + { + return AjaxResult.error(msg, null); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 警告消息 + */ + public static AjaxResult error(String msg, Object data) + { + return new AjaxResult(HttpStatus.ERROR, msg, data); + } + + /** + * 返回错误消息 + * + * @param code 状态码 + * @param msg 返回内容 + * @return 警告消息 + */ + public static AjaxResult error(int code, String msg) + { + return new AjaxResult(code, msg, null); + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/BaseEntity.java b/src/main/java/cn/sliyun/framework/web/domain/BaseEntity.java new file mode 100644 index 0000000..7b3c52d --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/BaseEntity.java @@ -0,0 +1,114 @@ +package cn.sliyun.framework.web.domain; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * Entity基类 + * + * @author ruoyi + */ +public class BaseEntity implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 搜索值 */ + private String searchValue; + + /** 创建者 */ + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** 更新者 */ + private String updateBy; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** 备注 */ + private String remark; + + /** 请求参数 */ + private Map params; + + public String getSearchValue() + { + return searchValue; + } + + public void setSearchValue(String searchValue) + { + this.searchValue = searchValue; + } + + public String getCreateBy() + { + return createBy; + } + + public void setCreateBy(String createBy) + { + this.createBy = createBy; + } + + public Date getCreateTime() + { + return createTime; + } + + public void setCreateTime(Date createTime) + { + this.createTime = createTime; + } + + public String getUpdateBy() + { + return updateBy; + } + + public void setUpdateBy(String updateBy) + { + this.updateBy = updateBy; + } + + public Date getUpdateTime() + { + return updateTime; + } + + public void setUpdateTime(Date updateTime) + { + this.updateTime = updateTime; + } + + public String getRemark() + { + return remark; + } + + public void setRemark(String remark) + { + this.remark = remark; + } + + public Map getParams() + { + if (params == null) + { + params = new HashMap<>(); + } + return params; + } + + public void setParams(Map params) + { + this.params = params; + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/Server.java b/src/main/java/cn/sliyun/framework/web/domain/Server.java new file mode 100644 index 0000000..59448fd --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/Server.java @@ -0,0 +1,240 @@ +package cn.sliyun.framework.web.domain; + +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import cn.sliyun.common.utils.Arith; +import cn.sliyun.common.utils.ip.IpUtils; +import cn.sliyun.framework.web.domain.server.Cpu; +import cn.sliyun.framework.web.domain.server.Jvm; +import cn.sliyun.framework.web.domain.server.Mem; +import cn.sliyun.framework.web.domain.server.Sys; +import cn.sliyun.framework.web.domain.server.SysFile; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.CentralProcessor.TickType; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.Util; + +/** + * 服务器相关信息 + * + * @author ruoyi + */ +public class Server +{ + private static final int OSHI_WAIT_SECOND = 1000; + + /** + * CPU相关信息 + */ + private Cpu cpu = new Cpu(); + + /** + * 內存相关信息 + */ + private Mem mem = new Mem(); + + /** + * JVM相关信息 + */ + private Jvm jvm = new Jvm(); + + /** + * 服务器相关信息 + */ + private Sys sys = new Sys(); + + /** + * 磁盘相关信息 + */ + private List sysFiles = new LinkedList(); + + public Cpu getCpu() + { + return cpu; + } + + public void setCpu(Cpu cpu) + { + this.cpu = cpu; + } + + public Mem getMem() + { + return mem; + } + + public void setMem(Mem mem) + { + this.mem = mem; + } + + public Jvm getJvm() + { + return jvm; + } + + public void setJvm(Jvm jvm) + { + this.jvm = jvm; + } + + public Sys getSys() + { + return sys; + } + + public void setSys(Sys sys) + { + this.sys = sys; + } + + public List getSysFiles() + { + return sysFiles; + } + + public void setSysFiles(List sysFiles) + { + this.sysFiles = sysFiles; + } + + public void copyTo() throws Exception + { + SystemInfo si = new SystemInfo(); + HardwareAbstractionLayer hal = si.getHardware(); + + setCpuInfo(hal.getProcessor()); + + setMemInfo(hal.getMemory()); + + setSysInfo(); + + setJvmInfo(); + + setSysFiles(si.getOperatingSystem()); + } + + /** + * 设置CPU信息 + */ + private void setCpuInfo(CentralProcessor processor) + { + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + Util.sleep(OSHI_WAIT_SECOND); + long[] ticks = processor.getSystemCpuLoadTicks(); + long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; + long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; + long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; + long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; + long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; + long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; + long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; + long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()); + cpu.setTotal(totalCpu); + cpu.setSys(cSys); + cpu.setUsed(user); + cpu.setWait(iowait); + cpu.setFree(idle); + } + + /** + * 设置内存信息 + */ + private void setMemInfo(GlobalMemory memory) + { + mem.setTotal(memory.getTotal()); + mem.setUsed(memory.getTotal() - memory.getAvailable()); + mem.setFree(memory.getAvailable()); + } + + /** + * 设置服务器信息 + */ + private void setSysInfo() + { + Properties props = System.getProperties(); + sys.setComputerName(IpUtils.getHostName()); + sys.setComputerIp(IpUtils.getHostIp()); + sys.setOsName(props.getProperty("os.name")); + sys.setOsArch(props.getProperty("os.arch")); + sys.setUserDir(props.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() throws UnknownHostException + { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime().totalMemory()); + jvm.setMax(Runtime.getRuntime().maxMemory()); + jvm.setFree(Runtime.getRuntime().freeMemory()); + jvm.setVersion(props.getProperty("java.version")); + jvm.setHome(props.getProperty("java.home")); + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) + { + FileSystem fileSystem = os.getFileSystem(); + List fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) + { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFile sysFile = new SysFile(); + sysFile.setDirName(fs.getMount()); + sysFile.setSysTypeName(fs.getType()); + sysFile.setTypeName(fs.getName()); + sysFile.setTotal(convertFileSize(total)); + sysFile.setFree(convertFileSize(free)); + sysFile.setUsed(convertFileSize(used)); + sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100)); + sysFiles.add(sysFile); + } + } + + /** + * 字节转换 + * + * @param size 字节大小 + * @return 转换后值 + */ + public String convertFileSize(long size) + { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + if (size >= gb) + { + return String.format("%.1f GB", (float) size / gb); + } + else if (size >= mb) + { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } + else if (size >= kb) + { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } + else + { + return String.format("%d B", size); + } + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/TreeEntity.java b/src/main/java/cn/sliyun/framework/web/domain/TreeEntity.java new file mode 100644 index 0000000..3f3c5cc --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/TreeEntity.java @@ -0,0 +1,79 @@ +package cn.sliyun.framework.web.domain; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tree基类 + * + * @author ruoyi + */ +public class TreeEntity extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 父菜单名称 */ + private String parentName; + + /** 父菜单ID */ + private Long parentId; + + /** 显示顺序 */ + private Integer orderNum; + + /** 祖级列表 */ + private String ancestors; + + /** 子部门 */ + private List children = new ArrayList<>(); + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + public String getAncestors() + { + return ancestors; + } + + public void setAncestors(String ancestors) + { + this.ancestors = ancestors; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/TreeSelect.java b/src/main/java/cn/sliyun/framework/web/domain/TreeSelect.java new file mode 100644 index 0000000..4692955 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/TreeSelect.java @@ -0,0 +1,77 @@ +package cn.sliyun.framework.web.domain; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonInclude; +import cn.sliyun.project.system.domain.SysDept; +import cn.sliyun.project.system.domain.SysMenu; + +/** + * Treeselect树结构实体类 + * + * @author ruoyi + */ +public class TreeSelect implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 节点ID */ + private Long id; + + /** 节点名称 */ + private String label; + + /** 子节点 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + public TreeSelect() + { + + } + + public TreeSelect(SysDept dept) + { + this.id = dept.getDeptId(); + this.label = dept.getDeptName(); + this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public TreeSelect(SysMenu menu) + { + this.id = menu.getMenuId(); + this.label = menu.getMenuName(); + this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public Long getId() + { + return id; + } + + public void setId(Long id) + { + this.id = id; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/server/Cpu.java b/src/main/java/cn/sliyun/framework/web/domain/server/Cpu.java new file mode 100644 index 0000000..1a63b84 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/server/Cpu.java @@ -0,0 +1,101 @@ +package cn.sliyun.framework.web.domain.server; + +import cn.sliyun.common.utils.Arith; + +/** + * CPU相关信息 + * + * @author ruoyi + */ +public class Cpu +{ + /** + * 核心数 + */ + private int cpuNum; + + /** + * CPU总的使用率 + */ + private double total; + + /** + * CPU系统使用率 + */ + private double sys; + + /** + * CPU用户使用率 + */ + private double used; + + /** + * CPU当前等待率 + */ + private double wait; + + /** + * CPU当前空闲率 + */ + private double free; + + public int getCpuNum() + { + return cpuNum; + } + + public void setCpuNum(int cpuNum) + { + this.cpuNum = cpuNum; + } + + public double getTotal() + { + return Arith.round(Arith.mul(total, 100), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getSys() + { + return Arith.round(Arith.mul(sys / total, 100), 2); + } + + public void setSys(double sys) + { + this.sys = sys; + } + + public double getUsed() + { + return Arith.round(Arith.mul(used / total, 100), 2); + } + + public void setUsed(double used) + { + this.used = used; + } + + public double getWait() + { + return Arith.round(Arith.mul(wait / total, 100), 2); + } + + public void setWait(double wait) + { + this.wait = wait; + } + + public double getFree() + { + return Arith.round(Arith.mul(free / total, 100), 2); + } + + public void setFree(double free) + { + this.free = free; + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/server/Jvm.java b/src/main/java/cn/sliyun/framework/web/domain/server/Jvm.java new file mode 100644 index 0000000..88139e4 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/server/Jvm.java @@ -0,0 +1,122 @@ +package cn.sliyun.framework.web.domain.server; + +import java.lang.management.ManagementFactory; +import cn.sliyun.common.utils.Arith; +import cn.sliyun.common.utils.DateUtils; + +/** + * JVM相关信息 + * + * @author ruoyi + */ +public class Jvm +{ + /** + * 当前JVM占用的内存总数(M) + */ + private double total; + + /** + * JVM最大可用内存总数(M) + */ + private double max; + + /** + * JVM空闲内存(M) + */ + private double free; + + /** + * JDK版本 + */ + private String version; + + /** + * JDK路径 + */ + private String home; + + public double getTotal() + { + return Arith.div(total, (1024 * 1024), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getMax() + { + return Arith.div(max, (1024 * 1024), 2); + } + + public void setMax(double max) + { + this.max = max; + } + + public double getFree() + { + return Arith.div(free, (1024 * 1024), 2); + } + + public void setFree(double free) + { + this.free = free; + } + + public double getUsed() + { + return Arith.div(total - free, (1024 * 1024), 2); + } + + public double getUsage() + { + return Arith.mul(Arith.div(total - free, total, 4), 100); + } + + /** + * 获取JDK名称 + */ + public String getName() + { + return ManagementFactory.getRuntimeMXBean().getVmName(); + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public String getHome() + { + return home; + } + + public void setHome(String home) + { + this.home = home; + } + + /** + * JDK启动时间 + */ + public String getStartTime() + { + return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate()); + } + + /** + * JDK运行时间 + */ + public String getRunTime() + { + return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate()); + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/server/Mem.java b/src/main/java/cn/sliyun/framework/web/domain/server/Mem.java new file mode 100644 index 0000000..cc44928 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/server/Mem.java @@ -0,0 +1,61 @@ +package cn.sliyun.framework.web.domain.server; + +import cn.sliyun.common.utils.Arith; + +/** + * 內存相关信息 + * + * @author ruoyi + */ +public class Mem +{ + /** + * 内存总量 + */ + private double total; + + /** + * 已用内存 + */ + private double used; + + /** + * 剩余内存 + */ + private double free; + + public double getTotal() + { + return Arith.div(total, (1024 * 1024 * 1024), 2); + } + + public void setTotal(long total) + { + this.total = total; + } + + public double getUsed() + { + return Arith.div(used, (1024 * 1024 * 1024), 2); + } + + public void setUsed(long used) + { + this.used = used; + } + + public double getFree() + { + return Arith.div(free, (1024 * 1024 * 1024), 2); + } + + public void setFree(long free) + { + this.free = free; + } + + public double getUsage() + { + return Arith.mul(Arith.div(used, total, 4), 100); + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/server/Sys.java b/src/main/java/cn/sliyun/framework/web/domain/server/Sys.java new file mode 100644 index 0000000..2050486 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/server/Sys.java @@ -0,0 +1,84 @@ +package cn.sliyun.framework.web.domain.server; + +/** + * 系统相关信息 + * + * @author ruoyi + */ +public class Sys +{ + /** + * 服务器名称 + */ + private String computerName; + + /** + * 服务器Ip + */ + private String computerIp; + + /** + * 项目路径 + */ + private String userDir; + + /** + * 操作系统 + */ + private String osName; + + /** + * 系统架构 + */ + private String osArch; + + public String getComputerName() + { + return computerName; + } + + public void setComputerName(String computerName) + { + this.computerName = computerName; + } + + public String getComputerIp() + { + return computerIp; + } + + public void setComputerIp(String computerIp) + { + this.computerIp = computerIp; + } + + public String getUserDir() + { + return userDir; + } + + public void setUserDir(String userDir) + { + this.userDir = userDir; + } + + public String getOsName() + { + return osName; + } + + public void setOsName(String osName) + { + this.osName = osName; + } + + public String getOsArch() + { + return osArch; + } + + public void setOsArch(String osArch) + { + this.osArch = osArch; + } +} diff --git a/src/main/java/cn/sliyun/framework/web/domain/server/SysFile.java b/src/main/java/cn/sliyun/framework/web/domain/server/SysFile.java new file mode 100644 index 0000000..a33eec2 --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/domain/server/SysFile.java @@ -0,0 +1,114 @@ +package cn.sliyun.framework.web.domain.server; + +/** + * 系统文件相关信息 + * + * @author ruoyi + */ +public class SysFile +{ + /** + * 盘符路径 + */ + private String dirName; + + /** + * 盘符类型 + */ + private String sysTypeName; + + /** + * 文件类型 + */ + private String typeName; + + /** + * 总大小 + */ + private String total; + + /** + * 剩余大小 + */ + private String free; + + /** + * 已经使用量 + */ + private String used; + + /** + * 资源的使用率 + */ + private double usage; + + public String getDirName() + { + return dirName; + } + + public void setDirName(String dirName) + { + this.dirName = dirName; + } + + public String getSysTypeName() + { + return sysTypeName; + } + + public void setSysTypeName(String sysTypeName) + { + this.sysTypeName = sysTypeName; + } + + public String getTypeName() + { + return typeName; + } + + public void setTypeName(String typeName) + { + this.typeName = typeName; + } + + public String getTotal() + { + return total; + } + + public void setTotal(String total) + { + this.total = total; + } + + public String getFree() + { + return free; + } + + public void setFree(String free) + { + this.free = free; + } + + public String getUsed() + { + return used; + } + + public void setUsed(String used) + { + this.used = used; + } + + public double getUsage() + { + return usage; + } + + public void setUsage(double usage) + { + this.usage = usage; + } +} diff --git a/src/main/java/cn/sliyun/framework/web/exception/GlobalExceptionHandler.java b/src/main/java/cn/sliyun/framework/web/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..c7bd38d --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/exception/GlobalExceptionHandler.java @@ -0,0 +1,136 @@ +package cn.sliyun.framework.web.exception; + +import cn.sliyun.common.core.Result; +import cn.sliyun.common.core.ResultGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.NoHandlerFoundException; +import cn.sliyun.common.exception.BaseException; +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.exception.DemoModeException; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.web.domain.AjaxResult; + +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +/** + * 全局异常处理器 + * + * @author ruoyi + */ +@RestControllerAdvice +public class GlobalExceptionHandler { + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * 基础异常 + */ + @ExceptionHandler(BaseException.class) + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + public Result baseException(BaseException e) { + return ResultGenerator.genFailResult(e.getMessage()); + } + + /** + * 业务异常 + */ + + @ExceptionHandler(NoHandlerFoundException.class) + @ResponseStatus(code = HttpStatus.NOT_FOUND) + public Result handlerNoFoundException(Exception e) { + log.error(e.getMessage(), e); + return ResultGenerator.genFailResult("路径不存在,请检查路径是否正确"); + } + + @ExceptionHandler(AccessDeniedException.class) + @ResponseStatus(code = HttpStatus.FORBIDDEN) + public Result handleAuthorizationException(AccessDeniedException e) { + log.error(e.getMessage()); + return ResultGenerator.genFailResult("没有权限,请联系管理员授权"); + } + + @ExceptionHandler(AccountExpiredException.class) + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + public Result handleAccountExpiredException(AccountExpiredException e) { + log.error(e.getMessage(), e); + return ResultGenerator.genFailResult(e.getMessage()); + } + + @ExceptionHandler(UsernameNotFoundException.class) + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + public Result handleUsernameNotFoundException(UsernameNotFoundException e) { + log.error(e.getMessage(), e); + return ResultGenerator.genFailResult(e.getMessage()); + } + + @ExceptionHandler(Exception.class) + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + public Result handleException(Exception e) { + log.error(e.getMessage(), e); + return ResultGenerator.genFailResult(e.getMessage()); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(BindException.class) + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + public Result validatedBindException(BindException e) { + for (int i = 0; i < e.getFieldErrors().size(); i++) { + return ResultGenerator.genFailResult(e.getFieldErrors().get(i).getDefaultMessage()); + } + return ResultGenerator.genFailResult(e.getMessage()); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseBody + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + public Result exceptionHandler(MethodArgumentNotValidException e) { + BindingResult bindingResult = e.getBindingResult(); + List allErrors = bindingResult.getAllErrors(); + + AtomicReference error = new AtomicReference<>(""); + allErrors.forEach(objectError -> { + FieldError fieldError = (FieldError) objectError; + error.set(fieldError.getField() + "|" + fieldError.getDefaultMessage()); + }); + return ResultGenerator.genFailResult(400, error.get()); + } + + /** + * 演示模式异常 + */ + @ExceptionHandler(DemoModeException.class) + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + public Result demoModeException(DemoModeException e) { + return ResultGenerator.genFailResult(400, e.getMessage()); + } + + /** + * 业务异常 + */ + @ExceptionHandler + @ResponseBody + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + public Result exceptionHandler(AppException e) { + return ResultGenerator.genFailResult(e.getCode(), e.getMessage()); + } + +} diff --git a/src/main/java/cn/sliyun/framework/web/page/PageDomain.java b/src/main/java/cn/sliyun/framework/web/page/PageDomain.java new file mode 100644 index 0000000..beab43f --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/page/PageDomain.java @@ -0,0 +1,72 @@ +package cn.sliyun.framework.web.page; + +import cn.sliyun.common.utils.StringUtils; + +/** + * 分页数据 + * + * @author ruoyi + */ +public class PageDomain +{ + /** 当前记录起始索引 */ + private Integer pageNum; + + /** 每页显示记录数 */ + private Integer pageSize; + + /** 排序列 */ + private String orderByColumn; + + /** 排序的方向desc或者asc */ + private String isAsc = "asc"; + + public String getOrderBy() + { + if (StringUtils.isEmpty(orderByColumn)) + { + return ""; + } + return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; + } + + public Integer getPageNum() + { + return pageNum; + } + + public void setPageNum(Integer pageNum) + { + this.pageNum = pageNum; + } + + public Integer getPageSize() + { + return pageSize; + } + + public void setPageSize(Integer pageSize) + { + this.pageSize = pageSize; + } + + public String getOrderByColumn() + { + return orderByColumn; + } + + public void setOrderByColumn(String orderByColumn) + { + this.orderByColumn = orderByColumn; + } + + public String getIsAsc() + { + return isAsc; + } + + public void setIsAsc(String isAsc) + { + this.isAsc = isAsc; + } +} diff --git a/src/main/java/cn/sliyun/framework/web/page/TableDataInfo.java b/src/main/java/cn/sliyun/framework/web/page/TableDataInfo.java new file mode 100644 index 0000000..a790def --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/page/TableDataInfo.java @@ -0,0 +1,85 @@ +package cn.sliyun.framework.web.page; + +import java.io.Serializable; +import java.util.List; + +/** + * 表格分页数据对象 + * + * @author ruoyi + */ +public class TableDataInfo implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 总记录数 */ + private long total; + + /** 列表数据 */ + private List rows; + + /** 消息状态码 */ + private int code; + + /** 消息内容 */ + private String msg; + + /** + * 表格数据对象 + */ + public TableDataInfo() + { + } + + /** + * 分页 + * + * @param list 列表数据 + * @param total 总记录数 + */ + public TableDataInfo(List list, int total) + { + this.rows = list; + this.total = total; + } + + public long getTotal() + { + return total; + } + + public void setTotal(long total) + { + this.total = total; + } + + public List getRows() + { + return rows; + } + + public void setRows(List rows) + { + this.rows = rows; + } + + public int getCode() + { + return code; + } + + public void setCode(int code) + { + this.code = code; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/framework/web/page/TableSupport.java b/src/main/java/cn/sliyun/framework/web/page/TableSupport.java new file mode 100644 index 0000000..a3188fe --- /dev/null +++ b/src/main/java/cn/sliyun/framework/web/page/TableSupport.java @@ -0,0 +1,49 @@ +package cn.sliyun.framework.web.page; + +import cn.sliyun.common.utils.ServletUtils; + +/** + * 表格数据处理 + * + * @author ruoyi + */ +public class TableSupport +{ + /** + * 当前记录起始索引 + */ + public static final String PAGE_NUM = "pageNum"; + + /** + * 每页显示记录数 + */ + public static final String PAGE_SIZE = "pageSize"; + + /** + * 排序列 + */ + public static final String ORDER_BY_COLUMN = "orderByColumn"; + + /** + * 排序的方向 "desc" 或者 "asc". + */ + public static final String IS_ASC = "isAsc"; + + /** + * 封装分页对象 + */ + public static PageDomain getPageDomain() + { + PageDomain pageDomain = new PageDomain(); + pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM)); + pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE)); + pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); + pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); + return pageDomain; + } + + public static PageDomain buildPageRequest() + { + return getPageDomain(); + } +} diff --git a/src/main/java/cn/sliyun/http/OkHttpUtils.java b/src/main/java/cn/sliyun/http/OkHttpUtils.java new file mode 100644 index 0000000..43484ca --- /dev/null +++ b/src/main/java/cn/sliyun/http/OkHttpUtils.java @@ -0,0 +1,160 @@ +package cn.sliyun.http; + +import cn.sliyun.http.builder.*; +import cn.sliyun.http.callback.BCallback; +import cn.sliyun.http.request.RequestCall; +import okhttp3.Call; +import okhttp3.OkHttpClient; +import okhttp3.Response; + +import java.io.IOException; + +/** + * Created by zhy on 15/8/17. + */ +public class OkHttpUtils { + public static final long DEFAULT_MILLISECONDS = 10_000L; + private volatile static OkHttpUtils mInstance; + private OkHttpClient mOkHttpClient; + + public OkHttpUtils(OkHttpClient okHttpClient) { + if (okHttpClient == null) { + mOkHttpClient = new OkHttpClient(); + } else { + mOkHttpClient = okHttpClient; + } + + } + + + public static OkHttpUtils initClient(OkHttpClient okHttpClient) { + if (mInstance == null) { + synchronized (OkHttpUtils.class) { + if (mInstance == null) { + mInstance = new OkHttpUtils(okHttpClient); + } + } + } + return mInstance; + } + + public static OkHttpUtils getInstance() { + return initClient(null); + } + + + public static void reset() { + if (mInstance != null) { + mInstance = null; + } + } + + + public OkHttpClient getOkHttpClient() { + return mOkHttpClient; + } + + public static GetBuilder get() { + return new GetBuilder(); + } + + public static PostStringBuilder postString() { + return new PostStringBuilder(); + } + + public static PostFileBuilder postFile() { + return new PostFileBuilder(); + } + + public static PostFormBuilder post() { + return new PostFormBuilder(); + } + + public static OtherRequestBuilder put() { + return new OtherRequestBuilder(METHOD.PUT); + } + + public static HeadBuilder head() { + return new HeadBuilder(); + } + + public static OtherRequestBuilder delete() { + return new OtherRequestBuilder(METHOD.DELETE); + } + + public static OtherRequestBuilder patch() { + return new OtherRequestBuilder(METHOD.PATCH); + } + + public void execute(final RequestCall requestCall, BCallback BCallback) { + if (BCallback == null) + BCallback = BCallback.sBCallbackDefault; + final BCallback finalBCallback = BCallback; + final int id = requestCall.getOkHttpRequest().getId(); + + requestCall.getCall().enqueue(new okhttp3.Callback() { + @Override + public void onFailure(Call call, final IOException e) { + sendFailResultCallback(call, e, finalBCallback, id); + } + + @Override + public void onResponse(final Call call, final Response response) { + try { + if (call.isCanceled()) { + sendFailResultCallback(call, new IOException("Canceled!"), finalBCallback, id); + return; + } + + if (!finalBCallback.validateReponse(response, id)) { + sendFailResultCallback(call, new IOException("request failed , reponse's code is : " + response.code()), finalBCallback, id); + return; + } + + Object o = finalBCallback.parseNetworkResponse(response, id); + sendSuccessResultCallback(o, finalBCallback, id); + } catch (Exception e) { + sendFailResultCallback(call, e, finalBCallback, id); + } finally { + if (response.body() != null) + response.body().close(); + } + + } + }); + } + + + public void sendFailResultCallback(final Call call, final Exception e, final BCallback BCallback, final int id) { + if (BCallback == null) return; + BCallback.onError(call, e, id); + BCallback.onAfter(id); + } + + public void sendSuccessResultCallback(final Object object, final BCallback BCallback, final int id) { + if (BCallback == null) return; + BCallback.onResponse(object, id); + BCallback.onAfter(id); + } + + public void cancelTag(Object tag) { + for (Call call : mOkHttpClient.dispatcher().queuedCalls()) { + if (tag.equals(call.request().tag())) { + call.cancel(); + } + } + for (Call call : mOkHttpClient.dispatcher().runningCalls()) { + if (tag.equals(call.request().tag())) { + call.cancel(); + } + } + } + + public static class METHOD { + public static final String HEAD = "HEAD"; + public static final String DELETE = "DELETE"; + public static final String PUT = "PUT"; + public static final String PATCH = "PATCH"; + } +} + diff --git a/src/main/java/cn/sliyun/http/builder/GetBuilder.java b/src/main/java/cn/sliyun/http/builder/GetBuilder.java new file mode 100644 index 0000000..71cf35d --- /dev/null +++ b/src/main/java/cn/sliyun/http/builder/GetBuilder.java @@ -0,0 +1,73 @@ +package cn.sliyun.http.builder; + + +import cn.sliyun.http.request.GetRequest; +import cn.sliyun.http.request.RequestCall; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +/** + * Created by zhy on 15/12/14. + */ +public class GetBuilder extends OkHttpRequestBuilder implements HasParamsable +{ + @Override + public RequestCall build() + { + if (params != null) + { + url = appendParams(url, params); + } + + return new GetRequest(url, tag, params, headers,id).build(); + } + + protected String appendParams(String url, Map params) + { + if (url == null || params == null || params.isEmpty()) + { + return url; + } + + StringBuffer builder =new StringBuffer(); + if (!url.contains("?")){ + builder.append(url+"?"); + }else { + builder.append(url); + + } + Set keys = params.keySet(); + Iterator iterator = keys.iterator(); + while (iterator.hasNext()) + { + String key = iterator.next(); + builder.append(key+"="+params.get(key)+"&"); + } + System.out.println("url:"+builder.toString()); + return builder.toString(); + } + + + @Override + public GetBuilder params(Map params) + { + this.params = params; + return this; + } + + @Override + public GetBuilder addParams(String key, String val) + { + if (this.params == null) + { + params = new LinkedHashMap<>(); + } + params.put(key, val); + return this; + } + + +} diff --git a/src/main/java/cn/sliyun/http/builder/HasParamsable.java b/src/main/java/cn/sliyun/http/builder/HasParamsable.java new file mode 100644 index 0000000..e6bd706 --- /dev/null +++ b/src/main/java/cn/sliyun/http/builder/HasParamsable.java @@ -0,0 +1,11 @@ +package cn.sliyun.http.builder; + +import java.util.Map; + +/** + * Created by zhy on 16/3/1. + */ +public interface HasParamsable { + OkHttpRequestBuilder params(Map params); + OkHttpRequestBuilder addParams(String key, String val); +} diff --git a/src/main/java/cn/sliyun/http/builder/HeadBuilder.java b/src/main/java/cn/sliyun/http/builder/HeadBuilder.java new file mode 100644 index 0000000..f56d11d --- /dev/null +++ b/src/main/java/cn/sliyun/http/builder/HeadBuilder.java @@ -0,0 +1,17 @@ +package cn.sliyun.http.builder; + +import cn.sliyun.http.OkHttpUtils; +import cn.sliyun.http.request.OtherRequest; +import cn.sliyun.http.request.RequestCall; + +/** + * Created by zhy on 16/3/2. + */ +public class HeadBuilder extends GetBuilder +{ + @Override + public RequestCall build() + { + return new OtherRequest(null, null, OkHttpUtils.METHOD.HEAD, url, tag, params, headers,id).build(); + } +} diff --git a/src/main/java/cn/sliyun/http/builder/OkHttpRequestBuilder.java b/src/main/java/cn/sliyun/http/builder/OkHttpRequestBuilder.java new file mode 100644 index 0000000..4681e25 --- /dev/null +++ b/src/main/java/cn/sliyun/http/builder/OkHttpRequestBuilder.java @@ -0,0 +1,55 @@ +package cn.sliyun.http.builder; + +import cn.sliyun.http.request.RequestCall; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Created by zhy on 15/12/14. + */ +public abstract class OkHttpRequestBuilder +{ + protected String url; + protected Object tag; + protected Map headers; + protected Map params; + protected int id; + + public T id(int id) + { + this.id = id; + return (T) this; + } + + public T url(String url) + { + this.url = url; + return (T) this; + } + + + public T tag(Object tag) + { + this.tag = tag; + return (T) this; + } + + public T headers(Map headers) + { + this.headers = headers; + return (T) this; + } + + public T addHeader(String key, String val) + { + if (this.headers == null) + { + headers = new LinkedHashMap<>(); + } + headers.put(key, val); + return (T) this; + } + + public abstract RequestCall build(); +} diff --git a/src/main/java/cn/sliyun/http/builder/OtherRequestBuilder.java b/src/main/java/cn/sliyun/http/builder/OtherRequestBuilder.java new file mode 100644 index 0000000..12a6e7f --- /dev/null +++ b/src/main/java/cn/sliyun/http/builder/OtherRequestBuilder.java @@ -0,0 +1,40 @@ +package cn.sliyun.http.builder; + +import cn.sliyun.http.request.OtherRequest; +import cn.sliyun.http.request.RequestCall; +import okhttp3.RequestBody; + +/** + * DELETE、PUT、PATCH等其他方法 + */ +public class OtherRequestBuilder extends OkHttpRequestBuilder +{ + private RequestBody requestBody; + private String method; + private String content; + + public OtherRequestBuilder(String method) + { + this.method = method; + } + + @Override + public RequestCall build() + { + return new OtherRequest(requestBody, content, method, url, tag, params, headers,id).build(); + } + + public OtherRequestBuilder requestBody(RequestBody requestBody) + { + this.requestBody = requestBody; + return this; + } + + public OtherRequestBuilder requestBody(String content) + { + this.content = content; + return this; + } + + +} diff --git a/src/main/java/cn/sliyun/http/builder/PostFileBuilder.java b/src/main/java/cn/sliyun/http/builder/PostFileBuilder.java new file mode 100644 index 0000000..48fe06a --- /dev/null +++ b/src/main/java/cn/sliyun/http/builder/PostFileBuilder.java @@ -0,0 +1,37 @@ +package cn.sliyun.http.builder; + +import cn.sliyun.http.request.PostFileRequest; +import cn.sliyun.http.request.RequestCall; +import okhttp3.MediaType; + +import java.io.File; + +/** + * Created by zhy on 15/12/14. + */ +public class PostFileBuilder extends OkHttpRequestBuilder +{ + private File file; + private MediaType mediaType; + + + public OkHttpRequestBuilder file(File file) + { + this.file = file; + return this; + } + + public OkHttpRequestBuilder mediaType(MediaType mediaType) + { + this.mediaType = mediaType; + return this; + } + + @Override + public RequestCall build() + { + return new PostFileRequest(url, tag, params, headers, file, mediaType,id).build(); + } + + +} diff --git a/src/main/java/cn/sliyun/http/builder/PostFormBuilder.java b/src/main/java/cn/sliyun/http/builder/PostFormBuilder.java new file mode 100644 index 0000000..4799d2c --- /dev/null +++ b/src/main/java/cn/sliyun/http/builder/PostFormBuilder.java @@ -0,0 +1,87 @@ +package cn.sliyun.http.builder; + +import cn.sliyun.http.request.PostFormRequest; +import cn.sliyun.http.request.RequestCall; + +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by zhy on 15/12/14. + */ +public class PostFormBuilder extends OkHttpRequestBuilder implements HasParamsable +{ + private List files = new ArrayList<>(); + + @Override + public RequestCall build() + { + return new PostFormRequest(url, tag, params, headers, files,id).build(); + } + + public PostFormBuilder files(String key, Map files) + { + for (String filename : files.keySet()) + { + this.files.add(new FileInput(key, filename, files.get(filename))); + } + return this; + } + + public PostFormBuilder addFile(String name, String filename, File file) + { + files.add(new FileInput(name, filename, file)); + return this; + } + + public static class FileInput + { + public String key; + public String filename; + public File file; + + public FileInput(String name, String filename, File file) + { + this.key = name; + this.filename = filename; + this.file = file; + } + + @Override + public String toString() + { + return "FileInput{" + + "key='" + key + '\'' + + ", filename='" + filename + '\'' + + ", file=" + file + + '}'; + } + } + + + + @Override + public PostFormBuilder params(Map params) + { + this.params = params; + return this; + } + + @Override + public PostFormBuilder addParams(String key, String val) + { + if (this.params == null) + { + params = new LinkedHashMap<>(); + } + params.put(key, val); + return this; + } + + + + +} diff --git a/src/main/java/cn/sliyun/http/builder/PostStringBuilder.java b/src/main/java/cn/sliyun/http/builder/PostStringBuilder.java new file mode 100644 index 0000000..519d5c0 --- /dev/null +++ b/src/main/java/cn/sliyun/http/builder/PostStringBuilder.java @@ -0,0 +1,35 @@ +package cn.sliyun.http.builder; + +import cn.sliyun.http.request.PostStringRequest; +import cn.sliyun.http.request.RequestCall; +import okhttp3.MediaType; + +/** + * Created by zhy on 15/12/14. + */ +public class PostStringBuilder extends OkHttpRequestBuilder +{ + private String content; + private MediaType mediaType; + + + public PostStringBuilder content(String content) + { + this.content = content; + return this; + } + + public PostStringBuilder mediaType(MediaType mediaType) + { + this.mediaType = mediaType; + return this; + } + + @Override + public RequestCall build() + { + return new PostStringRequest(url, tag, params, headers, content, mediaType,id).build(); + } + + +} diff --git a/src/main/java/cn/sliyun/http/callback/BCallback.java b/src/main/java/cn/sliyun/http/callback/BCallback.java new file mode 100644 index 0000000..4f9849d --- /dev/null +++ b/src/main/java/cn/sliyun/http/callback/BCallback.java @@ -0,0 +1,82 @@ +package cn.sliyun.http.callback; + +import okhttp3.Call; +import okhttp3.Request; +import okhttp3.Response; + +public abstract class BCallback +{ + /** + * UI Thread + * + * @param request + */ + public void onBefore(Request request, int id) + { + } + + /** + * UI Thread + * + * @param + */ + public void onAfter(int id) + { + } + + /** + * UI Thread + * + * @param progress + */ + public void inProgress(float progress, long total , int id) + { + + } + + /** + * if you parse reponse code in parseNetworkResponse, you should make this method return true. + * + * @param response + * @return + */ + public boolean validateReponse(Response response, int id) + { + return response.isSuccessful(); + } + + /** + * Thread Pool Thread + * + * @param response + */ + public abstract T parseNetworkResponse(Response response, int id) throws Exception; + + public abstract void onError(Call call, Exception e, int id); + + public abstract void onResponse(T response, int id); + + + public static BCallback sBCallbackDefault = new BCallback() + { + + @Override + public Object parseNetworkResponse(Response response, int id) throws Exception + { + return null; + } + + @Override + public void onError(Call call, Exception e, int id) + { + + } + + @Override + public void onResponse(Object response, int id) + { + + } + }; + +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/http/callback/GenericsCallback.java b/src/main/java/cn/sliyun/http/callback/GenericsCallback.java new file mode 100644 index 0000000..39bde4d --- /dev/null +++ b/src/main/java/cn/sliyun/http/callback/GenericsCallback.java @@ -0,0 +1,30 @@ +package cn.sliyun.http.callback; + +import okhttp3.Response; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; + +/** + * Created by JimGong on 2016/6/23. + */ + +public abstract class GenericsCallback extends BCallback { + IGenericsSerializator mGenericsSerializator; + + public GenericsCallback(IGenericsSerializator serializator) { + mGenericsSerializator = serializator; + } + + @Override + public T parseNetworkResponse(Response response, int id) throws IOException { + String string = response.body().string(); + Class entityClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + if (entityClass == String.class) { + return (T) string; + } + T bean = mGenericsSerializator.transform(string, entityClass); + return bean; + } + +} diff --git a/src/main/java/cn/sliyun/http/callback/IGenericsSerializator.java b/src/main/java/cn/sliyun/http/callback/IGenericsSerializator.java new file mode 100644 index 0000000..f4a9466 --- /dev/null +++ b/src/main/java/cn/sliyun/http/callback/IGenericsSerializator.java @@ -0,0 +1,8 @@ +package cn.sliyun.http.callback; + +/** + * Created by JimGong on 2016/6/23. + */ +public interface IGenericsSerializator { + T transform(String response, Class classOfT); +} diff --git a/src/main/java/cn/sliyun/http/callback/StringCallback.java b/src/main/java/cn/sliyun/http/callback/StringCallback.java new file mode 100644 index 0000000..d372920 --- /dev/null +++ b/src/main/java/cn/sliyun/http/callback/StringCallback.java @@ -0,0 +1,17 @@ +package cn.sliyun.http.callback; + +import okhttp3.Response; + +import java.io.IOException; + +/** + * Created by zhy on 15/12/14. + */ +public abstract class StringCallback extends BCallback +{ + @Override + public String parseNetworkResponse(Response response, int id) throws IOException + { + return response.body().string(); + } +} diff --git a/src/main/java/cn/sliyun/http/request/CountingRequestBody.java b/src/main/java/cn/sliyun/http/request/CountingRequestBody.java new file mode 100644 index 0000000..fa86323 --- /dev/null +++ b/src/main/java/cn/sliyun/http/request/CountingRequestBody.java @@ -0,0 +1,87 @@ +package cn.sliyun.http.request; + +import okhttp3.MediaType; +import okhttp3.RequestBody; +import okio.*; + +import java.io.IOException; + +/** + * Decorates an OkHttp request body to count the number of bytes written when writing it. Can + * decorate any request body, but is most useful for tracking the upload progress of large + * multipart requests. + * + * @author Leo Nikkilä + */ +public class CountingRequestBody extends RequestBody +{ + + protected RequestBody delegate; + protected Listener listener; + + protected CountingSink countingSink; + + public CountingRequestBody(RequestBody delegate, Listener listener) + { + this.delegate = delegate; + this.listener = listener; + } + + @Override + public MediaType contentType() + { + return delegate.contentType(); + } + + @Override + public long contentLength() + { + try + { + return delegate.contentLength(); + } catch (IOException e) + { + e.printStackTrace(); + } + return -1; + } + + @Override + public void writeTo(BufferedSink sink) throws IOException + { + + countingSink = new CountingSink(sink); + BufferedSink bufferedSink = Okio.buffer(countingSink); + + delegate.writeTo(bufferedSink); + + bufferedSink.flush(); + } + + protected final class CountingSink extends ForwardingSink + { + + private long bytesWritten = 0; + + public CountingSink(Sink delegate) + { + super(delegate); + } + + @Override + public void write(Buffer source, long byteCount) throws IOException + { + super.write(source, byteCount); + + bytesWritten += byteCount; + listener.onRequestProgress(bytesWritten, contentLength()); + } + + } + + public static interface Listener + { + public void onRequestProgress(long bytesWritten, long contentLength); + } + +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/http/request/GetRequest.java b/src/main/java/cn/sliyun/http/request/GetRequest.java new file mode 100644 index 0000000..6d671f0 --- /dev/null +++ b/src/main/java/cn/sliyun/http/request/GetRequest.java @@ -0,0 +1,31 @@ +package cn.sliyun.http.request; + +import okhttp3.Request; +import okhttp3.RequestBody; + +import java.util.Map; + +/** + * Created by zhy on 15/12/14. + */ +public class GetRequest extends OkHttpRequest +{ + public GetRequest(String url, Object tag, Map params, Map headers,int id) + { + super(url, tag, params, headers,id); + } + + @Override + protected RequestBody buildRequestBody() + { + return null; + } + + @Override + protected Request buildRequest(RequestBody requestBody) + { + return builder.get().build(); + } + + +} diff --git a/src/main/java/cn/sliyun/http/request/OkHttpRequest.java b/src/main/java/cn/sliyun/http/request/OkHttpRequest.java new file mode 100644 index 0000000..2dd0294 --- /dev/null +++ b/src/main/java/cn/sliyun/http/request/OkHttpRequest.java @@ -0,0 +1,93 @@ +package cn.sliyun.http.request; + +import cn.sliyun.http.callback.BCallback; +import cn.sliyun.http.utils.Exceptions; +import okhttp3.Headers; +import okhttp3.Request; +import okhttp3.RequestBody; + +import java.util.Map; + +/** + * Created by zhy on 15/11/6. + */ +public abstract class OkHttpRequest +{ + protected String url; + protected Object tag; + protected Map params; + protected Map headers; + protected int id; + + protected Request.Builder builder = new Request.Builder(); + + protected OkHttpRequest(String url, Object tag, + Map params, Map headers,int id) + { + this.url = url; + this.tag = tag; + this.params = params; + this.headers = headers; + this.id = id ; + + if (url == null) + { + Exceptions.illegalArgument("url can not be null."); + } + + initBuilder(); + } + + + + /** + * 初始化一些基本参数 url , tag , headers + */ + private void initBuilder() + { + builder.url(url).tag(tag); + appendHeaders(); + } + + protected abstract RequestBody buildRequestBody(); + + protected RequestBody wrapRequestBody(RequestBody requestBody, final BCallback BCallback) + { + return requestBody; + } + + protected abstract Request buildRequest(RequestBody requestBody); + + public RequestCall build() + { + return new RequestCall(this); + } + + + public Request generateRequest(BCallback BCallback) + { + RequestBody requestBody = buildRequestBody(); + RequestBody wrappedRequestBody = wrapRequestBody(requestBody, BCallback); + Request request = buildRequest(wrappedRequestBody); + return request; + } + + + protected void appendHeaders() + { + Headers.Builder headerBuilder = new Headers.Builder(); + if (headers == null || headers.isEmpty()) return; + + for (String key : headers.keySet()) + { + headerBuilder.add(key, headers.get(key)); + } + builder.headers(headerBuilder.build()); + } + + public int getId() + { + return id ; + } + +} diff --git a/src/main/java/cn/sliyun/http/request/OtherRequest.java b/src/main/java/cn/sliyun/http/request/OtherRequest.java new file mode 100644 index 0000000..be735fc --- /dev/null +++ b/src/main/java/cn/sliyun/http/request/OtherRequest.java @@ -0,0 +1,73 @@ +package cn.sliyun.http.request; + + +import cn.sliyun.http.OkHttpUtils; +import cn.sliyun.http.utils.Exceptions; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.internal.http.HttpMethod; +import org.apache.commons.lang.StringUtils; + +import java.util.Map; + +/** + * Created by zhy on 16/2/23. + */ +public class OtherRequest extends OkHttpRequest +{ + private static MediaType MEDIA_TYPE_PLAIN = MediaType.parse("text/plain;charset=utf-8"); + + private RequestBody requestBody; + private String method; + private String content; + + public OtherRequest(RequestBody requestBody, String content, String method, String url, Object tag, Map params, Map headers,int id) + { + super(url, tag, params, headers,id); + this.requestBody = requestBody; + this.method = method; + this.content = content; + + } + + @Override + protected RequestBody buildRequestBody() + { + if (requestBody == null && StringUtils.isEmpty(content) && HttpMethod.requiresRequestBody(method)) + { + Exceptions.illegalArgument("requestBody and content can not be null in method:" + method); + } + + if (requestBody == null && !StringUtils.isEmpty(content)) + { + requestBody = RequestBody.create(MEDIA_TYPE_PLAIN, content); + } + + return requestBody; + } + + @Override + protected Request buildRequest(RequestBody requestBody) + { + if (method.equals(OkHttpUtils.METHOD.PUT)) + { + builder.put(requestBody); + } else if (method.equals(OkHttpUtils.METHOD.DELETE)) + { + if (requestBody == null) + builder.delete(); + else + builder.delete(requestBody); + } else if (method.equals(OkHttpUtils.METHOD.HEAD)) + { + builder.head(); + } else if (method.equals(OkHttpUtils.METHOD.PATCH)) + { + builder.patch(requestBody); + } + + return builder.build(); + } + +} diff --git a/src/main/java/cn/sliyun/http/request/PostFileRequest.java b/src/main/java/cn/sliyun/http/request/PostFileRequest.java new file mode 100644 index 0000000..984e958 --- /dev/null +++ b/src/main/java/cn/sliyun/http/request/PostFileRequest.java @@ -0,0 +1,68 @@ +package cn.sliyun.http.request; + +import cn.sliyun.http.callback.BCallback; +import cn.sliyun.http.utils.Exceptions; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; + +import java.io.File; +import java.util.Map; + +/** + * Created by zhy on 15/12/14. + */ +public class PostFileRequest extends OkHttpRequest +{ + private static MediaType MEDIA_TYPE_STREAM = MediaType.parse("application/octet-stream"); + + private File file; + private MediaType mediaType; + + public PostFileRequest(String url, Object tag, Map params, Map headers, File file, MediaType mediaType,int id) + { + super(url, tag, params, headers,id); + this.file = file; + this.mediaType = mediaType; + + if (this.file == null) + { + Exceptions.illegalArgument("the file can not be null !"); + } + if (this.mediaType == null) + { + this.mediaType = MEDIA_TYPE_STREAM; + } + } + + @Override + protected RequestBody buildRequestBody() + { + return RequestBody.create(mediaType, file); + } + + @Override + protected RequestBody wrapRequestBody(RequestBody requestBody, final BCallback BCallback) + { + if (BCallback == null) return requestBody; + CountingRequestBody countingRequestBody = new CountingRequestBody(requestBody, new CountingRequestBody.Listener() + { + @Override + public void onRequestProgress(final long bytesWritten, final long contentLength) + { + BCallback.inProgress(bytesWritten * 1.0f / contentLength,contentLength,id); + + } + }); + return countingRequestBody; + } + + @Override + protected Request buildRequest(RequestBody requestBody) + { + return builder.post(requestBody).build(); + } + + + +} diff --git a/src/main/java/cn/sliyun/http/request/PostFormRequest.java b/src/main/java/cn/sliyun/http/request/PostFormRequest.java new file mode 100644 index 0000000..e21787f --- /dev/null +++ b/src/main/java/cn/sliyun/http/request/PostFormRequest.java @@ -0,0 +1,97 @@ +package cn.sliyun.http.request; + +import cn.sliyun.http.builder.PostFormBuilder; +import cn.sliyun.http.callback.BCallback; +import okhttp3.*; + +import java.io.UnsupportedEncodingException; +import java.net.FileNameMap; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.List; +import java.util.Map; + +/** + * Created by zhy on 15/12/14. + */ +public class PostFormRequest extends OkHttpRequest { + private List files; + + public PostFormRequest(String url, Object tag, Map params, Map headers, List files, int id) { + super(url, tag, params, headers, id); + this.files = files; + } + + @Override + protected RequestBody buildRequestBody() { + if (files == null || files.isEmpty()) { + FormBody.Builder builder = new FormBody.Builder(); + addParams(builder); + FormBody formBody = builder.build(); + return formBody; + } else { + MultipartBody.Builder builder = new MultipartBody.Builder() + .setType(MultipartBody.FORM); + addParams(builder); + + for (int i = 0; i < files.size(); i++) { + PostFormBuilder.FileInput fileInput = files.get(i); + RequestBody fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileInput.filename)), fileInput.file); + builder.addFormDataPart(fileInput.key, fileInput.filename, fileBody); + } + return builder.build(); + } + } + + @Override + protected RequestBody wrapRequestBody(RequestBody requestBody, final BCallback BCallback) { + if (BCallback == null) return requestBody; + CountingRequestBody countingRequestBody = new CountingRequestBody(requestBody, new CountingRequestBody.Listener() { + @Override + public void onRequestProgress(final long bytesWritten, final long contentLength) { + + BCallback.inProgress(bytesWritten * 1.0f / contentLength, contentLength, id); + + + } + }); + return countingRequestBody; + } + + @Override + protected Request buildRequest(RequestBody requestBody) { + return builder.post(requestBody).build(); + } + + private String guessMimeType(String path) { + FileNameMap fileNameMap = URLConnection.getFileNameMap(); + String contentTypeFor = null; + try { + contentTypeFor = fileNameMap.getContentTypeFor(URLEncoder.encode(path, "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + if (contentTypeFor == null) { + contentTypeFor = "application/octet-stream"; + } + return contentTypeFor; + } + + private void addParams(MultipartBody.Builder builder) { + if (params != null && !params.isEmpty()) { + for (String key : params.keySet()) { + builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + key + "\""), + RequestBody.create(null, params.get(key))); + } + } + } + + private void addParams(FormBody.Builder builder) { + if (params != null) { + for (String key : params.keySet()) { + builder.add(key, params.get(key)); + } + } + } + +} diff --git a/src/main/java/cn/sliyun/http/request/PostStringRequest.java b/src/main/java/cn/sliyun/http/request/PostStringRequest.java new file mode 100644 index 0000000..59d38d9 --- /dev/null +++ b/src/main/java/cn/sliyun/http/request/PostStringRequest.java @@ -0,0 +1,51 @@ +package cn.sliyun.http.request; + +import cn.sliyun.http.utils.Exceptions; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; + +import java.util.Map; + +/** + * Created by zhy on 15/12/14. + */ +public class PostStringRequest extends OkHttpRequest +{ + private static MediaType MEDIA_TYPE_PLAIN = MediaType.parse("text/plain;charset=utf-8"); + + private String content; + private MediaType mediaType; + + + public PostStringRequest(String url, Object tag, Map params, Map headers, String content, MediaType mediaType,int id) + { + super(url, tag, params, headers,id); + this.content = content; + this.mediaType = mediaType; + + if (this.content == null) + { + Exceptions.illegalArgument("the content can not be null !"); + } + if (this.mediaType == null) + { + this.mediaType = MEDIA_TYPE_PLAIN; + } + + } + + @Override + protected RequestBody buildRequestBody() + { + return RequestBody.create(mediaType, content); + } + + @Override + protected Request buildRequest( RequestBody requestBody) + { + return builder.post(requestBody).build(); + } + + +} diff --git a/src/main/java/cn/sliyun/http/request/RequestCall.java b/src/main/java/cn/sliyun/http/request/RequestCall.java new file mode 100644 index 0000000..0a89acd --- /dev/null +++ b/src/main/java/cn/sliyun/http/request/RequestCall.java @@ -0,0 +1,123 @@ +package cn.sliyun.http.request; + +import cn.sliyun.http.OkHttpUtils; +import cn.sliyun.http.callback.BCallback; +import okhttp3.Call; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * Created by zhy on 15/12/15. + * 对OkHttpRequest的封装,对外提供更多的接口:cancel(),readTimeOut()... + */ +public class RequestCall +{ + private OkHttpRequest okHttpRequest; + private Request request; + private Call call; + + private long readTimeOut; + private long writeTimeOut; + private long connTimeOut; + + private OkHttpClient clone; + + public RequestCall(OkHttpRequest request) + { + this.okHttpRequest = request; + } + + public RequestCall readTimeOut(long readTimeOut) + { + this.readTimeOut = readTimeOut; + return this; + } + + public RequestCall writeTimeOut(long writeTimeOut) + { + this.writeTimeOut = writeTimeOut; + return this; + } + + public RequestCall connTimeOut(long connTimeOut) + { + this.connTimeOut = connTimeOut; + return this; + } + + public Call buildCall(BCallback BCallback) + { + request = generateRequest(BCallback); + + if (readTimeOut > 0 || writeTimeOut > 0 || connTimeOut > 0) + { + readTimeOut = readTimeOut > 0 ? readTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS; + writeTimeOut = writeTimeOut > 0 ? writeTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS; + connTimeOut = connTimeOut > 0 ? connTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS; + + clone = OkHttpUtils.getInstance().getOkHttpClient().newBuilder() + .readTimeout(readTimeOut, TimeUnit.MILLISECONDS) + .writeTimeout(writeTimeOut, TimeUnit.MILLISECONDS) + .connectTimeout(connTimeOut, TimeUnit.MILLISECONDS) + .build(); + + call = clone.newCall(request); + } else + { + call = OkHttpUtils.getInstance().getOkHttpClient().newCall(request); + } + return call; + } + + private Request generateRequest(BCallback BCallback) + { + return okHttpRequest.generateRequest(BCallback); + } + + public void execute(BCallback BCallback) + { + buildCall(BCallback); + + if (BCallback != null) + { + BCallback.onBefore(request, getOkHttpRequest().getId()); + } + + OkHttpUtils.getInstance().execute(this, BCallback); + } + + public Call getCall() + { + return call; + } + + public Request getRequest() + { + return request; + } + + public OkHttpRequest getOkHttpRequest() + { + return okHttpRequest; + } + + public Response execute() throws IOException + { + buildCall(null); + return call.execute(); + } + + public void cancel() + { + if (call != null) + { + call.cancel(); + } + } + + +} diff --git a/src/main/java/cn/sliyun/http/utils/Exceptions.java b/src/main/java/cn/sliyun/http/utils/Exceptions.java new file mode 100644 index 0000000..8799a3f --- /dev/null +++ b/src/main/java/cn/sliyun/http/utils/Exceptions.java @@ -0,0 +1,14 @@ +package cn.sliyun.http.utils; + +/** + * Created by zhy on 15/12/14. + */ +public class Exceptions +{ + public static void illegalArgument(String msg, Object... params) + { + throw new IllegalArgumentException(String.format(msg, params)); + } + + +} diff --git a/src/main/java/cn/sliyun/http/utils/L.java b/src/main/java/cn/sliyun/http/utils/L.java new file mode 100644 index 0000000..635262e --- /dev/null +++ b/src/main/java/cn/sliyun/http/utils/L.java @@ -0,0 +1,19 @@ +package cn.sliyun.http.utils; + + +/** + * Created by zhy on 15/11/6. + */ +public class L +{ + private static boolean debug = false; + + public static void e(String msg) + { + if (debug) + { + } + } + +} + diff --git a/src/main/java/cn/sliyun/project/common/CaptchaController.java b/src/main/java/cn/sliyun/project/common/CaptchaController.java new file mode 100644 index 0000000..9034777 --- /dev/null +++ b/src/main/java/cn/sliyun/project/common/CaptchaController.java @@ -0,0 +1,82 @@ +package cn.sliyun.project.common; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import javax.annotation.Resource; +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; + +import cn.sliyun.common.utils.IdUtils; +import cn.sliyun.framework.security.service.SysLoginService; +import cn.sliyun.framework.web.domain.AjaxResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.FastByteArrayOutputStream; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import com.google.code.kaptcha.Producer; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.utils.sign.Base64; + +/** + * 验证码操作处理 + * + * @author ruoyi + */ +@RestController +public class CaptchaController { + @Resource(name = "captchaProducer") + private Producer captchaProducer; + + @Resource(name = "captchaProducerMath") + private Producer captchaProducerMath; + + + // 验证码类型 + private String captchaType ="math"; + + @Autowired + private SysLoginService loginService; + + + /** + * 生成验证码 + */ + @GetMapping("/captchaImage") + public AjaxResult getCode(HttpServletResponse response) throws IOException { + // 保存验证码信息 + String uuid = IdUtils.simpleUUID(); + String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; + + String capStr = null, code = null; + BufferedImage image = null; + + // 生成验证码 + if ("math".equals(captchaType)) { + String capText = captchaProducerMath.createText(); + capStr = capText.substring(0, capText.lastIndexOf("@")); + code = capText.substring(capText.lastIndexOf("@") + 1); + image = captchaProducerMath.createImage(capStr); + } else if ("char".equals(captchaType)) { + capStr = code = captchaProducer.createText(); + image = captchaProducer.createImage(capStr); + } + System.out.println("uuid:" + uuid + ""); + System.out.println("verifyKey:" + verifyKey + ""); + System.out.println("code:" + code + ""); + System.out.println("capStr:" + capStr + ""); + loginService.putVerifyMapCode(verifyKey,code); + // 转换流信息写出 + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); + try { + ImageIO.write(image, "jpg", os); + } catch (IOException e) { + return AjaxResult.error(e.getMessage()); + } + + AjaxResult ajax = AjaxResult.success(); + ajax.put("uuid", uuid); + ajax.put("img", Base64.encode(os.toByteArray())); + return ajax; + } +} diff --git a/src/main/java/cn/sliyun/project/common/CommonController.java b/src/main/java/cn/sliyun/project/common/CommonController.java new file mode 100644 index 0000000..b8ec6b6 --- /dev/null +++ b/src/main/java/cn/sliyun/project/common/CommonController.java @@ -0,0 +1,119 @@ +package cn.sliyun.project.common; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.config.RuoYiConfig; +import cn.sliyun.framework.config.ServerConfig; +import cn.sliyun.framework.web.domain.AjaxResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.utils.file.FileUploadUtils; +import cn.sliyun.common.utils.file.FileUtils; + +/** + * 通用请求处理 + * + * @author ruoyi + */ +@RestController +public class CommonController +{ + private static final Logger log = LoggerFactory.getLogger(CommonController.class); + + @Autowired + private ServerConfig serverConfig; + + /** + * 通用下载请求 + * + * @param fileName 文件名称 + * @param delete 是否删除 + */ + @GetMapping("common/download") + public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) + { + try + { + if (!FileUtils.checkAllowDownload(fileName)) + { + throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName)); + } + String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); + String filePath = RuoYiConfig.getDownloadPath() + fileName; + + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + FileUtils.setAttachmentResponseHeader(response, realFileName); + FileUtils.writeBytes(filePath, response.getOutputStream()); + if (delete) + { + FileUtils.deleteFile(filePath); + } + } + catch (Exception e) + { + log.error("下载文件失败", e); + } + } + + /** + * 通用上传请求 + */ + @PostMapping("/common/upload") + public AjaxResult uploadFile(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getUploadPath(); + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + String url = serverConfig.getUrl() + fileName; + AjaxResult ajax = AjaxResult.success(); + ajax.put("fileName", fileName); + ajax.put("url", url); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 本地资源通用下载 + */ + @GetMapping("/common/download/resource") + public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response) + throws Exception + { + try + { + if (!FileUtils.checkAllowDownload(resource)) + { + throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource)); + } + // 本地资源路径 + String localPath = RuoYiConfig.getProfile(); + // 数据库资源地址 + String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX); + // 下载名称 + String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + FileUtils.setAttachmentResponseHeader(response, downloadName); + FileUtils.writeBytes(downloadPath, response.getOutputStream()); + } + catch (Exception e) + { + log.error("下载文件失败", e); + } + } +} diff --git a/src/main/java/cn/sliyun/project/monitor/controller/ServerController.java b/src/main/java/cn/sliyun/project/monitor/controller/ServerController.java new file mode 100644 index 0000000..1ba82e6 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/controller/ServerController.java @@ -0,0 +1,27 @@ +package cn.sliyun.project.monitor.controller; + +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.domain.Server; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 服务器监控 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/server") +public class ServerController +{ + @PreAuthorize("@ss.hasPermi('monitor:server:list')") + @GetMapping() + public AjaxResult getInfo() throws Exception + { + Server server = new Server(); + server.copyTo(); + return AjaxResult.success(server); + } +} diff --git a/src/main/java/cn/sliyun/project/monitor/controller/SysLogininforController.java b/src/main/java/cn/sliyun/project/monitor/controller/SysLogininforController.java new file mode 100644 index 0000000..bab98c8 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/controller/SysLogininforController.java @@ -0,0 +1,68 @@ +package cn.sliyun.project.monitor.controller; + +import java.util.List; + +import cn.sliyun.common.utils.poi.ExcelUtil; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.monitor.domain.SysLogininfor; +import cn.sliyun.project.monitor.service.ISysLogininforService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 系统访问记录 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/logininfor") +public class SysLogininforController extends BaseController +{ + @Autowired + private ISysLogininforService logininforService; + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") + @GetMapping("/list") + public TableDataInfo list(SysLogininfor logininfor) + { + startPage(); + List list = logininforService.selectLogininforList(logininfor); + return getDataTable(list); + } + + @Log(title = "登录日志", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") + @GetMapping("/export") + public AjaxResult export(SysLogininfor logininfor) + { + List list = logininforService.selectLogininforList(logininfor); + ExcelUtil util = new ExcelUtil(SysLogininfor.class); + return util.exportExcel(list, "登录日志"); + } + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") + @Log(title = "登录日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{infoIds}") + public AjaxResult remove(@PathVariable Long[] infoIds) + { + return toAjax(logininforService.deleteLogininforByIds(infoIds)); + } + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") + @Log(title = "登录日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public AjaxResult clean() + { + logininforService.cleanLogininfor(); + return AjaxResult.success(); + } +} diff --git a/src/main/java/cn/sliyun/project/monitor/controller/SysOperlogController.java b/src/main/java/cn/sliyun/project/monitor/controller/SysOperlogController.java new file mode 100644 index 0000000..f8e0c40 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/controller/SysOperlogController.java @@ -0,0 +1,67 @@ +package cn.sliyun.project.monitor.controller; + +import java.util.List; + +import cn.sliyun.common.utils.poi.ExcelUtil; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.monitor.domain.SysOperLog; +import cn.sliyun.project.monitor.service.ISysOperLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 操作日志记录 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/operlog") +public class SysOperlogController extends BaseController +{ + @Autowired + private ISysOperLogService operLogService; + + @PreAuthorize("@ss.hasPermi('monitor:operlog:list')") + @GetMapping("/list") + public TableDataInfo list(SysOperLog operLog) + { + startPage(); + List list = operLogService.selectOperLogList(operLog); + return getDataTable(list); + } + + @Log(title = "操作日志", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('monitor:operlog:export')") + @GetMapping("/export") + public AjaxResult export(SysOperLog operLog) + { + List list = operLogService.selectOperLogList(operLog); + ExcelUtil util = new ExcelUtil(SysOperLog.class); + return util.exportExcel(list, "操作日志"); + } + + @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") + @DeleteMapping("/{operIds}") + public AjaxResult remove(@PathVariable Long[] operIds) + { + return toAjax(operLogService.deleteOperLogByIds(operIds)); + } + + @Log(title = "操作日志", businessType = BusinessType.CLEAN) + @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") + @DeleteMapping("/clean") + public AjaxResult clean() + { + operLogService.cleanOperLog(); + return AjaxResult.success(); + } +} diff --git a/src/main/java/cn/sliyun/project/monitor/controller/SysUserOnlineController.java b/src/main/java/cn/sliyun/project/monitor/controller/SysUserOnlineController.java new file mode 100644 index 0000000..9f87119 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/controller/SysUserOnlineController.java @@ -0,0 +1,89 @@ +package cn.sliyun.project.monitor.controller; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.monitor.domain.SysUserOnline; +import cn.sliyun.project.system.service.ISysUserOnlineService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 在线用户监控 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/monitor/online") +public class SysUserOnlineController extends BaseController +{ + @Autowired + private ISysUserOnlineService userOnlineService; + + + @PreAuthorize("@ss.hasPermi('monitor:online:list')") + @GetMapping("/list") + public TableDataInfo list(String ipaddr, String userName) + { + Collection keys =null;// redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*"); + List userOnlineList = new ArrayList(); + for (String key : keys) + { + LoginUser user = null; + if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) + { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) + { + userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); + } + } + else if (StringUtils.isNotEmpty(ipaddr)) + { + if (StringUtils.equals(ipaddr, user.getIpaddr())) + { + userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); + } + } + else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) + { + if (StringUtils.equals(userName, user.getUsername())) + { + userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); + } + } + else + { + userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); + } + } + Collections.reverse(userOnlineList); + userOnlineList.removeAll(Collections.singleton(null)); + return getDataTable(userOnlineList); + } + + /** + * 强退用户 + */ + @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')") + @Log(title = "在线用户", businessType = BusinessType.FORCE) + @DeleteMapping("/{tokenId}") + public AjaxResult forceLogout(@PathVariable String tokenId) + { +// redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId); + return AjaxResult.success(); + } +} diff --git a/src/main/java/cn/sliyun/project/monitor/domain/SysLogininfor.java b/src/main/java/cn/sliyun/project/monitor/domain/SysLogininfor.java new file mode 100644 index 0000000..7bfa752 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/domain/SysLogininfor.java @@ -0,0 +1,144 @@ +package cn.sliyun.project.monitor.domain; + +import java.util.Date; + +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.web.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 系统访问记录表 sys_logininfor + * + * @author ruoyi + */ +public class SysLogininfor extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + @Excel(name = "序号", cellType = Excel.ColumnType.NUMERIC) + private Long infoId; + + /** 用户账号 */ + @Excel(name = "用户账号") + private String userName; + + /** 登录状态 0成功 1失败 */ + @Excel(name = "登录状态", readConverterExp = "0=成功,1=失败") + private String status; + + /** 登录IP地址 */ + @Excel(name = "登录地址") + private String ipaddr; + + /** 登录地点 */ + @Excel(name = "登录地点") + private String loginLocation; + + /** 浏览器类型 */ + @Excel(name = "浏览器") + private String browser; + + /** 操作系统 */ + @Excel(name = "操作系统") + private String os; + + /** 提示消息 */ + @Excel(name = "提示消息") + private String msg; + + /** 访问时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "访问时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date loginTime; + + public Long getInfoId() + { + return infoId; + } + + public void setInfoId(Long infoId) + { + this.infoId = infoId; + } + + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } + + public Date getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Date loginTime) + { + this.loginTime = loginTime; + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/project/monitor/domain/SysOperLog.java b/src/main/java/cn/sliyun/project/monitor/domain/SysOperLog.java new file mode 100644 index 0000000..28d08e7 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/domain/SysOperLog.java @@ -0,0 +1,255 @@ +package cn.sliyun.project.monitor.domain; + +import java.util.Date; + +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.web.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 操作日志记录表 oper_log + * + * @author ruoyi + */ +public class SysOperLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 日志主键 */ + @Excel(name = "操作序号", cellType = Excel.ColumnType.NUMERIC) + private Long operId; + + /** 操作模块 */ + @Excel(name = "操作模块") + private String title; + + /** 业务类型(0其它 1新增 2修改 3删除) */ + @Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据") + private Integer businessType; + + /** 业务类型数组 */ + private Integer[] businessTypes; + + /** 请求方法 */ + @Excel(name = "请求方法") + private String method; + + /** 请求方式 */ + @Excel(name = "请求方式") + private String requestMethod; + + /** 操作类别(0其它 1后台用户 2手机端用户) */ + @Excel(name = "操作类别", readConverterExp = "0=其它,1=后台用户,2=手机端用户") + private Integer operatorType; + + /** 操作人员 */ + @Excel(name = "操作人员") + private String operName; + + /** 部门名称 */ + @Excel(name = "部门名称") + private String deptName; + + /** 请求url */ + @Excel(name = "请求地址") + private String operUrl; + + /** 操作地址 */ + @Excel(name = "操作地址") + private String operIp; + + /** 操作地点 */ + @Excel(name = "操作地点") + private String operLocation; + + /** 请求参数 */ + @Excel(name = "请求参数") + private String operParam; + + /** 返回参数 */ + @Excel(name = "返回参数") + private String jsonResult; + + /** 操作状态(0正常 1异常) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=异常") + private Integer status; + + /** 错误消息 */ + @Excel(name = "错误消息") + private String errorMsg; + + /** 操作时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date operTime; + + public Long getOperId() + { + return operId; + } + + public void setOperId(Long operId) + { + this.operId = operId; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public Integer getBusinessType() + { + return businessType; + } + + public void setBusinessType(Integer businessType) + { + this.businessType = businessType; + } + + public Integer[] getBusinessTypes() + { + return businessTypes; + } + + public void setBusinessTypes(Integer[] businessTypes) + { + this.businessTypes = businessTypes; + } + + public String getMethod() + { + return method; + } + + public void setMethod(String method) + { + this.method = method; + } + + public String getRequestMethod() + { + return requestMethod; + } + + public void setRequestMethod(String requestMethod) + { + this.requestMethod = requestMethod; + } + + public Integer getOperatorType() + { + return operatorType; + } + + public void setOperatorType(Integer operatorType) + { + this.operatorType = operatorType; + } + + public String getOperName() + { + return operName; + } + + public void setOperName(String operName) + { + this.operName = operName; + } + + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + public String getOperUrl() + { + return operUrl; + } + + public void setOperUrl(String operUrl) + { + this.operUrl = operUrl; + } + + public String getOperIp() + { + return operIp; + } + + public void setOperIp(String operIp) + { + this.operIp = operIp; + } + + public String getOperLocation() + { + return operLocation; + } + + public void setOperLocation(String operLocation) + { + this.operLocation = operLocation; + } + + public String getOperParam() + { + return operParam; + } + + public void setOperParam(String operParam) + { + this.operParam = operParam; + } + + public String getJsonResult() + { + return jsonResult; + } + + public void setJsonResult(String jsonResult) + { + this.jsonResult = jsonResult; + } + + public Integer getStatus() + { + return status; + } + + public void setStatus(Integer status) + { + this.status = status; + } + + public String getErrorMsg() + { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) + { + this.errorMsg = errorMsg; + } + + public Date getOperTime() + { + return operTime; + } + + public void setOperTime(Date operTime) + { + this.operTime = operTime; + } +} diff --git a/src/main/java/cn/sliyun/project/monitor/domain/SysUserOnline.java b/src/main/java/cn/sliyun/project/monitor/domain/SysUserOnline.java new file mode 100644 index 0000000..5b73aaa --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/domain/SysUserOnline.java @@ -0,0 +1,113 @@ +package cn.sliyun.project.monitor.domain; + +/** + * 当前在线会话 + * + * @author ruoyi + */ +public class SysUserOnline +{ + /** 会话编号 */ + private String tokenId; + + /** 部门名称 */ + private String deptName; + + /** 用户名称 */ + private String userName; + + /** 登录IP地址 */ + private String ipaddr; + + /** 登录地址 */ + private String loginLocation; + + /** 浏览器类型 */ + private String browser; + + /** 操作系统 */ + private String os; + + /** 登录时间 */ + private Long loginTime; + + public String getTokenId() + { + return tokenId; + } + + public void setTokenId(String tokenId) + { + this.tokenId = tokenId; + } + + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public Long getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Long loginTime) + { + this.loginTime = loginTime; + } +} diff --git a/src/main/java/cn/sliyun/project/monitor/mapper/SysLogininforMapper.java b/src/main/java/cn/sliyun/project/monitor/mapper/SysLogininforMapper.java new file mode 100644 index 0000000..68b6fef --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/mapper/SysLogininforMapper.java @@ -0,0 +1,43 @@ +package cn.sliyun.project.monitor.mapper; + +import java.util.List; + +import cn.sliyun.project.monitor.domain.SysLogininfor; + +/** + * 系统访问日志情况信息 数据层 + * + * @author ruoyi + */ +public interface SysLogininforMapper +{ + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + public void insertLogininfor(SysLogininfor logininfor); + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + public List selectLogininforList(SysLogininfor logininfor); + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + public int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + * + * @return 结果 + */ + public int cleanLogininfor(); +} diff --git a/src/main/java/cn/sliyun/project/monitor/mapper/SysOperLogMapper.java b/src/main/java/cn/sliyun/project/monitor/mapper/SysOperLogMapper.java new file mode 100644 index 0000000..fd2e140 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/mapper/SysOperLogMapper.java @@ -0,0 +1,49 @@ +package cn.sliyun.project.monitor.mapper; + +import java.util.List; + +import cn.sliyun.project.monitor.domain.SysOperLog; + +/** + * 操作日志 数据层 + * + * @author ruoyi + */ +public interface SysOperLogMapper +{ + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + public void insertOperlog(SysOperLog operLog); + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + public List selectOperLogList(SysOperLog operLog); + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + public int deleteOperLogByIds(Long[] operIds); + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + public SysOperLog selectOperLogById(Long operId); + + /** + * 清空操作日志 + */ + public void cleanOperLog(); +} diff --git a/src/main/java/cn/sliyun/project/monitor/service/ISysLogininforService.java b/src/main/java/cn/sliyun/project/monitor/service/ISysLogininforService.java new file mode 100644 index 0000000..093b4e9 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/service/ISysLogininforService.java @@ -0,0 +1,41 @@ +package cn.sliyun.project.monitor.service; + +import java.util.List; + +import cn.sliyun.project.monitor.domain.SysLogininfor; + +/** + * 系统访问日志情况信息 服务层 + * + * @author ruoyi + */ +public interface ISysLogininforService +{ + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + public void insertLogininfor(SysLogininfor logininfor); + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + public List selectLogininforList(SysLogininfor logininfor); + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return + */ + public int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + */ + public void cleanLogininfor(); +} diff --git a/src/main/java/cn/sliyun/project/monitor/service/ISysOperLogService.java b/src/main/java/cn/sliyun/project/monitor/service/ISysOperLogService.java new file mode 100644 index 0000000..21e75a6 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/service/ISysOperLogService.java @@ -0,0 +1,49 @@ +package cn.sliyun.project.monitor.service; + +import java.util.List; + +import cn.sliyun.project.monitor.domain.SysOperLog; + +/** + * 操作日志 服务层 + * + * @author ruoyi + */ +public interface ISysOperLogService +{ + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + public void insertOperlog(SysOperLog operLog); + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + public List selectOperLogList(SysOperLog operLog); + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + public int deleteOperLogByIds(Long[] operIds); + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + public SysOperLog selectOperLogById(Long operId); + + /** + * 清空操作日志 + */ + public void cleanOperLog(); +} diff --git a/src/main/java/cn/sliyun/project/monitor/service/impl/SysLogininforServiceImpl.java b/src/main/java/cn/sliyun/project/monitor/service/impl/SysLogininforServiceImpl.java new file mode 100644 index 0000000..9f9059d --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/service/impl/SysLogininforServiceImpl.java @@ -0,0 +1,66 @@ +package cn.sliyun.project.monitor.service.impl; + +import java.util.List; + +import cn.sliyun.project.monitor.domain.SysLogininfor; +import cn.sliyun.project.monitor.mapper.SysLogininforMapper; +import cn.sliyun.project.monitor.service.ISysLogininforService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 系统访问日志情况信息 服务层处理 + * + * @author ruoyi + */ +@Service +public class SysLogininforServiceImpl implements ISysLogininforService +{ + + @Autowired + private SysLogininforMapper logininforMapper; + + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + @Override + public void insertLogininfor(SysLogininfor logininfor) + { + logininforMapper.insertLogininfor(logininfor); + } + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + @Override + public List selectLogininforList(SysLogininfor logininfor) + { + return logininforMapper.selectLogininforList(logininfor); + } + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return + */ + @Override + public int deleteLogininforByIds(Long[] infoIds) + { + return logininforMapper.deleteLogininforByIds(infoIds); + } + + /** + * 清空系统登录日志 + */ + @Override + public void cleanLogininfor() + { + logininforMapper.cleanLogininfor(); + } +} diff --git a/src/main/java/cn/sliyun/project/monitor/service/impl/SysOperLogServiceImpl.java b/src/main/java/cn/sliyun/project/monitor/service/impl/SysOperLogServiceImpl.java new file mode 100644 index 0000000..3905e13 --- /dev/null +++ b/src/main/java/cn/sliyun/project/monitor/service/impl/SysOperLogServiceImpl.java @@ -0,0 +1,77 @@ +package cn.sliyun.project.monitor.service.impl; + +import java.util.List; + +import cn.sliyun.project.monitor.domain.SysOperLog; +import cn.sliyun.project.monitor.mapper.SysOperLogMapper; +import cn.sliyun.project.monitor.service.ISysOperLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 操作日志 服务层处理 + * + * @author ruoyi + */ +@Service +public class SysOperLogServiceImpl implements ISysOperLogService +{ + @Autowired + private SysOperLogMapper operLogMapper; + + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + @Override + public void insertOperlog(SysOperLog operLog) + { + operLogMapper.insertOperlog(operLog); + } + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + @Override + public List selectOperLogList(SysOperLog operLog) + { + return operLogMapper.selectOperLogList(operLog); + } + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + @Override + public int deleteOperLogByIds(Long[] operIds) + { + return operLogMapper.deleteOperLogByIds(operIds); + } + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + @Override + public SysOperLog selectOperLogById(Long operId) + { + return operLogMapper.selectOperLogById(operId); + } + + /** + * 清空操作日志 + */ + @Override + public void cleanOperLog() + { + operLogMapper.cleanOperLog(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysConfigController.java b/src/main/java/cn/sliyun/project/system/controller/SysConfigController.java new file mode 100644 index 0000000..4082ef6 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysConfigController.java @@ -0,0 +1,134 @@ +package cn.sliyun.project.system.controller; + +import java.util.List; + +import cn.sliyun.common.constant.UserConstants; +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.poi.ExcelUtil; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.system.domain.SysConfig; +import cn.sliyun.project.system.service.ISysConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 参数配置 信息操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/config") +public class SysConfigController extends BaseController +{ + @Autowired + private ISysConfigService configService; + + /** + * 获取参数配置列表 + */ + @PreAuthorize("@ss.hasPermi('system:config:list')") + @GetMapping("/list") + public TableDataInfo list(SysConfig config) + { + startPage(); + List list = configService.selectConfigList(config); + return getDataTable(list); + } + + @Log(title = "参数管理", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:config:export')") + @GetMapping("/export") + public AjaxResult export(SysConfig config) + { + List list = configService.selectConfigList(config); + ExcelUtil util = new ExcelUtil(SysConfig.class); + return util.exportExcel(list, "参数数据"); + } + + /** + * 根据参数编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:config:query')") + @GetMapping(value = "/{configId}") + public AjaxResult getInfo(@PathVariable Long configId) + { + return AjaxResult.success(configService.selectConfigById(configId)); + } + + /** + * 根据参数键名查询参数值 + */ + @GetMapping(value = "/configKey/{configKey}") + public AjaxResult getConfigKey(@PathVariable String configKey) + { + return AjaxResult.success(configService.selectConfigByKey(configKey)); + } + + /** + * 新增参数配置 + */ + @PreAuthorize("@ss.hasPermi('system:config:add')") + @Log(title = "参数管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysConfig config) + { + if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) + { + return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + config.setCreateBy(SecurityUtils.getUsername()); + return toAjax(configService.insertConfig(config)); + } + + /** + * 修改参数配置 + */ + @PreAuthorize("@ss.hasPermi('system:config:edit')") + @Log(title = "参数管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysConfig config) + { + if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) + { + return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + config.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(configService.updateConfig(config)); + } + + /** + * 删除参数配置 + */ + @PreAuthorize("@ss.hasPermi('system:config:remove')") + @Log(title = "参数管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{configIds}") + public AjaxResult remove(@PathVariable Long[] configIds) + { + return toAjax(configService.deleteConfigByIds(configIds)); + } + + /** + * 清空缓存 + */ + @PreAuthorize("@ss.hasPermi('system:config:remove')") + @Log(title = "参数管理", businessType = BusinessType.CLEAN) + @DeleteMapping("/clearCache") + public AjaxResult clearCache() + { + configService.clearCache(); + return AjaxResult.success(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysDeptController.java b/src/main/java/cn/sliyun/project/system/controller/SysDeptController.java new file mode 100644 index 0000000..0f52617 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysDeptController.java @@ -0,0 +1,164 @@ +package cn.sliyun.project.system.controller; + +import java.util.Iterator; +import java.util.List; + +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.project.system.domain.SysDept; +import cn.sliyun.project.system.service.ISysDeptService; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import cn.sliyun.common.constant.UserConstants; + +/** + * 部门信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/dept") +public class SysDeptController extends BaseController +{ + @Autowired + private ISysDeptService deptService; + + /** + * 获取部门列表 + */ + @PreAuthorize("@ss.hasPermi('system:dept:list')") + @GetMapping("/list") + public AjaxResult list(SysDept dept) + { + List depts = deptService.selectDeptList(dept); + return AjaxResult.success(depts); + } + + /** + * 查询部门列表(排除节点) + */ + @PreAuthorize("@ss.hasPermi('system:dept:list')") + @GetMapping("/list/exclude/{deptId}") + public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) + { + List depts = deptService.selectDeptList(new SysDept()); + Iterator it = depts.iterator(); + while (it.hasNext()) + { + SysDept d = (SysDept) it.next(); + if (d.getDeptId().intValue() == deptId + || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")) + { + it.remove(); + } + } + return AjaxResult.success(depts); + } + + /** + * 根据部门编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:dept:query')") + @GetMapping(value = "/{deptId}") + public AjaxResult getInfo(@PathVariable Long deptId) + { + return AjaxResult.success(deptService.selectDeptById(deptId)); + } + + /** + * 获取部门下拉树列表 + */ + @GetMapping("/treeselect") + public AjaxResult treeselect(SysDept dept) + { + List depts = deptService.selectDeptList(dept); + return AjaxResult.success(deptService.buildDeptTreeSelect(depts)); + } + + /** + * 加载对应角色部门列表树 + */ + @GetMapping(value = "/roleDeptTreeselect/{roleId}") + public AjaxResult roleDeptTreeselect(@PathVariable("roleId") Long roleId) + { + List depts = deptService.selectDeptList(new SysDept()); + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); + ajax.put("depts", deptService.buildDeptTreeSelect(depts)); + return ajax; + } + + /** + * 新增部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:add')") + @Log(title = "部门管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDept dept) + { + if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) + { + return AjaxResult.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + dept.setCreateBy(SecurityUtils.getUsername()); + return toAjax(deptService.insertDept(dept)); + } + + /** + * 修改部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:edit')") + @Log(title = "部门管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDept dept) + { + if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) + { + return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + else if (dept.getParentId().equals(dept.getDeptId())) + { + return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); + } + else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) + && deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0) + { + return AjaxResult.error("该部门包含未停用的子部门!"); + } + dept.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(deptService.updateDept(dept)); + } + + /** + * 删除部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:remove')") + @Log(title = "部门管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{deptId}") + public AjaxResult remove(@PathVariable Long deptId) + { + if (deptService.hasChildByDeptId(deptId)) + { + return AjaxResult.error("存在下级部门,不允许删除"); + } + if (deptService.checkDeptExistUser(deptId)) + { + return AjaxResult.error("部门存在用户,不允许删除"); + } + return toAjax(deptService.deleteDeptById(deptId)); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysDictDataController.java b/src/main/java/cn/sliyun/project/system/controller/SysDictDataController.java new file mode 100644 index 0000000..eeceb04 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysDictDataController.java @@ -0,0 +1,121 @@ +package cn.sliyun.project.system.controller; + +import java.util.ArrayList; +import java.util.List; + +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.poi.ExcelUtil; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.system.domain.SysDictData; +import cn.sliyun.project.system.service.ISysDictDataService; +import cn.sliyun.project.system.service.ISysDictTypeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据字典信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/dict/data") +public class SysDictDataController extends BaseController +{ + @Autowired + private ISysDictDataService dictDataService; + + @Autowired + private ISysDictTypeService dictTypeService; + + @PreAuthorize("@ss.hasPermi('system:dict:list')") + @GetMapping("/list") + public TableDataInfo list(SysDictData dictData) + { + startPage(); + List list = dictDataService.selectDictDataList(dictData); + return getDataTable(list); + } + + @Log(title = "字典数据", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:dict:export')") + @GetMapping("/export") + public AjaxResult export(SysDictData dictData) + { + List list = dictDataService.selectDictDataList(dictData); + ExcelUtil util = new ExcelUtil(SysDictData.class); + return util.exportExcel(list, "字典数据"); + } + + /** + * 查询字典数据详细 + */ + @PreAuthorize("@ss.hasPermi('system:dict:query')") + @GetMapping(value = "/{dictCode}") + public AjaxResult getInfo(@PathVariable Long dictCode) + { + return AjaxResult.success(dictDataService.selectDictDataById(dictCode)); + } + + /** + * 根据字典类型查询字典数据信息 + */ + @GetMapping(value = "/type/{dictType}") + public AjaxResult dictType(@PathVariable String dictType) + { + List data = dictTypeService.selectDictDataByType(dictType); + if (StringUtils.isNull(data)) + { + data = new ArrayList(); + } + return AjaxResult.success(data); + } + + /** + * 新增字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:add')") + @Log(title = "字典数据", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictData dict) + { + dict.setCreateBy(SecurityUtils.getUsername()); + return toAjax(dictDataService.insertDictData(dict)); + } + + /** + * 修改保存字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:edit')") + @Log(title = "字典数据", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDictData dict) + { + dict.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(dictDataService.updateDictData(dict)); + } + + /** + * 删除字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictCodes}") + public AjaxResult remove(@PathVariable Long[] dictCodes) + { + return toAjax(dictDataService.deleteDictDataByIds(dictCodes)); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysDictTypeController.java b/src/main/java/cn/sliyun/project/system/controller/SysDictTypeController.java new file mode 100644 index 0000000..9881600 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysDictTypeController.java @@ -0,0 +1,132 @@ +package cn.sliyun.project.system.controller; + +import java.util.List; + +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.poi.ExcelUtil; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.system.domain.SysDictType; +import cn.sliyun.project.system.service.ISysDictTypeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import cn.sliyun.common.constant.UserConstants; + +/** + * 数据字典信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/dict/type") +public class SysDictTypeController extends BaseController +{ + @Autowired + private ISysDictTypeService dictTypeService; + + @PreAuthorize("@ss.hasPermi('system:dict:list')") + @GetMapping("/list") + public TableDataInfo list(SysDictType dictType) + { + startPage(); + List list = dictTypeService.selectDictTypeList(dictType); + return getDataTable(list); + } + + @Log(title = "字典类型", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:dict:export')") + @GetMapping("/export") + public AjaxResult export(SysDictType dictType) + { + List list = dictTypeService.selectDictTypeList(dictType); + ExcelUtil util = new ExcelUtil(SysDictType.class); + return util.exportExcel(list, "字典类型"); + } + + /** + * 查询字典类型详细 + */ + @PreAuthorize("@ss.hasPermi('system:dict:query')") + @GetMapping(value = "/{dictId}") + public AjaxResult getInfo(@PathVariable Long dictId) + { + return AjaxResult.success(dictTypeService.selectDictTypeById(dictId)); + } + + /** + * 新增字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:add')") + @Log(title = "字典类型", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictType dict) + { + if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) + { + return AjaxResult.error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dict.setCreateBy(SecurityUtils.getUsername()); + return toAjax(dictTypeService.insertDictType(dict)); + } + + /** + * 修改字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:edit')") + @Log(title = "字典类型", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDictType dict) + { + if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) + { + return AjaxResult.error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dict.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(dictTypeService.updateDictType(dict)); + } + + /** + * 删除字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictIds}") + public AjaxResult remove(@PathVariable Long[] dictIds) + { + return toAjax(dictTypeService.deleteDictTypeByIds(dictIds)); + } + + /** + * 清空缓存 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.CLEAN) + @DeleteMapping("/clearCache") + public AjaxResult clearCache() + { + dictTypeService.clearCache(); + return AjaxResult.success(); + } + + /** + * 获取字典选择框列表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List dictTypes = dictTypeService.selectDictTypeAll(); + return AjaxResult.success(dictTypes); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysLoginController.java b/src/main/java/cn/sliyun/project/system/controller/SysLoginController.java new file mode 100644 index 0000000..6a7f868 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysLoginController.java @@ -0,0 +1,95 @@ +package cn.sliyun.project.system.controller; + +import java.util.List; +import java.util.Set; + +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.framework.security.LoginBody; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.SysLoginService; +import cn.sliyun.framework.security.service.SysPermissionService; +import cn.sliyun.framework.security.service.TokenService; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.project.system.domain.SysMenu; +import cn.sliyun.project.system.domain.SysUser; +import cn.sliyun.project.system.service.ISysMenuService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 登录验证 + * + * @author ruoyi + */ +@RestController +public class SysLoginController +{ + @Autowired + private SysLoginService loginService; + + @Autowired + private ISysMenuService menuService; + + @Autowired + private SysPermissionService permissionService; + + @Autowired + private TokenService tokenService; + + /** + * 登录方法 + * + * @param loginBody 登录信息 + * @return 结果 + */ + @PostMapping("/login") + public AjaxResult login(@RequestBody LoginBody loginBody) + { + AjaxResult ajax = AjaxResult.success(); + // 生成令牌 + String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), + loginBody.getUuid()); + ajax.put(Constants.TOKEN, token); + return ajax; + } + + /** + * 获取用户信息 + * + * @return 用户信息 + */ + @GetMapping("getInfo") + public AjaxResult getInfo() + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + SysUser user = loginUser.getUser(); + // 角色集合 + Set roles = permissionService.getRolePermission(user); + // 权限集合 + Set permissions = permissionService.getMenuPermission(user); + AjaxResult ajax = AjaxResult.success(); + ajax.put("user", user); + ajax.put("roles", roles); + ajax.put("permissions", permissions); + return ajax; + } + + /** + * 获取路由信息 + * + * @return 路由信息 + */ + @GetMapping("getRouters") + public AjaxResult getRouters() + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + // 用户信息 + SysUser user = loginUser.getUser(); + List menus = menuService.selectMenuTreeByUserId(user.getUserId()); + return AjaxResult.success(menuService.buildMenus(menus)); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysMenuController.java b/src/main/java/cn/sliyun/project/system/controller/SysMenuController.java new file mode 100644 index 0000000..2bf78ad --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysMenuController.java @@ -0,0 +1,158 @@ +package cn.sliyun.project.system.controller; + +import java.util.List; + +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.constant.UserConstants; +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.TokenService; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.project.system.domain.SysMenu; +import cn.sliyun.project.system.service.ISysMenuService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 菜单信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/menu") +public class SysMenuController extends BaseController +{ + @Autowired + private ISysMenuService menuService; + + @Autowired + private TokenService tokenService; + + /** + * 获取菜单列表 + */ + @PreAuthorize("@ss.hasPermi('system:menu:list')") + @GetMapping("/list") + public AjaxResult list(SysMenu menu) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + Long userId = loginUser.getUser().getUserId(); + List menus = menuService.selectMenuList(menu, userId); + return AjaxResult.success(menus); + } + + /** + * 根据菜单编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:menu:query')") + @GetMapping(value = "/{menuId}") + public AjaxResult getInfo(@PathVariable Long menuId) + { + return AjaxResult.success(menuService.selectMenuById(menuId)); + } + + /** + * 获取菜单下拉树列表 + */ + @GetMapping("/treeselect") + public AjaxResult treeselect(SysMenu menu) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + Long userId = loginUser.getUser().getUserId(); + List menus = menuService.selectMenuList(menu, userId); + return AjaxResult.success(menuService.buildMenuTreeSelect(menus)); + } + + /** + * 加载对应角色菜单列表树 + */ + @GetMapping(value = "/roleMenuTreeselect/{roleId}") + public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + List menus = menuService.selectMenuList(loginUser.getUser().getUserId()); + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); + ajax.put("menus", menuService.buildMenuTreeSelect(menus)); + return ajax; + } + + /** + * 新增菜单 + */ + @PreAuthorize("@ss.hasPermi('system:menu:add')") + @Log(title = "菜单管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysMenu menu) + { + if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) + { + return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) + && !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS)) + { + return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + menu.setCreateBy(SecurityUtils.getUsername()); + return toAjax(menuService.insertMenu(menu)); + } + + /** + * 修改菜单 + */ + @PreAuthorize("@ss.hasPermi('system:menu:edit')") + @Log(title = "菜单管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysMenu menu) + { + if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) + { + return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) + && !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS)) + { + return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + else if (menu.getMenuId().equals(menu.getParentId())) + { + return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); + } + menu.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(menuService.updateMenu(menu)); + } + + /** + * 删除菜单 + */ + @PreAuthorize("@ss.hasPermi('system:menu:remove')") + @Log(title = "菜单管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{menuId}") + public AjaxResult remove(@PathVariable("menuId") Long menuId) + { + if (menuService.hasChildByMenuId(menuId)) + { + return AjaxResult.error("存在子菜单,不允许删除"); + } + if (menuService.checkMenuExistRole(menuId)) + { + return AjaxResult.error("菜单已分配,不允许删除"); + } + return toAjax(menuService.deleteMenuById(menuId)); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/project/system/controller/SysNoticeController.java b/src/main/java/cn/sliyun/project/system/controller/SysNoticeController.java new file mode 100644 index 0000000..d377692 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysNoticeController.java @@ -0,0 +1,93 @@ +package cn.sliyun.project.system.controller; + +import java.util.List; + +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.system.domain.SysNotice; +import cn.sliyun.project.system.service.ISysNoticeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 公告 信息操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/notice") +public class SysNoticeController extends BaseController +{ + @Autowired + private ISysNoticeService noticeService; + + /** + * 获取通知公告列表 + */ + @PreAuthorize("@ss.hasPermi('system:notice:list')") + @GetMapping("/list") + public TableDataInfo list(SysNotice notice) + { + startPage(); + List list = noticeService.selectNoticeList(notice); + return getDataTable(list); + } + + /** + * 根据通知公告编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:notice:query')") + @GetMapping(value = "/{noticeId}") + public AjaxResult getInfo(@PathVariable Long noticeId) + { + return AjaxResult.success(noticeService.selectNoticeById(noticeId)); + } + + /** + * 新增通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:add')") + @Log(title = "通知公告", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysNotice notice) + { + notice.setCreateBy(SecurityUtils.getUsername()); + return toAjax(noticeService.insertNotice(notice)); + } + + /** + * 修改通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:edit')") + @Log(title = "通知公告", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysNotice notice) + { + notice.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(noticeService.updateNotice(notice)); + } + + /** + * 删除通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:remove')") + @Log(title = "通知公告", businessType = BusinessType.DELETE) + @DeleteMapping("/{noticeIds}") + public AjaxResult remove(@PathVariable Long[] noticeIds) + { + return toAjax(noticeService.deleteNoticeByIds(noticeIds)); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysPostController.java b/src/main/java/cn/sliyun/project/system/controller/SysPostController.java new file mode 100644 index 0000000..8f8fcfe --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysPostController.java @@ -0,0 +1,131 @@ +package cn.sliyun.project.system.controller; + +import java.util.List; + +import cn.sliyun.common.constant.UserConstants; +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.poi.ExcelUtil; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.system.domain.SysPost; +import cn.sliyun.project.system.service.ISysPostService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 岗位信息操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/post") +public class SysPostController extends BaseController +{ + @Autowired + private ISysPostService postService; + + /** + * 获取岗位列表 + */ + @PreAuthorize("@ss.hasPermi('system:post:list')") + @GetMapping("/list") + public TableDataInfo list(SysPost post) + { + startPage(); + List list = postService.selectPostList(post); + return getDataTable(list); + } + + @Log(title = "岗位管理", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:post:export')") + @GetMapping("/export") + public AjaxResult export(SysPost post) + { + List list = postService.selectPostList(post); + ExcelUtil util = new ExcelUtil(SysPost.class); + return util.exportExcel(list, "岗位数据"); + } + + /** + * 根据岗位编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:post:query')") + @GetMapping(value = "/{postId}") + public AjaxResult getInfo(@PathVariable Long postId) + { + return AjaxResult.success(postService.selectPostById(postId)); + } + + /** + * 新增岗位 + */ + @PreAuthorize("@ss.hasPermi('system:post:add')") + @Log(title = "岗位管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysPost post) + { + if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) + { + return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) + { + return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + post.setCreateBy(SecurityUtils.getUsername()); + return toAjax(postService.insertPost(post)); + } + + /** + * 修改岗位 + */ + @PreAuthorize("@ss.hasPermi('system:post:edit')") + @Log(title = "岗位管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysPost post) + { + if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) + { + return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) + { + return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + post.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(postService.updatePost(post)); + } + + /** + * 删除岗位 + */ + @PreAuthorize("@ss.hasPermi('system:post:remove')") + @Log(title = "岗位管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{postIds}") + public AjaxResult remove(@PathVariable Long[] postIds) + { + return toAjax(postService.deletePostByIds(postIds)); + } + + /** + * 获取岗位选择框列表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List posts = postService.selectPostAll(); + return AjaxResult.success(posts); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysProfileController.java b/src/main/java/cn/sliyun/project/system/controller/SysProfileController.java new file mode 100644 index 0000000..3b2cbed --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysProfileController.java @@ -0,0 +1,128 @@ +package cn.sliyun.project.system.controller; + +import java.io.IOException; + +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.file.FileUploadUtils; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.config.RuoYiConfig; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.TokenService; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.project.system.domain.SysUser; +import cn.sliyun.project.system.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 个人信息 业务处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/user/profile") +public class SysProfileController extends BaseController +{ + @Autowired + private ISysUserService userService; + + @Autowired + private TokenService tokenService; + + /** + * 个人信息 + */ + @GetMapping + public AjaxResult profile() + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + SysUser user = loginUser.getUser(); + AjaxResult ajax = AjaxResult.success(user); + ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername())); + ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername())); + return ajax; + } + + /** + * 修改用户 + */ + @Log(title = "个人信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult updateProfile(@RequestBody SysUser user) + { + if (userService.updateUserProfile(user) > 0) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + // 更新缓存用户信息 + loginUser.getUser().setNickName(user.getNickName()); + loginUser.getUser().setPhonenumber(user.getPhonenumber()); + loginUser.getUser().setEmail(user.getEmail()); + loginUser.getUser().setSex(user.getSex()); + tokenService.setLoginUser(loginUser); + return AjaxResult.success(); + } + return AjaxResult.error("修改个人信息异常,请联系管理员"); + } + + /** + * 重置密码 + */ + @Log(title = "个人信息", businessType = BusinessType.UPDATE) + @PutMapping("/updatePwd") + public AjaxResult updatePwd(String oldPassword, String newPassword) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + String userName = loginUser.getUsername(); + String password = loginUser.getPassword(); + if (!SecurityUtils.matchesPassword(oldPassword, password)) + { + return AjaxResult.error("修改密码失败,旧密码错误"); + } + if (SecurityUtils.matchesPassword(newPassword, password)) + { + return AjaxResult.error("新密码不能与旧密码相同"); + } + if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) + { + // 更新缓存用户密码 + loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword)); + tokenService.setLoginUser(loginUser); + return AjaxResult.success(); + } + return AjaxResult.error("修改密码异常,请联系管理员"); + } + + /** + * 头像上传 + */ + @Log(title = "用户头像", businessType = BusinessType.UPDATE) + @PostMapping("/avatar") + public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException + { + if (!file.isEmpty()) + { + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file); + if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) + { + AjaxResult ajax = AjaxResult.success(); + ajax.put("imgUrl", avatar); + // 更新缓存用户头像 + loginUser.getUser().setAvatar(avatar); + tokenService.setLoginUser(loginUser); + return ajax; + } + } + return AjaxResult.error("上传图片异常,请联系管理员"); + } +} diff --git a/src/main/java/cn/sliyun/project/system/controller/SysRoleController.java b/src/main/java/cn/sliyun/project/system/controller/SysRoleController.java new file mode 100644 index 0000000..994f4eb --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysRoleController.java @@ -0,0 +1,183 @@ +package cn.sliyun.project.system.controller; + +import java.util.List; + +import cn.sliyun.common.constant.UserConstants; +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.poi.ExcelUtil; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.SysPermissionService; +import cn.sliyun.framework.security.service.TokenService; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.system.domain.SysRole; +import cn.sliyun.project.system.service.ISysRoleService; +import cn.sliyun.project.system.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 角色信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/role") +public class SysRoleController extends BaseController +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private TokenService tokenService; + + @Autowired + private SysPermissionService permissionService; + + @Autowired + private ISysUserService userService; + + @PreAuthorize("@ss.hasPermi('system:role:list')") + @GetMapping("/list") + public TableDataInfo list(SysRole role) + { + startPage(); + List list = roleService.selectRoleList(role); + return getDataTable(list); + } + + @Log(title = "角色管理", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:role:export')") + @GetMapping("/export") + public AjaxResult export(SysRole role) + { + List list = roleService.selectRoleList(role); + ExcelUtil util = new ExcelUtil(SysRole.class); + return util.exportExcel(list, "角色数据"); + } + + /** + * 根据角色编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping(value = "/{roleId}") + public AjaxResult getInfo(@PathVariable Long roleId) + { + return AjaxResult.success(roleService.selectRoleById(roleId)); + } + + /** + * 新增角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:add')") + @Log(title = "角色管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysRole role) + { + if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) + { + return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) + { + return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + role.setCreateBy(SecurityUtils.getUsername()); + return toAjax(roleService.insertRole(role)); + + } + + /** + * 修改保存角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) + { + return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) + { + return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + role.setUpdateBy(SecurityUtils.getUsername()); + + if (roleService.updateRole(role) > 0) + { + // 更新缓存用户权限 + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) + { + loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser())); + loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName())); + tokenService.setLoginUser(loginUser); + } + return AjaxResult.success(); + } + return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员"); + } + + /** + * 修改保存数据权限 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping("/dataScope") + public AjaxResult dataScope(@RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + return toAjax(roleService.authDataScope(role)); + } + + /** + * 状态修改 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + role.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(roleService.updateRoleStatus(role)); + } + + /** + * 删除角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:remove')") + @Log(title = "角色管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{roleIds}") + public AjaxResult remove(@PathVariable Long[] roleIds) + { + return toAjax(roleService.deleteRoleByIds(roleIds)); + } + + /** + * 获取角色选择框列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + return AjaxResult.success(roleService.selectRoleAll()); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/project/system/controller/SysUserController.java b/src/main/java/cn/sliyun/project/system/controller/SysUserController.java new file mode 100644 index 0000000..42af46c --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/controller/SysUserController.java @@ -0,0 +1,206 @@ +package cn.sliyun.project.system.controller; + +import java.util.List; +import java.util.stream.Collectors; + +import cn.sliyun.common.constant.UserConstants; +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.ServletUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.poi.ExcelUtil; +import cn.sliyun.framework.aspectj.lang.annotation.Log; +import cn.sliyun.framework.aspectj.lang.enums.BusinessType; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.framework.security.service.TokenService; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import cn.sliyun.framework.web.page.TableDataInfo; +import cn.sliyun.project.system.domain.SysRole; +import cn.sliyun.project.system.domain.SysUser; +import cn.sliyun.project.system.service.ISysPostService; +import cn.sliyun.project.system.service.ISysRoleService; +import cn.sliyun.project.system.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 用户信息 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/user") +public class SysUserController extends BaseController +{ + @Autowired + private ISysUserService userService; + + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysPostService postService; + + @Autowired + private TokenService tokenService; + + /** + * 获取用户列表 + */ + @PreAuthorize("@ss.hasPermi('system:user:list')") + @GetMapping("/list") + public TableDataInfo list(SysUser user) + { + startPage(); + List list = userService.selectUserList(user); + return getDataTable(list); + } + + @Log(title = "用户管理", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:user:export')") + @GetMapping("/export") + public AjaxResult export(SysUser user) + { + List list = userService.selectUserList(user); + ExcelUtil util = new ExcelUtil(SysUser.class); + return util.exportExcel(list, "用户数据"); + } + + @Log(title = "用户管理", businessType = BusinessType.IMPORT) + @PreAuthorize("@ss.hasPermi('system:user:import')") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception + { + ExcelUtil util = new ExcelUtil(SysUser.class); + List userList = util.importExcel(file.getInputStream()); + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); + String operName = loginUser.getUsername(); + String message = userService.importUser(userList, updateSupport, operName); + return AjaxResult.success(message); + } + + @GetMapping("/importTemplate") + public AjaxResult importTemplate() + { + ExcelUtil util = new ExcelUtil(SysUser.class); + return util.importTemplateExcel("用户数据"); + } + + /** + * 根据用户编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:user:query')") + @GetMapping(value = { "/", "/{userId}" }) + public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) + { + AjaxResult ajax = AjaxResult.success(); + List roles = roleService.selectRoleAll(); + ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + ajax.put("posts", postService.selectPostAll()); + if (StringUtils.isNotNull(userId)) + { + ajax.put(AjaxResult.DATA_TAG, userService.selectUserById(userId)); + ajax.put("postIds", postService.selectPostListByUserId(userId)); + ajax.put("roleIds", roleService.selectRoleListByUserId(userId)); + } + return ajax; + } + + /** + * 新增用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:add')") + @Log(title = "用户管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysUser user) + { + if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName()))) + { + return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); + } + else if (StringUtils.isNotEmpty(user.getPhonenumber()) + && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) + { + return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) + && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) + { + return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setCreateBy(SecurityUtils.getUsername()); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + return toAjax(userService.insertUser(user)); + } + + /** + * 修改用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysUser user) + { + userService.checkUserAllowed(user); + if (StringUtils.isNotEmpty(user.getPhonenumber()) + && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) + { + return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) + && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) + { + return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(userService.updateUser(user)); + } + + /** + * 删除用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:remove')") + @Log(title = "用户管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + return toAjax(userService.deleteUserByIds(userIds)); + } + + /** + * 重置密码 + */ + @PreAuthorize("@ss.hasPermi('system:user:resetPwd')") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/resetPwd") + public AjaxResult resetPwd(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + user.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(userService.resetPwd(user)); + } + + /** + * 状态修改 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + user.setUpdateBy(SecurityUtils.getUsername()); + return toAjax(userService.updateUserStatus(user)); + } +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/project/system/domain/SysConfig.java b/src/main/java/cn/sliyun/project/system/domain/SysConfig.java new file mode 100644 index 0000000..14875e2 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysConfig.java @@ -0,0 +1,111 @@ +package cn.sliyun.project.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 参数配置表 sys_config + * + * @author ruoyi + */ +public class SysConfig extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 参数主键 */ + @Excel(name = "参数主键", cellType = Excel.ColumnType.NUMERIC) + private Long configId; + + /** 参数名称 */ + @Excel(name = "参数名称") + private String configName; + + /** 参数键名 */ + @Excel(name = "参数键名") + private String configKey; + + /** 参数键值 */ + @Excel(name = "参数键值") + private String configValue; + + /** 系统内置(Y是 N否) */ + @Excel(name = "系统内置", readConverterExp = "Y=是,N=否") + private String configType; + + public Long getConfigId() + { + return configId; + } + + public void setConfigId(Long configId) + { + this.configId = configId; + } + + @NotBlank(message = "参数名称不能为空") + @Size(min = 0, max = 100, message = "参数名称不能超过100个字符") + public String getConfigName() + { + return configName; + } + + public void setConfigName(String configName) + { + this.configName = configName; + } + + @NotBlank(message = "参数键名长度不能为空") + @Size(min = 0, max = 100, message = "参数键名长度不能超过100个字符") + public String getConfigKey() + { + return configKey; + } + + public void setConfigKey(String configKey) + { + this.configKey = configKey; + } + + @NotBlank(message = "参数键值不能为空") + @Size(min = 0, max = 500, message = "参数键值长度不能超过500个字符") + public String getConfigValue() + { + return configValue; + } + + public void setConfigValue(String configValue) + { + this.configValue = configValue; + } + + public String getConfigType() + { + return configType; + } + + public void setConfigType(String configType) + { + this.configType = configType; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("configId", getConfigId()) + .append("configName", getConfigName()) + .append("configKey", getConfigKey()) + .append("configValue", getConfigValue()) + .append("configType", getConfigType()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysDept.java b/src/main/java/cn/sliyun/project/system/domain/SysDept.java new file mode 100644 index 0000000..30a9bd8 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysDept.java @@ -0,0 +1,203 @@ +package cn.sliyun.project.system.domain; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 部门表 sys_dept + * + * @author ruoyi + */ +public class SysDept extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 部门ID */ + private Long deptId; + + /** 父部门ID */ + private Long parentId; + + /** 祖级列表 */ + private String ancestors; + + /** 部门名称 */ + private String deptName; + + /** 显示顺序 */ + private String orderNum; + + /** 负责人 */ + private String leader; + + /** 联系电话 */ + private String phone; + + /** 邮箱 */ + private String email; + + /** 部门状态:0正常,1停用 */ + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 父部门名称 */ + private String parentName; + + /** 子部门 */ + private List children = new ArrayList(); + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public String getAncestors() + { + return ancestors; + } + + public void setAncestors(String ancestors) + { + this.ancestors = ancestors; + } + + @NotBlank(message = "部门名称不能为空") + @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + @NotBlank(message = "显示顺序不能为空") + public String getOrderNum() + { + return orderNum; + } + + public void setOrderNum(String orderNum) + { + this.orderNum = orderNum; + } + + public String getLeader() + { + return leader; + } + + public void setLeader(String leader) + { + this.leader = leader; + } + + @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") + public String getPhone() + { + return phone; + } + + public void setPhone(String phone) + { + this.phone = phone; + } + + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("deptId", getDeptId()) + .append("parentId", getParentId()) + .append("ancestors", getAncestors()) + .append("deptName", getDeptName()) + .append("orderNum", getOrderNum()) + .append("leader", getLeader()) + .append("phone", getPhone()) + .append("email", getEmail()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysDictData.java b/src/main/java/cn/sliyun/project/system/domain/SysDictData.java new file mode 100644 index 0000000..73822f6 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysDictData.java @@ -0,0 +1,176 @@ +package cn.sliyun.project.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import cn.sliyun.common.constant.UserConstants; + +/** + * 字典数据表 sys_dict_data + * + * @author ruoyi + */ +public class SysDictData extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 字典编码 */ + @Excel(name = "字典编码", cellType = Excel.ColumnType.NUMERIC) + private Long dictCode; + + /** 字典排序 */ + @Excel(name = "字典排序", cellType = Excel.ColumnType.NUMERIC) + private Long dictSort; + + /** 字典标签 */ + @Excel(name = "字典标签") + private String dictLabel; + + /** 字典键值 */ + @Excel(name = "字典键值") + private String dictValue; + + /** 字典类型 */ + @Excel(name = "字典类型") + private String dictType; + + /** 样式属性(其他样式扩展) */ + private String cssClass; + + /** 表格字典样式 */ + private String listClass; + + /** 是否默认(Y是 N否) */ + @Excel(name = "是否默认", readConverterExp = "Y=是,N=否") + private String isDefault; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + public Long getDictCode() + { + return dictCode; + } + + public void setDictCode(Long dictCode) + { + this.dictCode = dictCode; + } + + public Long getDictSort() + { + return dictSort; + } + + public void setDictSort(Long dictSort) + { + this.dictSort = dictSort; + } + + @NotBlank(message = "字典标签不能为空") + @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") + public String getDictLabel() + { + return dictLabel; + } + + public void setDictLabel(String dictLabel) + { + this.dictLabel = dictLabel; + } + + @NotBlank(message = "字典键值不能为空") + @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") + public String getDictValue() + { + return dictValue; + } + + public void setDictValue(String dictValue) + { + this.dictValue = dictValue; + } + + @NotBlank(message = "字典类型不能为空") + @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") + public String getCssClass() + { + return cssClass; + } + + public void setCssClass(String cssClass) + { + this.cssClass = cssClass; + } + + public String getListClass() + { + return listClass; + } + + public void setListClass(String listClass) + { + this.listClass = listClass; + } + + public boolean getDefault() + { + return UserConstants.YES.equals(this.isDefault) ? true : false; + } + + public String getIsDefault() + { + return isDefault; + } + + public void setIsDefault(String isDefault) + { + this.isDefault = isDefault; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dictCode", getDictCode()) + .append("dictSort", getDictSort()) + .append("dictLabel", getDictLabel()) + .append("dictValue", getDictValue()) + .append("dictType", getDictType()) + .append("cssClass", getCssClass()) + .append("listClass", getListClass()) + .append("isDefault", getIsDefault()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysDictType.java b/src/main/java/cn/sliyun/project/system/domain/SysDictType.java new file mode 100644 index 0000000..7cef6f2 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysDictType.java @@ -0,0 +1,94 @@ +package cn.sliyun.project.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 字典类型表 sys_dict_type + * + * @author ruoyi + */ +public class SysDictType extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 字典主键 */ + @Excel(name = "字典主键", cellType = Excel.ColumnType.NUMERIC) + private Long dictId; + + /** 字典名称 */ + @Excel(name = "字典名称") + private String dictName; + + /** 字典类型 */ + @Excel(name = "字典类型") + private String dictType; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + public Long getDictId() + { + return dictId; + } + + public void setDictId(Long dictId) + { + this.dictId = dictId; + } + + @NotBlank(message = "字典名称不能为空") + @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") + public String getDictName() + { + return dictName; + } + + public void setDictName(String dictName) + { + this.dictName = dictName; + } + + @NotBlank(message = "字典类型不能为空") + @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dictId", getDictId()) + .append("dictName", getDictName()) + .append("dictType", getDictType()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysMenu.java b/src/main/java/cn/sliyun/project/system/domain/SysMenu.java new file mode 100644 index 0000000..4f872e4 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysMenu.java @@ -0,0 +1,246 @@ +package cn.sliyun.project.system.domain; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 菜单权限表 sys_menu + * + * @author ruoyi + */ +public class SysMenu extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 菜单ID */ + private Long menuId; + + /** 菜单名称 */ + private String menuName; + + /** 父菜单名称 */ + private String parentName; + + /** 父菜单ID */ + private Long parentId; + + /** 显示顺序 */ + private String orderNum; + + /** 路由地址 */ + private String path; + + /** 组件路径 */ + private String component; + + /** 是否为外链(0是 1否) */ + private String isFrame; + + /** 是否缓存(0缓存 1不缓存) */ + private String isCache; + + /** 类型(M目录 C菜单 F按钮) */ + private String menuType; + + /** 显示状态(0显示 1隐藏) */ + private String visible; + + /** 菜单状态(0显示 1隐藏) */ + private String status; + + /** 权限字符串 */ + private String perms; + + /** 菜单图标 */ + private String icon; + + /** 子菜单 */ + private List children = new ArrayList(); + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @NotBlank(message = "菜单名称不能为空") + @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符") + public String getMenuName() + { + return menuName; + } + + public void setMenuName(String menuName) + { + this.menuName = menuName; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + @NotBlank(message = "显示顺序不能为空") + public String getOrderNum() + { + return orderNum; + } + + public void setOrderNum(String orderNum) + { + this.orderNum = orderNum; + } + + @Size(min = 0, max = 200, message = "路由地址不能超过200个字符") + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + @Size(min = 0, max = 200, message = "组件路径不能超过255个字符") + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getIsFrame() + { + return isFrame; + } + + public void setIsFrame(String isFrame) + { + this.isFrame = isFrame; + } + + public String getIsCache() + { + return isCache; + } + + public void setIsCache(String isCache) + { + this.isCache = isCache; + } + + @NotBlank(message = "菜单类型不能为空") + public String getMenuType() + { + return menuType; + } + + public void setMenuType(String menuType) + { + this.menuType = menuType; + } + + public String getVisible() + { + return visible; + } + + public void setVisible(String visible) + { + this.visible = visible; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符") + public String getPerms() + { + return perms; + } + + public void setPerms(String perms) + { + this.perms = perms; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("menuId", getMenuId()) + .append("menuName", getMenuName()) + .append("parentId", getParentId()) + .append("orderNum", getOrderNum()) + .append("path", getPath()) + .append("component", getComponent()) + .append("isFrame", getIsFrame()) + .append("IsCache", getIsCache()) + .append("menuType", getMenuType()) + .append("visible", getVisible()) + .append("status ", getStatus()) + .append("perms", getPerms()) + .append("icon", getIcon()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysNotice.java b/src/main/java/cn/sliyun/project/system/domain/SysNotice.java new file mode 100644 index 0000000..514120e --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysNotice.java @@ -0,0 +1,101 @@ +package cn.sliyun.project.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 通知公告表 sys_notice + * + * @author ruoyi + */ +public class SysNotice extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 公告ID */ + private Long noticeId; + + /** 公告标题 */ + private String noticeTitle; + + /** 公告类型(1通知 2公告) */ + private String noticeType; + + /** 公告内容 */ + private String noticeContent; + + /** 公告状态(0正常 1关闭) */ + private String status; + + public Long getNoticeId() + { + return noticeId; + } + + public void setNoticeId(Long noticeId) + { + this.noticeId = noticeId; + } + + public void setNoticeTitle(String noticeTitle) + { + this.noticeTitle = noticeTitle; + } + + @NotBlank(message = "公告标题不能为空") + @Size(min = 0, max = 50, message = "公告标题不能超过50个字符") + public String getNoticeTitle() + { + return noticeTitle; + } + + public void setNoticeType(String noticeType) + { + this.noticeType = noticeType; + } + + public String getNoticeType() + { + return noticeType; + } + + public void setNoticeContent(String noticeContent) + { + this.noticeContent = noticeContent; + } + + public String getNoticeContent() + { + return noticeContent; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("noticeId", getNoticeId()) + .append("noticeTitle", getNoticeTitle()) + .append("noticeType", getNoticeType()) + .append("noticeContent", getNoticeContent()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysPost.java b/src/main/java/cn/sliyun/project/system/domain/SysPost.java new file mode 100644 index 0000000..99c2681 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysPost.java @@ -0,0 +1,123 @@ +package cn.sliyun.project.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 岗位表 sys_post + * + * @author ruoyi + */ +public class SysPost extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 岗位序号 */ + @Excel(name = "岗位序号", cellType = Excel.ColumnType.NUMERIC) + private Long postId; + + /** 岗位编码 */ + @Excel(name = "岗位编码") + private String postCode; + + /** 岗位名称 */ + @Excel(name = "岗位名称") + private String postName; + + /** 岗位排序 */ + @Excel(name = "岗位排序") + private String postSort; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 用户是否存在此岗位标识 默认不存在 */ + private boolean flag = false; + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @NotBlank(message = "岗位编码不能为空") + @Size(min = 0, max = 64, message = "岗位编码长度不能超过64个字符") + public String getPostCode() + { + return postCode; + } + + public void setPostCode(String postCode) + { + this.postCode = postCode; + } + + @NotBlank(message = "岗位名称不能为空") + @Size(min = 0, max = 50, message = "岗位名称长度不能超过50个字符") + public String getPostName() + { + return postName; + } + + public void setPostName(String postName) + { + this.postName = postName; + } + + @NotBlank(message = "显示顺序不能为空") + public String getPostSort() + { + return postSort; + } + + public void setPostSort(String postSort) + { + this.postSort = postSort; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("postId", getPostId()) + .append("postCode", getPostCode()) + .append("postName", getPostName()) + .append("postSort", getPostSort()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysRole.java b/src/main/java/cn/sliyun/project/system/domain/SysRole.java new file mode 100644 index 0000000..8a9f00b --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysRole.java @@ -0,0 +1,226 @@ +package cn.sliyun.project.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色表 sys_role + * + * @author ruoyi + */ +public class SysRole extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 角色ID */ + @Excel(name = "角色序号", cellType = Excel.ColumnType.NUMERIC) + private Long roleId; + + /** 角色名称 */ + @Excel(name = "角色名称") + private String roleName; + + /** 角色权限 */ + @Excel(name = "角色权限") + private String roleKey; + + /** 角色排序 */ + @Excel(name = "角色排序") + private String roleSort; + + /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限) */ + @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限") + private String dataScope; + + /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ + private boolean menuCheckStrictly; + + /** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */ + private boolean deptCheckStrictly; + + /** 角色状态(0正常 1停用) */ + @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 用户是否存在此角色标识 默认不存在 */ + private boolean flag = false; + + /** 菜单组 */ + private Long[] menuIds; + + /** 部门组(数据权限) */ + private Long[] deptIds; + + public SysRole() + { + + } + + public SysRole(Long roleId) + { + this.roleId = roleId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public boolean isAdmin() + { + return isAdmin(this.roleId); + } + + public static boolean isAdmin(Long roleId) + { + return roleId != null && 1L == roleId; + } + + @NotBlank(message = "角色名称不能为空") + @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符") + public String getRoleName() + { + return roleName; + } + + public void setRoleName(String roleName) + { + this.roleName = roleName; + } + + @NotBlank(message = "权限字符不能为空") + @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符") + public String getRoleKey() + { + return roleKey; + } + + public void setRoleKey(String roleKey) + { + this.roleKey = roleKey; + } + + @NotBlank(message = "显示顺序不能为空") + public String getRoleSort() + { + return roleSort; + } + + public void setRoleSort(String roleSort) + { + this.roleSort = roleSort; + } + + public String getDataScope() + { + return dataScope; + } + + public void setDataScope(String dataScope) + { + this.dataScope = dataScope; + } + + public boolean isMenuCheckStrictly() + { + return menuCheckStrictly; + } + + public void setMenuCheckStrictly(boolean menuCheckStrictly) + { + this.menuCheckStrictly = menuCheckStrictly; + } + + public boolean isDeptCheckStrictly() + { + return deptCheckStrictly; + } + + public void setDeptCheckStrictly(boolean deptCheckStrictly) + { + this.deptCheckStrictly = deptCheckStrictly; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + public Long[] getMenuIds() + { + return menuIds; + } + + public void setMenuIds(Long[] menuIds) + { + this.menuIds = menuIds; + } + + public Long[] getDeptIds() + { + return deptIds; + } + + public void setDeptIds(Long[] deptIds) + { + this.deptIds = deptIds; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("roleName", getRoleName()) + .append("roleKey", getRoleKey()) + .append("roleSort", getRoleSort()) + .append("dataScope", getDataScope()) + .append("menuCheckStrictly", isMenuCheckStrictly()) + .append("deptCheckStrictly", isDeptCheckStrictly()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysRoleDept.java b/src/main/java/cn/sliyun/project/system/domain/SysRoleDept.java new file mode 100644 index 0000000..3507657 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysRoleDept.java @@ -0,0 +1,46 @@ +package cn.sliyun.project.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和部门关联 sys_role_dept + * + * @author ruoyi + */ +public class SysRoleDept +{ + /** 角色ID */ + private Long roleId; + + /** 部门ID */ + private Long deptId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("deptId", getDeptId()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysRoleMenu.java b/src/main/java/cn/sliyun/project/system/domain/SysRoleMenu.java new file mode 100644 index 0000000..59df4fb --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysRoleMenu.java @@ -0,0 +1,46 @@ +package cn.sliyun.project.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和菜单关联 sys_role_menu + * + * @author ruoyi + */ +public class SysRoleMenu +{ + /** 角色ID */ + private Long roleId; + + /** 菜单ID */ + private Long menuId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("menuId", getMenuId()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysUser.java b/src/main/java/cn/sliyun/project/system/domain/SysUser.java new file mode 100644 index 0000000..87689e7 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysUser.java @@ -0,0 +1,327 @@ +package cn.sliyun.project.system.domain; + +import java.util.Date; +import java.util.List; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +import cn.sliyun.framework.aspectj.lang.annotation.Excel; +import cn.sliyun.framework.aspectj.lang.annotation.Excels; +import cn.sliyun.framework.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * 用户对象 sys_user + * + * @author ruoyi + */ +public class SysUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户ID */ + @Excel(name = "用户序号", cellType = Excel.ColumnType.NUMERIC, prompt = "用户编号") + private Long userId; + + /** 部门ID */ + @Excel(name = "部门编号", type = Excel.Type.IMPORT) + private Long deptId; + + /** 用户账号 */ + @Excel(name = "登录名称") + private String userName; + + /** 用户昵称 */ + @Excel(name = "用户名称") + private String nickName; + + /** 用户邮箱 */ + @Excel(name = "用户邮箱") + private String email; + + /** 手机号码 */ + @Excel(name = "手机号码") + private String phonenumber; + + /** 用户性别 */ + @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") + private String sex; + + /** 用户头像 */ + private String avatar; + + /** 密码 */ + private String password; + + /** 盐加密 */ + private String salt; + + /** 帐号状态(0正常 1停用) */ + @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 最后登录IP */ + @Excel(name = "最后登录IP", type = Excel.Type.EXPORT) + private String loginIp; + + /** 最后登录时间 */ + @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Excel.Type.EXPORT) + private Date loginDate; + + /** 部门对象 */ + @Excels({ + @Excel(name = "部门名称", targetAttr = "deptName", type = Excel.Type.EXPORT), + @Excel(name = "部门负责人", targetAttr = "leader", type = Excel.Type.EXPORT) + }) + private SysDept dept; + + /** 角色对象 */ + private List roles; + + /** 角色组 */ + private Long[] roleIds; + + /** 岗位组 */ + private Long[] postIds; + + public SysUser() + { + + } + + public SysUser(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public boolean isAdmin() + { + return isAdmin(this.userId); + } + + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") + public String getNickName() + { + return nickName; + } + + public void setNickName(String nickName) + { + this.nickName = nickName; + } + + @NotBlank(message = "用户账号不能为空") + @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") + public String getPhonenumber() + { + return phonenumber; + } + + public void setPhonenumber(String phonenumber) + { + this.phonenumber = phonenumber; + } + + public String getSex() + { + return sex; + } + + public void setSex(String sex) + { + this.sex = sex; + } + + public String getAvatar() + { + return avatar; + } + + public void setAvatar(String avatar) + { + this.avatar = avatar; + } + + @JsonIgnore + @JsonProperty + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getSalt() + { + return salt; + } + + public void setSalt(String salt) + { + this.salt = salt; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getLoginIp() + { + return loginIp; + } + + public void setLoginIp(String loginIp) + { + this.loginIp = loginIp; + } + + public Date getLoginDate() + { + return loginDate; + } + + public void setLoginDate(Date loginDate) + { + this.loginDate = loginDate; + } + + public SysDept getDept() + { + return dept; + } + + public void setDept(SysDept dept) + { + this.dept = dept; + } + + public List getRoles() + { + return roles; + } + + public void setRoles(List roles) + { + this.roles = roles; + } + + public Long[] getRoleIds() + { + return roleIds; + } + + public void setRoleIds(Long[] roleIds) + { + this.roleIds = roleIds; + } + + public Long[] getPostIds() + { + return postIds; + } + + public void setPostIds(Long[] postIds) + { + this.postIds = postIds; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("deptId", getDeptId()) + .append("userName", getUserName()) + .append("nickName", getNickName()) + .append("email", getEmail()) + .append("phonenumber", getPhonenumber()) + .append("sex", getSex()) + .append("avatar", getAvatar()) + .append("password", getPassword()) + .append("salt", getSalt()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("loginIp", getLoginIp()) + .append("loginDate", getLoginDate()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("dept", getDept()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysUserPost.java b/src/main/java/cn/sliyun/project/system/domain/SysUserPost.java new file mode 100644 index 0000000..545a9c2 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysUserPost.java @@ -0,0 +1,46 @@ +package cn.sliyun.project.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和岗位关联 sys_user_post + * + * @author ruoyi + */ +public class SysUserPost +{ + /** 用户ID */ + private Long userId; + + /** 岗位ID */ + private Long postId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("postId", getPostId()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/SysUserRole.java b/src/main/java/cn/sliyun/project/system/domain/SysUserRole.java new file mode 100644 index 0000000..170bb70 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/SysUserRole.java @@ -0,0 +1,46 @@ +package cn.sliyun.project.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和角色关联 sys_user_role + * + * @author ruoyi + */ +public class SysUserRole +{ + /** 用户ID */ + private Long userId; + + /** 角色ID */ + private Long roleId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("roleId", getRoleId()) + .toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/vo/MetaVo.java b/src/main/java/cn/sliyun/project/system/domain/vo/MetaVo.java new file mode 100644 index 0000000..95c7fbe --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/vo/MetaVo.java @@ -0,0 +1,71 @@ +package cn.sliyun.project.system.domain.vo; + +/** + * 路由显示信息 + * + * @author ruoyi + */ +public class MetaVo +{ + /** + * 设置该路由在侧边栏和面包屑中展示的名字 + */ + private String title; + + /** + * 设置该路由的图标,对应路径src/assets/icons/svg + */ + private String icon; + + /** + * 设置为true,则不会被 缓存 + */ + private boolean noCache; + + public MetaVo() + { + } + + public MetaVo(String title, String icon) + { + this.title = title; + this.icon = icon; + } + + public MetaVo(String title, String icon, boolean noCache) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + } + + public boolean isNoCache() + { + return noCache; + } + + public void setNoCache(boolean noCache) + { + this.noCache = noCache; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } +} diff --git a/src/main/java/cn/sliyun/project/system/domain/vo/RouterVo.java b/src/main/java/cn/sliyun/project/system/domain/vo/RouterVo.java new file mode 100644 index 0000000..6177362 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/domain/vo/RouterVo.java @@ -0,0 +1,133 @@ +package cn.sliyun.project.system.domain.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; + +/** + * 路由配置信息 + * + * @author ruoyi + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class RouterVo +{ + /** + * 路由名字 + */ + private String name; + + /** + * 路由地址 + */ + private String path; + + /** + * 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现 + */ + private boolean hidden; + + /** + * 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + */ + private String redirect; + + /** + * 组件地址 + */ + private String component; + + /** + * 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + */ + private Boolean alwaysShow; + + /** + * 其他元素 + */ + private MetaVo meta; + + /** + * 子路由 + */ + private List children; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public boolean getHidden() + { + return hidden; + } + + public void setHidden(boolean hidden) + { + this.hidden = hidden; + } + + public String getRedirect() + { + return redirect; + } + + public void setRedirect(String redirect) + { + this.redirect = redirect; + } + + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public Boolean getAlwaysShow() + { + return alwaysShow; + } + + public void setAlwaysShow(Boolean alwaysShow) + { + this.alwaysShow = alwaysShow; + } + + public MetaVo getMeta() + { + return meta; + } + + public void setMeta(MetaVo meta) + { + this.meta = meta; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysConfigMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysConfigMapper.java new file mode 100644 index 0000000..71b5ab2 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysConfigMapper.java @@ -0,0 +1,69 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysConfig; + +/** + * 参数配置 数据层 + * + * @author ruoyi + */ +public interface SysConfigMapper +{ + /** + * 查询参数配置信息 + * + * @param config 参数配置信息 + * @return 参数配置信息 + */ + public SysConfig selectConfig(SysConfig config); + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + public List selectConfigList(SysConfig config); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数配置信息 + */ + public SysConfig checkConfigKeyUnique(String configKey); + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int insertConfig(SysConfig config); + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int updateConfig(SysConfig config); + + /** + * 删除参数配置 + * + * @param configId 参数ID + * @return 结果 + */ + public int deleteConfigById(Long configId); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + * @return 结果 + */ + public int deleteConfigByIds(Long[] configIds); +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysDeptMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysDeptMapper.java new file mode 100644 index 0000000..55cebcb --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysDeptMapper.java @@ -0,0 +1,119 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysDept; +import org.apache.ibatis.annotations.Param; + +/** + * 部门管理 数据层 + * + * @author ruoyi + */ +public interface SysDeptMapper +{ + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + public List selectDeptList(SysDept dept); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @param deptCheckStrictly 部门树选择项是否关联显示 + * @return 选中部门列表 + */ + public List selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + public SysDept selectDeptById(Long deptId); + + /** + * 根据ID查询所有子部门 + * + * @param deptId 部门ID + * @return 部门列表 + */ + public List selectChildrenDeptById(Long deptId); + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + public int selectNormalChildrenDeptById(Long deptId); + + /** + * 是否存在子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + public int hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 + */ + public int checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param deptName 部门名称 + * @param parentId 父部门ID + * @return 结果 + */ + public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId); + + /** + * 新增部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int insertDept(SysDept dept); + + /** + * 修改部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int updateDept(SysDept dept); + + /** + * 修改所在部门的父级部门状态 + * + * @param dept 部门 + */ + public void updateDeptStatus(SysDept dept); + + /** + * 修改子元素关系 + * + * @param depts 子元素 + * @return 结果 + */ + public int updateDeptChildren(@Param("depts") List depts); + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + public int deleteDeptById(Long deptId); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysDictDataMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysDictDataMapper.java new file mode 100644 index 0000000..2ebdd00 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysDictDataMapper.java @@ -0,0 +1,96 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysDictData; +import org.apache.ibatis.annotations.Param; + +/** + * 字典表 数据层 + * + * @author ruoyi + */ +public interface SysDictDataMapper +{ + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + public List selectDictDataList(SysDictData dictData); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + public List selectDictDataByType(String dictType); + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(@Param("dictType") String dictType, @Param("dictValue") String dictValue); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * 查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据 + */ + public int countDictDataByType(String dictType); + + /** + * 通过字典ID删除字典数据信息 + * + * @param dictCode 字典数据ID + * @return 结果 + */ + public int deleteDictDataById(Long dictCode); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + * @return 结果 + */ + public int deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int updateDictData(SysDictData dictData); + + /** + * 同步修改字典类型 + * + * @param oldDictType 旧字典类型 + * @param newDictType 新旧字典类型 + * @return 结果 + */ + public int updateDictDataType(@Param("oldDictType") String oldDictType, @Param("newDictType") String newDictType); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysDictTypeMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysDictTypeMapper.java new file mode 100644 index 0000000..b590632 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysDictTypeMapper.java @@ -0,0 +1,86 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysDictType; +import org.apache.ibatis.annotations.Mapper; + +/** + * 字典表 数据层 + * + * @author ruoyi + */ +@Mapper +public interface SysDictTypeMapper +{ + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + public List selectDictTypeAll(); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 通过字典ID删除字典信息 + * + * @param dictId 字典ID + * @return 结果 + */ + public int deleteDictTypeById(Long dictId); + + /** + * 批量删除字典类型信息 + * + * @param dictIds 需要删除的字典ID + * @return 结果 + */ + public int deleteDictTypeByIds(Long[] dictIds); + + /** + * 新增字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * 修改字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + public SysDictType checkDictTypeUnique(String dictType); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysMenuMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysMenuMapper.java new file mode 100644 index 0000000..9ef016a --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysMenuMapper.java @@ -0,0 +1,118 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysMenu; +import org.apache.ibatis.annotations.Param; + +/** + * 菜单表 数据层 + * + * @author ruoyi + */ +public interface SysMenuMapper +{ + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + public List selectMenuList(SysMenu menu); + + /** + * 根据用户所有权限 + * + * @return 权限列表 + */ + public List selectMenuPerms(); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + public List selectMenuListByUserId(SysMenu menu); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + public List selectMenuPermsByUserId(Long userId); + + /** + * 根据用户ID查询菜单 + * + * @return 菜单列表 + */ + public List selectMenuTreeAll(); + + /** + * 根据用户ID查询菜单 + * + * @param username 用户ID + * @return 菜单列表 + */ + public List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @param menuCheckStrictly 菜单树选择项是否关联显示 + * @return 选中菜单列表 + */ + public List selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + public SysMenu selectMenuById(Long menuId); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int hasChildByMenuId(Long menuId); + + /** + * 新增菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int insertMenu(SysMenu menu); + + /** + * 修改菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int updateMenu(SysMenu menu); + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int deleteMenuById(Long menuId); + + /** + * 校验菜单名称是否唯一 + * + * @param menuName 菜单名称 + * @param parentId 父菜单ID + * @return 结果 + */ + public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysNoticeMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysNoticeMapper.java new file mode 100644 index 0000000..d43e0ee --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysNoticeMapper.java @@ -0,0 +1,61 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysNotice; + +/** + * 通知公告表 数据层 + * + * @author ruoyi + */ +public interface SysNoticeMapper +{ + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + public SysNotice selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + public List selectNoticeList(SysNotice notice); + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int insertNotice(SysNotice notice); + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int updateNotice(SysNotice notice); + + /** + * 批量删除公告 + * + * @param noticeId 公告ID + * @return 结果 + */ + public int deleteNoticeById(Long noticeId); + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + public int deleteNoticeByIds(Long[] noticeIds); +} \ No newline at end of file diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysPostMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysPostMapper.java new file mode 100644 index 0000000..cec843e --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysPostMapper.java @@ -0,0 +1,100 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysPost; + +/** + * 岗位信息 数据层 + * + * @author ruoyi + */ +public interface SysPostMapper +{ + /** + * 查询岗位数据集合 + * + * @param post 岗位信息 + * @return 岗位数据集合 + */ + public List selectPostList(SysPost post); + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + public List selectPostAll(); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + public SysPost selectPostById(Long postId); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + public List selectPostListByUserId(Long userId); + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + public List selectPostsByUserName(String userName); + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + public int deletePostById(Long postId); + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + public int deletePostByIds(Long[] postIds); + + /** + * 修改岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int updatePost(SysPost post); + + /** + * 新增岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int insertPost(SysPost post); + + /** + * 校验岗位名称 + * + * @param postName 岗位名称 + * @return 结果 + */ + public SysPost checkPostNameUnique(String postName); + + /** + * 校验岗位编码 + * + * @param postCode 岗位编码 + * @return 结果 + */ + public SysPost checkPostCodeUnique(String postCode); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysRoleDeptMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysRoleDeptMapper.java new file mode 100644 index 0000000..a90da68 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysRoleDeptMapper.java @@ -0,0 +1,45 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysRoleDept; + +/** + * 角色与部门关联表 数据层 + * + * @author ruoyi + */ +public interface SysRoleDeptMapper +{ + /** + * 通过角色ID删除角色和部门关联 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleDeptByRoleId(Long roleId); + + /** + * 批量删除角色部门关联信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteRoleDept(Long[] ids); + + /** + * 查询部门使用数量 + * + * @param deptId 部门ID + * @return 结果 + */ + public int selectCountRoleDeptByDeptId(Long deptId); + + /** + * 批量新增角色部门信息 + * + * @param roleDeptList 角色部门列表 + * @return 结果 + */ + public int batchRoleDept(List roleDeptList); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysRoleMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysRoleMapper.java new file mode 100644 index 0000000..e46d945 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysRoleMapper.java @@ -0,0 +1,108 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysRole; + +/** + * 角色表 数据层 + * + * @author ruoyi + */ +public interface SysRoleMapper +{ + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + public List selectRoleList(SysRole role); + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + public List selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + public List selectRoleAll(); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + public List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + public SysRole selectRoleById(Long roleId); + + /** + * 根据用户ID查询角色 + * + * @param userName 用户名 + * @return 角色列表 + */ + public List selectRolesByUserName(String userName); + + /** + * 校验角色名称是否唯一 + * + * @param roleName 角色名称 + * @return 角色信息 + */ + public SysRole checkRoleNameUnique(String roleName); + + /** + * 校验角色权限是否唯一 + * + * @param roleKey 角色权限 + * @return 角色信息 + */ + public SysRole checkRoleKeyUnique(String roleKey); + + /** + * 修改角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRole(SysRole role); + + /** + * 新增角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int insertRole(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleById(Long roleId); + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + public int deleteRoleByIds(Long[] roleIds); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysRoleMenuMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysRoleMenuMapper.java new file mode 100644 index 0000000..1f4c90f --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysRoleMenuMapper.java @@ -0,0 +1,45 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysRoleMenu; + +/** + * 角色与菜单关联表 数据层 + * + * @author ruoyi + */ +public interface SysRoleMenuMapper +{ + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int checkMenuExistRole(Long menuId); + + /** + * 通过角色ID删除角色和菜单关联 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleMenuByRoleId(Long roleId); + + /** + * 批量删除角色菜单关联信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteRoleMenu(Long[] ids); + + /** + * 批量新增角色菜单信息 + * + * @param roleMenuList 角色菜单列表 + * @return 结果 + */ + public int batchRoleMenu(List roleMenuList); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysUserMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysUserMapper.java new file mode 100644 index 0000000..4918912 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysUserMapper.java @@ -0,0 +1,112 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysUser; +import org.apache.ibatis.annotations.Param; + +/** + * 用户表 数据层 + * + * @author ruoyi + */ +public interface SysUserMapper +{ + /** + * 根据条件分页查询用户列表 + * + * @param sysUser 用户信息 + * @return 用户信息集合信息 + */ + public List selectUserList(SysUser sysUser); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + public SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + public SysUser selectUserById(Long userId); + + /** + * 新增用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int insertUser(SysUser user); + + /** + * 修改用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUser(SysUser user); + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar); + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + public int resetUserPwd(@Param("userName") String userName, @Param("password") String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserById(Long userId); + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + public int deleteUserByIds(Long[] userIds); + + /** + * 校验用户名称是否唯一 + * + * @param userName 用户名称 + * @return 结果 + */ + public int checkUserNameUnique(String userName); + + /** + * 校验手机号码是否唯一 + * + * @param phonenumber 手机号码 + * @return 结果 + */ + public SysUser checkPhoneUnique(String phonenumber); + + /** + * 校验email是否唯一 + * + * @param email 用户邮箱 + * @return 结果 + */ + public SysUser checkEmailUnique(String email); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysUserPostMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysUserPostMapper.java new file mode 100644 index 0000000..e345922 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysUserPostMapper.java @@ -0,0 +1,45 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysUserPost; + +/** + * 用户与岗位关联表 数据层 + * + * @author ruoyi + */ +public interface SysUserPostMapper +{ + /** + * 通过用户ID删除用户和岗位关联 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserPostByUserId(Long userId); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 批量删除用户和岗位关联 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteUserPost(Long[] ids); + + /** + * 批量新增用户岗位信息 + * + * @param userPostList 用户角色列表 + * @return 结果 + */ + public int batchUserPost(List userPostList); +} diff --git a/src/main/java/cn/sliyun/project/system/mapper/SysUserRoleMapper.java b/src/main/java/cn/sliyun/project/system/mapper/SysUserRoleMapper.java new file mode 100644 index 0000000..a9cf7ea --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/mapper/SysUserRoleMapper.java @@ -0,0 +1,63 @@ +package cn.sliyun.project.system.mapper; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysUserRole; +import org.apache.ibatis.annotations.Param; + +/** + * 用户与角色关联表 数据层 + * + * @author ruoyi + */ +public interface SysUserRoleMapper +{ + /** + * 通过用户ID删除用户和角色关联 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserRoleByUserId(Long userId); + + /** + * 批量删除用户和角色关联 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteUserRole(Long[] ids); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + public int countUserRoleByRoleId(Long roleId); + + /** + * 批量新增用户角色信息 + * + * @param userRoleList 用户角色列表 + * @return 结果 + */ + public int batchUserRole(List userRoleList); + + /** + * 删除用户和角色关联信息 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + public int deleteUserRoleInfo(SysUserRole userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + * @return 结果 + */ + public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysConfigService.java b/src/main/java/cn/sliyun/project/system/service/ISysConfigService.java new file mode 100644 index 0000000..47ea3e5 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysConfigService.java @@ -0,0 +1,74 @@ +package cn.sliyun.project.system.service; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysConfig; + +/** + * 参数配置 服务层 + * + * @author ruoyi + */ +public interface ISysConfigService +{ + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return 参数配置信息 + */ + public SysConfig selectConfigById(Long configId); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数键值 + */ + public String selectConfigByKey(String configKey); + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + public List selectConfigList(SysConfig config); + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int insertConfig(SysConfig config); + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int updateConfig(SysConfig config); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + * @return 结果 + */ + public int deleteConfigByIds(Long[] configIds); + + /** + * 清空缓存数据 + */ + public void clearCache(); + + /** + * 校验参数键名是否唯一 + * + * @param config 参数信息 + * @return 结果 + */ + public String checkConfigKeyUnique(SysConfig config); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysDeptService.java b/src/main/java/cn/sliyun/project/system/service/ISysDeptService.java new file mode 100644 index 0000000..9c3587c --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysDeptService.java @@ -0,0 +1,110 @@ +package cn.sliyun.project.system.service; + +import java.util.List; + +import cn.sliyun.framework.web.domain.TreeSelect; +import cn.sliyun.project.system.domain.SysDept; + +/** + * 部门管理 服务层 + * + * @author ruoyi + */ +public interface ISysDeptService +{ + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + public List selectDeptList(SysDept dept); + + /** + * 构建前端所需要树结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + public List buildDeptTree(List depts); + + /** + * 构建前端所需要下拉树结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + public List buildDeptTreeSelect(List depts); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + public List selectDeptListByRoleId(Long roleId); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + public SysDept selectDeptById(Long deptId); + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + public int selectNormalChildrenDeptById(Long deptId); + + /** + * 是否存在部门子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + public boolean hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + public boolean checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + public String checkDeptNameUnique(SysDept dept); + + /** + * 新增保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int insertDept(SysDept dept); + + /** + * 修改保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int updateDept(SysDept dept); + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + public int deleteDeptById(Long deptId); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysDictDataService.java b/src/main/java/cn/sliyun/project/system/service/ISysDictDataService.java new file mode 100644 index 0000000..0b16f20 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysDictDataService.java @@ -0,0 +1,62 @@ +package cn.sliyun.project.system.service; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysDictData; + +/** + * 字典 业务层 + * + * @author ruoyi + */ +public interface ISysDictDataService +{ + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + public List selectDictDataList(SysDictData dictData); + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(String dictType, String dictValue); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + * @return 结果 + */ + public int deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增保存字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改保存字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int updateDictData(SysDictData dictData); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysDictTypeService.java b/src/main/java/cn/sliyun/project/system/service/ISysDictTypeService.java new file mode 100644 index 0000000..898649b --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysDictTypeService.java @@ -0,0 +1,90 @@ +package cn.sliyun.project.system.service; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysDictData; +import cn.sliyun.project.system.domain.SysDictType; + +/** + * 字典 业务层 + * + * @author ruoyi + */ +public interface ISysDictTypeService +{ + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + public List selectDictTypeAll(); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + public List selectDictDataByType(String dictType); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 批量删除字典信息 + * + * @param dictIds 需要删除的字典ID + * @return 结果 + */ + public int deleteDictTypeByIds(Long[] dictIds); + + /** + * 清空缓存数据 + */ + public void clearCache(); + + /** + * 新增保存字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * 修改保存字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + public String checkDictTypeUnique(SysDictType dictType); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysMenuService.java b/src/main/java/cn/sliyun/project/system/service/ISysMenuService.java new file mode 100644 index 0000000..da56bce --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysMenuService.java @@ -0,0 +1,137 @@ +package cn.sliyun.project.system.service; + +import java.util.List; +import java.util.Set; + +import cn.sliyun.framework.web.domain.TreeSelect; +import cn.sliyun.project.system.domain.SysMenu; +import cn.sliyun.project.system.domain.vo.RouterVo; + +/** + * 菜单 业务层 + * + * @author ruoyi + */ +public interface ISysMenuService +{ + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuList(Long userId); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuList(SysMenu menu, Long userId); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + public Set selectMenuPermsByUserId(Long userId); + + /** + * 根据用户ID查询菜单树信息 + * + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + public List selectMenuListByRoleId(Long roleId); + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + public List buildMenus(List menus); + + /** + * 构建前端所需要树结构 + * + * @param menus 菜单列表 + * @return 树结构列表 + */ + public List buildMenuTree(List menus); + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + public List buildMenuTreeSelect(List menus); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + public SysMenu selectMenuById(Long menuId); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + public boolean hasChildByMenuId(Long menuId); + + /** + * 查询菜单是否存在角色 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + public boolean checkMenuExistRole(Long menuId); + + /** + * 新增保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int insertMenu(SysMenu menu); + + /** + * 修改保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int updateMenu(SysMenu menu); + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int deleteMenuById(Long menuId); + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + public String checkMenuNameUnique(SysMenu menu); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysNoticeService.java b/src/main/java/cn/sliyun/project/system/service/ISysNoticeService.java new file mode 100644 index 0000000..a200c12 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysNoticeService.java @@ -0,0 +1,61 @@ +package cn.sliyun.project.system.service; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysNotice; + +/** + * 公告 服务层 + * + * @author ruoyi + */ +public interface ISysNoticeService +{ + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + public SysNotice selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + public List selectNoticeList(SysNotice notice); + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int insertNotice(SysNotice notice); + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int updateNotice(SysNotice notice); + + /** + * 删除公告信息 + * + * @param noticeId 公告ID + * @return 结果 + */ + public int deleteNoticeById(Long noticeId); + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + public int deleteNoticeByIds(Long[] noticeIds); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysPostService.java b/src/main/java/cn/sliyun/project/system/service/ISysPostService.java new file mode 100644 index 0000000..2a84133 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysPostService.java @@ -0,0 +1,101 @@ +package cn.sliyun.project.system.service; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysPost; + +/** + * 岗位信息 服务层 + * + * @author ruoyi + */ +public interface ISysPostService +{ + /** + * 查询岗位信息集合 + * + * @param post 岗位信息 + * @return 岗位列表 + */ + public List selectPostList(SysPost post); + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + public List selectPostAll(); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + public SysPost selectPostById(Long postId); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + public List selectPostListByUserId(Long userId); + + /** + * 校验岗位名称 + * + * @param post 岗位信息 + * @return 结果 + */ + public String checkPostNameUnique(SysPost post); + + /** + * 校验岗位编码 + * + * @param post 岗位信息 + * @return 结果 + */ + public String checkPostCodeUnique(SysPost post); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + public int deletePostById(Long postId); + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + * @throws Exception 异常 + */ + public int deletePostByIds(Long[] postIds); + + /** + * 新增保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int insertPost(SysPost post); + + /** + * 修改保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int updatePost(SysPost post); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysRoleService.java b/src/main/java/cn/sliyun/project/system/service/ISysRoleService.java new file mode 100644 index 0000000..881fad7 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysRoleService.java @@ -0,0 +1,132 @@ +package cn.sliyun.project.system.service; + +import java.util.List; +import java.util.Set; + +import cn.sliyun.project.system.domain.SysRole; + +/** + * 角色业务层 + * + * @author ruoyi + */ +public interface ISysRoleService +{ + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + public List selectRoleList(SysRole role); + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 权限列表 + */ + public Set selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + public List selectRoleAll(); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + public List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + public SysRole selectRoleById(Long roleId); + + /** + * 校验角色名称是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + public String checkRoleNameUnique(SysRole role); + + /** + * 校验角色权限是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + public String checkRoleKeyUnique(SysRole role); + + /** + * 校验角色是否允许操作 + * + * @param role 角色信息 + */ + public void checkRoleAllowed(SysRole role); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + public int countUserRoleByRoleId(Long roleId); + + /** + * 新增保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int insertRole(SysRole role); + + /** + * 修改保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRole(SysRole role); + + /** + * 修改角色状态 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRoleStatus(SysRole role); + + /** + * 修改数据权限信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int authDataScope(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleById(Long roleId); + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + public int deleteRoleByIds(Long[] roleIds); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysUserOnlineService.java b/src/main/java/cn/sliyun/project/system/service/ISysUserOnlineService.java new file mode 100644 index 0000000..ed2969b --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysUserOnlineService.java @@ -0,0 +1,48 @@ +package cn.sliyun.project.system.service; + +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.project.monitor.domain.SysUserOnline; + +/** + * 在线用户 服务层 + * + * @author ruoyi + */ +public interface ISysUserOnlineService +{ + /** + * 通过登录地址查询信息 + * + * @param ipaddr 登录地址 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user); + + /** + * 通过用户名称查询信息 + * + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByUserName(String userName, LoginUser user); + + /** + * 通过登录地址/用户名称查询信息 + * + * @param ipaddr 登录地址 + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user); + + /** + * 设置在线用户信息 + * + * @param user 用户信息 + * @return 在线用户 + */ + public SysUserOnline loginUserToUserOnline(LoginUser user); +} diff --git a/src/main/java/cn/sliyun/project/system/service/ISysUserService.java b/src/main/java/cn/sliyun/project/system/service/ISysUserService.java new file mode 100644 index 0000000..d1d18f7 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/ISysUserService.java @@ -0,0 +1,168 @@ +package cn.sliyun.project.system.service; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysUser; + +/** + * 用户 业务层 + * + * @author ruoyi + */ +public interface ISysUserService +{ + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectUserList(SysUser user); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + public SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + public SysUser selectUserById(Long userId); + + /** + * 根据用户ID查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + public String selectUserRoleGroup(String userName); + + /** + * 根据用户ID查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + public String selectUserPostGroup(String userName); + + /** + * 校验用户名称是否唯一 + * + * @param userName 用户名称 + * @return 结果 + */ + public String checkUserNameUnique(String userName); + + /** + * 校验手机号码是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + public String checkPhoneUnique(SysUser user); + + /** + * 校验email是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + public String checkEmailUnique(SysUser user); + + /** + * 校验用户是否允许操作 + * + * @param user 用户信息 + */ + public void checkUserAllowed(SysUser user); + + /** + * 新增用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int insertUser(SysUser user); + + /** + * 修改用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUser(SysUser user); + + /** + * 修改用户状态 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUserStatus(SysUser user); + + /** + * 修改用户基本信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUserProfile(SysUser user); + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + public boolean updateUserAvatar(String userName, String avatar); + + /** + * 重置用户密码 + * + * @param user 用户信息 + * @return 结果 + */ + public int resetPwd(SysUser user); + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + public int resetUserPwd(String userName, String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserById(Long userId); + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + public int deleteUserByIds(Long[] userIds); + + /** + * 导入用户数据 + * + * @param userList 用户数据列表 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param operName 操作用户 + * @return 结果 + */ + public String importUser(List userList, Boolean isUpdateSupport, String operName); +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysConfigServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysConfigServiceImpl.java new file mode 100644 index 0000000..49fb227 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,192 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.List; +import javax.annotation.PostConstruct; + +import cn.sliyun.common.constant.Constants; +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.project.system.domain.SysConfig; +import cn.sliyun.project.system.mapper.SysConfigMapper; +import cn.sliyun.project.system.service.ISysConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import cn.sliyun.common.constant.UserConstants; + +/** + * 参数配置 服务层实现 + * + * @author ruoyi + */ +@Service +public class SysConfigServiceImpl implements ISysConfigService +{ + @Autowired + private SysConfigMapper configMapper; + +// @Autowired +// private RedisCache redisCache; + + /** + * 项目启动时,初始化参数到缓存 + */ + @PostConstruct + public void init() + { + List configsList = configMapper.selectConfigList(new SysConfig()); + for (SysConfig config : configsList) + { +// redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + } + + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return 参数配置信息 + */ + @Override + public SysConfig selectConfigById(Long configId) + { + SysConfig config = new SysConfig(); + config.setConfigId(configId); + return configMapper.selectConfig(config); + } + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数key + * @return 参数键值 + */ + @Override + public String selectConfigByKey(String configKey) + { + String configValue = null;//Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey))); + if (StringUtils.isNotEmpty(configValue)) + { + return configValue; + } + SysConfig config = new SysConfig(); + config.setConfigKey(configKey); + SysConfig retConfig = configMapper.selectConfig(config); + if (StringUtils.isNotNull(retConfig)) + { +// redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); + return retConfig.getConfigValue(); + } + return StringUtils.EMPTY; + } + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + @Override + public List selectConfigList(SysConfig config) + { + return configMapper.selectConfigList(config); + } + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public int insertConfig(SysConfig config) + { + int row = configMapper.insertConfig(config); + if (row > 0) + { +// redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + return row; + } + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public int updateConfig(SysConfig config) + { + int row = configMapper.updateConfig(config); + if (row > 0) + { +// redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + return row; + } + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + * @return 结果 + */ + @Override + public int deleteConfigByIds(Long[] configIds) + { + for (Long configId : configIds) + { + SysConfig config = selectConfigById(configId); + if (StringUtils.equals(UserConstants.YES, config.getConfigType())) + { + throw new AppException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); + } + } + int count = configMapper.deleteConfigByIds(configIds); + if (count > 0) + { +// Collection keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*"); +// redisCache.deleteObject(keys); + } + return count; + } + + /** + * 清空缓存数据 + */ + @Override + public void clearCache() + { +// Collection keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*"); +// redisCache.deleteObject(keys); + } + + /** + * 校验参数键名是否唯一 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public String checkConfigKeyUnique(SysConfig config) + { + Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId(); + SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey()); + if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 设置cache key + * + * @param configKey 参数键 + * @return 缓存键key + */ + private String getCacheKey(String configKey) + { + return Constants.SYS_CONFIG_KEY + configKey; + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysDeptServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysDeptServiceImpl.java new file mode 100644 index 0000000..195e15d --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,307 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import cn.sliyun.common.constant.UserConstants; +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.DataScope; +import cn.sliyun.framework.web.domain.TreeSelect; +import cn.sliyun.project.system.domain.SysDept; +import cn.sliyun.project.system.domain.SysRole; +import cn.sliyun.project.system.mapper.SysDeptMapper; +import cn.sliyun.project.system.mapper.SysRoleMapper; +import cn.sliyun.project.system.service.ISysDeptService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 部门管理 服务实现 + * + * @author ruoyi + */ +@Service +public class SysDeptServiceImpl implements ISysDeptService +{ + @Autowired + private SysDeptMapper deptMapper; + + @Autowired + private SysRoleMapper roleMapper; + + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + @Override + @DataScope(deptAlias = "d") + public List selectDeptList(SysDept dept) + { + return deptMapper.selectDeptList(dept); + } + + /** + * 构建前端所需要树结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + @Override + public List buildDeptTree(List depts) + { + List returnList = new ArrayList(); + List tempList = new ArrayList(); + for (SysDept dept : depts) + { + tempList.add(dept.getDeptId()); + } + for (Iterator iterator = depts.iterator(); iterator.hasNext();) + { + SysDept dept = (SysDept) iterator.next(); + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(dept.getParentId())) + { + recursionFn(depts, dept); + returnList.add(dept); + } + } + if (returnList.isEmpty()) + { + returnList = depts; + } + return returnList; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + @Override + public List buildDeptTreeSelect(List depts) + { + List deptTrees = buildDeptTree(depts); + return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + @Override + public List selectDeptListByRoleId(Long roleId) + { + SysRole role = roleMapper.selectRoleById(roleId); + return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly()); + } + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + @Override + public SysDept selectDeptById(Long deptId) + { + return deptMapper.selectDeptById(deptId); + } + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + @Override + public int selectNormalChildrenDeptById(Long deptId) + { + return deptMapper.selectNormalChildrenDeptById(deptId); + } + + /** + * 是否存在子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public boolean hasChildByDeptId(Long deptId) + { + int result = deptMapper.hasChildByDeptId(deptId); + return result > 0 ? true : false; + } + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + @Override + public boolean checkDeptExistUser(Long deptId) + { + int result = deptMapper.checkDeptExistUser(deptId); + return result > 0 ? true : false; + } + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public String checkDeptNameUnique(SysDept dept) + { + Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId(); + SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId()); + if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 新增保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public int insertDept(SysDept dept) + { + SysDept info = deptMapper.selectDeptById(dept.getParentId()); + // 如果父节点不为正常状态,则不允许新增子节点 + if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) + { + throw new AppException("部门停用,不允许新增"); + } + dept.setAncestors(info.getAncestors() + "," + dept.getParentId()); + return deptMapper.insertDept(dept); + } + + /** + * 修改保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public int updateDept(SysDept dept) + { + SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId()); + SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId()); + if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept)) + { + String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId(); + String oldAncestors = oldDept.getAncestors(); + dept.setAncestors(newAncestors); + updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); + } + int result = deptMapper.updateDept(dept); + if (UserConstants.DEPT_NORMAL.equals(dept.getStatus())) + { + // 如果该部门是启用状态,则启用该部门的所有上级部门 + updateParentDeptStatus(dept); + } + return result; + } + + /** + * 修改该部门的父级部门状态 + * + * @param dept 当前部门 + */ + private void updateParentDeptStatus(SysDept dept) + { + String updateBy = dept.getUpdateBy(); + dept = deptMapper.selectDeptById(dept.getDeptId()); + dept.setUpdateBy(updateBy); + deptMapper.updateDeptStatus(dept); + } + + /** + * 修改子元素关系 + * + * @param deptId 被修改的部门ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) + { + List children = deptMapper.selectChildrenDeptById(deptId); + for (SysDept child : children) + { + child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors)); + } + if (children.size() > 0) + { + deptMapper.updateDeptChildren(children); + } + } + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public int deleteDeptById(Long deptId) + { + return deptMapper.deleteDeptById(deptId); + } + + /** + * 递归列表 + */ + private void recursionFn(List list, SysDept t) + { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysDept tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysDept t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysDept n = (SysDept) it.next(); + if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, SysDept t) + { + return getChildList(list, t).size() > 0 ? true : false; + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysDictDataServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 0000000..93b32d5 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,110 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.List; + +import cn.sliyun.common.utils.DictUtils; +import cn.sliyun.project.system.domain.SysDictData; +import cn.sliyun.project.system.mapper.SysDictDataMapper; +import cn.sliyun.project.system.service.ISysDictDataService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 字典 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysDictDataServiceImpl implements ISysDictDataService +{ + @Autowired + private SysDictDataMapper dictDataMapper; + + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataList(SysDictData dictData) + { + return dictDataMapper.selectDictDataList(dictData); + } + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + @Override + public String selectDictLabel(String dictType, String dictValue) + { + return dictDataMapper.selectDictLabel(dictType, dictValue); + } + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + @Override + public SysDictData selectDictDataById(Long dictCode) + { + return dictDataMapper.selectDictDataById(dictCode); + } + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + * @return 结果 + */ + @Override + public int deleteDictDataByIds(Long[] dictCodes) + { + int row = dictDataMapper.deleteDictDataByIds(dictCodes); + if (row > 0) + { + DictUtils.clearDictCache(); + } + return row; + } + + /** + * 新增保存字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + @Override + public int insertDictData(SysDictData dictData) + { + int row = dictDataMapper.insertDictData(dictData); + if (row > 0) + { + DictUtils.clearDictCache(); + } + return row; + } + + /** + * 修改保存字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + @Override + public int updateDictData(SysDictData dictData) + { + int row = dictDataMapper.updateDictData(dictData); + if (row > 0) + { + DictUtils.clearDictCache(); + } + return row; + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysDictTypeServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 0000000..4a02e1b --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysDictTypeServiceImpl.java @@ -0,0 +1,205 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.List; +import javax.annotation.PostConstruct; + +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.DictUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.project.system.domain.SysDictData; +import cn.sliyun.project.system.domain.SysDictType; +import cn.sliyun.project.system.mapper.SysDictDataMapper; +import cn.sliyun.project.system.mapper.SysDictTypeMapper; +import cn.sliyun.project.system.service.ISysDictTypeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import cn.sliyun.common.constant.UserConstants; + +/** + * 字典 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysDictTypeServiceImpl implements ISysDictTypeService +{ + @Autowired + private SysDictTypeMapper dictTypeMapper; + + @Autowired + private SysDictDataMapper dictDataMapper; + + /** + * 项目启动时,初始化字典到缓存 + */ + @PostConstruct + public void init() + { + List dictTypeList = dictTypeMapper.selectDictTypeAll(); + for (SysDictType dictType : dictTypeList) + { + List dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType()); + DictUtils.setDictCache(dictType.getDictType(), dictDatas); + } + } + + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeList(SysDictType dictType) + { + return dictTypeMapper.selectDictTypeList(dictType); + } + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeAll() + { + return dictTypeMapper.selectDictTypeAll(); + } + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataByType(String dictType) + { + List dictDatas = DictUtils.getDictCache(dictType); + if (StringUtils.isNotEmpty(dictDatas)) + { + return dictDatas; + } + dictDatas = dictDataMapper.selectDictDataByType(dictType); + if (StringUtils.isNotEmpty(dictDatas)) + { + DictUtils.setDictCache(dictType, dictDatas); + return dictDatas; + } + return null; + } + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeById(Long dictId) + { + return dictTypeMapper.selectDictTypeById(dictId); + } + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeByType(String dictType) + { + return dictTypeMapper.selectDictTypeByType(dictType); + } + + /** + * 批量删除字典类型信息 + * + * @param dictIds 需要删除的字典ID + * @return 结果 + */ + @Override + public int deleteDictTypeByIds(Long[] dictIds) + { + for (Long dictId : dictIds) + { + SysDictType dictType = selectDictTypeById(dictId); + if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0) + { + throw new AppException(String.format("%1$s已分配,不能删除", dictType.getDictName())); + } + } + int count = dictTypeMapper.deleteDictTypeByIds(dictIds); + if (count > 0) + { + DictUtils.clearDictCache(); + } + return count; + } + + /** + * 清空缓存数据 + */ + @Override + public void clearCache() + { + DictUtils.clearDictCache(); + } + + /** + * 新增保存字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + @Override + public int insertDictType(SysDictType dictType) + { + int row = dictTypeMapper.insertDictType(dictType); + if (row > 0) + { + DictUtils.clearDictCache(); + } + return row; + } + + /** + * 修改保存字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + @Override + @Transactional + public int updateDictType(SysDictType dictType) + { + SysDictType oldDict = dictTypeMapper.selectDictTypeById(dictType.getDictId()); + dictDataMapper.updateDictDataType(oldDict.getDictType(), dictType.getDictType()); + int row = dictTypeMapper.updateDictType(dictType); + if (row > 0) + { + DictUtils.clearDictCache(); + } + return row; + } + + /** + * 校验字典类型称是否唯一 + * + * @param dict 字典类型 + * @return 结果 + */ + @Override + public String checkDictTypeUnique(SysDictType dict) + { + Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId(); + SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType()); + if (StringUtils.isNotNull(dictType) && dictType.getDictId().longValue() != dictId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysMenuServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..b650797 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,466 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.web.domain.TreeSelect; +import cn.sliyun.project.system.domain.SysMenu; +import cn.sliyun.project.system.domain.SysRole; +import cn.sliyun.project.system.domain.SysUser; +import cn.sliyun.project.system.domain.vo.MetaVo; +import cn.sliyun.project.system.domain.vo.RouterVo; +import cn.sliyun.project.system.mapper.SysMenuMapper; +import cn.sliyun.project.system.mapper.SysRoleMapper; +import cn.sliyun.project.system.mapper.SysRoleMenuMapper; +import cn.sliyun.project.system.service.ISysMenuService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import cn.sliyun.common.constant.UserConstants; + +/** + * 菜单 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysMenuServiceImpl implements ISysMenuService +{ + public static final String PREMISSION_STRING = "perms[\"{0}\"]"; + + @Autowired + private SysMenuMapper menuMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysRoleMenuMapper roleMenuMapper; + + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + @Override + public List selectMenuList(Long userId) + { + return selectMenuList(new SysMenu(), userId); + } + + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + @Override + public List selectMenuList(SysMenu menu, Long userId) + { + List menuList = null; + // 管理员显示所有菜单信息 + if (SysUser.isAdmin(userId)) + { + menuList = menuMapper.selectMenuList(menu); + } + else + { + menu.getParams().put("userId", userId); + menuList = menuMapper.selectMenuListByUserId(menu); + } + return menuList; + } + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectMenuPermsByUserId(Long userId) + { + List perms = menuMapper.selectMenuPermsByUserId(userId); + Set permsSet = new HashSet<>(); + for (String perm : perms) + { + if (StringUtils.isNotEmpty(perm)) + { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户名称 + * @return 菜单列表 + */ + @Override + public List selectMenuTreeByUserId(Long userId) + { + List menus = null; + if (SecurityUtils.isAdmin(userId)) + { + menus = menuMapper.selectMenuTreeAll(); + } + else + { + menus = menuMapper.selectMenuTreeByUserId(userId); + } + return getChildPerms(menus, 0); + } + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + @Override + public List selectMenuListByRoleId(Long roleId) + { + SysRole role = roleMapper.selectRoleById(roleId); + return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly()); + } + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + @Override + public List buildMenus(List menus) + { + List routers = new LinkedList(); + for (SysMenu menu : menus) + { + RouterVo router = new RouterVo(); + router.setHidden("1".equals(menu.getVisible())); + router.setName(getRouteName(menu)); + router.setPath(getRouterPath(menu)); + router.setComponent(getComponent(menu)); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()))); + List cMenus = menu.getChildren(); + if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) + { + router.setAlwaysShow(true); + router.setRedirect("noRedirect"); + router.setChildren(buildMenus(cMenus)); + } + else if (isMeunFrame(menu)) + { + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponent()); + children.setName(StringUtils.capitalize(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()))); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + /** + * 构建前端所需要树结构 + * + * @param menus 菜单列表 + * @return 树结构列表 + */ + @Override + public List buildMenuTree(List menus) + { + List returnList = new ArrayList(); + List tempList = new ArrayList(); + for (SysMenu dept : menus) + { + tempList.add(dept.getMenuId()); + } + for (Iterator iterator = menus.iterator(); iterator.hasNext();) + { + SysMenu menu = (SysMenu) iterator.next(); + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(menu.getParentId())) + { + recursionFn(menus, menu); + returnList.add(menu); + } + } + if (returnList.isEmpty()) + { + returnList = menus; + } + return returnList; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + @Override + public List buildMenuTreeSelect(List menus) + { + List menuTrees = buildMenuTree(menus); + return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + @Override + public SysMenu selectMenuById(Long menuId) + { + return menuMapper.selectMenuById(menuId); + } + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean hasChildByMenuId(Long menuId) + { + int result = menuMapper.hasChildByMenuId(menuId); + return result > 0 ? true : false; + } + + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean checkMenuExistRole(Long menuId) + { + int result = roleMenuMapper.checkMenuExistRole(menuId); + return result > 0 ? true : false; + } + + /** + * 新增保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public int insertMenu(SysMenu menu) + { + return menuMapper.insertMenu(menu); + } + + /** + * 修改保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public int updateMenu(SysMenu menu) + { + return menuMapper.updateMenu(menu); + } + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public int deleteMenuById(Long menuId) + { + return menuMapper.deleteMenuById(menuId); + } + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public String checkMenuNameUnique(SysMenu menu) + { + Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId(); + SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId()); + if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 获取路由名称 + * + * @param menu 菜单信息 + * @return 路由名称 + */ + public String getRouteName(SysMenu menu) + { + String routerName = StringUtils.capitalize(menu.getPath()); + // 非外链并且是一级目录(类型为目录) + if (isMeunFrame(menu)) + { + routerName = StringUtils.EMPTY; + } + return routerName; + } + + /** + * 获取路由地址 + * + * @param menu 菜单信息 + * @return 路由地址 + */ + public String getRouterPath(SysMenu menu) + { + String routerPath = menu.getPath(); + // 非外链并且是一级目录(类型为目录) + if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) + && UserConstants.NO_FRAME.equals(menu.getIsFrame())) + { + routerPath = "/" + menu.getPath(); + } + // 非外链并且是一级目录(类型为菜单) + else if (isMeunFrame(menu)) + { + routerPath = "/"; + } + return routerPath; + } + + /** + * 获取组件信息 + * + * @param menu 菜单信息 + * @return 组件信息 + */ + public String getComponent(SysMenu menu) + { + String component = UserConstants.LAYOUT; + if (StringUtils.isNotEmpty(menu.getComponent()) && !isMeunFrame(menu)) + { + component = menu.getComponent(); + } + else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) + { + component = UserConstants.PARENT_VIEW; + } + return component; + } + + /** + * 是否为菜单内部跳转 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isMeunFrame(SysMenu menu) + { + return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + && menu.getIsFrame().equals(UserConstants.NO_FRAME); + } + + /** + * 是否为parent_view组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isParentView(SysMenu menu) + { + return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); + } + + /** + * 根据父节点的ID获取所有子节点 + * + * @param list 分类表 + * @param parentId 传入的父节点ID + * @return String + */ + public List getChildPerms(List list, int parentId) + { + List returnList = new ArrayList(); + for (Iterator iterator = list.iterator(); iterator.hasNext();) + { + SysMenu t = (SysMenu) iterator.next(); + // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 + if (t.getParentId() == parentId) + { + recursionFn(list, t); + returnList.add(t); + } + } + return returnList; + } + + /** + * 递归列表 + * + * @param list + * @param t + */ + private void recursionFn(List list, SysMenu t) + { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysMenu tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysMenu t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysMenu n = (SysMenu) it.next(); + if (n.getParentId().longValue() == t.getMenuId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, SysMenu t) + { + return getChildList(list, t).size() > 0 ? true : false; + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysNoticeServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 0000000..11d55f5 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,93 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.List; + +import cn.sliyun.project.system.domain.SysNotice; +import cn.sliyun.project.system.mapper.SysNoticeMapper; +import cn.sliyun.project.system.service.ISysNoticeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 公告 服务层实现 + * + * @author ruoyi + */ +@Service +public class SysNoticeServiceImpl implements ISysNoticeService +{ + @Autowired + private SysNoticeMapper noticeMapper; + + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + @Override + public SysNotice selectNoticeById(Long noticeId) + { + return noticeMapper.selectNoticeById(noticeId); + } + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + @Override + public List selectNoticeList(SysNotice notice) + { + return noticeMapper.selectNoticeList(notice); + } + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + @Override + public int insertNotice(SysNotice notice) + { + return noticeMapper.insertNotice(notice); + } + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + @Override + public int updateNotice(SysNotice notice) + { + return noticeMapper.updateNotice(notice); + } + + /** + * 删除公告对象 + * + * @param noticeId 公告ID + * @return 结果 + */ + @Override + public int deleteNoticeById(Long noticeId) + { + return noticeMapper.deleteNoticeById(noticeId); + } + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + @Override + public int deleteNoticeByIds(Long[] noticeIds) + { + return noticeMapper.deleteNoticeByIds(noticeIds); + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysPostServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysPostServiceImpl.java new file mode 100644 index 0000000..a909547 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysPostServiceImpl.java @@ -0,0 +1,180 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.List; + +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.project.system.domain.SysPost; +import cn.sliyun.project.system.mapper.SysPostMapper; +import cn.sliyun.project.system.mapper.SysUserPostMapper; +import cn.sliyun.project.system.service.ISysPostService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import cn.sliyun.common.constant.UserConstants; + +/** + * 岗位信息 服务层处理 + * + * @author ruoyi + */ +@Service +public class SysPostServiceImpl implements ISysPostService +{ + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + /** + * 查询岗位信息集合 + * + * @param post 岗位信息 + * @return 岗位信息集合 + */ + @Override + public List selectPostList(SysPost post) + { + return postMapper.selectPostList(post); + } + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + @Override + public List selectPostAll() + { + return postMapper.selectPostAll(); + } + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + @Override + public SysPost selectPostById(Long postId) + { + return postMapper.selectPostById(postId); + } + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + @Override + public List selectPostListByUserId(Long userId) + { + return postMapper.selectPostListByUserId(userId); + } + + /** + * 校验岗位名称是否唯一 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public String checkPostNameUnique(SysPost post) + { + Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId(); + SysPost info = postMapper.checkPostNameUnique(post.getPostName()); + if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验岗位编码是否唯一 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public String checkPostCodeUnique(SysPost post) + { + Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId(); + SysPost info = postMapper.checkPostCodeUnique(post.getPostCode()); + if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public int countUserPostById(Long postId) + { + return userPostMapper.countUserPostById(postId); + } + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public int deletePostById(Long postId) + { + return postMapper.deletePostById(postId); + } + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + * @throws Exception 异常 + */ + @Override + public int deletePostByIds(Long[] postIds) + { + for (Long postId : postIds) + { + SysPost post = selectPostById(postId); + if (countUserPostById(postId) > 0) + { + throw new AppException(String.format("%1$s已分配,不能删除", post.getPostName())); + } + } + return postMapper.deletePostByIds(postIds); + } + + /** + * 新增保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public int insertPost(SysPost post) + { + return postMapper.insertPost(post); + } + + /** + * 修改保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public int updatePost(SysPost post) + { + return postMapper.updatePost(post); + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysRoleServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..8b8f0c5 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,329 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.common.utils.spring.SpringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.DataScope; +import cn.sliyun.project.system.domain.SysRole; +import cn.sliyun.project.system.domain.SysRoleDept; +import cn.sliyun.project.system.domain.SysRoleMenu; +import cn.sliyun.project.system.mapper.SysRoleDeptMapper; +import cn.sliyun.project.system.mapper.SysRoleMapper; +import cn.sliyun.project.system.mapper.SysRoleMenuMapper; +import cn.sliyun.project.system.mapper.SysUserRoleMapper; +import cn.sliyun.project.system.service.ISysRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import cn.sliyun.common.constant.UserConstants; + +/** + * 角色 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysRoleServiceImpl implements ISysRoleService +{ + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysRoleMenuMapper roleMenuMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysRoleDeptMapper roleDeptMapper; + + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + @Override + @DataScope(deptAlias = "d") + public List selectRoleList(SysRole role) + { + return roleMapper.selectRoleList(role); + } + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectRolePermissionByUserId(Long userId) + { + List perms = roleMapper.selectRolePermissionByUserId(userId); + Set permsSet = new HashSet<>(); + for (SysRole perm : perms) + { + if (StringUtils.isNotNull(perm)) + { + permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(","))); + } + } + return permsSet; + } + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + @Override + public List selectRoleAll() + { + return SpringUtils.getAopProxy(this).selectRoleList(new SysRole()); + } + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + @Override + public List selectRoleListByUserId(Long userId) + { + return roleMapper.selectRoleListByUserId(userId); + } + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + @Override + public SysRole selectRoleById(Long roleId) + { + return roleMapper.selectRoleById(roleId); + } + + /** + * 校验角色名称是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public String checkRoleNameUnique(SysRole role) + { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色权限是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public String checkRoleKeyUnique(SysRole role) + { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色是否允许操作 + * + * @param role 角色信息 + */ + @Override + public void checkRoleAllowed(SysRole role) + { + if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin()) + { + throw new AppException("不允许操作超级管理员角色"); + } + } + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + public int countUserRoleByRoleId(Long roleId) + { + return userRoleMapper.countUserRoleByRoleId(roleId); + } + + /** + * 新增保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional + public int insertRole(SysRole role) + { + // 新增角色信息 + roleMapper.insertRole(role); + return insertRoleMenu(role); + } + + /** + * 修改保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional + public int updateRole(SysRole role) + { + // 修改角色信息 + roleMapper.updateRole(role); + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId()); + return insertRoleMenu(role); + } + + /** + * 修改角色状态 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public int updateRoleStatus(SysRole role) + { + return roleMapper.updateRole(role); + } + + /** + * 修改数据权限信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional + public int authDataScope(SysRole role) + { + // 修改角色信息 + roleMapper.updateRole(role); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId()); + // 新增角色和部门信息(数据权限) + return insertRoleDept(role); + } + + /** + * 新增角色菜单信息 + * + * @param role 角色对象 + */ + public int insertRoleMenu(SysRole role) + { + int rows = 1; + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long menuId : role.getMenuIds()) + { + SysRoleMenu rm = new SysRoleMenu(); + rm.setRoleId(role.getRoleId()); + rm.setMenuId(menuId); + list.add(rm); + } + if (list.size() > 0) + { + rows = roleMenuMapper.batchRoleMenu(list); + } + return rows; + } + + /** + * 新增角色部门信息(数据权限) + * + * @param role 角色对象 + */ + public int insertRoleDept(SysRole role) + { + int rows = 1; + // 新增角色与部门(数据权限)管理 + List list = new ArrayList(); + for (Long deptId : role.getDeptIds()) + { + SysRoleDept rd = new SysRoleDept(); + rd.setRoleId(role.getRoleId()); + rd.setDeptId(deptId); + list.add(rd); + } + if (list.size() > 0) + { + rows = roleDeptMapper.batchRoleDept(list); + } + return rows; + } + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + @Transactional + public int deleteRoleById(Long roleId) + { + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenuByRoleId(roleId); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDeptByRoleId(roleId); + return roleMapper.deleteRoleById(roleId); + } + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + @Override + @Transactional + public int deleteRoleByIds(Long[] roleIds) + { + for (Long roleId : roleIds) + { + checkRoleAllowed(new SysRole(roleId)); + SysRole role = selectRoleById(roleId); + if (countUserRoleByRoleId(roleId) > 0) + { + throw new AppException(String.format("%1$s已分配,不能删除", role.getRoleName())); + } + } + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenu(roleIds); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDept(roleIds); + return roleMapper.deleteRoleByIds(roleIds); + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysUserOnlineServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysUserOnlineServiceImpl.java new file mode 100644 index 0000000..ad6601d --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysUserOnlineServiceImpl.java @@ -0,0 +1,96 @@ +package cn.sliyun.project.system.service.impl; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.security.LoginUser; +import cn.sliyun.project.system.service.ISysUserOnlineService; +import org.springframework.stereotype.Service; +import cn.sliyun.project.monitor.domain.SysUserOnline; + +/** + * 在线用户 服务层处理 + * + * @author ruoyi + */ +@Service +public class SysUserOnlineServiceImpl implements ISysUserOnlineService +{ + /** + * 通过登录地址查询信息 + * + * @param ipaddr 登录地址 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user) + { + if (StringUtils.equals(ipaddr, user.getIpaddr())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 通过用户名称查询信息 + * + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByUserName(String userName, LoginUser user) + { + if (StringUtils.equals(userName, user.getUsername())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 通过登录地址/用户名称查询信息 + * + * @param ipaddr 登录地址 + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user) + { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 设置在线用户信息 + * + * @param user 用户信息 + * @return 在线用户 + */ + @Override + public SysUserOnline loginUserToUserOnline(LoginUser user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser())) + { + return null; + } + SysUserOnline sysUserOnline = new SysUserOnline(); + sysUserOnline.setTokenId(user.getToken()); + sysUserOnline.setUserName(user.getUsername()); + sysUserOnline.setIpaddr(user.getIpaddr()); + sysUserOnline.setLoginLocation(user.getLoginLocation()); + sysUserOnline.setBrowser(user.getBrowser()); + sysUserOnline.setOs(user.getOs()); + sysUserOnline.setLoginTime(user.getLoginTime()); + if (StringUtils.isNotNull(user.getUser().getDept())) + { + sysUserOnline.setDeptName(user.getUser().getDept().getDeptName()); + } + return sysUserOnline; + } +} diff --git a/src/main/java/cn/sliyun/project/system/service/impl/SysUserServiceImpl.java b/src/main/java/cn/sliyun/project/system/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..349ce69 --- /dev/null +++ b/src/main/java/cn/sliyun/project/system/service/impl/SysUserServiceImpl.java @@ -0,0 +1,464 @@ +package cn.sliyun.project.system.service.impl; + +import java.util.ArrayList; +import java.util.List; + +import cn.sliyun.common.exception.AppException; +import cn.sliyun.common.utils.SecurityUtils; +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.aspectj.lang.annotation.DataScope; +import cn.sliyun.project.system.service.ISysConfigService; +import cn.sliyun.project.system.service.ISysUserService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import cn.sliyun.common.constant.UserConstants; +import cn.sliyun.project.system.domain.SysPost; +import cn.sliyun.project.system.domain.SysRole; +import cn.sliyun.project.system.domain.SysUser; +import cn.sliyun.project.system.domain.SysUserPost; +import cn.sliyun.project.system.domain.SysUserRole; +import cn.sliyun.project.system.mapper.SysPostMapper; +import cn.sliyun.project.system.mapper.SysRoleMapper; +import cn.sliyun.project.system.mapper.SysUserMapper; +import cn.sliyun.project.system.mapper.SysUserPostMapper; +import cn.sliyun.project.system.mapper.SysUserRoleMapper; + +/** + * 用户 业务层处理 + * + * @author ruoyi + */ +@Service +public class SysUserServiceImpl implements ISysUserService +{ + private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); + + @Autowired + private SysUserMapper userMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + @Autowired + private ISysConfigService configService; + + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUserList(SysUser user) + { + return userMapper.selectUserList(user); + } + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + @Override + public SysUser selectUserByUserName(String userName) + { + return userMapper.selectUserByUserName(userName); + } + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + @Override + public SysUser selectUserById(Long userId) + { + return userMapper.selectUserById(userId); + } + + /** + * 查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserRoleGroup(String userName) + { + List list = roleMapper.selectRolesByUserName(userName); + StringBuffer idsStr = new StringBuffer(); + for (SysRole role : list) + { + idsStr.append(role.getRoleName()).append(","); + } + if (StringUtils.isNotEmpty(idsStr.toString())) + { + return idsStr.substring(0, idsStr.length() - 1); + } + return idsStr.toString(); + } + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserPostGroup(String userName) + { + List list = postMapper.selectPostsByUserName(userName); + StringBuffer idsStr = new StringBuffer(); + for (SysPost post : list) + { + idsStr.append(post.getPostName()).append(","); + } + if (StringUtils.isNotEmpty(idsStr.toString())) + { + return idsStr.substring(0, idsStr.length() - 1); + } + return idsStr.toString(); + } + + /** + * 校验用户名称是否唯一 + * + * @param userName 用户名称 + * @return 结果 + */ + @Override + public String checkUserNameUnique(String userName) + { + int count = userMapper.checkUserNameUnique(userName); + if (count > 0) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验用户名称是否唯一 + * + * @param user 用户信息 + * @return + */ + @Override + public String checkPhoneUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验email是否唯一 + * + * @param user 用户信息 + * @return + */ + @Override + public String checkEmailUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkEmailUnique(user.getEmail()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验用户是否允许操作 + * + * @param user 用户信息 + */ + @Override + public void checkUserAllowed(SysUser user) + { + if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) + { + throw new AppException("不允许操作超级管理员用户"); + } + } + + /** + * 新增保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional + public int insertUser(SysUser user) + { + // 新增用户信息 + int rows = userMapper.insertUser(user); + // 新增用户岗位关联 + insertUserPost(user); + // 新增用户与角色管理 + insertUserRole(user); + return rows; + } + + /** + * 修改保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional + public int updateUser(SysUser user) + { + Long userId = user.getUserId(); + // 删除用户与角色关联 + userRoleMapper.deleteUserRoleByUserId(userId); + // 新增用户与角色管理 + insertUserRole(user); + // 删除用户与岗位关联 + userPostMapper.deleteUserPostByUserId(userId); + // 新增用户与岗位管理 + insertUserPost(user); + return userMapper.updateUser(user); + } + + /** + * 修改用户状态 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int updateUserStatus(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 修改用户基本信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int updateUserProfile(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + @Override + public boolean updateUserAvatar(String userName, String avatar) + { + return userMapper.updateUserAvatar(userName, avatar) > 0; + } + + /** + * 重置用户密码 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int resetPwd(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + @Override + public int resetUserPwd(String userName, String password) + { + return userMapper.resetUserPwd(userName, password); + } + + /** + * 新增用户角色信息 + * + * @param user 用户对象 + */ + public void insertUserRole(SysUser user) + { + Long[] roles = user.getRoleIds(); + if (StringUtils.isNotNull(roles)) + { + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long roleId : roles) + { + SysUserRole ur = new SysUserRole(); + ur.setUserId(user.getUserId()); + ur.setRoleId(roleId); + list.add(ur); + } + if (list.size() > 0) + { + userRoleMapper.batchUserRole(list); + } + } + } + + /** + * 新增用户岗位信息 + * + * @param user 用户对象 + */ + public void insertUserPost(SysUser user) + { + Long[] posts = user.getPostIds(); + if (StringUtils.isNotNull(posts)) + { + // 新增用户与岗位管理 + List list = new ArrayList(); + for (Long postId : posts) + { + SysUserPost up = new SysUserPost(); + up.setUserId(user.getUserId()); + up.setPostId(postId); + list.add(up); + } + if (list.size() > 0) + { + userPostMapper.batchUserPost(list); + } + } + } + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + @Override + @Transactional + public int deleteUserById(Long userId) + { + // 删除用户与角色关联 + userRoleMapper.deleteUserRoleByUserId(userId); + // 删除用户与岗位表 + userPostMapper.deleteUserPostByUserId(userId); + return userMapper.deleteUserById(userId); + } + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + @Override + @Transactional + public int deleteUserByIds(Long[] userIds) + { + for (Long userId : userIds) + { + checkUserAllowed(new SysUser(userId)); + } + // 删除用户与角色关联 + userRoleMapper.deleteUserRole(userIds); + // 删除用户与岗位关联 + userPostMapper.deleteUserPost(userIds); + return userMapper.deleteUserByIds(userIds); + } + + /** + * 导入用户数据 + * + * @param userList 用户数据列表 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param operName 操作用户 + * @return 结果 + */ + @Override + public String importUser(List userList, Boolean isUpdateSupport, String operName) + { + if (StringUtils.isNull(userList) || userList.size() == 0) + { + throw new AppException("导入用户数据不能为空!"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + String password = configService.selectConfigByKey("sys.user.initPassword"); + for (SysUser user : userList) + { + try + { + // 验证是否存在这个用户 + SysUser u = userMapper.selectUserByUserName(user.getUserName()); + if (StringUtils.isNull(u)) + { + user.setPassword(SecurityUtils.encryptPassword(password)); + user.setCreateBy(operName); + this.insertUser(user); + successNum++; + successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 导入成功"); + } + else if (isUpdateSupport) + { + user.setUpdateBy(operName); + this.updateUser(user); + successNum++; + successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 更新成功"); + } + else + { + failureNum++; + failureMsg.append("
" + failureNum + "、账号 " + user.getUserName() + " 已存在"); + } + } + catch (Exception e) + { + failureNum++; + String msg = "
" + failureNum + "、账号 " + user.getUserName() + " 导入失败:"; + failureMsg.append(msg + e.getMessage()); + log.error(msg, e); + } + } + if (failureNum > 0) + { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new AppException(failureMsg.toString()); + } + else + { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } +} diff --git a/src/main/java/cn/sliyun/project/tool/swagger/TestController.java b/src/main/java/cn/sliyun/project/tool/swagger/TestController.java new file mode 100644 index 0000000..cdbade9 --- /dev/null +++ b/src/main/java/cn/sliyun/project/tool/swagger/TestController.java @@ -0,0 +1,151 @@ +package cn.sliyun.project.tool.swagger; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import cn.sliyun.common.utils.StringUtils; +import cn.sliyun.framework.web.controller.BaseController; +import cn.sliyun.framework.web.domain.AjaxResult; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; + +/** + * swagger 用户测试方法 + * + * @author ruoyi + */ +@Api("用户信息管理") +@RestController +@RequestMapping("/test/user") +public class TestController extends BaseController { + private final static Map users = new LinkedHashMap(); + + { + users.put(1, new UserEntity(1, "admin", "admin123", "15888888888")); + users.put(2, new UserEntity(2, "ry", "admin123", "15666666666")); + } + + @ApiOperation("获取用户列表") + @GetMapping("/list") + public AjaxResult userList() { + List userList = new ArrayList(users.values()); + return AjaxResult.success(userList); + } + + @ApiOperation("获取用户详细") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path") + @GetMapping("/{userId}") + public AjaxResult getUser(@PathVariable Integer userId) { + if (!users.isEmpty() && users.containsKey(userId)) { + return AjaxResult.success(users.get(userId)); + } else { + return AjaxResult.error("用户不存在"); + } + } + + @ApiOperation("新增用户") + @ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity") + @PostMapping("/save") + public AjaxResult save(UserEntity user) { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) { + return AjaxResult.error("用户ID不能为空"); + } + return AjaxResult.success(users.put(user.getUserId(), user)); + } + + @ApiOperation("更新用户") + @ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity") + @PutMapping("/update") + public AjaxResult update(UserEntity user) { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) { + return AjaxResult.error("用户ID不能为空"); + } + if (users.isEmpty() || !users.containsKey(user.getUserId())) { + return AjaxResult.error("用户不存在"); + } + users.remove(user.getUserId()); + return AjaxResult.success(users.put(user.getUserId(), user)); + } + + @ApiOperation("删除用户信息") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path") + @DeleteMapping("/{userId}") + public AjaxResult delete(@PathVariable Integer userId) { + if (!users.isEmpty() && users.containsKey(userId)) { + users.remove(userId); + return AjaxResult.success(); + } else { + return AjaxResult.error("用户不存在"); + } + } +} + +@ApiModel("用户实体") +class UserEntity { + @ApiModelProperty("用户ID") + private Integer userId; + + @ApiModelProperty("用户名称") + private String username; + + @ApiModelProperty("用户密码") + private String password; + + @ApiModelProperty("用户手机") + private String mobile; + + public UserEntity() { + + } + + public UserEntity(Integer userId, String username, String password, String mobile) { + this.userId = userId; + this.username = username; + this.password = password; + this.mobile = mobile; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } +} diff --git a/src/main/resources/META-INF/spring-devtools.properties b/src/main/resources/META-INF/spring-devtools.properties new file mode 100644 index 0000000..2b23f85 --- /dev/null +++ b/src/main/resources/META-INF/spring-devtools.properties @@ -0,0 +1 @@ +restart.include.json=/com.alibaba.fastjson.*.jar \ No newline at end of file diff --git a/src/main/resources/application-druid.properties b/src/main/resources/application-druid.properties new file mode 100644 index 0000000..52ade92 --- /dev/null +++ b/src/main/resources/application-druid.properties @@ -0,0 +1,27 @@ +spring.datasource.type=com.alibaba.druid.pool.DruidDataSource +spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://rm-wz99smt6zjv8tt10x1250109m.mysql.rds.aliyuncs.com:3306/sliyun +spring.datasource.username=sliyun +spring.datasource.password=Nf46KD8MCTN3jWKZ +spring.datasource.druid.initialSize=5 +spring.datasource.druid.minIdle=10 +spring.datasource.druid.maxActive=20 +spring.datasource.druid.maxWait=60000 +spring.datasource.druid.timeBetweenEvictionRunsMillis=60000 +spring.datasource.druid.minEvictableIdleTimeMillis=300000 +spring.datasource.druid.maxEvictableIdleTimeMillis=900000 +spring.datasource.druid.validationQuery=SELECT 1 FROM DUAL +spring.datasource.druid.testWhileIdle=true +spring.datasource.druid.testOnBorrow=false +spring.datasource.druid.testOnReturn=false +spring.datasource.druid.webStatFilter.enabled=true +spring.datasource.druid.statViewServlet.enabled=true +spring.datasource.druid.statViewServlet.allow= +spring.datasource.druid.statViewServlet.url-pattern=/druid/* +spring.datasource.druid.statViewServlet.login-username= +spring.datasource.druid.statViewServlet.login-password= +spring.datasource.druid.filter.stat.enabled=true +spring.datasource.druid.filter.stat.log-slow-sql=true +spring.datasource.druid.filter.stat.slow-sql-millis=1000 +spring.datasource.druid.filter.stat.merge-sql=true +spring.datasource.druid.filter.wall.config.multi-statement-allow=true diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..90fab70 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,54 @@ +ruoyi.name=RuoYi +ruoyi.version=3.4.0 +ruoyi.copyrightYear=2021 +ruoyi.demoEnabled=true +ruoyi.profile=D:/ruoyi/uploadPath +ruoyi.addressEnabled=false + +server.port=8891 +server.servlet.context-path=/ +server.tomcat.uri-encoding=UTF-8 +server.tomcat.max-threads=800 +server.tomcat.min-spare-threads=30 +logging.level.cn.sliyun=debug +logging.level.org.springframework=warn +spring.messages.basename=i18n/messages +spring.profiles.active=druid +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=20MB +spring.devtools.restart.enabled=true + +# token +token.header=Authorization +token.secret=abcdefghijklmnopqrstuvwxyz +token.expireTime=30 + +# mybatis +mybatis.typeAliasesPackage=cn.sliyun.project.**.domain,cn.sliyun.api.**.mapper +mybatis.mapperLocations=classpath*:mybatis/**/*Mapper.xml +mybatis.configLocation=classpath:mybatis/mybatis-config.xml + +# pagehelper +pagehelper.helperDialect=mysql +pagehelper.reasonable=true +pagehelper.supportMethodsArguments=true +pagehelper.params=count=countSql + +# swagger +swagger.enabled=true +swagger.pathMapping=/dev-api + +# xss +xss.enabled=true +xss.excludes=/system/notice/* +xss.urlPatterns=/system/*,/monitor/*,/tool/* + + + +#OSS suanliyun@dev-cloud.onaliyun.com +oss.file.endpoint=oss-cn-shenzhen.aliyuncs.com +oss.file.keyid=LTAI4Fzx7TLLrN9UegkH6kxT +oss.file.keysecret=5bEch3N7yWRDCudGvtfrh7pwaMIQO1 +oss.file.filehost= +oss.file.bucketname=suanlicloud + diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000..15b45aa --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,26 @@ +//////////////////////////////////////////////////////////////////// +// _ooOoo_ // +// o8888888o // +// 88" . "88 // +// (| ^_^ |) // +// O\ = /O // +// ____/`---'\____ // +// .' \\| |// `. // +// / \\||| : |||// \ // +// / _||||| -:- |||||- \ // +// | | \\\ - /// | | // +// | \_| ''\---/'' | | // +// \ .-\__ `-` ___/-. / // +// ___`. .' /--.--\ `. . ___ // +// ."" '< `.___\_<|>_/___.' >'"". // +// | | : `- \`.;`\ _ /`;.`/ - ` : | | // +// \ \ `-. \_ __\ /__ _/ .-` / / // +// ========`-.____`-.___\_____/___.-`____.-'======== // +// `=---=' // +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // +// 佛祖保佑 永不宕机 永无BUG // +//////////////////////////////////////////////////////////////////// +application.version: ${application.version} +application.formatted-version: ${application.formatted-version} +springboot -version: ${spring-boot.version} +springboot-formatted-version: ${spring-boot.formatted-version} \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..73e2a88 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/sys-info.log + + + + ${log.path}/sys-info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/sys-error.log + + + + ${log.path}/sys-error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + ${log.path}/sys-user.log + + + ${log.path}/sys-user.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/monitor/SysLogininforMapper.xml b/src/main/resources/mybatis/monitor/SysLogininforMapper.xml new file mode 100644 index 0000000..b95df13 --- /dev/null +++ b/src/main/resources/mybatis/monitor/SysLogininforMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + insert into sys_logininfor (user_name, status, ipaddr, login_location, browser, os, msg, login_time) + values (#{userName}, #{status}, #{ipaddr}, #{loginLocation}, #{browser}, #{os}, #{msg}, sysdate()) + + + + + + delete from sys_logininfor where info_id in + + #{infoId} + + + + + truncate table sys_logininfor + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/monitor/SysOperLogMapper.xml b/src/main/resources/mybatis/monitor/SysOperLogMapper.xml new file mode 100644 index 0000000..ea3faaf --- /dev/null +++ b/src/main/resources/mybatis/monitor/SysOperLogMapper.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time + from sys_oper_log + + + + insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time) + values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, sysdate()) + + + + + + delete from sys_oper_log where oper_id in + + #{operId} + + + + + + + truncate table sys_oper_log + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/mybatis-config.xml b/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 0000000..e8b52be --- /dev/null +++ b/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/src/main/resources/mybatis/system/SysConfigMapper.xml b/src/main/resources/mybatis/system/SysConfigMapper.xml new file mode 100644 index 0000000..08608f3 --- /dev/null +++ b/src/main/resources/mybatis/system/SysConfigMapper.xml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + select config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark + from sys_config + + + + + + + and config_id = #{configId} + + + and config_key = #{configKey} + + + + + + + + + + + + insert into sys_config ( + config_name, + config_key, + config_value, + config_type, + create_by, + remark, + create_time + )values( + #{configName}, + #{configKey}, + #{configValue}, + #{configType}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update sys_config + + config_name = #{configName}, + config_key = #{configKey}, + config_value = #{configValue}, + config_type = #{configType}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where config_id = #{configId} + + + + delete from sys_config where config_id = #{configId} + + + + delete from sys_config where config_id in + + #{configId} + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysDeptMapper.xml b/src/main/resources/mybatis/system/SysDeptMapper.xml new file mode 100644 index 0000000..2ae67c5 --- /dev/null +++ b/src/main/resources/mybatis/system/SysDeptMapper.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time + from sys_dept d + + + + + + + + + + + + + + + + + + + + insert into sys_dept( + dept_id, + parent_id, + dept_name, + ancestors, + order_num, + leader, + phone, + email, + status, + create_by, + create_time + )values( + #{deptId}, + #{parentId}, + #{deptName}, + #{ancestors}, + #{orderNum}, + #{leader}, + #{phone}, + #{email}, + #{status}, + #{createBy}, + sysdate() + ) + + + + update sys_dept + + parent_id = #{parentId}, + dept_name = #{deptName}, + ancestors = #{ancestors}, + order_num = #{orderNum}, + leader = #{leader}, + phone = #{phone}, + email = #{email}, + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where dept_id = #{deptId} + + + + update sys_dept set ancestors = + + when #{item.deptId} then #{item.ancestors} + + where dept_id in + + #{item.deptId} + + + + + update sys_dept + + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where dept_id in (${ancestors}) + + + + update sys_dept set del_flag = '2' where dept_id = #{deptId} + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysDictDataMapper.xml b/src/main/resources/mybatis/system/SysDictDataMapper.xml new file mode 100644 index 0000000..24abaf4 --- /dev/null +++ b/src/main/resources/mybatis/system/SysDictDataMapper.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark + from sys_dict_data + + + + + + + + + + + + + + delete from sys_dict_data where dict_code = #{dictCode} + + + + delete from sys_dict_data where dict_code in + + #{dictCode} + + + + + update sys_dict_data + + dict_sort = #{dictSort}, + dict_label = #{dictLabel}, + dict_value = #{dictValue}, + dict_type = #{dictType}, + css_class = #{cssClass}, + list_class = #{listClass}, + is_default = #{isDefault}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where dict_code = #{dictCode} + + + + update sys_dict_data set dict_type = #{newDictType} where dict_type = #{oldDictType} + + + + insert into sys_dict_data( + dict_sort, + dict_label, + dict_value, + dict_type, + css_class, + list_class, + is_default, + status, + remark, + create_by, + create_time + )values( + #{dictSort}, + #{dictLabel}, + #{dictValue}, + #{dictType}, + #{cssClass}, + #{listClass}, + #{isDefault}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysDictTypeMapper.xml b/src/main/resources/mybatis/system/SysDictTypeMapper.xml new file mode 100644 index 0000000..ab179f1 --- /dev/null +++ b/src/main/resources/mybatis/system/SysDictTypeMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + select dict_id, dict_name, dict_type, status, create_by, create_time, remark + from sys_dict_type + + + + + + + + + + + + + + delete from sys_dict_type where dict_id = #{dictId} + + + + delete from sys_dict_type where dict_id in + + #{dictId} + + + + + update sys_dict_type + + dict_name = #{dictName}, + dict_type = #{dictType}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where dict_id = #{dictId} + + + + insert into sys_dict_type( + dict_name, + dict_type, + status, + remark, + create_by, + create_time + )values( + #{dictName}, + #{dictType}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysMenuMapper.xml b/src/main/resources/mybatis/system/SysMenuMapper.xml new file mode 100644 index 0000000..2b58c2f --- /dev/null +++ b/src/main/resources/mybatis/system/SysMenuMapper.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + select menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time + from sys_menu + + + + + + + + + + + + + + + + + + + + + + + + update sys_menu + + menu_name = #{menuName}, + parent_id = #{parentId}, + order_num = #{orderNum}, + path = #{path}, + component = #{component}, + is_frame = #{isFrame}, + is_cache = #{isCache}, + menu_type = #{menuType}, + visible = #{visible}, + status = #{status}, + perms = #{perms}, + icon = #{icon}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where menu_id = #{menuId} + + + + insert into sys_menu( + menu_id, + parent_id, + menu_name, + order_num, + path, + component, + is_frame, + is_cache, + menu_type, + visible, + status, + perms, + icon, + remark, + create_by, + create_time + )values( + #{menuId}, + #{parentId}, + #{menuName}, + #{orderNum}, + #{path}, + #{component}, + #{isFrame}, + #{isCache}, + #{menuType}, + #{visible}, + #{status}, + #{perms}, + #{icon}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from sys_menu where menu_id = #{menuId} + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysNoticeMapper.xml b/src/main/resources/mybatis/system/SysNoticeMapper.xml new file mode 100644 index 0000000..51d1f40 --- /dev/null +++ b/src/main/resources/mybatis/system/SysNoticeMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + select notice_id, notice_title, notice_type, cast(notice_content as char) as notice_content, status, create_by, create_time, update_by, update_time, remark + from sys_notice + + + + + + + + insert into sys_notice ( + notice_title, + notice_type, + notice_content, + status, + remark, + create_by, + create_time + )values( + #{noticeTitle}, + #{noticeType}, + #{noticeContent}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update sys_notice + + notice_title = #{noticeTitle}, + notice_type = #{noticeType}, + notice_content = #{noticeContent}, + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where notice_id = #{noticeId} + + + + delete from sys_notice where notice_id = #{noticeId} + + + + delete from sys_notice where notice_id in + + #{noticeId} + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysPostMapper.xml b/src/main/resources/mybatis/system/SysPostMapper.xml new file mode 100644 index 0000000..f5b613a --- /dev/null +++ b/src/main/resources/mybatis/system/SysPostMapper.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + select post_id, post_code, post_name, post_sort, status, create_by, create_time, remark + from sys_post + + + + + + + + + + + + + + + + + + update sys_post + + post_code = #{postCode}, + post_name = #{postName}, + post_sort = #{postSort}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where post_id = #{postId} + + + + insert into sys_post( + post_id, + post_code, + post_name, + post_sort, + status, + remark, + create_by, + create_time + )values( + #{postId}, + #{postCode}, + #{postName}, + #{postSort}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from sys_post where post_id = #{postId} + + + + delete from sys_post where post_id in + + #{postId} + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysRoleDeptMapper.xml b/src/main/resources/mybatis/system/SysRoleDeptMapper.xml new file mode 100644 index 0000000..b482b79 --- /dev/null +++ b/src/main/resources/mybatis/system/SysRoleDeptMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_role_dept where role_id=#{roleId} + + + + + + delete from sys_role_dept where role_id in + + #{roleId} + + + + + insert into sys_role_dept(role_id, dept_id) values + + (#{item.roleId},#{item.deptId}) + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysRoleMapper.xml b/src/main/resources/mybatis/system/SysRoleMapper.xml new file mode 100644 index 0000000..852f2ef --- /dev/null +++ b/src/main/resources/mybatis/system/SysRoleMapper.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly, + r.status, r.del_flag, r.create_time, r.remark + from sys_role r + left join sys_user_role ur on ur.role_id = r.role_id + left join sys_user u on u.user_id = ur.user_id + left join sys_dept d on u.dept_id = d.dept_id + + + + + + + + + + + + + + + + + + + + insert into sys_role( + role_id, + role_name, + role_key, + role_sort, + data_scope, + menu_check_strictly, + dept_check_strictly, + status, + remark, + create_by, + create_time + )values( + #{roleId}, + #{roleName}, + #{roleKey}, + #{roleSort}, + #{dataScope}, + #{menuCheckStrictly}, + #{deptCheckStrictly}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update sys_role + + role_name = #{roleName}, + role_key = #{roleKey}, + role_sort = #{roleSort}, + data_scope = #{dataScope}, + menu_check_strictly = #{menuCheckStrictly}, + dept_check_strictly = #{deptCheckStrictly}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where role_id = #{roleId} + + + + update sys_user set status = #{status} where user_id = #{userId} + + + + delete from sys_role where role_id = #{roleId} + + + + update sys_role set del_flag = '2' where role_id in + + #{roleId} + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysRoleMenuMapper.xml b/src/main/resources/mybatis/system/SysRoleMenuMapper.xml new file mode 100644 index 0000000..2ce33fb --- /dev/null +++ b/src/main/resources/mybatis/system/SysRoleMenuMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + delete from sys_role_menu where role_id=#{roleId} + + + + delete from sys_role_menu where role_id in + + #{roleId} + + + + + insert into sys_role_menu(role_id, menu_id) values + + (#{item.roleId},#{item.menuId}) + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysUserMapper.xml b/src/main/resources/mybatis/system/SysUserMapper.xml new file mode 100644 index 0000000..e769e17 --- /dev/null +++ b/src/main/resources/mybatis/system/SysUserMapper.xml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, + d.dept_id, d.parent_id, d.dept_name, d.order_num, d.leader, d.status as dept_status, + r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status + from sys_user u + left join sys_dept d on u.dept_id = d.dept_id + left join sys_user_role ur on u.user_id = ur.user_id + left join sys_role r on r.role_id = ur.role_id + + + + + + + + + + + + + + + + insert into sys_user( + user_id, + dept_id, + user_name, + nick_name, + email, + avatar, + phonenumber, + sex, + password, + status, + create_by, + remark, + create_time + )values( + #{userId}, + #{deptId}, + #{userName}, + #{nickName}, + #{email}, + #{avatar}, + #{phonenumber}, + #{sex}, + #{password}, + #{status}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update sys_user + + dept_id = #{deptId}, + user_name = #{userName}, + nick_name = #{nickName}, + email = #{email}, + phonenumber = #{phonenumber}, + sex = #{sex}, + avatar = #{avatar}, + password = #{password}, + status = #{status}, + login_ip = #{loginIp}, + login_date = #{loginDate}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where user_id = #{userId} + + + + update sys_user set status = #{status} where user_id = #{userId} + + + + update sys_user set avatar = #{avatar} where user_name = #{userName} + + + + update sys_user set password = #{password} where user_name = #{userName} + + + + delete from sys_user where user_id = #{userId} + + + + update sys_user set del_flag = '2' where user_id in + + #{userId} + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysUserPostMapper.xml b/src/main/resources/mybatis/system/SysUserPostMapper.xml new file mode 100644 index 0000000..7cc31be --- /dev/null +++ b/src/main/resources/mybatis/system/SysUserPostMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_user_post where user_id=#{userId} + + + + + + delete from sys_user_post where user_id in + + #{userId} + + + + + insert into sys_user_post(user_id, post_id) values + + (#{item.userId},#{item.postId}) + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/SysUserRoleMapper.xml b/src/main/resources/mybatis/system/SysUserRoleMapper.xml new file mode 100644 index 0000000..9421709 --- /dev/null +++ b/src/main/resources/mybatis/system/SysUserRoleMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + delete from sys_user_role where user_id=#{userId} + + + + + + delete from sys_user_role where user_id in + + #{userId} + + + + + insert into sys_user_role(user_id, role_id) values + + (#{item.userId},#{item.roleId}) + + + + + delete from sys_user_role where user_id=#{userId} and role_id=#{roleId} + + + + delete from sys_user_role where role_id=#{roleId} and user_id in + + #{userId} + + + \ No newline at end of file