├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── demo.png ├── demo1.jpg ├── demo2.jpg ├── demo3.jpg ├── demo4.png ├── dev ├── Dockerfile └── docker-compose.yml ├── dmo3.jpg ├── golang.conf ├── mvnw ├── mvnw.cmd ├── pom.xml ├── scripts └── init.sh └── src ├── main ├── java │ └── com │ │ └── bektz │ │ └── dataplatformsoar │ │ ├── DataPlatformSoarApplication.java │ │ ├── config.java │ │ ├── configs │ │ ├── MyWebSocketHandler.java │ │ ├── ParamValidAop.java │ │ ├── SoarConfiguration.java │ │ └── WebSocketConfig.java │ │ ├── constants │ │ ├── Common.java │ │ ├── JdbcConstants.java │ │ ├── QueryStatus.java │ │ └── QueryType.java │ │ ├── controller │ │ ├── PageController.java │ │ ├── SchemaController.java │ │ ├── SoarController.java │ │ └── handler │ │ │ └── ControllerExceptionHandleAdvice.java │ │ ├── exception │ │ ├── BektzClientException.java │ │ ├── BektzException.java │ │ ├── BektzServerException.java │ │ └── SqlParserException.java │ │ ├── repository │ │ ├── SecretColumnRepository.java │ │ └── domain │ │ │ └── SecretColumn.java │ │ ├── req │ │ ├── SchemaReq.java │ │ └── SqlVerifyReq.java │ │ ├── resp │ │ ├── GenericResponse.java │ │ ├── JdbcResultResp.java │ │ ├── SchemaResp.java │ │ └── SqlVerifyResp.java │ │ ├── service │ │ ├── SchemaService.java │ │ ├── SoarService.java │ │ └── jdbc │ │ │ ├── DataSourceManager.java │ │ │ └── JdbcTemplate.java │ │ └── sqlparser │ │ ├── ColumnItem.java │ │ ├── CommonFactory.java │ │ ├── SqlParserService.java │ │ └── druid │ │ ├── AbstractDruidSqlParSer.java │ │ ├── DruidParserHasAsterisk.java │ │ ├── DruidParserNonAsterisk.java │ │ ├── DruidSqlParser.java │ │ └── visitor │ │ └── DefineMySqlSchemaStatVisitor.java └── resources │ ├── application.yml │ ├── soar.yml │ ├── static │ ├── css │ │ └── prism.css │ ├── images │ │ └── face │ │ │ ├── 0.gif │ │ │ ├── 1.gif │ │ │ ├── 10.gif │ │ │ ├── 11.gif │ │ │ ├── 12.gif │ │ │ ├── 13.gif │ │ │ ├── 14.gif │ │ │ ├── 15.gif │ │ │ ├── 16.gif │ │ │ ├── 17.gif │ │ │ ├── 18.gif │ │ │ ├── 19.gif │ │ │ ├── 2.gif │ │ │ ├── 20.gif │ │ │ ├── 21.gif │ │ │ ├── 22.gif │ │ │ ├── 23.gif │ │ │ ├── 24.gif │ │ │ ├── 25.gif │ │ │ ├── 26.gif │ │ │ ├── 27.gif │ │ │ ├── 28.gif │ │ │ ├── 29.gif │ │ │ ├── 3.gif │ │ │ ├── 30.gif │ │ │ ├── 31.gif │ │ │ ├── 32.gif │ │ │ ├── 33.gif │ │ │ ├── 34.gif │ │ │ ├── 35.gif │ │ │ ├── 36.gif │ │ │ ├── 37.gif │ │ │ ├── 38.gif │ │ │ ├── 39.gif │ │ │ ├── 4.gif │ │ │ ├── 40.gif │ │ │ ├── 41.gif │ │ │ ├── 42.gif │ │ │ ├── 43.gif │ │ │ ├── 44.gif │ │ │ ├── 45.gif │ │ │ ├── 46.gif │ │ │ ├── 47.gif │ │ │ ├── 48.gif │ │ │ ├── 49.gif │ │ │ ├── 5.gif │ │ │ ├── 50.gif │ │ │ ├── 51.gif │ │ │ ├── 52.gif │ │ │ ├── 53.gif │ │ │ ├── 54.gif │ │ │ ├── 55.gif │ │ │ ├── 56.gif │ │ │ ├── 57.gif │ │ │ ├── 58.gif │ │ │ ├── 59.gif │ │ │ ├── 6.gif │ │ │ ├── 60.gif │ │ │ ├── 61.gif │ │ │ ├── 62.gif │ │ │ ├── 63.gif │ │ │ ├── 64.gif │ │ │ ├── 65.gif │ │ │ ├── 66.gif │ │ │ ├── 67.gif │ │ │ ├── 68.gif │ │ │ ├── 69.gif │ │ │ ├── 7.gif │ │ │ ├── 70.gif │ │ │ ├── 71.gif │ │ │ ├── 8.gif │ │ │ └── 9.gif │ ├── jquery.js │ ├── js │ │ ├── form.js │ │ ├── lay.js │ │ ├── prism.js │ │ └── websocket.js │ └── layui │ │ ├── css │ │ ├── layui.css │ │ ├── layui.mobile.css │ │ └── modules │ │ │ ├── code.css │ │ │ ├── laydate │ │ │ └── default │ │ │ │ └── laydate.css │ │ │ └── layer │ │ │ └── default │ │ │ ├── icon-ext.png │ │ │ ├── icon.png │ │ │ ├── layer.css │ │ │ ├── loading-0.gif │ │ │ ├── loading-1.gif │ │ │ └── loading-2.gif │ │ ├── font │ │ ├── iconfont.eot │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ └── iconfont.woff │ │ ├── images │ │ └── face │ │ │ ├── 0.gif │ │ │ ├── 1.gif │ │ │ ├── 10.gif │ │ │ ├── 11.gif │ │ │ ├── 12.gif │ │ │ ├── 13.gif │ │ │ ├── 14.gif │ │ │ ├── 15.gif │ │ │ ├── 16.gif │ │ │ ├── 17.gif │ │ │ ├── 18.gif │ │ │ ├── 19.gif │ │ │ ├── 2.gif │ │ │ ├── 20.gif │ │ │ ├── 21.gif │ │ │ ├── 22.gif │ │ │ ├── 23.gif │ │ │ ├── 24.gif │ │ │ ├── 25.gif │ │ │ ├── 26.gif │ │ │ ├── 27.gif │ │ │ ├── 28.gif │ │ │ ├── 29.gif │ │ │ ├── 3.gif │ │ │ ├── 30.gif │ │ │ ├── 31.gif │ │ │ ├── 32.gif │ │ │ ├── 33.gif │ │ │ ├── 34.gif │ │ │ ├── 35.gif │ │ │ ├── 36.gif │ │ │ ├── 37.gif │ │ │ ├── 38.gif │ │ │ ├── 39.gif │ │ │ ├── 4.gif │ │ │ ├── 40.gif │ │ │ ├── 41.gif │ │ │ ├── 42.gif │ │ │ ├── 43.gif │ │ │ ├── 44.gif │ │ │ ├── 45.gif │ │ │ ├── 46.gif │ │ │ ├── 47.gif │ │ │ ├── 48.gif │ │ │ ├── 49.gif │ │ │ ├── 5.gif │ │ │ ├── 50.gif │ │ │ ├── 51.gif │ │ │ ├── 52.gif │ │ │ ├── 53.gif │ │ │ ├── 54.gif │ │ │ ├── 55.gif │ │ │ ├── 56.gif │ │ │ ├── 57.gif │ │ │ ├── 58.gif │ │ │ ├── 59.gif │ │ │ ├── 6.gif │ │ │ ├── 60.gif │ │ │ ├── 61.gif │ │ │ ├── 62.gif │ │ │ ├── 63.gif │ │ │ ├── 64.gif │ │ │ ├── 65.gif │ │ │ ├── 66.gif │ │ │ ├── 67.gif │ │ │ ├── 68.gif │ │ │ ├── 69.gif │ │ │ ├── 7.gif │ │ │ ├── 70.gif │ │ │ ├── 71.gif │ │ │ ├── 8.gif │ │ │ └── 9.gif │ │ ├── lay │ │ └── modules │ │ │ ├── carousel.js │ │ │ ├── code.js │ │ │ ├── colorpicker.js │ │ │ ├── element.js │ │ │ ├── flow.js │ │ │ ├── form.js │ │ │ ├── jquery.js │ │ │ ├── laydate.js │ │ │ ├── layedit.js │ │ │ ├── layer.js │ │ │ ├── laypage.js │ │ │ ├── laytpl.js │ │ │ ├── mobile.js │ │ │ ├── rate.js │ │ │ ├── slider.js │ │ │ ├── table.js │ │ │ ├── tree.js │ │ │ ├── upload.js │ │ │ └── util.js │ │ ├── layui.all.js │ │ └── layui.js │ └── templates │ ├── index.html │ └── schema.html └── test └── java └── com └── bektz └── dataplatformsoar ├── DataPlatformSoarApplicationTests.java ├── MysqlTest.java ├── SqlParserTest.java ├── service └── SoarServiceTest.java └── sqlparser └── DruidSqlParserTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # data-platform-soar 2 | 3 | ## 介绍 4 | 基于小米开源工具soar的java应用(sql审核平台),本项目是一个简单的spring boot应用,前端是采用前端开源框架layui,前端与后端的通信采用的是websocket方式 5 | ```txt 6 | 1.可以动态添加数据库,对指定表进行数据查询(没有对查询数据量没有限制) 7 | 2.集成soar,可以对平日的sql进行审核分析,规范sql的编写 8 | 3.通过druid对sql进行解析,可以对查询表做屏蔽敏感字段(需要完善) 9 | ``` 10 | 11 | ### 运行 12 | 13 | #### 1. 推荐方式 14 | ``` shell 15 | 1.请参考soar的官方教程安装soar,并将soar的路径加入环境变量 16 | 17 | 2.进入项目主目录 18 | 19 | 3.mvn package -Dmaven.test.skip=true dependency:copy 20 | 21 | 4.cd dev 22 | 23 | 5.nohup java -jar data-soar.jar & 24 | 25 | ``` 26 | ``` html 27 | 通过 http://localhost:8080 访问 28 | ``` 29 | 30 | #### 2. docker运行 31 | 32 | ``` shell 33 | 1.进入项目主目录 34 | 2.mvn package dependency:copy 35 | 3.wget http://golangtc.com/static/go/go1.10.3.linux-amd64.tar.gz 36 | 4.docker build -f dev/Dockerfile -t boot-soar:latest --rm=true . 37 | 5.docker run 38 | ``` 39 | ``` html 40 | 通过 http://localhost:8080 访问 41 | ``` 42 | 43 | ### DEMO 44 | ![Aaron Swartz](https://github.com/beiketianzhuang/data-platform-verfiy/blob/master/demo1.jpg) 45 | ![Aaron Swartz](https://github.com/beiketianzhuang/data-platform-verfiy/blob/master/demo2.jpg) 46 | ![Aaron Swartz](https://github.com/beiketianzhuang/data-platform-verfiy/blob/master/demo3.jpg) 47 | ![Aaron Swartz](https://github.com/beiketianzhuang/data-platform-verfiy/blob/master/demo4.png) 48 | -------------------------------------------------------------------------------- /demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/demo.png -------------------------------------------------------------------------------- /demo1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/demo1.jpg -------------------------------------------------------------------------------- /demo2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/demo2.jpg -------------------------------------------------------------------------------- /demo3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/demo3.jpg -------------------------------------------------------------------------------- /demo4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/demo4.png -------------------------------------------------------------------------------- /dev/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos 2 | MAINTAINER chenlang@lattebank.com 3 | 4 | RUN yum install -y \ 5 | java-1.8.0-openjdk \ 6 | java-1.8.0-openjdk-devel \ 7 | wget \ 8 | git 9 | 10 | ADD go1.10.3.linux-amd64.tar.gz /root 11 | ADD golang.conf /root/golang.conf 12 | RUN mv /root/go /usr/local/ 13 | RUN cat /root/golang.conf >> /etc/profile 14 | RUN echo "source /etc/profile" >> /root/.bashrc 15 | RUN mkdir -p /home/golang 16 | 17 | ENV TZ Asia/Shanghai 18 | ENV JAVA_HOME /etc/alternatives/jre 19 | ENV SERVER_PORT 8080 20 | ENV JMX_PORT 1099 21 | ENV JAVA_OPTS "-Xmx2G -Xms500M" 22 | ENV APP_NAME data-soar 23 | ENV SPRING_PROFILES_ACTIVE dev 24 | 25 | RUN mkdir /tmp/deploy/ 26 | COPY dev/data-soar.jar /tmp/deploy/app.jar 27 | RUN go get -d github.com/XiaoMi/soar 28 | RUN cd ${GOPATH}/src/github.com/XiaoMi/soar && make 29 | 30 | EXPOSE 8080 1099 31 | 32 | ENTRYPOINT exec java $JAVA_OPTS -jar /tmp/deploy/app.jar -------------------------------------------------------------------------------- /dev/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | mysql: 4 | image: mariadb:latest 5 | container_name: mysql_service 6 | volumes: 7 | - ./data/mysql/data:/var/lib/mysql 8 | ports: 9 | - 3306:3306 10 | environment: 11 | - MYSQL_ROOT_PASSWORD=root 12 | data-platform-soar: 13 | build: . 14 | ports: 15 | - "8080:8080" 16 | networks: 17 | - local 18 | links: 19 | - "mysql" -------------------------------------------------------------------------------- /dmo3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/dmo3.jpg -------------------------------------------------------------------------------- /golang.conf: -------------------------------------------------------------------------------- 1 | export GOROOT=/usr/local/go 2 | export GOBIN=$GOROOT/bin 3 | export PATH=$PATH:$GOBIN 4 | export GOPATH=/home/golang -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" 124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( 125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | echo Found %WRAPPER_JAR% 132 | ) else ( 133 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 134 | echo Downloading from: %DOWNLOAD_URL% 135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" 136 | echo Finished downloading %WRAPPER_JAR% 137 | ) 138 | @REM End of extension 139 | 140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 141 | if ERRORLEVEL 1 goto error 142 | goto end 143 | 144 | :error 145 | set ERROR_CODE=1 146 | 147 | :end 148 | @endlocal & set ERROR_CODE=%ERROR_CODE% 149 | 150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 154 | :skipRcPost 155 | 156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 158 | 159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 160 | 161 | exit /B %ERROR_CODE% 162 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.bektz 7 | data-platform-soar 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | data-platform-soar 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.0.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.apache.commons 30 | commons-lang3 31 | 3.4 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-test 40 | test 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-web 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-websocket 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-data-jpa 53 | 54 | 55 | org.projectlombok 56 | lombok 57 | 1.18.2 58 | 59 | 60 | com.github.jsqlparser 61 | jsqlparser 62 | 1.2 63 | 64 | 65 | org.junit.jupiter 66 | junit-jupiter-api 67 | RELEASE 68 | 69 | 70 | org.springframework.boot 71 | spring-boot-starter-aop 72 | 73 | 74 | com.alibaba 75 | druid 76 | 1.1.10 77 | 78 | 79 | org.springframework.boot 80 | spring-boot-starter-thymeleaf 81 | 82 | 83 | org.springframework.boot 84 | spring-boot-starter-json 85 | 86 | 87 | org.springframework.boot 88 | spring-boot-devtools 89 | true 90 | 91 | 92 | mysql 93 | mysql-connector-java 94 | 95 | 96 | org.springframework.boot 97 | spring-boot-configuration-processor 98 | true 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | org.apache.maven.plugins 107 | maven-dependency-plugin 108 | 2.8 109 | 110 | 111 | copy-installed 112 | install 113 | 114 | copy 115 | 116 | 117 | 118 | 119 | 120 | 121 | ${project.groupId} 122 | ${project.artifactId} 123 | ${project.version} 124 | ${project.packaging} 125 | true 126 | data-soar.jar 127 | 128 | 129 | dev 130 | 131 | 132 | 133 | org.springframework.boot 134 | spring-boot-maven-plugin 135 | 136 | 137 | org.apache.maven.plugins 138 | maven-surefire-plugin 139 | 140 | false 141 | 142 | 143 | 144 | org.springframework.boot 145 | spring-boot-maven-plugin 146 | 147 | 148 | true 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /scripts/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | echo 'Check install environment' 5 | 6 | cmd="soar" 7 | 8 | if ! command -v "${cmd}" &> /dev/null ; then 9 | echo -e "\033[91m${cmd} is not set.Eg:\nalias ${cmd}=/root/${cmd}\nexport ${cmd}=/root/${cmd}\033[0m" 10 | wget https://github.com/XiaoMi/soar/releases/download/v0.8.1/soar.linux-amd64 -O soar 11 | chmod a+x soar 12 | go get -d github.com/XiaoMi/soar 13 | cd ${GOPATH}/src/github.com/XiaoMi/soar && make 14 | exit 1 15 | else 16 | echo "${cmd} is ok" 17 | fi -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/DataPlatformSoarApplication.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 7 | import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration; 8 | 9 | @SpringBootApplication 10 | @EnableAutoConfiguration(exclude={JdbcTemplateAutoConfiguration.class,DataSourceAutoConfiguration.class}) 11 | public class DataPlatformSoarApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(DataPlatformSoarApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/config.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.env.YamlPropertySourceLoader; 5 | import org.springframework.core.env.PropertySource; 6 | import org.springframework.core.io.ClassPathResource; 7 | import org.springframework.core.io.Resource; 8 | 9 | import java.io.IOException; 10 | 11 | public class config { 12 | private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); 13 | 14 | @Test 15 | public void test () { 16 | Resource path = new ClassPathResource("soar.yml"); 17 | PropertySource propertySource = loadYaml(path); 18 | } 19 | 20 | private PropertySource loadYaml(Resource path) { 21 | if (!path.exists()) { 22 | throw new IllegalArgumentException("Resource " + path + " does not exist"); 23 | } 24 | try { 25 | return this.loader.load("custom-resource", path).get(0); 26 | } 27 | catch (IOException ex) { 28 | throw new IllegalStateException( 29 | "Failed to load yaml configuration from " + path, ex); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/configs/MyWebSocketHandler.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.configs; 2 | 3 | import com.bektz.dataplatformsoar.req.SqlVerifyReq; 4 | import com.bektz.dataplatformsoar.resp.JdbcResultResp; 5 | import com.bektz.dataplatformsoar.resp.SqlVerifyResp; 6 | import com.bektz.dataplatformsoar.service.SchemaService; 7 | import com.bektz.dataplatformsoar.service.SoarService; 8 | import com.bektz.dataplatformsoar.sqlparser.SqlParserService; 9 | import com.fasterxml.jackson.databind.ObjectMapper; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Component; 14 | import org.springframework.web.socket.TextMessage; 15 | import org.springframework.web.socket.WebSocketSession; 16 | import org.springframework.web.socket.handler.TextWebSocketHandler; 17 | 18 | import java.io.IOException; 19 | import java.util.Map; 20 | 21 | import static org.apache.commons.lang3.StringUtils.contains; 22 | import static org.apache.commons.lang3.StringUtils.substringAfter; 23 | 24 | @Slf4j 25 | @Component 26 | public class MyWebSocketHandler extends TextWebSocketHandler { 27 | 28 | 29 | @Autowired 30 | private SoarService soarService; 31 | @Autowired 32 | private SchemaService schemaService; 33 | @Autowired 34 | private SqlParserService sqlParserService; 35 | @Autowired 36 | private ObjectMapper mapper; 37 | 38 | private static final String CONNECTION_HEART_BEAT_MESSAGE = "HeartBeat"; 39 | private static final String EXECUTE_QUERY_SQL_MARK = ":::"; 40 | private static final String PARSER_SQL_COLUMN_MARK = "==="; 41 | 42 | @Override 43 | public void handleTextMessage(WebSocketSession session, TextMessage message) { 44 | if (message.getPayloadLength() == 0 || message.getPayload().equals(CONNECTION_HEART_BEAT_MESSAGE)) { 45 | return; 46 | } 47 | try { 48 | boolean contains = contains(message.getPayload(), EXECUTE_QUERY_SQL_MARK); 49 | //sql执行 50 | if (contains) { 51 | String[] split = StringUtils.split(message.getPayload(), EXECUTE_QUERY_SQL_MARK); 52 | JdbcResultResp jdbcResultResp = schemaService.executeSql(SqlVerifyReq.builder().schema(split[0]).sql(split[1]).build()); 53 | sendMessage(session, mapper.writeValueAsString(jdbcResultResp)); 54 | 55 | } else if (contains(message.getPayload(), PARSER_SQL_COLUMN_MARK)) { 56 | String s = substringAfter(message.getPayload(), PARSER_SQL_COLUMN_MARK); 57 | Map map = sqlParserService.parserSql(s); 58 | sendMessage(session, mapper.writeValueAsString(map)); 59 | } else { 60 | SqlVerifyReq sqlVerifyReq = SqlVerifyReq.builder().sql(message.getPayload()).build(); 61 | SqlVerifyResp verify = soarService.verify(sqlVerifyReq); 62 | sendMessage(session, mapper.writeValueAsString(verify)); 63 | } 64 | 65 | } catch (Exception e) { 66 | log.error("sql分析或执行sql失败 sql:{}", message.getPayload(), e); 67 | } 68 | } 69 | 70 | private void sendMessage(WebSocketSession webSocketSession, String message) throws IOException { 71 | TextMessage textMessage = new TextMessage(message); 72 | webSocketSession.sendMessage(textMessage); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/configs/ParamValidAop.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.configs; 2 | 3 | import com.bektz.dataplatformsoar.resp.GenericResponse; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.aspectj.lang.ProceedingJoinPoint; 6 | import org.aspectj.lang.annotation.Around; 7 | import org.aspectj.lang.annotation.Aspect; 8 | import org.aspectj.lang.annotation.Pointcut; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.validation.BindingResult; 12 | import org.springframework.validation.ObjectError; 13 | 14 | import java.util.List; 15 | 16 | 17 | @Slf4j 18 | @Aspect 19 | @Configuration 20 | public class ParamValidAop { 21 | 22 | ThreadLocal startTime = new ThreadLocal<>(); 23 | 24 | @Pointcut("within(@org.springframework.web.bind.annotation.RestController *) || within(@org.springframework.stereotype.Controller *)") 25 | public void excude() { 26 | } 27 | 28 | @Around("excude()") 29 | public Object doAround(ProceedingJoinPoint pjp) throws Throwable { 30 | Object[] args = pjp.getArgs(); 31 | for (Object arg : args) { 32 | if (arg instanceof BindingResult) { 33 | BindingResult result = (BindingResult) arg; 34 | if (result.getErrorCount() > 0) { 35 | List allErrors = result.getAllErrors(); 36 | StringBuilder sb = new StringBuilder(); 37 | for (ObjectError allError : allErrors) { 38 | sb.append(allError.getDefaultMessage()).append(";"); 39 | } 40 | return ResponseEntity.badRequest().body(GenericResponse.CLIENT_ERROR.setMessage(sb.toString())); 41 | } 42 | } 43 | } 44 | return pjp.proceed(); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/configs/SoarConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.configs; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.io.Serializable; 8 | import java.util.Map; 9 | 10 | @Data 11 | @ConfigurationProperties("soar-configs.skills") 12 | @Component 13 | public class SoarConfiguration { 14 | 15 | private Map skillsMap; 16 | 17 | public Map getSkillsMap() { 18 | return skillsMap; 19 | } 20 | 21 | @Data 22 | public static class Skill implements Serializable { 23 | private int type; 24 | private boolean isDefault; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/configs/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.configs; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.socket.WebSocketHandler; 7 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 8 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 9 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 10 | import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; 11 | 12 | @Configuration 13 | @EnableWebSocket 14 | public class WebSocketConfig implements WebSocketConfigurer { 15 | 16 | @Autowired 17 | private MyWebSocketHandler myWebSocketHandler; 18 | 19 | @Override 20 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 21 | registry.addHandler(myWebSocketHandler, "/myHandler") 22 | .addInterceptors(new HttpSessionHandshakeInterceptor()); 23 | } 24 | 25 | @Bean 26 | public WebSocketHandler myHandler() { 27 | return myWebSocketHandler; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/constants/Common.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.constants; 2 | 3 | public final class Common { 4 | public static final String ILLEGAL_INSTANCE_MESSAGE ="非法实例化异常"; 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/constants/JdbcConstants.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.constants; 2 | 3 | public final class JdbcConstants { 4 | 5 | public static final int QUERY_FAILURE_CODE = 5001; 6 | public static final String QUERY_FAILURE_MESSAGE = "查询sql失败,请稍后再试"; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/constants/QueryStatus.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.constants; 2 | 3 | import java.util.Objects; 4 | 5 | public enum QueryStatus { 6 | 7 | SUCCESS("查询成功"), FAILURE("查询失败"); 8 | public String value; 9 | private QueryStatus(String value) { 10 | this.value = value; 11 | } 12 | public Boolean isSuccess() { 13 | return Objects.equals(SUCCESS, this); 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/constants/QueryType.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.constants; 2 | 3 | public enum QueryType { 4 | ALL,PART 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/controller/PageController.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.controller; 2 | 3 | 4 | import com.bektz.dataplatformsoar.resp.SchemaResp; 5 | import com.bektz.dataplatformsoar.service.SchemaService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.ui.Model; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | 12 | import java.util.List; 13 | 14 | @Controller 15 | public class PageController { 16 | @Autowired 17 | private SchemaService schemaService; 18 | 19 | @GetMapping(value = {"/index", "/"}) 20 | public String index(Model model) { 21 | List schemaResps = schemaService.getSchemaResps(); 22 | model.addAttribute("schemaResps", schemaResps); 23 | return "index"; 24 | } 25 | 26 | 27 | @GetMapping(value = "/page/{page}") 28 | public String verify(@PathVariable("page") String page) { 29 | return page; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/controller/SchemaController.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.controller; 2 | 3 | import com.bektz.dataplatformsoar.req.SchemaReq; 4 | import com.bektz.dataplatformsoar.req.SqlVerifyReq; 5 | import com.bektz.dataplatformsoar.resp.GenericResponse; 6 | import com.bektz.dataplatformsoar.resp.JdbcResultResp; 7 | import com.bektz.dataplatformsoar.resp.SchemaResp; 8 | import com.bektz.dataplatformsoar.service.SchemaService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.ui.Model; 13 | import org.springframework.validation.BindingResult; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import javax.validation.Valid; 17 | import java.util.Collections; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | 22 | @Controller 23 | public class SchemaController { 24 | 25 | @Autowired 26 | private SchemaService schemaService; 27 | 28 | @PostMapping(value = "/schemas") 29 | public ResponseEntity addSchema(@RequestBody @Valid SchemaReq schemaReq, BindingResult result) { 30 | schemaService.addSchema(schemaReq); 31 | return ResponseEntity.ok(GenericResponse.SUCCESS); 32 | } 33 | 34 | @GetMapping(value = "/schemas/{schema}") 35 | public String allTablesBySchema(@PathVariable("schema") String shcema, Model model) { 36 | SchemaResp schemaResp = schemaService.getSchemaResp(shcema); 37 | model.addAttribute("schemaResps", Collections.singletonList(schemaResp)); 38 | return "index::table_refresh"; 39 | } 40 | 41 | @GetMapping(value = "/schemas/all") 42 | public String allSchemas(Model model) { 43 | List schemaResps = schemaService.getSchemaResps(); 44 | model.addAttribute("schemaResps", schemaResps); 45 | return "index::schema_refresh"; 46 | } 47 | 48 | @PostMapping(value = "/schemas/tables/sql::execute") 49 | public JdbcResultResp executeSql(@RequestBody @Valid SqlVerifyReq sqlVerifyReq, BindingResult result) { 50 | return schemaService.executeSql(sqlVerifyReq); 51 | } 52 | 53 | @ResponseBody 54 | @GetMapping(value = "/schemas/tables/{schema}") 55 | public Map> getablesBySchema(@PathVariable("schema") String schema) { 56 | return schemaService.tablesAndSchemas(schema); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/controller/SoarController.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.controller; 2 | 3 | import com.bektz.dataplatformsoar.req.SqlVerifyReq; 4 | import com.bektz.dataplatformsoar.resp.SqlVerifyResp; 5 | import com.bektz.dataplatformsoar.service.SoarService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | 12 | @Controller 13 | public class SoarController { 14 | @Autowired 15 | private SoarService soarService; 16 | 17 | @ResponseBody 18 | @PostMapping(value = "/soar/sql::verify") 19 | public SqlVerifyResp verify(@RequestBody SqlVerifyReq sqlVerifyReq) { 20 | return soarService.verify(sqlVerifyReq); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/controller/handler/ControllerExceptionHandleAdvice.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.controller.handler; 2 | 3 | import com.bektz.dataplatformsoar.exception.BektzClientException; 4 | import com.bektz.dataplatformsoar.exception.BektzException; 5 | import com.bektz.dataplatformsoar.exception.BektzServerException; 6 | import com.bektz.dataplatformsoar.resp.GenericResponse; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.web.bind.annotation.ControllerAdvice; 12 | import org.springframework.web.bind.annotation.ExceptionHandler; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | @Slf4j 16 | @ControllerAdvice(annotations = {RestController.class, Controller.class}) 17 | public class ControllerExceptionHandleAdvice { 18 | 19 | @ExceptionHandler 20 | public ResponseEntity handleException(BektzException e) { 21 | GenericResponse genericResponse = GenericResponse.builder().code(e.getCode()).status(e.getStatus()).message(e.getMessage()).build(); 22 | if (e instanceof BektzServerException) { 23 | log.error("[ServerError]: ", e); 24 | } else if (e instanceof BektzClientException) { 25 | log.warn("[ClientWarn]: ", e); 26 | } else { 27 | return new ResponseEntity<>(GenericResponse.SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR); 28 | } 29 | return new ResponseEntity<>(genericResponse, HttpStatus.valueOf(e.getStatus())); 30 | } 31 | 32 | @ExceptionHandler 33 | public ResponseEntity handleException(Exception e) { 34 | GenericResponse genericResponse = GenericResponse.builder().code(500).status(500).message("系统繁忙!请稍后再试").build(); 35 | return new ResponseEntity<>(genericResponse, HttpStatus.valueOf(500)); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/exception/BektzClientException.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | public class BektzClientException extends BektzException { 6 | 7 | 8 | public BektzClientException(int code, String message) { 9 | super(HttpStatus.UNPROCESSABLE_ENTITY.value(), code, message); 10 | } 11 | 12 | public BektzClientException(int status, int code, String message) { 13 | super(status, code, message); 14 | } 15 | 16 | public BektzClientException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/exception/BektzException.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.exception; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class BektzException extends RuntimeException { 7 | private int code; 8 | private int status; 9 | private String message; 10 | 11 | public BektzException(String message, Throwable throwable) { 12 | super(message, throwable); 13 | } 14 | 15 | public BektzException(int code, String message) { 16 | this.code = code; 17 | this.message = message; 18 | } 19 | 20 | public BektzException(int status, int code, String message) { 21 | this.status = status; 22 | this.code = code; 23 | this.message = message; 24 | } 25 | 26 | public BektzException(int code, String message, Throwable cause) { 27 | super(message, cause); 28 | this.code = code; 29 | this.message = message; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/exception/BektzServerException.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | public class BektzServerException extends BektzException { 6 | 7 | 8 | public BektzServerException(int code, String message) { 9 | super(HttpStatus.INTERNAL_SERVER_ERROR.value(), code, message); 10 | } 11 | 12 | public BektzServerException(int status, int code, String message) { 13 | super(status, code, message); 14 | } 15 | 16 | public BektzServerException(int code, String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/exception/SqlParserException.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.exception; 2 | 3 | import java.io.PrintStream; 4 | import java.io.PrintWriter; 5 | 6 | public class SqlParserException extends BektzClientException { 7 | 8 | private static final long serialVersionUID = -1099039459759769980L; 9 | 10 | private Throwable cause = null; 11 | 12 | 13 | public SqlParserException(String arg0) { 14 | super(2001, arg0); 15 | } 16 | 17 | 18 | public SqlParserException(String arg0, Throwable arg1) { 19 | super(arg0, arg1); 20 | this.cause = arg1; 21 | } 22 | 23 | @Override 24 | public Throwable getCause() { 25 | return this.cause; 26 | } 27 | 28 | @Override 29 | public void printStackTrace() { 30 | this.printStackTrace(System.err); 31 | } 32 | 33 | @Override 34 | public void printStackTrace(PrintWriter pw) { 35 | super.printStackTrace(pw); 36 | if (this.cause != null) { 37 | pw.println("Caused by:"); 38 | this.cause.printStackTrace(pw); 39 | } 40 | 41 | } 42 | 43 | @Override 44 | public void printStackTrace(PrintStream ps) { 45 | super.printStackTrace(ps); 46 | if (this.cause != null) { 47 | ps.println("Caused by:"); 48 | this.cause.printStackTrace(ps); 49 | } 50 | 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/repository/SecretColumnRepository.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.repository; 2 | 3 | import com.bektz.dataplatformsoar.repository.domain.SecretColumn; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface SecretColumnRepository extends JpaRepository { 9 | 10 | public SecretColumn getSecretColumnByColumnAndTableAndSchemaName(String column, String table, String schemaName); 11 | 12 | public List getSecretColumnsByTableAndSchemaName(String table, String schemaName); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/repository/domain/SecretColumn.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.repository.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Builder 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class SecretColumn { 13 | 14 | private Long id; 15 | 16 | //数据库名 17 | private String schemaName; 18 | 19 | //表名 20 | private String table; 21 | 22 | //字段 23 | private String column; 24 | 25 | //是否敏感字段:1-敏感,0-非敏感 26 | private Boolean isSecret; 27 | 28 | //字段类型(MOBILE, CARD_NO, ID_NO) 29 | private String columnType; 30 | 31 | //敏感类型:SECRECT(敏感), SUSPECTED_SECRET(疑似敏感) 32 | private String secretType; 33 | 34 | private String createdBy; 35 | 36 | private String updatedBy; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/req/SchemaReq.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.req; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.validation.constraints.NotBlank; 9 | import javax.validation.constraints.NotNull; 10 | 11 | @Builder 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class SchemaReq { 16 | 17 | @NotBlank(message = "数据库地址不能为空") 18 | private String address; 19 | @NotBlank(message = "数据库不能为空") 20 | private String schema; 21 | @NotBlank(message = "用户名不能为空") 22 | private String username; 23 | @NotNull(message = "密码不能为空") 24 | private String password; 25 | @NotNull(message = "端口不能为空") 26 | private Integer port; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/req/SqlVerifyReq.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.req; 2 | 3 | import lombok.*; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | 7 | @Getter 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | @Setter 11 | @Builder 12 | public class SqlVerifyReq { 13 | @NotBlank(message = "sql语句不能为空") 14 | private String sql; 15 | @NotBlank(message = "请选择数据库后再执行sql") 16 | private String schema; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/resp/GenericResponse.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.resp; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import static org.apache.logging.log4j.util.Strings.EMPTY; 9 | 10 | @Data 11 | @Builder 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class GenericResponse { 15 | private int code = 0; 16 | 17 | private String message = EMPTY; 18 | 19 | @Builder.Default 20 | private Boolean succeed = false; 21 | 22 | private int status = 200; 23 | 24 | public static final GenericResponse SUCCESS = new GenericResponse(0, "处理成功", true, 200); 25 | 26 | public static final GenericResponse SERVER_ERROR = new GenericResponse(1001, "服务器异常,请稍后再试", false, 500); 27 | 28 | public static final GenericResponse CLIENT_ERROR = new GenericResponse(2001, "参数不正确", false, 400); 29 | 30 | public GenericResponse setMessage(String message) { 31 | this.message = message; 32 | return this; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/resp/JdbcResultResp.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.resp; 2 | 3 | import com.bektz.dataplatformsoar.constants.QueryStatus; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @Accessors(chain = true) 19 | public class JdbcResultResp { 20 | @Builder.Default 21 | private List resultMeta = new ArrayList<>(); 22 | @Builder.Default 23 | private List> result = new ArrayList<>(); 24 | private QueryStatus queryStatus; 25 | @Builder.Default 26 | private Long queryTimeInMs = 0L; 27 | private String queryErrorMsg; 28 | private String queryResultMsg; 29 | 30 | } -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/resp/SchemaResp.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.resp; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class SchemaResp { 16 | private String schema; 17 | private Map> tables; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/resp/SqlVerifyResp.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.resp; 2 | 3 | import lombok.*; 4 | 5 | /** 6 | * sql审核对象 7 | */ 8 | @Getter 9 | @Setter 10 | @Builder 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class SqlVerifyResp { 14 | private String verifyInfo; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/service/SchemaService.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.service; 2 | 3 | import com.bektz.dataplatformsoar.req.SchemaReq; 4 | import com.bektz.dataplatformsoar.req.SqlVerifyReq; 5 | import com.bektz.dataplatformsoar.resp.JdbcResultResp; 6 | import com.bektz.dataplatformsoar.resp.SchemaResp; 7 | import com.bektz.dataplatformsoar.service.jdbc.DataSourceManager; 8 | import com.bektz.dataplatformsoar.service.jdbc.JdbcTemplate; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | import javax.sql.DataSource; 14 | import java.util.*; 15 | 16 | @Service 17 | public class SchemaService { 18 | 19 | @Autowired 20 | private DataSourceManager dataSourceManager; 21 | 22 | @Autowired 23 | private JdbcTemplate jdbcTemplate; 24 | 25 | 26 | public void addSchema(SchemaReq schemaReq) { 27 | dataSourceManager.initDataSource(schemaReq); 28 | } 29 | 30 | public Map> tablesAndSchemas(String schema) { 31 | Set schemas = dataSourceManager.getDataSourceMap().keySet(); 32 | Map> items = new HashMap<>(2); 33 | if (StringUtils.isBlank(schema)) { 34 | items.put("tables", new ArrayList<>()); 35 | } 36 | if (!StringUtils.isBlank(schema)) { 37 | items.put("tables", jdbcTemplate.allTablesInSchema(schema)); 38 | } 39 | items.put("schemas", new ArrayList<>(schemas)); 40 | return items; 41 | } 42 | 43 | public List getSchemaResps() { 44 | Map dataSourceMap = dataSourceManager.getDataSourceMap(); 45 | List schemaResps = new ArrayList<>(dataSourceMap.size()); 46 | dataSourceMap.forEach((key, value) -> { 47 | Map> tableMaps = new HashMap<>(); 48 | List tables = jdbcTemplate.allTablesInSchema(key); 49 | for (String table : tables) { 50 | List columns = jdbcTemplate.allColumnInTable(key, table); 51 | tableMaps.put(table, columns); 52 | } 53 | schemaResps.add(SchemaResp.builder().schema(key).tables(tableMaps).build()); 54 | }); 55 | return schemaResps; 56 | } 57 | 58 | public SchemaResp getSchemaResp(String schema) { 59 | List tables = jdbcTemplate.allTablesInSchema(schema); 60 | Map> tableMaps = new HashMap<>(); 61 | for (String table : tables) { 62 | List columns = jdbcTemplate.allColumnInTable(schema, table); 63 | tableMaps.put(table, columns); 64 | } 65 | return SchemaResp.builder().schema(schema).tables(tableMaps).build(); 66 | } 67 | 68 | 69 | public JdbcResultResp executeSql(SqlVerifyReq sqlVerifyReq) { 70 | Map dataSourceMap = dataSourceManager.getDataSourceMap(); 71 | DataSource dataSource = dataSourceMap.get(sqlVerifyReq.getSchema()); 72 | 73 | //todo 对敏感字段做脱敏查询 74 | JdbcResultResp jdbcResultResp = jdbcTemplate.executeSql(dataSource, sqlVerifyReq.getSql()); 75 | return jdbcResultResp; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/service/SoarService.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.service; 2 | 3 | import com.bektz.dataplatformsoar.configs.SoarConfiguration; 4 | import com.bektz.dataplatformsoar.req.SqlVerifyReq; 5 | import com.bektz.dataplatformsoar.resp.SqlVerifyResp; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.util.StringUtils; 10 | 11 | import java.io.BufferedReader; 12 | import java.io.IOException; 13 | import java.io.InputStreamReader; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.stream.Collectors; 18 | 19 | @Service 20 | public class SoarService { 21 | 22 | //-log-output=/Users/chenlang/work/src/github.com/XiaoMi/ 23 | private static final String CMD = "%s/soar '-query=%s' '-report-type=text'"; 24 | 25 | @Value("${soar-configs.execuable_path}") 26 | private String soarPath; 27 | 28 | @Autowired 29 | private SoarConfiguration soarConfiguration; 30 | 31 | public SqlVerifyResp verify(SqlVerifyReq sqlVerifyReq) { 32 | String[] cmds = {"/bin/sh", "-c", String.format(CMD, soarPath, sqlVerifyReq.getSql())}; 33 | Map skillsMap = soarConfiguration.getSkillsMap(); 34 | List verifyInfos = new ArrayList<>(); 35 | Process process; 36 | try { 37 | process = Runtime.getRuntime().exec(cmds); 38 | BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); 39 | String line; 40 | while ((line = input.readLine()) != null) { 41 | verifyInfos.add(line); 42 | } 43 | input.close(); 44 | } catch (IOException e) { 45 | } 46 | // List infos = verifyInfos.parallelStream().filter(verifyInfo -> !StringUtils.isEmpty(verifyInfo)).collect(Collectors.toList()); 47 | String sqlInfo = String.join("
", verifyInfos); 48 | return SqlVerifyResp.builder().verifyInfo(sqlInfo).build(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/service/jdbc/DataSourceManager.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.service.jdbc; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import com.bektz.dataplatformsoar.exception.BektzClientException; 5 | import com.bektz.dataplatformsoar.req.SchemaReq; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.sql.DataSource; 10 | import java.sql.Connection; 11 | import java.util.Collections; 12 | import java.util.Map; 13 | import java.util.concurrent.ConcurrentHashMap; 14 | 15 | @Slf4j 16 | @Service 17 | public class DataSourceManager { 18 | 19 | private static final String MYSQL_CONNECTION_URL_TEMPLATE = "jdbc:mysql://%s:%s/%s"; 20 | private ConcurrentHashMap dataSourceMap = new ConcurrentHashMap(); 21 | 22 | public void initDataSource(SchemaReq schemaReq) { 23 | DruidDataSource dataSource = new DruidDataSource(); 24 | dataSource.setUsername(schemaReq.getUsername()); 25 | dataSource.setUrl(String.format(MYSQL_CONNECTION_URL_TEMPLATE, schemaReq.getAddress(), schemaReq.getPort(), schemaReq.getSchema())); 26 | dataSource.setPassword(schemaReq.getPassword()); 27 | dataSource.setMaxActive(2); 28 | dataSource.setTestOnBorrow(true); 29 | dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 30 | dataSource.setQueryTimeout(10); 31 | try (Connection ignored = dataSource.getConnection(1000)) { 32 | dataSourceMap.put(schemaReq.getSchema(), dataSource); 33 | } catch (Exception e) { 34 | log.warn("初始化数据库数据源失败 参数{} ", schemaReq); 35 | throw new BektzClientException(1001, "添加数据库失败"); 36 | } 37 | 38 | } 39 | 40 | public Map getDataSourceMap() { 41 | return Collections.unmodifiableMap(dataSourceMap); 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/service/jdbc/JdbcTemplate.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.service.jdbc; 2 | 3 | import com.alibaba.druid.util.JdbcUtils; 4 | import com.bektz.dataplatformsoar.exception.BektzServerException; 5 | import com.bektz.dataplatformsoar.resp.JdbcResultResp; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.util.CollectionUtils; 10 | 11 | import javax.sql.DataSource; 12 | import java.util.LinkedList; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.Objects; 16 | 17 | import static com.bektz.dataplatformsoar.constants.JdbcConstants.QUERY_FAILURE_CODE; 18 | import static com.bektz.dataplatformsoar.constants.JdbcConstants.QUERY_FAILURE_MESSAGE; 19 | import static com.bektz.dataplatformsoar.constants.QueryStatus.FAILURE; 20 | import static com.bektz.dataplatformsoar.constants.QueryStatus.SUCCESS; 21 | import static java.util.stream.Collectors.toList; 22 | 23 | @Slf4j 24 | @Service() 25 | public class JdbcTemplate { 26 | 27 | private static final String SHOW_TABLES = "show tables"; 28 | private static final String SHOW_COLUMNS_TABLE = "select `table_name` as tableName, `column_key` as columnKey, " + 29 | "`column_name` as columnName, `column_type` as columnType, " + 30 | "`column_comment` as columnComment, `column_default` as columnDefault, `is_nullable` as isNullable " + 31 | "from information_schema.columns where `table_schema` = '%s' and `table_name` in ( '%s' );"; 32 | private static final String SHOW_TABLE_FIELD = "Tables_in_%s"; 33 | 34 | 35 | @Autowired 36 | private DataSourceManager dataSourceManager; 37 | 38 | 39 | public List allColumnInTable(String schema, String table) { 40 | Map dataSourceMap = dataSourceManager.getDataSourceMap(); 41 | DataSource dataSource = dataSourceMap.get(schema); 42 | JdbcResultResp result = executeSql(dataSource, String.format(SHOW_COLUMNS_TABLE, schema, table)); 43 | if (Objects.equals(result.getQueryStatus(), SUCCESS)) { 44 | return result.getResult() 45 | .stream() 46 | .map(map -> (String) map.get("columnName")) 47 | .collect(toList()); 48 | } 49 | throw new BektzServerException(QUERY_FAILURE_CODE, QUERY_FAILURE_MESSAGE); 50 | } 51 | 52 | public List allTablesInSchema(String schema) { 53 | Map dataSourceMap = dataSourceManager.getDataSourceMap(); 54 | DataSource dataSource = dataSourceMap.get(schema); 55 | JdbcResultResp result = executeSql(dataSource, SHOW_TABLES); 56 | if (Objects.equals(result.getQueryStatus(), SUCCESS)) { 57 | return result.getResult() 58 | .stream() 59 | .map(map -> (String) map.get(String.format(SHOW_TABLE_FIELD, schema))) 60 | .collect(toList()); 61 | } 62 | throw new BektzServerException(QUERY_FAILURE_CODE, QUERY_FAILURE_MESSAGE); 63 | } 64 | 65 | 66 | public JdbcResultResp executeSql(DataSource dataSource, String sql) { 67 | try { 68 | long startTime = System.currentTimeMillis(); 69 | List> result = JdbcUtils.executeQuery(dataSource, sql); 70 | LinkedList metaData = new LinkedList(); 71 | if (!CollectionUtils.isEmpty(result)) { 72 | Map map = result.get(0); 73 | map.forEach((key, value) -> metaData.addLast(key)); 74 | 75 | } 76 | long endTime = System.currentTimeMillis(); 77 | return JdbcResultResp.builder().queryResultMsg(SUCCESS.value).resultMeta(metaData).queryStatus(SUCCESS).result(result).queryTimeInMs(endTime - startTime).build(); 78 | } catch (Exception e) { 79 | log.error("执行sql失败 sql:{}", sql, e); 80 | return JdbcResultResp.builder().queryResultMsg(FAILURE.value).queryStatus(FAILURE).queryErrorMsg(e.getMessage()).build(); 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/sqlparser/ColumnItem.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.apache.commons.lang3.StringUtils; 8 | 9 | @Data 10 | @Builder 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class ColumnItem { 14 | private String schemaName; 15 | private String tableAlias; 16 | private String tableName; 17 | private String columnName; 18 | private String columnAlias; 19 | 20 | @Builder.Default 21 | private boolean identity = false; 22 | 23 | public boolean getIdentity() { 24 | return StringUtils.equalsIgnoreCase(columnAlias, columnName); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/sqlparser/CommonFactory.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class CommonFactory implements ApplicationContextAware { 10 | 11 | private ApplicationContext applicationContext; 12 | 13 | public T getBean(String beanName) { 14 | return (T) applicationContext.getBean(beanName); 15 | } 16 | 17 | @Override 18 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 19 | this.applicationContext = applicationContext; 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/sqlparser/SqlParserService.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser; 2 | 3 | import com.alibaba.druid.sql.SQLUtils; 4 | import com.alibaba.druid.sql.ast.SQLStatement; 5 | import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; 6 | import com.alibaba.druid.sql.parser.ParserException; 7 | import com.bektz.dataplatformsoar.sqlparser.druid.DruidSqlParser; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.Set; 16 | 17 | import static com.alibaba.druid.util.JdbcConstants.MYSQL; 18 | 19 | @Slf4j 20 | @Service 21 | public class SqlParserService { 22 | 23 | @Autowired 24 | private DruidSqlParser druidSqlParser; 25 | 26 | public Map parserSql(String sql) { 27 | Map map = new HashMap<>(); 28 | List stmtList; 29 | try { 30 | stmtList = SQLUtils.parseStatements(sql, MYSQL); 31 | } catch (ParserException e) { 32 | map.put("error", "请输入正确的sql"); 33 | return map; 34 | } 35 | if (stmtList.size() > 1 || !(stmtList.get(0) instanceof SQLSelectStatement)) { 36 | map.put("error", "不好意思只支持单条的查询sql"); 37 | return map; 38 | } 39 | //查询的字段 40 | Map columnItemMap = druidSqlParser.parserSql(sql); 41 | map.put("parserSql", columnItemMap.keySet()); 42 | Map> allColumns = druidSqlParser.parserSqlAllColumns(sql); 43 | //sql中所有的字段和表 44 | map.put("allColumns", allColumns); 45 | return map; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/sqlparser/druid/AbstractDruidSqlParSer.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser.druid; 2 | 3 | import com.alibaba.druid.sql.ast.SQLStatement; 4 | import com.alibaba.druid.sql.ast.statement.SQLSelect; 5 | import com.alibaba.druid.sql.ast.statement.SQLSelectItem; 6 | import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; 7 | import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; 8 | import com.alibaba.druid.stat.TableStat; 9 | import com.bektz.dataplatformsoar.sqlparser.ColumnItem; 10 | import com.bektz.dataplatformsoar.sqlparser.druid.visitor.DefineMySqlSchemaStatVisitor; 11 | import org.apache.commons.lang3.StringUtils; 12 | 13 | import java.util.Collection; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | public abstract class AbstractDruidSqlParSer { 19 | 20 | protected static final String ALL_COLUMNS_MARK = "*"; 21 | private static final int SCHEMA_AND_TABLE_COUNT = 2; 22 | protected static final String UNKNOWN_TABLE = "UNKNOWN"; 23 | 24 | 25 | public abstract Map parserSql(DefineMySqlSchemaStatVisitor mySqlSchemaStatVisitor, SQLStatement sqlStatement); 26 | 27 | 28 | /** 29 | * 获取最外层字段和别名 30 | * 31 | * @return 32 | */ 33 | protected List parserOutermostColumns(SQLStatement sqlStatement) { 34 | SQLSelect select = ((SQLSelectStatement) sqlStatement).getSelect(); 35 | SQLSelectQueryBlock query = (SQLSelectQueryBlock) select.getQuery(); 36 | return query.getSelectList(); 37 | } 38 | 39 | 40 | /** 41 | * 查询的字段中出现了UNKNOWN_TABLE时 42 | * 说明表中有些字段无法确认是哪张表的,所以初步认为该字段属于所有表 43 | * 44 | * @return 45 | */ 46 | protected Map getColumnItemsHasUnknownTable(DefineMySqlSchemaStatVisitor mySqlSchemaStatVisitor, Collection columns) { 47 | 48 | Map columnItemMap = new HashMap<>(); 49 | Map tables = mySqlSchemaStatVisitor.getTables(); 50 | tables.forEach((key, value) -> { 51 | for (TableStat.Column column : columns) { 52 | ColumnItem columnItem = ColumnItem.builder().schemaName(getSchemaName(column)).tableName(getTableName(column)).columnName(column.getName()).build(); 53 | columnItemMap.put(formatColumnsKey(getTableName(column), column.getName()), columnItem); 54 | } 55 | }); 56 | return columnItemMap; 57 | } 58 | 59 | protected String getSchemaName(TableStat.Column column) { 60 | return getTableNameOrSchemaName(column, 0); 61 | } 62 | 63 | protected String getTableName(TableStat.Column column) { 64 | String tableName = getTableNameOrSchemaName(column, 1); 65 | return StringUtils.isBlank(tableName) ? column.getName() : tableName; 66 | } 67 | 68 | protected String getTableNameOrSchemaName(TableStat.Column column, int index) { 69 | String[] split = StringUtils.split(column.getTable(), "."); 70 | if (split.length == SCHEMA_AND_TABLE_COUNT) { 71 | return split[index]; 72 | } 73 | return StringUtils.EMPTY; 74 | } 75 | 76 | protected String formatColumnsKey(String tableName, String columnName) { 77 | String[] split = StringUtils.split(tableName, "."); 78 | if (split.length == SCHEMA_AND_TABLE_COUNT) { 79 | tableName = split[1]; 80 | } 81 | return tableName + "." + columnName; 82 | } 83 | 84 | protected String getSchemaName(TableStat.Name table) { 85 | return getTableNameOrSchemaName(table, 0); 86 | } 87 | 88 | protected String getTableName(TableStat.Name table) { 89 | String tableName = getTableNameOrSchemaName(table, 1); 90 | return StringUtils.isBlank(tableName) ? table.getName() : tableName; 91 | } 92 | 93 | protected String getTableNameOrSchemaName(TableStat.Name table, int index) { 94 | String[] split = StringUtils.split(table.getName(), "."); 95 | if (split.length == SCHEMA_AND_TABLE_COUNT) { 96 | return split[index]; 97 | } 98 | return StringUtils.EMPTY; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/sqlparser/druid/DruidParserHasAsterisk.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser.druid; 2 | 3 | import com.alibaba.druid.sql.ast.SQLStatement; 4 | import com.alibaba.druid.stat.TableStat; 5 | import com.bektz.dataplatformsoar.sqlparser.ColumnItem; 6 | import com.bektz.dataplatformsoar.sqlparser.druid.visitor.DefineMySqlSchemaStatVisitor; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Collection; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | import static java.util.stream.Collectors.toSet; 15 | 16 | /** 17 | * 最外层查询有 * 时 18 | * 19 | * @return 20 | */ 21 | @Component("hasAsterisk") 22 | public class DruidParserHasAsterisk extends AbstractDruidSqlParSer { 23 | 24 | @Override 25 | public Map parserSql(DefineMySqlSchemaStatVisitor mySqlSchemaStatVisitor, SQLStatement sqlStatement) { 26 | Map columnItemMap = new HashMap<>(); 27 | Collection columns = mySqlSchemaStatVisitor.getColumns(); 28 | for (TableStat.Column column : columns) { 29 | if (column.isSelect()) { 30 | ColumnItem columnItem = ColumnItem.builder().schemaName(getSchemaName(column)).tableName(getTableName(column)).columnName(column.getName()).build(); 31 | columnItemMap.put(formatColumnsKey(column.getTable(), column.getName()), columnItem); 32 | } 33 | } 34 | Set tables = mySqlSchemaStatVisitor.getTables().keySet(); 35 | Set itemTables = columnItemMap.values().stream().map(ColumnItem::getTableName).collect(toSet()); 36 | for (TableStat.Name table : tables) { 37 | String tableName = getTableName(table); 38 | if (!itemTables.contains(tableName)) { 39 | ColumnItem columnItem = ColumnItem.builder().schemaName(getSchemaName(table)).tableName(tableName).columnName(ALL_COLUMNS_MARK).build(); 40 | columnItemMap.put(formatColumnsKey(tableName, ALL_COLUMNS_MARK), columnItem); 41 | } 42 | } 43 | 44 | return columnItemMap; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/sqlparser/druid/DruidParserNonAsterisk.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser.druid; 2 | 3 | import com.alibaba.druid.sql.ast.SQLStatement; 4 | import com.alibaba.druid.sql.ast.statement.SQLSelectItem; 5 | import com.alibaba.druid.stat.TableStat; 6 | import com.bektz.dataplatformsoar.sqlparser.ColumnItem; 7 | import com.bektz.dataplatformsoar.sqlparser.druid.visitor.DefineMySqlSchemaStatVisitor; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.HashMap; 11 | import java.util.LinkedList; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | /** 16 | * sql最外层没有*号时 17 | */ 18 | @Component("nonAsterisk") 19 | public class DruidParserNonAsterisk extends AbstractDruidSqlParSer { 20 | 21 | @Override 22 | public Map parserSql(DefineMySqlSchemaStatVisitor mySqlSchemaStatVisitor, SQLStatement sqlStatement) { 23 | LinkedList columns = new LinkedList<>(); 24 | Map columnItemMap = new HashMap<>(); 25 | List outermostColumns = parserOutermostColumns(sqlStatement); 26 | for (SQLSelectItem outermostColumn : outermostColumns) { 27 | TableStat.Column column = mySqlSchemaStatVisitor.getColumn(outermostColumn.getExpr()); 28 | if (UNKNOWN_TABLE.equals(column.getTable())) { 29 | columns.addFirst(column); 30 | } 31 | if (!UNKNOWN_TABLE.equals(column.getTable())) { 32 | ColumnItem columnItem = ColumnItem.builder().schemaName(getSchemaName(column)).tableName(getTableName(column)).columnName(column.getName()).build(); 33 | columnItemMap.put(formatColumnsKey(column.getTable(), column.getName()), columnItem); 34 | } 35 | } 36 | Map columnItems = getColumnItemsHasUnknownTable(mySqlSchemaStatVisitor, columns); 37 | columnItemMap.putAll(columnItems); 38 | return columnItemMap; 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/sqlparser/druid/DruidSqlParser.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser.druid; 2 | 3 | import com.alibaba.druid.sql.SQLUtils; 4 | import com.alibaba.druid.sql.ast.SQLStatement; 5 | import com.alibaba.druid.sql.ast.statement.SQLSelectItem; 6 | import com.alibaba.druid.stat.TableStat; 7 | import com.bektz.dataplatformsoar.sqlparser.ColumnItem; 8 | import com.bektz.dataplatformsoar.sqlparser.CommonFactory; 9 | import com.bektz.dataplatformsoar.sqlparser.druid.visitor.DefineMySqlSchemaStatVisitor; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.Collection; 14 | import java.util.List; 15 | import java.util.Map; 16 | import java.util.Set; 17 | 18 | import static com.alibaba.druid.util.JdbcConstants.MYSQL; 19 | import static java.util.stream.Collectors.*; 20 | 21 | @Service 22 | public class DruidSqlParser extends AbstractDruidSqlParSer { 23 | 24 | @Autowired 25 | private CommonFactory commonFactory; 26 | 27 | public Map parserSql(String sql) { 28 | List stmtList = SQLUtils.parseStatements(sql, MYSQL); 29 | DefineMySqlSchemaStatVisitor mySqlSchemaStatVisitor = new DefineMySqlSchemaStatVisitor(); 30 | SQLStatement sqlStatement = stmtList.get(0); 31 | sqlStatement.accept(mySqlSchemaStatVisitor); 32 | return parserSql(mySqlSchemaStatVisitor, sqlStatement); 33 | } 34 | 35 | public Map> parserSqlAllColumns(String sql) { 36 | List stmtList = SQLUtils.parseStatements(sql, MYSQL); 37 | DefineMySqlSchemaStatVisitor mySqlSchemaStatVisitor = new DefineMySqlSchemaStatVisitor(); 38 | SQLStatement sqlStatement = stmtList.get(0); 39 | sqlStatement.accept(mySqlSchemaStatVisitor); 40 | Collection columns = mySqlSchemaStatVisitor.getColumns(); 41 | return columns.stream().collect(groupingBy(TableStat.Column::getTable, mapping(TableStat.Column::getName, toSet()))); 42 | } 43 | 44 | @Override 45 | public Map parserSql(DefineMySqlSchemaStatVisitor mySqlSchemaStatVisitor, SQLStatement sqlStatement) { 46 | AbstractDruidSqlParSer druidSqlParSer; 47 | List outermostColumns = parserOutermostColumns(sqlStatement); 48 | boolean hasAsterisk = outermostColumns.stream().anyMatch(item -> ALL_COLUMNS_MARK.equals(item.toString())); 49 | if (hasAsterisk) { 50 | druidSqlParSer = commonFactory.getBean("hasAsterisk"); 51 | } else { 52 | druidSqlParSer = commonFactory.getBean("nonAsterisk"); 53 | } 54 | return druidSqlParSer.parserSql(mySqlSchemaStatVisitor, sqlStatement); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/bektz/dataplatformsoar/sqlparser/druid/visitor/DefineMySqlSchemaStatVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser.druid.visitor; 2 | 3 | import com.alibaba.druid.sql.ast.SQLExpr; 4 | import com.alibaba.druid.sql.ast.statement.SQLSelectItem; 5 | import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; 6 | import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; 7 | import com.alibaba.druid.stat.TableStat; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | public class DefineMySqlSchemaStatVisitor extends MySqlSchemaStatVisitor { 13 | 14 | public List items = new ArrayList<>(); 15 | 16 | 17 | @Override 18 | public boolean visit(SQLSelectQueryBlock x) { 19 | items.addAll(x.getSelectList()); 20 | return super.visit(x); 21 | } 22 | 23 | @Override 24 | public TableStat.Column getColumn(SQLExpr expr) { 25 | return super.getColumn(expr); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | soar-configs: 2 | execuable_path: ${soar} 3 | user: root 4 | password: 123456 5 | host: 127.0.0.1 6 | port: 3306 7 | database: blog 8 | skills: 9 | -report-type: 10 | type: 1 11 | default: true 12 | -allow-online-as-test: 13 | type : 1 14 | default: true 15 | -profiling: 16 | type : 1 17 | default: true 18 | -verbose: 19 | type : 1 20 | default: true 21 | spring: 22 | aop: 23 | proxy-target-class: true 24 | auto: true 25 | thymeleaf: 26 | prefix: classpath:/templates/ 27 | check-template: true 28 | mode: HTML5 29 | cache: false 30 | -------------------------------------------------------------------------------- /src/main/resources/soar.yml: -------------------------------------------------------------------------------- 1 | soar_configs: 2 | execuable_path: ${soar} 3 | user: root 4 | password: 123456 5 | host: 127.0.0.1 6 | port: 3306 7 | database: blog 8 | skills: 9 | -report-type: 10 | type: 1 11 | default: true 12 | -allow-online-as-test: 13 | type : 1 14 | default: true 15 | -profiling: 16 | type : 1 17 | default: true 18 | -verbose: 19 | type : 1 20 | default: true 21 | -------------------------------------------------------------------------------- /src/main/resources/static/css/prism.css: -------------------------------------------------------------------------------- 1 | /* PrismJS 1.15.0 2 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+sql+plsql */ 3 | /** 4 | * prism.js default theme for JavaScript, CSS and HTML 5 | * Based on dabblet (http://dabblet.com) 6 | * @author Lea Verou 7 | */ 8 | 9 | code[class*="language-"], 10 | pre[class*="language-"] { 11 | color: black; 12 | background: none; 13 | text-shadow: 0 1px white; 14 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 15 | text-align: left; 16 | white-space: pre; 17 | word-spacing: normal; 18 | word-break: normal; 19 | word-wrap: normal; 20 | line-height: 1.5; 21 | 22 | -moz-tab-size: 4; 23 | -o-tab-size: 4; 24 | tab-size: 4; 25 | 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | } 31 | 32 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, 33 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { 34 | text-shadow: none; 35 | background: #b3d4fc; 36 | } 37 | 38 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection, 39 | code[class*="language-"]::selection, code[class*="language-"] ::selection { 40 | text-shadow: none; 41 | background: #b3d4fc; 42 | } 43 | 44 | @media print { 45 | code[class*="language-"], 46 | pre[class*="language-"] { 47 | text-shadow: none; 48 | } 49 | } 50 | 51 | /* Code blocks */ 52 | pre[class*="language-"] { 53 | padding: 1em; 54 | margin: .5em 0; 55 | overflow: auto; 56 | } 57 | 58 | :not(pre) > code[class*="language-"], 59 | pre[class*="language-"] { 60 | background: #f5f2f0; 61 | } 62 | 63 | /* Inline code */ 64 | :not(pre) > code[class*="language-"] { 65 | padding: .1em; 66 | border-radius: .3em; 67 | white-space: normal; 68 | } 69 | 70 | .token.comment, 71 | .token.prolog, 72 | .token.doctype, 73 | .token.cdata { 74 | color: slategray; 75 | } 76 | 77 | .token.punctuation { 78 | color: #999; 79 | } 80 | 81 | .namespace { 82 | opacity: .7; 83 | } 84 | 85 | .token.property, 86 | .token.tag, 87 | .token.boolean, 88 | .token.number, 89 | .token.constant, 90 | .token.symbol, 91 | .token.deleted { 92 | color: #905; 93 | } 94 | 95 | .token.selector, 96 | .token.attr-name, 97 | .token.string, 98 | .token.char, 99 | .token.builtin, 100 | .token.inserted { 101 | color: #690; 102 | } 103 | 104 | .token.operator, 105 | .token.entity, 106 | .token.url, 107 | .language-css .token.string, 108 | .style .token.string { 109 | color: #9a6e3a; 110 | background: hsla(0, 0%, 100%, .5); 111 | } 112 | 113 | .token.atrule, 114 | .token.attr-value, 115 | .token.keyword { 116 | color: #07a; 117 | } 118 | 119 | .token.function, 120 | .token.class-name { 121 | color: #DD4A68; 122 | } 123 | 124 | .token.regex, 125 | .token.important, 126 | .token.variable { 127 | color: #e90; 128 | } 129 | 130 | .token.important, 131 | .token.bold { 132 | font-weight: bold; 133 | } 134 | .token.italic { 135 | font-style: italic; 136 | } 137 | 138 | .token.entity { 139 | cursor: help; 140 | } 141 | 142 | -------------------------------------------------------------------------------- /src/main/resources/static/images/face/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/0.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/1.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/10.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/11.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/12.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/13.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/13.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/14.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/14.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/15.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/15.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/16.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/17.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/18.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/18.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/19.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/19.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/2.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/20.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/21.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/21.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/22.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/22.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/23.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/23.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/24.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/24.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/25.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/26.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/26.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/27.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/27.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/28.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/28.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/29.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/29.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/3.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/30.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/30.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/31.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/31.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/32.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/32.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/33.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/33.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/34.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/34.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/35.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/35.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/36.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/36.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/37.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/37.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/38.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/38.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/39.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/39.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/4.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/40.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/40.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/41.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/41.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/42.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/42.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/43.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/43.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/44.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/44.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/45.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/45.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/46.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/46.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/47.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/47.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/48.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/48.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/49.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/49.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/5.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/50.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/51.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/51.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/52.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/52.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/53.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/53.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/54.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/54.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/55.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/55.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/56.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/56.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/57.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/57.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/58.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/58.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/59.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/59.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/6.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/60.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/60.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/61.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/61.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/62.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/62.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/63.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/63.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/64.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/64.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/65.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/65.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/66.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/66.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/67.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/67.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/68.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/68.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/69.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/69.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/7.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/70.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/70.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/71.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/71.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/8.gif -------------------------------------------------------------------------------- /src/main/resources/static/images/face/9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/images/face/9.gif -------------------------------------------------------------------------------- /src/main/resources/static/js/form.js: -------------------------------------------------------------------------------- 1 | $.fn.serializeObject = function() { 2 | var o = {}; 3 | var a = this.serializeArray(); 4 | $.each(a, function() { 5 | if (o[this.name]) { 6 | if (!o[this.name].push) { 7 | o[this.name] = [ o[this.name] ]; 8 | } 9 | o[this.name].push(this.value || ''); 10 | } else { 11 | o[this.name] = this.value || ''; 12 | } 13 | }); 14 | return o; 15 | }; 16 | -------------------------------------------------------------------------------- /src/main/resources/static/js/lay.js: -------------------------------------------------------------------------------- 1 | layui.use(['form', 'layer','element','table'], function () { //独立版的layer无需执行这一句 2 | var $ = layui.jquery, layer = layui.layer; //独立版的layer无需执行这一句 3 | var form = layui.form; 4 | var element = layui.element; 5 | var table = layui.table; 6 | //触发事件 7 | var active = { 8 | notice: function () { 9 | //示范一个公告层 10 | layer.open({ 11 | type: 1 12 | , title: false //不显示标题栏 13 | , closeBtn: false 14 | , area: '600px;' 15 | , shade: 0.8 16 | , id: 'LAY_layuipro' //设定一个id,防止重复弹出 17 | , btn: ['添加', '取消'] 18 | , btnAlign: 'c' 19 | , moveType: 1 //拖拽模式,0或者1 20 | , content: $("#form") 21 | , yes: function (index, layero) { 22 | $.ajax({ 23 | url: "/schemas", 24 | type: "post", 25 | data: JSON.stringify($('#sub').serializeObject()), 26 | contentType: "application/json", 27 | dataType: "JSON", 28 | success: function (data) { 29 | layer.msg(data.message, { 30 | time: 2000, 31 | }); 32 | layer.close(index); 33 | // console.log(JSON.parse(JSON.stringify($('#sub').serializeObject())).schema); 34 | // $('.layui-anim.layui-anim-upbit').append('
'+JSON.parse(JSON.stringify($('#sub').serializeObject())).schema+'
') 35 | // $('#schema_refresh').append(''); 36 | window.location.reload() 37 | }, 38 | error: function (e, data) { 39 | console.log(e.responseJSON.message) 40 | console.log(data) 41 | layer.msg(e.responseJSON.message, { 42 | time: 3000, 43 | }) 44 | } 45 | }); 46 | } 47 | }); 48 | } 49 | 50 | }; 51 | 52 | $('#layerDemo .layui-btn').on('click', function () { 53 | var othis = $(this), method = othis.data('method'); 54 | active[method] ? active[method].call(this, othis) : ''; 55 | }); 56 | 57 | //定义form表单规则 58 | form.verify({ 59 | title: function (value) { 60 | if (value.length < 5) { 61 | return '标题至少得5个字符啊'; 62 | } 63 | } 64 | , pass: [/(.+){6,12}$/, '密码必须6到12位'] 65 | , content: function (value) { 66 | layedit.sync(editIndex); 67 | } 68 | }); 69 | 70 | form.on('select(get_tables)', function (data) { 71 | if (data.value == '') { 72 | return; 73 | } 74 | localStorage.setItem("schema",data.value); 75 | $('#table_refresh').load("/schemas/" + data.value); 76 | }); 77 | 78 | //获取hash来切换选项卡,假设当前地址的hash为lay-id对应的值 79 | var layid = location.hash.replace(/^#test1=/, ''); 80 | element.tabChange('test1', layid); //假设当前地址为:http://a.com#test1=222,那么选项卡会自动切换到“发送消息”这一项 81 | 82 | //监听Tab切换,以改变地址hash值 83 | element.on('tab(test1)', function(){ 84 | location.hash = 'test1='+ this.getAttribute('lay-id'); 85 | }); 86 | 87 | table.render({ 88 | elem: '#queryResult' 89 | , data: [] //数据接口 90 | , page: true //开启分页 91 | , cols: [] 92 | }); 93 | }); -------------------------------------------------------------------------------- /src/main/resources/static/js/websocket.js: -------------------------------------------------------------------------------- 1 | var ws = new WebSocket("ws://localhost:8080/myHandler"); 2 | ws.onmessage = function (message) { 3 | console.log(message.data); 4 | if (JSON.parse(message.data).verifyInfo !== null && JSON.parse(message.data).verifyInfo !== undefined) { 5 | showResponse(message.data); 6 | } 7 | if (JSON.parse(message.data).queryStatus !== null && JSON.parse(message.data).queryStatus !== undefined) { 8 | showQueryResult(message.data); 9 | } 10 | 11 | if (JSON.parse(message.data).parserSql !== null && JSON.parse(message.data).parserSql !== undefined || JSON.parse(message.data).error != undefined) { 12 | showParserSql(message.data); 13 | } 14 | }; 15 | 16 | 17 | ws.onclose = function (p1) { 18 | 19 | }; 20 | 21 | ws.onopen = function (evnt) { 22 | console.log("onopen: ", evnt); 23 | heartCheck.start(); 24 | }; 25 | 26 | //发送心跳数据 27 | var heartCheck = { 28 | timeout: 20000,//10s 29 | timeoutObj: null, 30 | reset: function () { 31 | clearInterval(this.timeoutObj); 32 | this.start(); 33 | }, 34 | start: function () { 35 | this.timeoutObj = setInterval(function () { 36 | if (ws.readyState == 1) { 37 | ws.send("HeartBeat"); 38 | } 39 | }, this.timeout) 40 | } 41 | }; 42 | 43 | function showResponse(message) { 44 | var response = $("#response"); 45 | console.log(JSON.parse(message)); 46 | response.html(JSON.parse(message).verifyInfo); 47 | var ele = layui.element; 48 | ele.tabChange('docDemoTabBrief', 'verfiyResult'); 49 | } 50 | 51 | 52 | var cols = []; 53 | var data = []; 54 | 55 | function showQueryResult(message) { 56 | data = JSON.parse(message).result; 57 | var metas = []; 58 | var status = JSON.parse(message).queryStatus; 59 | if ("FAILURE" === status) { 60 | 61 | layer.prompt({ 62 | formType: 2, 63 | value: JSON.parse(message).queryErrorMsg, 64 | title: '错误提示', 65 | area: ['600px', '200px'] //自定义文本域宽高 66 | }, function (value, index, elem) { 67 | layer.close(1); 68 | layer.close(2) 69 | }); 70 | return; 71 | } 72 | for (var i = 0; i < JSON.parse(message).resultMeta.length; i++) { 73 | var meta = {field: JSON.parse(message).resultMeta[i], title: JSON.parse(message).resultMeta[i]}; 74 | metas[i] = meta; 75 | console.log(meta); 76 | } 77 | console.log(metas); 78 | cols[0] = metas; 79 | console.log(cols); 80 | console.log(data); 81 | var table = layui.table; 82 | table.render({ 83 | elem: '#queryResult' 84 | , data: data //数据接口 85 | , page: true //开启分页 86 | , cols: cols 87 | }); 88 | var ele = layui.element; 89 | ele.tabChange('docDemoTabBrief', 'queryResult'); 90 | } 91 | 92 | function showParserSql(message) { 93 | var error = JSON.parse(message).error; 94 | if (undefined !== error) { 95 | layui.use('layer', function () { 96 | var layer = layui.layer; 97 | layer.msg(JSON.parse(message).error); 98 | }); 99 | return; 100 | } 101 | var response = $("#columnParser"); 102 | console.log(JSON.parse(message)); 103 | ; 104 | var msg = ''; 105 | for (var i = 0; i < JSON.parse(message).parserSql.length; i++) { 106 | msg += JSON.parse(message).parserSql[i] + "
"; 107 | } 108 | response.html(msg); 109 | var ele = layui.element; 110 | ele.tabChange('docDemoTabBrief', 'columnParser'); 111 | } -------------------------------------------------------------------------------- /src/main/resources/static/layui/css/layui.mobile.css: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,legend,li,ol,p,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}html{font:12px 'Helvetica Neue','PingFang SC',STHeitiSC-Light,Helvetica,Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0)}a{text-decoration:none;background:0 0}a:active,a:hover{outline:0}table{border-collapse:collapse;border-spacing:0}li{list-style:none}b,strong{font-weight:700}h1,h2,h3,h4,h5,h6{font-weight:500}address,cite,dfn,em,var{font-style:normal}dfn{font-style:italic}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}img{border:0;vertical-align:bottom}.layui-inline,input,label{vertical-align:middle}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;outline:0}button,select{text-transform:none}select{-webkit-appearance:none;border:none}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=1.0.7);src:url(../font/iconfont.eot?v=1.0.7#iefix) format('embedded-opentype'),url(../font/iconfont.woff?v=1.0.7) format('woff'),url(../font/iconfont.ttf?v=1.0.7) format('truetype'),url(../font/iconfont.svg?v=1.0.7#iconfont) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge,.layui-upload-iframe{position:absolute;width:0;height:0}.layui-edge{border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:active{background-color:#d2d2d2!important;color:#fff!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-upload-iframe{border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}@-webkit-keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-left{-webkit-animation-name:layui-m-anim-left;animation-name:layui-m-anim-left}@-webkit-keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-right{-webkit-animation-name:layui-m-anim-right;animation-name:layui-m-anim-right}@-webkit-keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}.layui-m-anim-lout{-webkit-animation-name:layui-m-anim-lout;animation-name:layui-m-anim-lout}@-webkit-keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}.layui-m-anim-rout{-webkit-animation-name:layui-m-anim-rout;animation-name:layui-m-anim-rout}.layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px} -------------------------------------------------------------------------------- /src/main/resources/static/layui/css/modules/code.css: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none} -------------------------------------------------------------------------------- /src/main/resources/static/layui/css/modules/laydate/default/laydate.css: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | .laydate-set-ym,.layui-laydate,.layui-laydate *,.layui-laydate-list{box-sizing:border-box}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate{position:absolute;z-index:66666666;margin:5px 0;border-radius:2px;font-size:14px;-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:laydate-upbit;animation-name:laydate-upbit}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}@-webkit-keyframes laydate-upbit{from{-webkit-transform:translate3d(0,20px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes laydate-upbit{from{transform:translate3d(0,20px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon,.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.laydate-set-ym span,.layui-laydate-header i{padding:0 5px;cursor:pointer}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;color:#999;font-size:18px}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:5px;text-align:center}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;height:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px 20px}.layui-laydate-footer span{margin-right:15px;display:inline-block;cursor:pointer;font-size:12px}.layui-laydate-footer span:hover{color:#5FB878}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{height:26px;line-height:26px;margin:0 0 0 -1px;padding:0 10px;border:1px solid #C9C9C9;background-color:#fff;white-space:nowrap;vertical-align:top;border-radius:2px}.layui-laydate-list>li,.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle}.layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;background-color:#fff}.layui-laydate-list>li{position:relative;width:33.3%;height:36px;line-height:36px;margin:3px 0;text-align:center;cursor:pointer}.laydate-month-list>li{width:25%;margin:17px 0}.laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.laydate-time-list p{position:relative;top:-4px;line-height:29px}.laydate-time-list ol{height:181px;overflow:hidden}.laydate-time-list>li:hover ol{overflow-y:auto}.laydate-time-list ol li{width:130%;padding-left:33px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px}.layui-laydate-range{width:546px}.layui-laydate-range .laydate-main-list-0 .laydate-next-m,.layui-laydate-range .laydate-main-list-0 .laydate-next-y,.layui-laydate-range .laydate-main-list-1 .laydate-prev-m,.layui-laydate-range .laydate-main-list-1 .laydate-prev-y{display:none}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content{border-left:1px solid #e2e2e2}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#666}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#5FB878}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{font-weight:400;color:#333}.layui-laydate-content td{color:#666}.layui-laydate-content td.laydate-selected{background-color:#00F7DE}.laydate-selected:hover{background-color:#00F7DE!important}.layui-laydate-content td:hover,.layui-laydate-list li:hover{background-color:#eaeaea;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.laydate-selected.laydate-day-next,.laydate-selected.laydate-day-prev{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#FF5722}.laydate-day-mark::after{background-color:#5FB878}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#5FB878}.layui-laydate .layui-this{background-color:#009688!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#009688}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead,.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-selected,.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#009688!important}.laydate-theme-grid .laydate-selected.laydate-day-next,.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px} -------------------------------------------------------------------------------- /src/main/resources/static/layui/css/modules/layer/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/css/modules/layer/default/icon-ext.png -------------------------------------------------------------------------------- /src/main/resources/static/layui/css/modules/layer/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/css/modules/layer/default/icon.png -------------------------------------------------------------------------------- /src/main/resources/static/layui/css/modules/layer/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/css/modules/layer/default/loading-0.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/css/modules/layer/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/css/modules/layer/default/loading-1.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/css/modules/layer/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/css/modules/layer/default/loading-2.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/font/iconfont.eot -------------------------------------------------------------------------------- /src/main/resources/static/layui/font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/font/iconfont.ttf -------------------------------------------------------------------------------- /src/main/resources/static/layui/font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/font/iconfont.woff -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/0.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/1.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/10.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/11.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/12.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/13.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/13.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/14.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/14.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/15.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/15.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/16.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/17.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/18.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/18.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/19.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/19.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/2.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/20.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/21.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/21.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/22.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/22.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/23.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/23.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/24.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/24.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/25.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/26.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/26.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/27.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/27.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/28.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/28.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/29.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/29.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/3.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/30.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/30.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/31.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/31.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/32.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/32.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/33.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/33.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/34.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/34.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/35.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/35.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/36.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/36.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/37.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/37.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/38.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/38.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/39.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/39.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/4.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/40.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/40.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/41.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/41.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/42.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/42.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/43.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/43.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/44.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/44.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/45.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/45.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/46.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/46.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/47.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/47.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/48.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/48.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/49.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/49.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/5.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/50.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/51.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/51.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/52.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/52.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/53.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/53.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/54.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/54.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/55.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/55.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/56.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/56.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/57.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/57.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/58.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/58.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/59.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/59.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/6.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/60.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/60.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/61.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/61.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/62.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/62.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/63.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/63.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/64.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/64.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/65.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/65.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/66.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/66.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/67.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/67.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/68.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/68.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/69.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/69.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/7.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/70.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/70.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/71.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/71.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/8.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/images/face/9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beiketianzhuang/data-platform-soar/47e0d4f06d05b142cb57ef34891ad545af408427/src/main/resources/static/layui/images/face/9.gif -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/carousel.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(e){"use strict";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t="carousel",a="layui-this",l=">*[carousel-item]>*",o="layui-carousel-left",r="layui-carousel-right",d="layui-carousel-prev",s="layui-carousel-next",u="layui-carousel-arrow",c="layui-carousel-ind",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr("lay-anim",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['",'"].join(""));n.elem.attr("lay-arrow",n.arrow),n.elem.find("."+u)[0]&&n.elem.find("."+u).remove(),n.elem.append(t),t.on("click",function(){var n=i(this),t=n.attr("lay-type");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['
    ',function(){var i=[];return layui.each(e.elemItem,function(e){i.push("")}),i.join("")}(),"
"].join(""));n.elem.attr("lay-indicator",n.indicator),n.elem.find("."+c)[0]&&n.elem.find("."+c).remove(),n.elem.append(t),"updown"===n.anim&&t.css("margin-top",-(t.height()/2)),t.find("li").on("hover"===n.trigger?"mouseover":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide("add",a-n.index):a/g,">").replace(/'/g,"'").replace(/"/g,""")),c.html('
  1. '+o.replace(/[\r\t\n]+/g,"
  2. ")+"
"),c.find(">.layui-code-h3")[0]||c.prepend('

'+(c.attr("lay-title")||e.title||"code")+(e.about?'layui.code':"")+"

");var d=c.find(">.layui-code-ol");c.addClass("layui-box layui-code-view"),(c.attr("lay-skin")||e.skin)&&c.addClass("layui-code-"+(c.attr("lay-skin")||e.skin)),(d.find("li").length/100|0)>0&&d.css("margin-left",(d.find("li").length/100|0)+"px"),(c.attr("lay-height")||e.height)&&d.css("max-height",c.attr("lay-height")||e.height)})})}).addcss("modules/code.css","skincodecss"); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/element.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(t){"use strict";var a=layui.$,i=(layui.hint(),layui.device()),e="element",l="layui-this",n="layui-show",s=function(){this.config={}};s.prototype.set=function(t){var i=this;return a.extend(!0,i.config,t),i},s.prototype.on=function(t,a){return layui.onevent.call(this,e,t,a)},s.prototype.tabAdd=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.children(".layui-tab-bar"),o=l.children(".layui-tab-content"),r='
  • "+(i.title||"unnaming")+"
  • ";return s[0]?s.before(r):n.append(r),o.append('
    '+(i.content||"")+"
    "),f.hideTabMore(!0),f.tabAuto(),this},s.prototype.tabDelete=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+i+'"]');return f.tabDelete(null,s),this},s.prototype.tabChange=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+i+'"]');return f.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(t){t=t||{},b.on("click",t.headerElem,function(i){var e=a(this).index();f.tabClick.call(this,i,e,null,t)})},s.prototype.progress=function(t,i){var e="layui-progress",l=a("."+e+"[lay-filter="+t+"]"),n=l.find("."+e+"-bar"),s=n.find("."+e+"-text");return n.css("width",i),s.text(i),this};var o=".layui-nav",r="layui-nav-item",c="layui-nav-bar",u="layui-nav-tree",d="layui-nav-child",y="layui-nav-more",h="layui-anim layui-anim-upbit",f={tabClick:function(t,i,s,o){o=o||{};var r=s||a(this),i=i||r.parent().children("li").index(r),c=o.headerElem?r.parent():r.parents(".layui-tab").eq(0),u=o.bodyElem?a(o.bodyElem):c.children(".layui-tab-content").children(".layui-tab-item"),d=r.find("a"),y=c.attr("lay-filter");"javascript:;"!==d.attr("href")&&"_blank"===d.attr("target")||(r.addClass(l).siblings().removeClass(l),u.eq(i).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,"tab("+y+")",{elem:c,index:i})},tabDelete:function(t,i){var n=i||a(this).parent(),s=n.index(),o=n.parents(".layui-tab").eq(0),r=o.children(".layui-tab-content").children(".layui-tab-item"),c=o.attr("lay-filter");n.hasClass(l)&&(n.next()[0]?f.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&f.tabClick.call(n.prev()[0],null,s-1)),n.remove(),r.eq(s).remove(),setTimeout(function(){f.tabAuto()},50),layui.event.call(this,e,"tabDelete("+c+")",{elem:o,index:s})},tabAuto:function(){var t="layui-tab-more",e="layui-tab-bar",l="layui-tab-close",n=this;a(".layui-tab").each(function(){var s=a(this),o=s.children(".layui-tab-title"),r=(s.children(".layui-tab-content").children(".layui-tab-item"),'lay-stope="tabmore"'),c=a('');if(n===window&&8!=i.ie&&f.hideTabMore(!0),s.attr("lay-allowClose")&&o.find("li").each(function(){var t=a(this);if(!t.find("."+l)[0]){var i=a('');i.on("click",f.tabDelete),t.append(i)}}),"string"!=typeof s.attr("lay-unauto"))if(o.prop("scrollWidth")>o.outerWidth()+1){if(o.find("."+e)[0])return;o.append(c),s.attr("overflow",""),c.on("click",function(a){o[this.title?"removeClass":"addClass"](t),this.title=this.title?"":"收缩"})}else o.find("."+e).remove(),s.removeAttr("overflow")})},hideTabMore:function(t){var i=a(".layui-tab-title");t!==!0&&"tabmore"===a(t.target).attr("lay-stope")||(i.removeClass("layui-tab-more"),i.find(".layui-tab-bar").attr("title",""))},clickThis:function(){var t=a(this),i=t.parents(o),n=i.attr("lay-filter"),s=t.parent(),c=t.siblings("."+d),y="string"==typeof s.attr("lay-unselect");"javascript:;"!==t.attr("href")&&"_blank"===t.attr("target")||y||c[0]||(i.find("."+l).removeClass(l),s.addClass(l)),i.hasClass(u)&&(c.removeClass(h),c[0]&&(s["none"===c.css("display")?"addClass":"removeClass"](r+"ed"),"all"===i.attr("lay-shrink")&&s.siblings().removeClass(r+"ed"))),layui.event.call(this,e,"nav("+n+")",t)},collapse:function(){var t=a(this),i=t.find(".layui-colla-icon"),l=t.siblings(".layui-colla-content"),s=t.parents(".layui-collapse").eq(0),o=s.attr("lay-filter"),r="none"===l.css("display");if("string"==typeof s.attr("lay-accordion")){var c=s.children(".layui-colla-item").children("."+n);c.siblings(".layui-colla-title").children(".layui-colla-icon").html(""),c.removeClass(n)}l[r?"addClass":"removeClass"](n),i.html(r?"":""),layui.event.call(this,e,"collapse("+o+")",{title:t,content:l,show:r})}};s.prototype.init=function(t,e){var l=function(){return e?'[lay-filter="'+e+'"]':""}(),s={tab:function(){f.tabAuto.call({})},nav:function(){var t=200,e={},s={},p={},b=function(l,o,r){var c=a(this),f=c.find("."+d);o.hasClass(u)?l.css({top:c.position().top,height:c.children("a").outerHeight(),opacity:1}):(f.addClass(h),l.css({left:c.position().left+parseFloat(c.css("marginLeft")),top:c.position().top+c.height()-l.height()}),e[r]=setTimeout(function(){l.css({width:c.width(),opacity:1})},i.ie&&i.ie<10?0:t),clearTimeout(p[r]),"block"===f.css("display")&&clearTimeout(s[r]),s[r]=setTimeout(function(){f.addClass(n),c.find("."+y).addClass(y+"d")},300))};a(o+l).each(function(i){var l=a(this),o=a(''),h=l.find("."+r);l.find("."+c)[0]||(l.append(o),h.on("mouseenter",function(){b.call(this,o,l,i)}).on("mouseleave",function(){l.hasClass(u)||(clearTimeout(s[i]),s[i]=setTimeout(function(){l.find("."+d).removeClass(n),l.find("."+y).removeClass(y+"d")},300))}),l.on("mouseleave",function(){clearTimeout(e[i]),p[i]=setTimeout(function(){l.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},t)})),h.find("a").each(function(){var t=a(this),i=(t.parent(),t.siblings("."+d));i[0]&&!t.children("."+y)[0]&&t.append(''),t.off("click",f.clickThis).on("click",f.clickThis)})})},breadcrumb:function(){var t=".layui-breadcrumb";a(t+l).each(function(){var t=a(this),i="lay-separator",e=t.attr(i)||"/",l=t.find("a");l.next("span["+i+"]")[0]||(l.each(function(t){t!==l.length-1&&a(this).after(""+e+"")}),t.css("visibility","visible"))})},progress:function(){var t="layui-progress";a("."+t+l).each(function(){var i=a(this),e=i.find(".layui-progress-bar"),l=e.attr("lay-percent");e.css("width",function(){return/^.+\/.+$/.test(l)?100*new Function("return "+l)()+"%":l}()),i.attr("lay-showPercent")&&setTimeout(function(){e.html(''+l+"")},350)})},collapse:function(){var t="layui-collapse";a("."+t+l).each(function(){var t=a(this).find(".layui-colla-item");t.each(function(){var t=a(this),i=t.find(".layui-colla-title"),e=t.find(".layui-colla-content"),l="none"===e.css("display");i.find(".layui-colla-icon").remove(),i.append(''+(l?"":"")+""),i.off("click",f.collapse).on("click",f.collapse)})})}};return s[t]?s[t]():layui.each(s,function(t,a){a()})},s.prototype.render=s.prototype.init;var p=new s,b=a(document);p.render();var v=".layui-tab-title li";b.on("click",v,f.tabClick),b.on("click",f.hideTabMore),a(window).on("resize",f.tabAuto),t(e,p)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/flow.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(e){"use strict";var l=layui.$,o=function(e){},t='';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var f=l(e.elem);if(f[0]){var m=l(e.scrollElem||document),u=e.mb||50,s=!("isAuto"in e)||e.isAuto,v=e.end||"没有更多了",y=e.scrollElem&&e.scrollElem!==document,d="加载更多",h=l('");f.find(".layui-flow-more")[0]||f.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(v):h.find("a").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find("a").html(t),"function"==typeof e.done&&e.done(++c,p)};if(g(),h.find("a").on("click",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+" img",scrollElem:e.scrollElem});return s?(m.on("scroll",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=y?e.height():l(window).height(),n=y?e.prop("scrollHeight"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||"img",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr("src")){var m=e.attr("lay-src");layui.img(m,function(){var l=t.lazyimg.elem.eq(i);e.attr("src",m).removeAttr("lay-src"),l[0]&&f(l),i++})}},f=function(e,o){var f=a?(o||n).height():l(window).height(),m=n.scrollTop(),u=m+f;if(t.lazyimg.elem=l(r),e)c(e,f);else for(var s=0;su)break}};if(f(),!o){var m;n.on("scroll",function(){var e=l(this);m&&clearTimeout(m),m=setTimeout(function(){f(null,e)},50)}),o=!0}return f},e("flow",new o)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/form.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("layer",function(e){"use strict";var t=layui.$,i=layui.layer,a=layui.hint(),n=layui.device(),l="form",r=".layui-form",s="layui-this",o="layui-hide",c="layui-disabled",u=function(){this.config={verify:{required:[/[\S]+/,"必填项不能为空"],phone:[/^1\d{10}$/,"请输入正确的手机号"],email:[/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,"邮箱格式不正确"],url:[/(^#)|(^http(s*):\/\/[^\s]+\.[^\s]+)/,"链接格式不正确"],number:function(e){if(!e||isNaN(e))return"只能填写数字"},date:[/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/,"日期格式不正确"],identity:[/(^\d{15}$)|(^\d{17}(x|X|\d)$)/,"请输入正确的身份证号"]}}};u.prototype.set=function(e){var i=this;return t.extend(!0,i.config,e),i},u.prototype.verify=function(e){var i=this;return t.extend(!0,i.config.verify,e),i},u.prototype.on=function(e,t){return layui.onevent.call(this,l,e,t)},u.prototype.val=function(e,i){var a=t(r+'[lay-filter="'+e+'"]');a.each(function(e,a){var n=t(this);layui.each(i,function(e,t){var i,a=n.find('[name="'+e+'"]');a[0]&&(i=a[0].type,"checkbox"===i?a[0].checked=t:"radio"===i?a.each(function(){this.value===t&&(this.checked=!0)}):a.val(t))})}),f.render(null,e)},u.prototype.render=function(e,i){var n=this,u=t(r+function(){return i?'[lay-filter="'+i+'"]':""}()),d={select:function(){var e,i="请选择",a="layui-form-select",n="layui-select-title",r="layui-select-none",d="",f=u.find("select"),v=function(i,l){t(i.target).parent().hasClass(n)&&!l||(t("."+a).removeClass(a+"ed "+a+"up"),e&&d&&e.val(d)),e=null},y=function(i,u,f){var y,p=t(this),m=i.find("."+n),k=m.find("input"),x=i.find("dl"),g=x.children("dd"),b=this.selectedIndex;if(!u){var C=function(){var e=i.offset().top+i.outerHeight()+5-h.scrollTop(),t=x.outerHeight();b=p[0].selectedIndex,i.addClass(a+"ed"),g.removeClass(o),y=null,g.eq(b).addClass(s).siblings().removeClass(s),e+t>h.height()&&e>=t&&i.addClass(a+"up"),$()},w=function(e){i.removeClass(a+"ed "+a+"up"),k.blur(),y=null,e||T(k.val(),function(e){var i=p[0].selectedIndex;e&&(d=t(p[0].options[i]).html(),0===i&&d===k.attr("placeholder")&&(d=""),k.val(d||""))})},$=function(){var e=x.children("dd."+s);if(e[0]){var t=e.position().top,i=x.height(),a=e.height();t>i&&x.scrollTop(t+x.scrollTop()-i+a-5),t<0&&x.scrollTop(t+x.scrollTop()-5)}};m.on("click",function(e){i.hasClass(a+"ed")?w():(v(e,!0),C()),x.find("."+r).remove()}),m.find(".layui-edge").on("click",function(){k.focus()}),k.on("keyup",function(e){var t=e.keyCode;9===t&&C()}).on("keydown",function(e){var t=e.keyCode;9===t&&w();var i=function(t,a){var n,l;e.preventDefault();var r=function(){var e=x.children("dd."+s);if(x.children("dd."+o)[0]&&"next"===t){var i=x.children("dd:not(."+o+",."+c+")"),n=i.eq(0).index();if(n>=0&&n无匹配项

    '):x.find("."+r).remove()},"keyup"),""===t&&x.find("."+r).remove(),void $())};f&&k.on("keyup",j).on("blur",function(i){var a=p[0].selectedIndex;e=k,d=t(p[0].options[a]).html(),0===a&&d===k.attr("placeholder")&&(d=""),setTimeout(function(){T(k.val(),function(e){d||k.val("")},"blur")},200)}),g.on("click",function(){var e=t(this),a=e.attr("lay-value"),n=p.attr("lay-filter");return!e.hasClass(c)&&(e.hasClass("layui-select-tips")?k.val(""):(k.val(e.text()),e.addClass(s)),e.siblings().removeClass(s),p.val(a).removeClass("layui-form-danger"),layui.event.call(this,l,"select("+n+")",{elem:p[0],value:a,othis:i}),w(!0),!1)}),i.find("dl>dt").on("click",function(e){return!1}),t(document).off("click",v).on("click",v)}};f.each(function(e,l){var r=t(this),o=r.next("."+a),u=this.disabled,d=l.value,f=t(l.options[l.selectedIndex]),v=l.options[0];if("string"==typeof r.attr("lay-ignore"))return r.show();var h="string"==typeof r.attr("lay-search"),p=v?v.value?i:v.innerHTML||i:i,m=t(['
    ','
    ','','
    ','
    ',function(e){var t=[];return layui.each(e,function(e,a){0!==e||a.value?"optgroup"===a.tagName.toLowerCase()?t.push("
    "+a.label+"
    "):t.push('
    '+a.innerHTML+"
    "):t.push('
    '+(a.innerHTML||i)+"
    ")}),0===t.length&&t.push('
    没有选项
    '),t.join("")}(r.find("*"))+"
    ","
    "].join(""));o[0]&&o.remove(),r.after(m),y.call(this,m,u,h)})},checkbox:function(){var e={checkbox:["layui-form-checkbox","layui-form-checked","checkbox"],_switch:["layui-form-switch","layui-form-onswitch","switch"]},i=u.find("input[type=checkbox]"),a=function(e,i){var a=t(this);e.on("click",function(){var t=a.attr("lay-filter"),n=(a.attr("lay-text")||"").split("|");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(i[1]).find("em").text(n[1])):(a[0].checked=!0,e.addClass(i[1]).find("em").text(n[0])),layui.event.call(a[0],l,i[2]+"("+t+")",{elem:a[0],value:a[0].value,othis:e}))})};i.each(function(i,n){var l=t(this),r=l.attr("lay-skin"),s=(l.attr("lay-text")||"").split("|"),o=this.disabled;"switch"===r&&(r="_"+r);var u=e[r]||e.checkbox;if("string"==typeof l.attr("lay-ignore"))return l.show();var d=l.next("."+u[0]),f=t(['
    ",function(){var e=n.title.replace(/\s/g,""),t={checkbox:[e?""+n.title+"":"",''].join(""),_switch:""+((n.checked?s[0]:s[1])||"")+""};return t[r]||t.checkbox}(),"
    "].join(""));d[0]&&d.remove(),l.after(f),a.call(this,f,u)})},radio:function(){var e="layui-form-radio",i=["",""],a=u.find("input[type=radio]"),n=function(a){var n=t(this),s="layui-anim-scaleSpring";a.on("click",function(){var o=n[0].name,c=n.parents(r),u=n.attr("lay-filter"),d=c.find("input[name="+o.replace(/(\.|#|\[|\])/g,"\\$1")+"]");n[0].disabled||(layui.each(d,function(){var a=t(this).next("."+e);this.checked=!1,a.removeClass(e+"ed"),a.find(".layui-icon").removeClass(s).html(i[1])}),n[0].checked=!0,a.addClass(e+"ed"),a.find(".layui-icon").addClass(s).html(i[0]),layui.event.call(n[0],l,"radio("+u+")",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=t(this),s=r.next("."+e),o=this.disabled;if("string"==typeof r.attr("lay-ignore"))return r.show();s[0]&&s.remove();var u=t(['
    ',''+i[l.checked?0:1]+"","
    "+function(){var e=l.title||"";return"string"==typeof r.next().attr("lay-radio")&&(e=r.next().html(),r.next().remove()),e}()+"
    ","
    "].join(""));r.after(u),n.call(this,u)})}};return e?d[e]?d[e]():a.error("不支持的"+e+"表单渲染"):layui.each(d,function(e,t){t()}),n};var d=function(){var e=t(this),a=f.config.verify,s=null,o="layui-form-danger",c={},u=e.parents(r),d=u.find("*[lay-verify]"),v=e.parents("form")[0],h=u.find("input,select,textarea"),y=e.attr("lay-filter");if(layui.each(d,function(e,l){var r=t(this),c=r.attr("lay-verify").split("|"),u=r.attr("lay-verType"),d=r.val();if(r.removeClass(o),layui.each(c,function(e,t){var c,f="",v="function"==typeof a[t];if(a[t]){var c=v?f=a[t](d,l):!a[t][0].test(d);if(f=f||a[t][1],c)return"tips"===u?i.tips(f,function(){return"string"==typeof r.attr("lay-ignore")||"select"!==l.tagName.toLowerCase()&&!/^checkbox|radio$/.test(l.type)?r:r.next()}(),{tips:1}):"alert"===u?i.alert(f,{title:"提示",shadeClose:!0}):i.msg(f,{icon:5,shift:6}),n.android||n.ios||l.focus(),r.addClass(o),s=!0}}),s)return s}),s)return!1;var p={};return layui.each(h,function(e,t){if(t.name=(t.name||"").replace(/^\s*|\s*&/,""),t.name){if(/^.*\[\]$/.test(t.name)){var i=t.name.match(/^(.*)\[\]$/g)[0];p[i]=0|p[i],t.name=t.name.replace(/^(.*)\[\]$/,"$1["+p[i]++ +"]")}/^checkbox|radio$/.test(t.type)&&!t.checked||(c[t.name]=t.value)}}),layui.event.call(this,l,"submit("+y+")",{elem:this,form:v,field:c})},f=new u,v=t(document),h=t(window);f.render(),v.on("reset",r,function(){var e=t(this).attr("lay-filter");setTimeout(function(){f.render(null,e)},50)}),v.on("submit",r,d).on("click","*[lay-submit]",d),e(l,f)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/laypage.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define(function(e){"use strict";var a=document,t="getElementById",n="getElementsByTagName",i="laypage",r="layui-disabled",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if("object"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups="groups"in a?0|a.groups:5;a.layout="object"==typeof a.layout?a.layout:["prev","page","next"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits="object"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev="prev"in a?a.prev:"上一页",a.next="next"in a?a.next:"下一页";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?''+a.prev+"":""}(),page:function(){var e=[];if(a.count<1)return"";n>1&&a.first!==!1&&0!==t&&e.push(''+(a.first||1)+"");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r2&&e.push('');r<=u;r++)r===a.curr?e.push('"+r+""):e.push(''+r+"");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1…'),0!==t&&e.push(''+(a.last||a.pages)+"")),e.join("")}(),next:function(){return a.next?''+a.next+"":""}(),count:'共 '+a.count+" 条",limit:function(){var e=['"}(),refresh:['','',""].join(""),skip:function(){return['到第','','页',""].join("")}()};return['
    ',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join("")}(),"
    "].join("")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n]("button")[0],l=e[n]("input")[0],p=e[n]("select")[0],c=function(){var e=0|l.value.replace(/\s|\D/g,"");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;oi.pages||(i.curr=e,t.render())});p&&s.on(p,"change",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,"click",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n]("input")[0];t&&s.on(t,"keyup",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\D/.test(n)&&(this.value=n.replace(/\D/,"")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t]("layui-laypage-"+i.index);n.jump(s),i.hash&&!e&&(location.hash="!"+i.hash+"="+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent("on"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/laytpl.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define(function(e){"use strict";var r={open:"{{",close:"}}"},c={exp:function(e){return new RegExp(e,"g")},query:function(e,c,t){var o=["#([\\s\\S])+?","([^{#}])*?"][e||0];return n((c||"")+r.open+o+r.close+(t||""))},escape:function(e){return String(e||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")},error:function(e,r){var c="Laytpl Error:";return"object"==typeof console&&console.error(c+e+"\n"+(r||"")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n("^"+r.open+"#",""),l=n(r.close+"$","");e=e.replace(/\s+|\r|\t|\n/g," ").replace(n(r.open+"#"),r.open+"# ").replace(n(r.close+"}"),"} "+r.close).replace(/\\/g,"\\\\").replace(n(r.open+"!(.+?)!"+r.close),function(e){return e=e.replace(n("^"+r.open+"!"),"").replace(n("!"+r.close),"").replace(n(r.open+"|"+r.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(c.query(),function(e){return e=e.replace(a,"").replace(l,""),'";'+e.replace(/\\/g,"")+';view+="'}).replace(c.query(1),function(e){var c='"+(';return e.replace(/\s/g,"")===r.open+r.close?"":(e=e.replace(n(r.open+"|"+r.close),""),/^=/.test(e)&&(e=e.replace(/^=/,""),c='"+_escape_('),c+e.replace(/\\/g,"")+')+"')}),e='"use strict";var view = "'+e+'";return view;';try{return o.cache=e=new Function("d, _escape_",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error("no data")};var o=function(e){return"string"!=typeof e?c.error("Template not found"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v="1.2.0",e("laytpl",o)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/rate.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(e){"use strict";var a=layui.jquery,i={config:{},index:layui.rate?layui.rate.index+1e4:0,set:function(e){var i=this;return i.config=a.extend({},i.config,e),i},on:function(e,a){return layui.onevent.call(this,n,e,a)}},l=function(){var e=this,a=e.config;return{setvalue:function(a){e.setvalue.call(e,a)},config:a}},n="rate",t="layui-rate",o="layui-icon-rate",s="layui-icon-rate-solid",u="layui-icon-rate-half",r="layui-icon-rate-solid layui-icon-rate-half",c="layui-icon-rate-solid layui-icon-rate",f="layui-icon-rate layui-icon-rate-half",v=function(e){var l=this;l.index=++i.index,l.config=a.extend({},l.config,i.config,e),l.render()};v.prototype.config={length:5,text:!1,readonly:!1,half:!1,value:0,theme:""},v.prototype.render=function(){var e=this,i=e.config,l=i.theme?'style="color: '+i.theme+';"':"";i.elem=a(i.elem),parseInt(i.value)!==i.value&&(i.half||(i.value=Math.ceil(i.value)-i.value<.5?Math.ceil(i.value):Math.floor(i.value)));for(var n='
      ",u=1;u<=i.length;u++){var r='
    • ";i.half&&parseInt(i.value)!==i.value&&u==Math.ceil(i.value)?n=n+'
    • ":n+=r}n+="
    "+(i.text?''+i.value+"星":"")+"";var c=i.elem,f=c.next("."+t);f[0]&&f.remove(),e.elemTemp=a(n),i.span=e.elemTemp.next("span"),i.setText&&i.setText(i.value),c.html(e.elemTemp),c.addClass("layui-inline"),i.readonly||e.action()},v.prototype.setvalue=function(e){var a=this,i=a.config;i.value=e,a.render()},v.prototype.action=function(){var e=this,i=e.config,l=e.elemTemp,n=l.find("i").width();l.children("li").each(function(e){var t=e+1,v=a(this);v.on("click",function(e){if(i.value=t,i.half){var o=e.pageX-a(this).offset().left;o<=n/2&&(i.value=i.value-.5)}i.text&&l.next("span").text(i.value+"星"),i.choose&&i.choose(i.value),i.setText&&i.setText(i.value)}),v.on("mousemove",function(e){if(l.find("i").each(function(){a(this).addClass(o).removeClass(r)}),l.find("i:lt("+t+")").each(function(){a(this).addClass(s).removeClass(f)}),i.half){var c=e.pageX-a(this).offset().left;c<=n/2&&v.children("i").addClass(u).removeClass(s)}}),v.on("mouseleave",function(){l.find("i").each(function(){a(this).addClass(o).removeClass(r)}),l.find("i:lt("+Math.floor(i.value)+")").each(function(){a(this).addClass(s).removeClass(f)}),i.half&&parseInt(i.value)!==i.value&&l.children("li:eq("+Math.floor(i.value)+")").children("i").addClass(u).removeClass(c)})})},v.prototype.events=function(){var e=this;e.config},i.render=function(e){var a=new v(e);return l.call(a)},e(n,i)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/slider.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(e){"use strict";var i=layui.jquery,t={config:{},index:layui.slider?layui.slider.index+1e4:0,set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,n,e,i)}},a=function(){var e=this,i=e.config;return{setValue:function(i,t){return e.slide("set",i,t||0)},config:i}},n="slider",l="layui-disabled",s="layui-slider",r="layui-slider-bar",o="layui-slider-wrap",u="layui-slider-wrap-btn",d="layui-slider-tips",v="layui-slider-input",c="layui-slider-input-txt",m="layui-slider-input-btn",p="layui-slider-hover",f=function(e){var a=this;a.index=++t.index,a.config=i.extend({},a.config,t.config,e),a.render()};f.prototype.config={type:"default",min:0,max:100,value:0,step:1,showstep:!1,tips:!0,input:!1,range:!1,height:200,disabled:!1,theme:"#009688"},f.prototype.render=function(){var e=this,t=e.config;if(t.step<1&&(t.step=1),t.maxt.min?a:t.min,t.value[1]=n>t.min?n:t.min,t.value[0]=t.value[0]>t.max?t.max:t.value[0],t.value[1]=t.value[1]>t.max?t.max:t.value[1];var r=Math.floor((t.value[0]-t.min)/(t.max-t.min)*100),v=Math.floor((t.value[1]-t.min)/(t.max-t.min)*100),m=v-r+"%";r+="%",v+="%"}else{"object"==typeof t.value&&(t.value=Math.min.apply(null,t.value)),t.valuet.max&&(t.value=t.max);var m=Math.floor((t.value-t.min)/(t.max-t.min)*100)+"%"}var p=t.disabled?"#c2c2c2":t.theme,f='
    '+(t.tips?'
    ':"")+'
    '+(t.range?'
    ':"")+"
    ",h=i(t.elem),y=h.next("."+s);if(y[0]&&y.remove(),e.elemTemp=i(f),t.range?(e.elemTemp.find("."+o).eq(0).data("value",t.value[0]),e.elemTemp.find("."+o).eq(1).data("value",t.value[1])):e.elemTemp.find("."+o).data("value",t.value),h.html(e.elemTemp),"vertical"===t.type&&e.elemTemp.height(t.height+"px"),t.showstep){for(var g=(t.max-t.min)/t.step,b="",x=1;x')}e.elemTemp.append(b)}if(t.input&&!t.range){var w=i('
    ');h.css("position","relative"),h.append(w),h.find("."+c).children("input").val(t.value),"vertical"===t.type?w.css({left:0,top:-48}):e.elemTemp.css("margin-right",w.outerWidth()+15)}t.disabled?(e.elemTemp.addClass(l),e.elemTemp.find("."+u).addClass(l)):e.slide(),e.elemTemp.find("."+u).on("mouseover",function(){var a="vertical"===t.type?t.height:e.elemTemp[0].offsetWidth,n=e.elemTemp.find("."+o),l="vertical"===t.type?a-i(this).parent()[0].offsetTop-n.height():i(this).parent()[0].offsetLeft,s=l/a*100,r=i(this).parent().data("value"),u=t.setTips?t.setTips(r):r;e.elemTemp.find("."+d).html(u),"vertical"===t.type?e.elemTemp.find("."+d).css({bottom:s+"%","margin-bottom":"20px",display:"inline-block"}):e.elemTemp.find("."+d).css({left:s+"%",display:"inline-block"})}).on("mouseout",function(){e.elemTemp.find("."+d).css("display","none")})},f.prototype.slide=function(e,t,a){var n=this,l=n.config,s=n.elemTemp,f=function(){return"vertical"===l.type?l.height:s[0].offsetWidth},h=s.find("."+o),y=s.next("."+v),g=y.children("."+c).children("input").val(),b=100/((l.max-l.min)/Math.ceil(l.step)),x=function(e,i){e=Math.ceil(e)*b>100?Math.ceil(e)*b:Math.round(e)*b,e=e>100?100:e,h.eq(i).css("vertical"===l.type?"bottom":"left",e+"%");var t=T(h[0].offsetLeft),a=l.range?T(h[1].offsetLeft):0;"vertical"===l.type?(s.find("."+d).css({bottom:e+"%","margin-bottom":"20px"}),t=T(f()-h[0].offsetTop-h.height()),a=l.range?T(f()-h[1].offsetTop-h.height()):0):s.find("."+d).css("left",e+"%"),t=t>100?100:t,a=a>100?100:a;var n=Math.min(t,a),o=Math.abs(t-a);"vertical"===l.type?s.find("."+r).css({height:o+"%",bottom:n+"%"}):s.find("."+r).css({width:o+"%",left:n+"%"});var u=l.min+Math.round((l.max-l.min)*e/100);if(g=u,y.children("."+c).children("input").val(g),h.eq(i).data("value",u),u=l.setTips?l.setTips(u):u,s.find("."+d).html(u),l.range){var v=[h.eq(0).data("value"),h.eq(1).data("value")];v[0]>v[1]&&v.reverse()}l.change&&l.change(l.range?v:u)},T=function(e){var i=e/f()*100/b,t=Math.round(i)*b;return e==f()&&(t=Math.ceil(i)*b),t},w=i(['
    f()&&(r=f());var o=r/f()*100/b;x(o,e),t.addClass(p),s.find("."+d).show(),i.preventDefault()},o=function(){t.removeClass(p),s.find("."+d).hide()};M(r,o)})}),s.on("click",function(e){var t=i("."+u);if(!t.is(event.target)&&0===t.has(event.target).length&&t.length){var a,n="vertical"===l.type?f()-e.clientY+i(this).offset().top:e.clientX-i(this).offset().left;n<0&&(n=0),n>f()&&(n=f());var s=n/f()*100/b;a=l.range?"vertical"===l.type?Math.abs(n-parseInt(i(h[0]).css("bottom")))>Math.abs(n-parseInt(i(h[1]).css("bottom")))?1:0:Math.abs(n-h[0].offsetLeft)>Math.abs(n-h[1].offsetLeft)?1:0:0,x(s,a),e.preventDefault()}}),y.hover(function(){var e=i(this);e.children("."+m).fadeIn("fast")},function(){var e=i(this);e.children("."+m).fadeOut("fast")}),y.children("."+m).children("i").each(function(e){i(this).on("click",function(){g=1==e?g-l.stepl.max?l.max:Number(g)+l.step;var i=(g-l.min)/(l.max-l.min)*100/b;x(i,0)})});var q=function(){var e=this.value;e=isNaN(e)?0:e,e=el.max?l.max:e,this.value=e;var i=(e-l.min)/(l.max-l.min)*100/b;x(i,0)};y.children("."+c).children("input").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),q.call(this))}).on("change",q)},f.prototype.events=function(){var e=this;e.config},t.render=function(e){var i=new f(e);return a.call(i)},e(n,t)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/tree.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(e){"use strict";var o=layui.$,a=layui.hint(),i="layui-tree-enter",r=function(e){this.options=e},t={arrow:["",""],checkbox:["",""],radio:["",""],branch:["",""],leaf:""};r.prototype.init=function(e){var o=this;e.addClass("layui-box layui-tree"),o.options.skin&&e.addClass("layui-tree-skin-"+o.options.skin),o.tree(e),o.on(e)},r.prototype.tree=function(e,a){var i=this,r=i.options,n=a||r.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('
      '),s=o(["
    • ",function(){return l?''+(n.spread?t.arrow[1]:t.arrow[0])+"":""}(),function(){return r.check?''+("checkbox"===r.check?t.checkbox[0]:"radio"===r.check?t.radio[0]:"")+"":""}(),function(){return'"+(''+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+"")+(""+(n.name||"未命名")+"")}(),"
    • "].join(""));l&&(s.append(c),i.tree(c,n.children)),e.append(s),"function"==typeof r.click&&i.click(s,n),i.spread(s,n),r.drag&&i.drag(s,n)})},r.prototype.click=function(e,o){var a=this,i=a.options;e.children("a").on("click",function(e){layui.stope(e),i.click(o)})},r.prototype.spread=function(e,o){var a=this,i=(a.options,e.children(".layui-tree-spread")),r=e.children("ul"),n=e.children("a"),l=function(){e.data("spread")?(e.data("spread",null),r.removeClass("layui-show"),i.html(t.arrow[0]),n.find(".layui-icon").html(t.branch[0])):(e.data("spread",!0),r.addClass("layui-show"),i.html(t.arrow[1]),n.find(".layui-icon").html(t.branch[1]))};r[0]&&(i.on("click",l),n.on("dblclick",l))},r.prototype.on=function(e){var a=this,r=a.options,t="layui-tree-drag";e.find("i").on("selectstart",function(e){return!1}),r.drag&&o(document).on("mousemove",function(e){var i=a.move;if(i.from){var r=(i.to,o('
      '));e.preventDefault(),o("."+t)[0]||o("body").append(r);var n=o("."+t)[0]?o("."+t):r;n.addClass("layui-show").html(i.from.elem.children("a").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on("mouseup",function(){var e=a.move;e.from&&(e.from.elem.children("a").removeClass(i),e.to&&e.to.elem.children("a").removeClass(i),a.move={},o("."+t).remove())})},r.prototype.move={},r.prototype.drag=function(e,a){var r=this,t=(r.options,e.children("a")),n=function(){var t=o(this),n=r.move;n.from&&(n.to={item:a,elem:e},t.addClass(i))};t.on("mousedown",function(){var o=r.move;o.from={item:a,elem:e}}),t.on("mouseenter",n).on("mousemove",n).on("mouseleave",function(){var e=o(this),a=r.move;a.from&&(delete a.to,e.removeClass(i))})},e("tree",function(e){var i=new r(e=e||{}),t=o(e.elem);return t[0]?void i.init(t):a.error("layui.tree 没有找到"+e.elem+"元素")})}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/upload.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("layer",function(e){"use strict";var i=layui.$,t=layui.layer,n=layui.hint(),a=layui.device(),o={config:{},set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,r,e,i)}},l=function(){var e=this;return{upload:function(i){e.upload.call(e,i)},config:e.config}},r="upload",u="layui-upload-file",c="layui-upload-form",f="layui-upload-iframe",s="layui-upload-choose",p=function(e){var t=this;t.config=i.extend({},t.config,o.config,e),t.render()};p.prototype.config={accept:"images",exts:"",auto:!0,bindAction:"",url:"",field:"file",method:"post",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var t=this,e=t.config;e.elem=i(e.elem),e.bindAction=i(e.bindAction),t.file(),t.events()},p.prototype.file=function(){var e=this,t=e.config,n=e.elemFile=i(['"].join("")),o=t.elem.next();(o.hasClass(u)||o.hasClass(c))&&o.remove(),a.ie&&a.ie<10&&t.elem.wrap('
      '),e.isFile()?(e.elemFile=t.elem,t.field=t.elem[0].name):t.elem.after(n),a.ie&&a.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,t=e.config,n=i(''),a=i(['
      ',"
      "].join(""));i("#"+f)[0]||i("body").append(n),t.elem.next().hasClass(c)||(e.elemFile.wrap(a),t.elem.next("."+c).append(function(){var e=[];return layui.each(t.data,function(i,t){t="function"==typeof t?t():t,e.push('')}),e.join("")}()))},p.prototype.msg=function(e){return t.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return"input"===e.tagName.toLocaleLowerCase()&&"file"===e.type},p.prototype.preview=function(e){var i=this;window.FileReader&&layui.each(i.chooseFiles,function(i,t){var n=new FileReader;n.readAsDataURL(t),n.onload=function(){e&&e(i,t,this.result)}})},p.prototype.upload=function(e,t){var n,o=this,l=o.config,r=o.elemFile[0],u=function(){var t=0,n=0,a=e||o.files||o.chooseFiles||r.files,u=function(){l.multiple&&t+n===o.fileLength&&"function"==typeof l.allDone&&l.allDone({total:o.fileLength,successful:t,aborted:n})};layui.each(a,function(e,a){var r=new FormData;r.append(l.field,a),layui.each(l.data,function(e,i){i="function"==typeof i?i():i,r.append(e,i)}),i.ajax({url:l.url,type:"post",data:r,contentType:!1,processData:!1,dataType:"json",headers:l.headers||{},success:function(i){t++,d(e,i),u()},error:function(){n++,o.msg("请求上传接口出现异常"),m(e),u()}})})},c=function(){var e=i("#"+f);o.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var i,t=e.contents().find("body");try{i=t.text()}catch(n){o.msg("获取上传后的响应信息出现异常"),clearInterval(p.timer),m()}i&&(clearInterval(p.timer),t.html(""),d(0,i))},30)},d=function(e,i){if(o.elemFile.next("."+s).remove(),r.value="","object"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},o.msg("请对上传接口返回有效JSON")}"function"==typeof l.done&&l.done(i,e||0,function(e){o.upload(e)})},m=function(e){l.auto&&(r.value=""),"function"==typeof l.error&&l.error(e||0,function(e){o.upload(e)})},h=l.exts,v=function(){var i=[];return layui.each(e||o.chooseFiles,function(e,t){i.push(t.name)}),i}(),g={preview:function(e){o.preview(e)},upload:function(e,i){var t={};t[e]=i,o.upload(t)},pushFile:function(){return o.files=o.files||{},layui.each(o.chooseFiles,function(e,i){o.files[e]=i}),o.files},resetFile:function(e,i,t){var n=new File([i],t);o.files=o.files||{},o.files[e]=n}},y=function(){if("choose"!==t&&!l.auto||(l.choose&&l.choose(g),"choose"!==t))return l.before&&l.before(g),a.ie?a.ie>9?u():c():void u()};if(v=0===v.length?r.value.match(/[^\/\\]+\..+/g)||[]||"":v,0!==v.length){switch(l.accept){case"file":if(h&&!RegExp("\\w\\.("+h+")$","i").test(escape(v)))return o.msg("选择的文件中包含不支持的格式"),r.value="";break;case"video":if(!RegExp("\\w\\.("+(h||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(v)))return o.msg("选择的视频中包含不支持的格式"),r.value="";break;case"audio":if(!RegExp("\\w\\.("+(h||"mp3|wav|mid")+")$","i").test(escape(v)))return o.msg("选择的音频中包含不支持的格式"),r.value="";break;default:if(layui.each(v,function(e,i){RegExp("\\w\\.("+(h||"jpg|png|gif|bmp|jpeg$")+")","i").test(escape(i))||(n=!0)}),n)return o.msg("选择的图片中包含不支持的格式"),r.value=""}if(o.fileLength=function(){var i=0,t=e||o.files||o.chooseFiles||r.files;return layui.each(t,function(){i++}),i}(),l.number&&o.fileLength>l.number)return o.msg("同时最多只能上传的数量为:"+l.number);if(l.size>0&&!(a.ie&&a.ie<10)){var F;if(layui.each(o.chooseFiles,function(e,i){if(i.size>1024*l.size){var t=l.size/1024;t=t>=1?t.toFixed(2)+"MB":l.size+"KB",r.value="",F=t}}),F)return o.msg("文件不能超过"+F)}y()}},p.prototype.events=function(){var e=this,t=e.config,o=function(i){e.chooseFiles={},layui.each(i,function(i,t){var n=(new Date).getTime();e.chooseFiles[n+"-"+i]=t})},l=function(i,n){var a=e.elemFile,o=i.length>1?i.length+"个文件":(i[0]||{}).name||a[0].value.match(/[^\/\\]+\..+/g)||[]||"";a.next().hasClass(s)&&a.next().remove(),e.upload(null,"choose"),e.isFile()||t.choose||a.after(''+o+"")};t.elem.off("upload.start").on("upload.start",function(){var a=i(this),o=a.attr("lay-data");if(o)try{o=new Function("return "+o)(),e.config=i.extend({},t,o)}catch(l){n.error("Upload element property lay-data configuration item has a syntax error: "+o)}e.config.item=a,e.elemFile[0].click()}),a.ie&&a.ie<10||t.elem.off("upload.over").on("upload.over",function(){var e=i(this);e.attr("lay-over","")}).off("upload.leave").on("upload.leave",function(){var e=i(this);e.removeAttr("lay-over")}).off("upload.drop").on("upload.drop",function(n,a){var r=i(this),u=a.originalEvent.dataTransfer.files||[];r.removeAttr("lay-over"),o(u),t.auto?e.upload(u):l(u)}),e.elemFile.off("upload.change").on("upload.change",function(){var i=this.files||[];o(i),t.auto?e.upload():l(i)}),t.bindAction.off("upload.action").on("upload.action",function(){e.upload()}),t.elem.data("haveEvents")||(e.elemFile.on("change",function(){i(this).trigger("upload.change")}),t.elem.on("click",function(){e.isFile()||i(this).trigger("upload.start")}),t.drag&&t.elem.on("dragover",function(e){e.preventDefault(),i(this).trigger("upload.over")}).on("dragleave",function(e){i(this).trigger("upload.leave")}).on("drop",function(e){e.preventDefault(),i(this).trigger("upload.drop",e)}),t.bindAction.on("click",function(){i(this).trigger("upload.action")}),t.elem.data("haveEvents",!0))},o.render=function(e){var i=new p(e);return l.call(i)},e(r,o)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/lay/modules/util.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;layui.define("jquery",function(t){"use strict";var e=layui.$,i={fixbar:function(t){var i,a,n="layui-fixbar",r="layui-fixbar-top",o=e(document),l=e("body");t=e.extend({showHeight:200},t),t.bar1=t.bar1===!0?"":t.bar1,t.bar2=t.bar2===!0?"":t.bar2,t.bgcolor=t.bgcolor?"background-color:"+t.bgcolor:"";var c=[t.bar1,t.bar2,""],g=e(['
        ',t.bar1?'
      • '+c[0]+"
      • ":"",t.bar2?'
      • '+c[1]+"
      • ":"",'
      • '+c[2]+"
      • ","
      "].join("")),s=g.find("."+r),u=function(){var e=o.scrollTop();e>=t.showHeight?i||(s.show(),i=1):i&&(s.hide(),i=0)};e("."+n)[0]||("object"==typeof t.css&&g.css(t.css),l.append(g),u(),g.find("li").on("click",function(){var i=e(this),a=i.attr("lay-type");"top"===a&&e("html,body").animate({scrollTop:0},200),t.click&&t.click.call(this,a)}),o.on("scroll",function(){clearTimeout(a),a=setTimeout(function(){u()},100)}))},countdown:function(t,e,i){var a=this,n="function"==typeof e,r=new Date(t).getTime(),o=new Date(!e||n?(new Date).getTime():e).getTime(),l=r-o,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];n&&(i=e);var g=setTimeout(function(){a.countdown(t,o+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],e,g),l<=0&&clearTimeout(g),g},timeAgo:function(t,e){var i=this,a=[[],[]],n=(new Date).getTime()-new Date(t).getTime();return n>6912e5?(n=new Date(t),a[0][0]=i.digit(n.getFullYear(),4),a[0][1]=i.digit(n.getMonth()+1),a[0][2]=i.digit(n.getDate()),e||(a[1][0]=i.digit(n.getHours()),a[1][1]=i.digit(n.getMinutes()),a[1][2]=i.digit(n.getSeconds())),a[0].join("-")+" "+a[1].join(":")):n>=864e5?(n/1e3/60/60/24|0)+"天前":n>=36e5?(n/1e3/60/60|0)+"小时前":n>=12e4?(n/1e3/60|0)+"分钟前":n<0?"未来":"刚刚"},digit:function(t,e){var i="";t=String(t),e=e||2;for(var a=t.length;a/g,">").replace(/'/g,"'").replace(/"/g,""")}};!function(t,e,i){"$:nomunge";function a(){n=e[l](function(){r.each(function(){var e=t(this),i=e.width(),a=e.height(),n=t.data(this,g);(i!==n.w||a!==n.h)&&e.trigger(c,[n.w=i,n.h=a])}),a()},o[s])}var n,r=t([]),o=t.resize=t.extend(t.resize,{}),l="setTimeout",c="resize",g=c+"-special-event",s="delay",u="throttleWindow";o[s]=250,o[u]=!0,t.event.special[c]={setup:function(){if(!o[u]&&this[l])return!1;var e=t(this);r=r.add(e),t.data(this,g,{w:e.width(),h:e.height()}),1===r.length&&a()},teardown:function(){if(!o[u]&&this[l])return!1;var e=t(this);r=r.not(e),e.removeData(g),r.length||clearTimeout(n)},add:function(e){function a(e,a,r){var o=t(this),l=t.data(this,g)||{};l.w=a!==i?a:o.width(),l.h=r!==i?r:o.height(),n.apply(this,arguments)}if(!o[u]&&this[l])return!1;var n;return t.isFunction(e)?(n=e,a):(n=e.handler,void(e.handler=a))}}}(e,window),t("util",i)}); -------------------------------------------------------------------------------- /src/main/resources/static/layui/layui.js: -------------------------------------------------------------------------------- 1 | /** layui-v2.4.5 MIT License By https://www.layui.com */ 2 | ;!function(e){"use strict";var t=document,o={modules:{},status:{},timeout:10,event:{}},n=function(){this.v="2.4.5"},r=function(){var e=t.currentScript?t.currentScript.src:function(){for(var e,o=t.scripts,n=o.length-1,r=n;r>0;r--)if("interactive"===o[r].readyState){e=o[r].src;break}return e||o[n].src}();return e.substring(0,e.lastIndexOf("/")+1)}(),i=function(t){e.console&&console.error&&console.error("Layui hint: "+t)},a="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),u={layer:"modules/layer",laydate:"modules/laydate",laypage:"modules/laypage",laytpl:"modules/laytpl",layim:"modules/layim",layedit:"modules/layedit",form:"modules/form",upload:"modules/upload",tree:"modules/tree",table:"modules/table",element:"modules/element",rate:"modules/rate",colorpicker:"modules/colorpicker",slider:"modules/slider",carousel:"modules/carousel",flow:"modules/flow",util:"modules/util",code:"modules/code",jquery:"modules/jquery",mobile:"modules/mobile","layui.all":"../layui.all"};n.prototype.cache=o,n.prototype.define=function(e,t){var n=this,r="function"==typeof e,i=function(){var e=function(e,t){layui[e]=t,o.status[e]=!0};return"function"==typeof t&&t(function(n,r){e(n,r),o.callback[n]=function(){t(e)}}),this};return r&&(t=e,e=[]),layui["layui.all"]||!layui["layui.all"]&&layui["layui.mobile"]?i.call(n):(n.use(e,i),n)},n.prototype.use=function(e,n,l){function s(e,t){var n="PLaySTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/;("load"===e.type||n.test((e.currentTarget||e.srcElement).readyState))&&(o.modules[f]=t,d.removeChild(v),function r(){return++m>1e3*o.timeout/4?i(f+" is not a valid module"):void(o.status[f]?c():setTimeout(r,4))}())}function c(){l.push(layui[f]),e.length>1?y.use(e.slice(1),n,l):"function"==typeof n&&n.apply(layui,l)}var y=this,p=o.dir=o.dir?o.dir:r,d=t.getElementsByTagName("head")[0];e="string"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(y.each(e,function(t,o){"jquery"===o&&e.splice(t,1)}),layui.jquery=layui.$=jQuery);var f=e[0],m=0;if(l=l||[],o.host=o.host||(p.match(/\/\/([\s\S]+?)\//)||["//"+location.host+"/"])[0],0===e.length||layui["layui.all"]&&u[f]||!layui["layui.all"]&&layui["layui.mobile"]&&u[f])return c(),y;if(o.modules[f])!function g(){return++m>1e3*o.timeout/4?i(f+" is not a valid module"):void("string"==typeof o.modules[f]&&o.status[f]?c():setTimeout(g,4))}();else{var v=t.createElement("script"),h=(u[f]?p+"lay/":/^\{\/\}/.test(y.modules[f])?"":o.base||"")+(y.modules[f]||f)+".js";h=h.replace(/^\{\/\}/,""),v.async=!0,v.charset="utf-8",v.src=h+function(){var e=o.version===!0?o.v||(new Date).getTime():o.version||"";return e?"?v="+e:""}(),d.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf("[native code")<0||a?v.addEventListener("load",function(e){s(e,h)},!1):v.attachEvent("onreadystatechange",function(e){s(e,h)}),o.modules[f]=h}return y},n.prototype.getStyle=function(t,o){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](o)},n.prototype.link=function(e,n,r){var a=this,u=t.createElement("link"),l=t.getElementsByTagName("head")[0];"string"==typeof n&&(r=n);var s=(r||e).replace(/\.|\//g,""),c=u.id="layuicss-"+s,y=0;return u.rel="stylesheet",u.href=e+(o.debug?"?v="+(new Date).getTime():""),u.media="all",t.getElementById(c)||l.appendChild(u),"function"!=typeof n?a:(function p(){return++y>1e3*o.timeout/100?i(e+" timeout"):void(1989===parseInt(a.getStyle(t.getElementById(c),"width"))?function(){n()}():setTimeout(p,100))}(),a)},o.callback={},n.prototype.factory=function(e){if(layui[e])return"function"==typeof o.callback[e]?o.callback[e]:null},n.prototype.addcss=function(e,t,n){return layui.link(o.dir+"css/"+e,t,n)},n.prototype.img=function(e,t,o){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,"function"==typeof t&&t(n)},void(n.onerror=function(e){n.onerror=null,"function"==typeof o&&o(e)}))},n.prototype.config=function(e){e=e||{};for(var t in e)o[t]=e[t];return this},n.prototype.modules=function(){var e={};for(var t in u)e[t]=u[t];return e}(),n.prototype.extend=function(e){var t=this;e=e||{};for(var o in e)t[o]||t.modules[o]?i("模块名 "+o+" 已被占用"):t.modules[o]=e[o];return t},n.prototype.router=function(e){var t=this,e=e||location.hash,o={path:[],search:{},hash:(e.match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(e)?(e=e.replace(/^#\//,""),o.href="/"+e,e=e.replace(/([^#])(#.*$)/,"$1").split("/")||[],t.each(e,function(e,t){/^\w+=/.test(t)?function(){t=t.split("="),o.search[t[0]]=t[1]}():o.path.push(t)}),o):o},n.prototype.data=function(t,o,n){if(t=t||"layui",n=n||localStorage,e.JSON&&e.JSON.parse){if(null===o)return delete n[t];o="object"==typeof o?o:{key:o};try{var r=JSON.parse(n[t])}catch(i){var r={}}return"value"in o&&(r[o.key]=o.value),o.remove&&delete r[o.key],n[t]=JSON.stringify(r),o.key?r[o.key]:r}},n.prototype.sessionData=function(e,t){return this.data(e,t,sessionStorage)},n.prototype.device=function(t){var o=navigator.userAgent.toLowerCase(),n=function(e){var t=new RegExp(e+"/([^\\s\\_\\-]+)");return e=(o.match(t)||[])[1],e||!1},r={os:function(){return/windows/.test(o)?"windows":/linux/.test(o)?"linux":/iphone|ipod|ipad|ios/.test(o)?"ios":/mac/.test(o)?"mac":void 0}(),ie:function(){return!!(e.ActiveXObject||"ActiveXObject"in e)&&((o.match(/msie\s(\d+)/)||[])[1]||"11")}(),weixin:n("micromessenger")};return t&&!r[t]&&(r[t]=n(t)),r.android=/android/.test(o),r.ios="ios"===r.os,r},n.prototype.hint=function(){return{error:i}},n.prototype.each=function(e,t){var o,n=this;if("function"!=typeof t)return n;if(e=e||[],e.constructor===Object){for(o in e)if(t.call(e[o],o,e[o]))break}else for(o=0;oi?1:r 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 |
      11 |
      12 | 13 |
      14 | 15 |
      16 |
      17 |
      18 | 19 |
      20 | 21 |
      22 |
      23 |
      24 | 25 |
      26 | 27 |
      28 |
      29 |
      30 | 31 |
      32 | 33 |
      34 |
      35 | 36 | 37 | 38 | 39 | 40 |
      41 | 42 | -------------------------------------------------------------------------------- /src/test/java/com/bektz/dataplatformsoar/DataPlatformSoarApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DataPlatformSoarApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/bektz/dataplatformsoar/MysqlTest.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import com.alibaba.druid.pool.DruidPooledConnection; 5 | import com.alibaba.druid.util.JdbcUtils; 6 | import org.junit.Assert; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import java.sql.SQLException; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public class MysqlTest { 15 | 16 | 17 | DruidDataSource dataSource = null; 18 | 19 | @Before 20 | public void setup() throws Exception { 21 | dataSource = new DruidDataSource(); 22 | dataSource.setUsername("root"); 23 | dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/local"); 24 | dataSource.setPassword("root"); 25 | dataSource.setMaxActive(2); 26 | dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 27 | DruidPooledConnection connection = dataSource.getConnection(1000); 28 | } 29 | 30 | 31 | @Test 32 | public void mysqlTest() throws SQLException { 33 | boolean asyncInit = dataSource.isAsyncInit(); 34 | System.out.println(asyncInit); 35 | // DruidPooledConnection connection = dataSource.getConnection(); 36 | // Statement statement = connection.createStatement(); 37 | // boolean execute = statement.execute("select 1"); 38 | // System.out.println(execute); 39 | } 40 | 41 | 42 | @Test 43 | public void jdbcUtilsTest() throws Exception { 44 | List> show_tables = JdbcUtils.executeQuery(dataSource, "select * from test"); 45 | Assert.assertTrue(show_tables.size() > 0); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/com/bektz/dataplatformsoar/service/SoarServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.service; 2 | 3 | import com.bektz.dataplatformsoar.req.SqlVerifyReq; 4 | import com.bektz.dataplatformsoar.resp.SqlVerifyResp; 5 | import org.junit.Assert; 6 | import org.junit.jupiter.api.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import static org.junit.jupiter.api.Assertions.*; 13 | 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | class SoarServiceTest { 17 | @Autowired 18 | private SoarService soarService; 19 | 20 | @Test 21 | void verify() { 22 | SqlVerifyResp verify = soarService.verify(SqlVerifyReq.builder().sql("CREATE TABLE `testfyl` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`test` varchar(20) DEFAULT NULL,`dfa` varchar(20) DEFAULT NULL,`hhh` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULTCHARSET=utf8mb4;").build()); 23 | Assert.assertNotNull(verify); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/test/java/com/bektz/dataplatformsoar/sqlparser/DruidSqlParserTest.java: -------------------------------------------------------------------------------- 1 | package com.bektz.dataplatformsoar.sqlparser; 2 | 3 | import com.bektz.dataplatformsoar.sqlparser.druid.DruidSqlParser; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.util.Map; 7 | 8 | class DruidSqlParserTest { 9 | 10 | 11 | String[] sqls = new String[]{ 12 | // "SELECT * ,username FROM MY_TABLE1, MY_TABLE2, (SELECT username FROM MY_TABLE3) LEFT OUTER JOIN MY_TABLE4 \" +\n" + 13 | // " \" WHERE ID = (SELECT MAX(ID) FROM MY_TABLE5) AND ID2 IN (SELECT * FROM MY_TABLE6)", 14 | "select a.name c from (select alert.name from alert inner join user on alert.id = user.id) a", 15 | "select a.m cc , a.nnn from (select c.mobile as m ,c.nnn nnn from card c where c.id = 1) a", 16 | "select u.name,u.no from (select u.name name ,c.card_no no from user u inner join card c on u.id = c.id) u", 17 | "select * from (select a,avg(*) b from alert) c", 18 | "select a.na a from (select u.name as na , u.age from user u inner join alert al on alert.id = user.id) a", 19 | "select a.m as cc from (select c.mobile as m from (select mobile from card) c) a", 20 | "select * from firekylin.alert", 21 | "select st.sname,st.sno from student st join (select sc.sno sn,count(sc.cno) cou from sc group by sc.sno) scs on st.sno=scs.sn where scs.cou <(select count(cno) from course);", 22 | "select distinct st.sno, sname\n" + 23 | " from student st\n" + 24 | " join sc sc on (st.sno = sc.sno)\n" + 25 | " where sc.cno in (select cno from sc where sno = 's001') and sc.sno<>'s001';" 26 | }; 27 | 28 | @Test 29 | void parserRealMetaData() { 30 | DruidSqlParser druidSqlParser = new DruidSqlParser(); 31 | for (String sql : sqls) { 32 | Map columnItems = druidSqlParser.parserSql(sql); 33 | System.out.println(columnItems); 34 | } 35 | } 36 | 37 | 38 | @Test 39 | void parserTest() { 40 | String sql = "select distinct st.sno, sname\n" + 41 | " from student st\n" + 42 | " join sc sc on (st.sno = sc.sno)\n" + 43 | " where sc.cno in (select cno from sc where sno = 's001') and sc.sno<>'s001';"; 44 | DruidSqlParser druidSqlParser = new DruidSqlParser(); 45 | Map columnItems = druidSqlParser.parserSql(sql); 46 | System.out.println(columnItems); 47 | 48 | } 49 | } --------------------------------------------------------------------------------