init
11
.idea/$PROJECT_FILE$
generated
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AnalysisProjectProfileManager">
|
||||
<option name="PROJECT_PROFILE" />
|
||||
<option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
|
||||
<list size="0" />
|
||||
</component>
|
||||
<component name="SuppressionsComponent">
|
||||
<option name="suppComments" value="[]" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
13
.idea/compiler.xml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="ko-time" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
20
.idea/jarRepositories.xml
generated
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
17
.idea/misc.xml
generated
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
<component name="SuppressionsComponent">
|
||||
<option name="suppComments" value="[]" />
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/qaplug_profiles.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AnalysisProjectProfileManager">
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
|
||||
<scopes />
|
||||
<profiles>
|
||||
<profile profile_name="Project Default" version="1.0" is_locked="false" />
|
||||
</profiles>
|
||||
<list size="0" />
|
||||
</component>
|
||||
</project>
|
||||
109
README.md
Normal file
@ -0,0 +1,109 @@
|
||||
# koTime
|
||||
|
||||
#### 介绍
|
||||
koTime是一个springboot项目性能分析工具,通过追踪方法调用链路以及对应的运行时长快速定位性能瓶颈:
|
||||
|
||||
|
||||
|
||||
优点:
|
||||
> * 无缝集成springboot,使用简单
|
||||
> * 通过简单配置集成,与业务逻辑无耦合
|
||||
|
||||
|
||||
缺点:
|
||||
> * 目前仅适用于单机版,不支持分布式和集群
|
||||
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. 引入依赖 或者 下载发行版本
|
||||
```
|
||||
<dependency>
|
||||
<groupId>cn.langpy</groupId>
|
||||
<artifactId>simsearch</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
```
|
||||
2. 配置信息
|
||||
|
||||
在application.yml中配置
|
||||
```
|
||||
sim-search.dir=xxx //索引位置,可不填,使用默认位置:当前项目下的indexs目录(第一次运行需手动创建)
|
||||
sim-search.size.core=10 //创建索引的核心线程数量,根据cpu自行决定,可不填,默认为10
|
||||
sim-search.size.max=10 //创建索引的最大线程数量,根据cpu自行决定,可不填,默认为200
|
||||
sim-search.size.queue=1000 //创建索引的线程队列容量,自行决定,可不填,默认为20000
|
||||
sim-search.index.init=true 重启时是否要对之前的索引进行删除,默认为false
|
||||
```
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. 在需要创建索引的实体上标注需要创建索引的字段
|
||||
```java
|
||||
import cn.langpy.simsearch.annotation.IndexColumn;
|
||||
import cn.langpy.simsearch.annotation.IndexId;
|
||||
|
||||
public class Student {
|
||||
/*索引唯一id*/
|
||||
@IndexId
|
||||
private String id;
|
||||
/*需要创建索引的字段*/
|
||||
@IndexColumn
|
||||
private String studentName;
|
||||
@IndexColumn
|
||||
private String schoolName;
|
||||
private String age;
|
||||
}
|
||||
```
|
||||
|
||||
2. 在需要创建索引的方法上加上创建索引的注解
|
||||
|
||||
```java
|
||||
|
||||
```
|
||||
|
||||
3. 在需要删除索引的方法上加上删除索引的注解
|
||||
|
||||
```java
|
||||
|
||||
```
|
||||
|
||||
4. 搜索的时候自定义一个空的方法,加上注解即可
|
||||
|
||||
```java
|
||||
|
||||
```
|
||||
注意:搜索结果仅仅是搜索出加上@IndexId和@IndexColumn的字段,具体内容自行往业务数据库查询
|
||||
|
||||
#### 版本说明
|
||||
|
||||
1.接口列表总览
|
||||
|
||||
在列表中会显示该接口的运行耗时,如果为绿色则无需优化,如果为红色,需要详细查看问题所在
|
||||
|
||||
|
||||

|
||||
|
||||
2.调用详情
|
||||
|
||||
点开接口时,会显示该接口的调用链路以及运行时长
|
||||
|
||||

|
||||
|
||||
#### 版本说明
|
||||
|
||||
> V1.0-snapshots:提供基础索引创建、删除和检索功能
|
||||
|
||||
> V1.1:增加重启索引初始化功能
|
||||
|
||||
> V1.2:搜索时,如果未找到搜索,可走默认模式
|
||||
|
||||
#### 问题说明
|
||||
|
||||
1. 本项目中使用了aspectjweaver依赖,如果引入的项目中没有该依赖,自行引入
|
||||
```
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>xxx</version>
|
||||
</dependency>
|
||||
```
|
||||
2
ko-time.iml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4" />
|
||||
130
pom.xml
Normal file
@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>koTime</artifactId>
|
||||
<version>1.0</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>5.2.7.RELEASE</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.20</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.6.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>5.2.11.RELEASE</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot</artifactId>
|
||||
<version>2.3.1.RELEASE</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>9.0.36</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
12
src/main/java/cn/langpy/kotime/annotation/ComputeTime.java
Normal file
@ -0,0 +1,12 @@
|
||||
package cn.langpy.kotime.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComputeTime {
|
||||
String value() default "chinese";
|
||||
}
|
||||
7
src/main/java/cn/langpy/kotime/config/LoadConfig.java
Normal file
@ -0,0 +1,7 @@
|
||||
package cn.langpy.kotime.config;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@ComponentScan("cn.langpy.kotime")
|
||||
public class LoadConfig {
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.model.RunTimeNode;
|
||||
import cn.langpy.kotime.model.SystemStatistic;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import cn.langpy.kotime.util.MethodType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/koTime")
|
||||
@Slf4j
|
||||
public class KoTimeController {
|
||||
@GetMapping
|
||||
public String index(Model model, HttpServletRequest request) {
|
||||
List<RunTimeNode> list = Context.get(MethodType.Controller);
|
||||
model.addAttribute("list",list);
|
||||
SystemStatistic system = Context.getStatistic();
|
||||
model.addAttribute("system",system);
|
||||
return "index";
|
||||
}
|
||||
@GetMapping("/getTree")
|
||||
@ResponseBody
|
||||
public RunTimeNode getTree(String methodName,Model model, HttpServletRequest request) {
|
||||
return Context.getTree(methodName);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package cn.langpy.kotime.handler;
|
||||
|
||||
import cn.langpy.kotime.annotation.ComputeTime;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class ComputeTimeHandler {
|
||||
|
||||
|
||||
|
||||
@Pointcut("@annotation(cn.langpy.kotime.annotation.ComputeTime)")
|
||||
public void preProcess(){
|
||||
}
|
||||
|
||||
@Around("preProcess()")
|
||||
public Object doAroundCompute(ProceedingJoinPoint pjp) throws Throwable{
|
||||
ComputeTime computeTime = ((MethodSignature)pjp.getSignature()).getMethod().getAnnotation(ComputeTime.class);
|
||||
long begin = System.nanoTime();
|
||||
Object obj=pjp.proceed();
|
||||
long end =System.nanoTime();
|
||||
if ("chinese".equals(computeTime.value())) {
|
||||
log.info("调用方法={},耗时={}毫秒",pjp.getTarget().getClass().getName()+"."+pjp.getSignature().getName(),(end-begin)/1000000);
|
||||
}else{
|
||||
log.info("method={},runTime={}ms",pjp.getTarget().getClass().getName()+"."+pjp.getSignature().getName(),(end-begin)/1000000);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package cn.langpy.kotime.handler;
|
||||
|
||||
|
||||
import cn.langpy.kotime.model.RunTimeNode;
|
||||
import cn.langpy.kotime.util.Common;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
|
||||
@Aspect
|
||||
public interface ComputeTimeHandlerInterface {
|
||||
|
||||
@Pointcut("")
|
||||
void prog();
|
||||
|
||||
@Around("prog()")
|
||||
default Object globalCompute(ProceedingJoinPoint pjp) throws Throwable{
|
||||
long begin = System.nanoTime();
|
||||
Object obj=pjp.proceed();
|
||||
long end =System.nanoTime();
|
||||
String packName = this.getClass().getPackage().getName();
|
||||
RunTimeNode parent = Common.getParentRunTimeNode(packName);
|
||||
RunTimeNode current = Common.getCurrentRunTimeNode(pjp,((end-begin)/1000000.0));
|
||||
Context.set(parent,current);
|
||||
return obj;
|
||||
}
|
||||
|
||||
}
|
||||
120
src/main/java/cn/langpy/kotime/model/RunTimeNode.java
Normal file
@ -0,0 +1,120 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
import cn.langpy.kotime.util.MethodType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class RunTimeNode implements Comparable<RunTimeNode> {
|
||||
private String name;
|
||||
private String className;
|
||||
private String methodName;
|
||||
private Double avgRunTime = 0.0;
|
||||
private Double value = 0.0;
|
||||
private String avgRunTimeUnit = "ms";
|
||||
private MethodType methodType;
|
||||
private List<RunTimeNode> children;
|
||||
@Override
|
||||
public int compareTo(RunTimeNode ob) {
|
||||
return this.avgRunTime.compareTo(ob.getAvgRunTime());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAvgRunTimeUnit() {
|
||||
return avgRunTimeUnit;
|
||||
}
|
||||
|
||||
public void setAvgRunTimeUnit(String avgRunTimeUnit) {
|
||||
this.avgRunTimeUnit = avgRunTimeUnit;
|
||||
}
|
||||
|
||||
public MethodType getMethodType() {
|
||||
return methodType;
|
||||
}
|
||||
|
||||
public void setMethodType(MethodType methodType) {
|
||||
this.methodType = methodType;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public void setClassName(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
public void setMethodName(String methodName) {
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
public Double getAvgRunTime() {
|
||||
return avgRunTime;
|
||||
}
|
||||
|
||||
public void setAvgRunTime(Double avgRunTime) {
|
||||
this.avgRunTime = avgRunTime;
|
||||
}
|
||||
|
||||
|
||||
public List<RunTimeNode> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<RunTimeNode> children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
RunTimeNode that = (RunTimeNode) o;
|
||||
return Objects.equals(className, that.className) &&
|
||||
Objects.equals(methodName, that.methodName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(className, methodName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RunTimeNode{" +
|
||||
"className='" + className + '\'' +
|
||||
", methodName='" + methodName + '\'' +
|
||||
", avgRunTime=" + avgRunTime +
|
||||
", avgRunTimeUnit='" + avgRunTimeUnit + '\'' +
|
||||
", methodType=" + methodType +
|
||||
", children=" + children +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
68
src/main/java/cn/langpy/kotime/model/SystemStatistic.java
Normal file
@ -0,0 +1,68 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
|
||||
public class SystemStatistic {
|
||||
private String name;
|
||||
private Double avgRunTime = 0.0;
|
||||
private Double maxRunTime = 0.0;
|
||||
private Double minRunTime = 0.0;
|
||||
private Integer totalNum;
|
||||
private Integer delayNum;
|
||||
private Integer normalNum;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Double getAvgRunTime() {
|
||||
return avgRunTime;
|
||||
}
|
||||
|
||||
public void setAvgRunTime(Double avgRunTime) {
|
||||
this.avgRunTime = avgRunTime;
|
||||
}
|
||||
|
||||
public Double getMaxRunTime() {
|
||||
return maxRunTime;
|
||||
}
|
||||
|
||||
public void setMaxRunTime(Double maxRunTime) {
|
||||
this.maxRunTime = maxRunTime;
|
||||
}
|
||||
|
||||
public Double getMinRunTime() {
|
||||
return minRunTime;
|
||||
}
|
||||
|
||||
public void setMinRunTime(Double minRunTime) {
|
||||
this.minRunTime = minRunTime;
|
||||
}
|
||||
|
||||
public Integer getTotalNum() {
|
||||
return totalNum;
|
||||
}
|
||||
|
||||
public void setTotalNum(Integer totalNum) {
|
||||
this.totalNum = totalNum;
|
||||
}
|
||||
|
||||
public Integer getDelayNum() {
|
||||
return delayNum;
|
||||
}
|
||||
|
||||
public void setDelayNum(Integer delayNum) {
|
||||
this.delayNum = delayNum;
|
||||
}
|
||||
|
||||
public Integer getNormalNum() {
|
||||
return normalNum;
|
||||
}
|
||||
|
||||
public void setNormalNum(Integer normalNum) {
|
||||
this.normalNum = normalNum;
|
||||
}
|
||||
}
|
||||
91
src/main/java/cn/langpy/kotime/util/Common.java
Normal file
@ -0,0 +1,91 @@
|
||||
package cn.langpy.kotime.util;
|
||||
|
||||
import cn.langpy.kotime.model.RunTimeNode;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Common {
|
||||
|
||||
public static RunTimeNode getParentRunTimeNode(String packName) {
|
||||
String parentClassName = "";
|
||||
String parentMothodName = "";
|
||||
StackTraceElement[] stacks = Thread.currentThread().getStackTrace();
|
||||
String[] packNameSplit = packName.split("\\.");
|
||||
String filter = packNameSplit.length>1 ? packNameSplit[0]+"."+packNameSplit[1] : packNameSplit[0];
|
||||
int stacksLength = stacks.length;
|
||||
for (int i = 0; i < stacksLength; i++) {
|
||||
StackTraceElement stack = stacks[i];
|
||||
if (stack.getClassName().startsWith(filter)&& !stack.getClassName().contains("$")) {
|
||||
parentClassName = stack.getClassName();
|
||||
parentMothodName = stack.getMethodName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
RunTimeNode parent = new RunTimeNode();
|
||||
parent.setClassName(parentClassName);
|
||||
parent.setMethodName(parentMothodName);
|
||||
parent.setName(parentClassName.substring(parentClassName.lastIndexOf(".")+1)+"."+parentMothodName);
|
||||
parent.setMethodType(getMethodType(parentClassName));
|
||||
parent.setChildren(new ArrayList<>());
|
||||
return parent;
|
||||
}
|
||||
|
||||
public static RunTimeNode getCurrentRunTimeNode(ProceedingJoinPoint pjp,Double runTime) {
|
||||
String className = pjp.getTarget().getClass().getName();
|
||||
String methodName = pjp.getSignature().getName();
|
||||
RunTimeNode current = new RunTimeNode();
|
||||
current.setName(className.substring(className.lastIndexOf(".")+1)+"."+methodName);
|
||||
current.setClassName(className);
|
||||
current.setMethodName(methodName);
|
||||
current.setAvgRunTime(runTime);
|
||||
current.setChildren(new ArrayList<>());
|
||||
current.setMethodType(getMethodType(pjp));
|
||||
return current;
|
||||
}
|
||||
|
||||
public static MethodType getMethodType(ProceedingJoinPoint pjp) {
|
||||
MethodType methodType = null;
|
||||
Class<?> targetClass = pjp.getTarget().getClass();
|
||||
if (targetClass.getAnnotation(Controller.class)!=null || targetClass.getAnnotation(RestController.class)!=null) {
|
||||
methodType = MethodType.Controller;
|
||||
}else if (targetClass.getAnnotation(Service.class)!=null) {
|
||||
methodType = MethodType.Service;
|
||||
}else if (targetClass.getAnnotation(Repository.class)!=null) {
|
||||
methodType = MethodType.Dao;
|
||||
}
|
||||
if (methodType == null) {
|
||||
String className = pjp.getTarget().getClass().getName().toLowerCase();
|
||||
if (className.contains("controller")) {
|
||||
methodType = MethodType.Controller;
|
||||
}else if (className.contains("service")) {
|
||||
methodType = MethodType.Service;
|
||||
}else if (className.contains("dao") || className.contains("mapper")) {
|
||||
methodType = MethodType.Dao;
|
||||
}else{
|
||||
methodType = MethodType.Others;
|
||||
}
|
||||
}
|
||||
return methodType;
|
||||
}
|
||||
|
||||
public static MethodType getMethodType(String className) {
|
||||
MethodType methodType = null;
|
||||
className = className.toLowerCase();
|
||||
if (className.contains("controller")) {
|
||||
methodType = MethodType.Controller;
|
||||
}else if (className.contains("service")) {
|
||||
methodType = MethodType.Service;
|
||||
}else if (className.contains("dao") || className.contains("mapper")) {
|
||||
methodType = MethodType.Dao;
|
||||
}else{
|
||||
methodType = MethodType.Others;
|
||||
}
|
||||
return methodType;
|
||||
}
|
||||
|
||||
}
|
||||
112
src/main/java/cn/langpy/kotime/util/Context.java
Normal file
@ -0,0 +1,112 @@
|
||||
package cn.langpy.kotime.util;
|
||||
|
||||
import cn.langpy.kotime.model.RunTimeNode;
|
||||
import cn.langpy.kotime.model.SystemStatistic;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class Context {
|
||||
|
||||
private static Map<String, RunTimeNode> runTimeNodeMap;
|
||||
static {
|
||||
runTimeNodeMap = new HashMap<>();
|
||||
}
|
||||
|
||||
|
||||
public static void set(RunTimeNode parent,RunTimeNode current) {
|
||||
|
||||
String parentKey = parent.getClassName()+"."+parent.getMethodName();
|
||||
String currentKey = current.getClassName()+"."+current.getMethodName();
|
||||
if (!currentKey.contains("$")) {
|
||||
log.info("调用方法="+currentKey+",耗时="+current.getAvgRunTime()+"毫秒");
|
||||
}else {
|
||||
return;
|
||||
}
|
||||
if (".".equals(parentKey)) {
|
||||
if (runTimeNodeMap.containsKey(currentKey)) {
|
||||
runTimeNodeMap.get(currentKey).setAvgRunTime(current.getAvgRunTime());
|
||||
}else{
|
||||
runTimeNodeMap.put(currentKey,current);
|
||||
}
|
||||
}else if (runTimeNodeMap.containsKey(parentKey)) {
|
||||
RunTimeNode hisRunTimeNode = runTimeNodeMap.get(parentKey);
|
||||
List<RunTimeNode> hisRunTimeNodeChildren = hisRunTimeNode.getChildren();
|
||||
if (hisRunTimeNodeChildren!=null) {
|
||||
if (hisRunTimeNodeChildren.contains(current)) {
|
||||
int hisLength = hisRunTimeNodeChildren.size();
|
||||
for (int i = 0; i < hisLength; i++) {
|
||||
if (hisRunTimeNodeChildren.get(i)==current) {
|
||||
current.setAvgRunTime((current.getAvgRunTime()+hisRunTimeNode.getChildren().get(i).getAvgRunTime())/2.0);
|
||||
hisRunTimeNodeChildren.set(i,current) ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
hisRunTimeNodeChildren.add(current);
|
||||
}
|
||||
} else {
|
||||
List<RunTimeNode> list = new ArrayList<>();
|
||||
list.add(current);
|
||||
hisRunTimeNode.setChildren(list);
|
||||
}
|
||||
runTimeNodeMap.put(parentKey,hisRunTimeNode);
|
||||
}else{
|
||||
List<RunTimeNode> list = new ArrayList<>();
|
||||
list.add(current);
|
||||
parent.setChildren(list);
|
||||
runTimeNodeMap.put(parentKey,parent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static RunTimeNode get(String key) {
|
||||
return runTimeNodeMap.get(key);
|
||||
}
|
||||
public static List<RunTimeNode> get(MethodType methodType) {
|
||||
return runTimeNodeMap.values().stream()
|
||||
.filter(runTimeNode -> runTimeNode.getMethodType()==methodType)
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
public static RunTimeNode getTree(String key) {
|
||||
RunTimeNode root = runTimeNodeMap.get(key);
|
||||
if (root==null) {
|
||||
return root;
|
||||
}
|
||||
root.setValue(root.getAvgRunTime());
|
||||
List<RunTimeNode> children = root.getChildren();
|
||||
if (children!=null&&children.size()>0) {
|
||||
children.forEach(child->{
|
||||
String childKey = child.getClassName()+"."+child.getMethodName();
|
||||
RunTimeNode newChild = getTree(childKey);
|
||||
if (newChild!=null) {
|
||||
child.setChildren(newChild.getChildren());
|
||||
child.setValue(child.getAvgRunTime());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static SystemStatistic getStatistic() {
|
||||
List<RunTimeNode> controllerApis = get(MethodType.Controller);
|
||||
SystemStatistic systemStatistic = new SystemStatistic();
|
||||
int delayNum = (int)controllerApis.stream().filter(controllerApi -> controllerApi.getAvgRunTime() >= 800).count();
|
||||
systemStatistic.setDelayNum(delayNum);
|
||||
int normalNum = (int)controllerApis.stream().filter(controllerApi -> controllerApi.getAvgRunTime() < 800).count();
|
||||
systemStatistic.setNormalNum(normalNum);
|
||||
int totalNum = (int)controllerApis.stream().count();
|
||||
systemStatistic.setTotalNum(totalNum);
|
||||
Double max = controllerApis.stream().map(api->api.getAvgRunTime()).max(Double::compareTo).get();
|
||||
Double min = controllerApis.stream().map(api->api.getAvgRunTime()).min(Double::compareTo).get();
|
||||
Double avg = controllerApis.stream().map(api->api.getAvgRunTime()).collect(Collectors.averagingDouble(Double::doubleValue));
|
||||
systemStatistic.setMaxRunTime(max);
|
||||
systemStatistic.setMinRunTime(min);
|
||||
systemStatistic.setAvgRunTime(avg);
|
||||
return systemStatistic;
|
||||
}
|
||||
}
|
||||
8
src/main/java/cn/langpy/kotime/util/MethodType.java
Normal file
@ -0,0 +1,8 @@
|
||||
package cn.langpy.kotime.util;
|
||||
|
||||
public enum MethodType {
|
||||
Controller,
|
||||
Service,
|
||||
Dao,
|
||||
Others;
|
||||
}
|
||||
2
src/main/resources/META-INF/spring.factories
Normal file
@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
cn.langpy.kotime.config.LoadConfig
|
||||
15
src/main/resources/application-koTime.yml
Normal file
@ -0,0 +1,15 @@
|
||||
spring:
|
||||
mvc:
|
||||
static-path-pattern: /static/**
|
||||
freemarker:
|
||||
allow-request-override: false
|
||||
cache: true
|
||||
check-template-location: true
|
||||
charset: UTF-8
|
||||
content-type: text/html
|
||||
suffix: .html
|
||||
template-loader-path: classpath:/templates
|
||||
expose-request-attributes: false
|
||||
expose-session-attributes: false
|
||||
expose-spring-macro-helpers: false
|
||||
request-context-attribute: ctx
|
||||
22
src/main/resources/static/echarts.min.js
vendored
Normal file
6
src/main/resources/static/jquery.min.js
vendored
Normal file
464
src/main/resources/static/layui/css/global.css
Normal file
@ -0,0 +1,464 @@
|
||||
/**
|
||||
|
||||
layui官网
|
||||
By 贤心
|
||||
|
||||
*/
|
||||
|
||||
|
||||
h1,h2,h3{font-size: 14px;}
|
||||
::-webkit-input-placeholder{color: #999}
|
||||
|
||||
/* 布局 */
|
||||
.site-inline{font-size: 0;}
|
||||
.site-tree, .site-content{display: inline-block; *display:inline; *zoom:1; vertical-align: top; font-size: 14px;}
|
||||
.site-tree{width: 220px; min-height: 900px; padding: 5px 0 20px;}
|
||||
.site-content{width: 899px; min-height: 900px; padding: 20px 0 10px 20px;}
|
||||
|
||||
/* 头部 */
|
||||
.header{height: 59px; border-bottom: 1px solid #404553; background-color: #393D49;}
|
||||
.logo{position: absolute; left: 0; top: 16px;}
|
||||
.logo img{width: 82px; height: 31px;}
|
||||
|
||||
.header .layui-nav{position: absolute; right: 0; top: 0; padding: 0; background: none;}
|
||||
.header .layui-nav .layui-nav-item{margin: 0 20px; }
|
||||
.header .layui-nav .layui-nav-item[mobile]{display: none;}
|
||||
|
||||
.header .layui-container .logo{left: 15px;}
|
||||
.header .layui-container .layui-nav{right: 15px;}
|
||||
.header .layui-nav .layui-badge,
|
||||
.header .layui-nav .layui-badge-dot{right: 0;}
|
||||
|
||||
.menu{position: absolute; right: 0; top: 0; line-height: 65px;}
|
||||
.menu a{display:inline-block; *display:inline; *zoom:1; vertical-align:top;}
|
||||
.menu a{position: relative; padding: 0 20px; margin: 0 20px; color: #c2c2c2; font-size: 14px;}
|
||||
.menu a:hover{color: #fff; transition: all .5s; -webkit-transition: all .5s}
|
||||
.menu a.this{color: #fff}
|
||||
.menu a.this::after{content: ''; position: absolute; left: 0; bottom: -1px; width: 100%; height: 5px; background-color: #5FB878;}
|
||||
|
||||
.header-index{}
|
||||
.header-index .site-banner-bg{}
|
||||
.header-index[spring]{border: none; background-color: #0D1206}
|
||||
.header-index[summer]{border: none; background-color: #0A0E11}
|
||||
.header-index[autumn]{border: none; background-color: #100903}
|
||||
.header-index[winter]{border: none; background-color: #110F25/*#06041C*/}
|
||||
|
||||
.header-demo{height: 60px; border-bottom: none;}
|
||||
.header-demo .logo{left: 40px;}
|
||||
.header-demo .layui-nav{top: 0;}
|
||||
.header-demo .layui-nav .layui-nav-item{margin: 0 10px;}
|
||||
|
||||
.header-demo .layui-nav .layui-this a{padding: 0 30px;}
|
||||
|
||||
|
||||
.component{position: absolute; width: 160px; left: 120px; top: 16px; }
|
||||
.component .layui-input{height: 30px; padding-left: 12px; background-color: #424652; background-color: rgba(255,255,255,.05); border: none 0; color: #fff; color: rgba(255,255,255,.5); font-size: 12px;}
|
||||
.component .layui-form-select .layui-edge{display: none; border-top-color: #999;}
|
||||
.component .layui-form-select dl{top: 36px; background-color: rgba(255,255,255,.9)}
|
||||
.header-demo .component{left: 185px;}
|
||||
|
||||
|
||||
/* 子侧边 */
|
||||
.layui-side-child{width: 160px!important; left: 200px; bottom: 60px!important; border-right: 1px solid #eee; background-color: #fff;}
|
||||
.layui-side-child .layui-side-scroll{width: 170px;}
|
||||
.layui-side-child .layui-nav{padding: 10px 0; width: 160px; border-radius: 0; background: none}
|
||||
.layui-side-child .layui-nav-child{border-radius: 0;}
|
||||
.layui-side-child .layui-nav .layui-nav-title a,
|
||||
.layui-side-child .layui-nav .layui-nav-title a:hover,
|
||||
.layui-side-child .layui-nav-itemed>a{color: #666 !important;}
|
||||
.layui-side-child .layui-nav-itemed .layui-nav-child{margin-bottom: 10px; background: none !important;}
|
||||
.layui-side-child .layui-nav .layui-nav-item a{height: 30px; line-height: 30px; color: #666;}
|
||||
.layui-side-child .layui-nav .layui-nav-item a:hover{background: none !important;}
|
||||
.layui-side-child .layui-nav .layui-nav-child a{color: #999 !important;}
|
||||
.layui-side-child .layui-nav .layui-nav-more{display: none;}
|
||||
.layui-side-child .layui-nav-tree .layui-this,
|
||||
.layui-side-child .layui-nav-tree .layui-this>a,
|
||||
.layui-side-child .layui-nav-tree .layui-nav-child dd.layui-this,
|
||||
.layui-side-child .layui-nav-tree .layui-nav-child dd.layui-this a{background: none; color: #5FB878 !important;}
|
||||
.layui-side-child .layui-nav .layui-nav-child a:hover{color: #009688 !important}
|
||||
.layui-side-child .layui-nav-bar{background-color: #5FB878;}
|
||||
|
||||
|
||||
/* 底部 */
|
||||
.footer{padding: 30px 0; line-height: 30px; text-align: center; color: #666; font-weight: 300;}
|
||||
body .layui-layout-admin .footer-demo{height: 50px; line-height: 50px; padding: 5px 0;}
|
||||
.footer a{padding: 0 5px;}
|
||||
.site-union{color: #999;}
|
||||
.site-union>*{display: inline-block; vertical-align: middle;}
|
||||
.site-union a[sponsor] img{width: 80px;}
|
||||
.site-union span{position: relative; top: 5px;}
|
||||
.site-union span a{padding: 0; display: inline; color: #999;}
|
||||
.site-union span a:hover{text-decoration: underline;}
|
||||
.site-union .site-union-desc{display: block; margin-bottom: 10px;}
|
||||
|
||||
.footer-demo p,
|
||||
.footer-demo .site-union,
|
||||
.footer-demo .site-union p{display: inline-block; vertical-align: middle; padding-right: 10px;}
|
||||
.footer-demo .site-union{position: relative; top: -5px;}
|
||||
.footer-demo .site-union .site-union-desc{margin-bottom: 0; padding-right: 0;}
|
||||
.footer-demo .site-union a[sponsor] img{position: relative; top: 3px;}
|
||||
|
||||
/* 首页banner部分 */
|
||||
.site-banner{position: relative; height: 600px; text-align: center; overflow: hidden; background-color: #393D49;}
|
||||
.site-banner-bg
|
||||
,.site-banner-main{position: absolute; left: 0; top: 0; width: 100%; height: 100%;}
|
||||
.site-banner-bg{background-position: center 0;}
|
||||
|
||||
|
||||
.site-zfj{padding-top: 25px; height: 220px;}
|
||||
.site-zfj i{position: absolute; left: 50%; top: 50px; width: 200px; height: 200px; margin-left: -100px; font-size: 180px; color: #c2c2c2;}
|
||||
|
||||
@keyframes site-zfj {
|
||||
0% {opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg) scale(1);}
|
||||
10% {opacity: 0.8; transform: translate3d(-100px, 0px, 0) rotate(10deg) scale(0.7);}
|
||||
35% {opacity: 0.6; transform: translate3d(100px, 0px, 0) rotate(30deg) scale(0.4);}
|
||||
50% {opacity: 0.4; transform: translate3d(0, 0, 0) rotate(360deg) scale(0);}
|
||||
80% {opacity: 0.2; transform: translate3d(0, 0, 0) rotate(720deg) scale(1);}
|
||||
90% {opacity: 0.1; transform: translate3d(0, 0, 0) rotate(3600deg) scale(6);}
|
||||
100% {opacity: 1; transform: translate3d(0, 0, 0) rotate(3600deg) scale(1);}
|
||||
}
|
||||
|
||||
@keyframes site-desc {
|
||||
0% { transform: scale(1.1);}
|
||||
100% {transform: scale(1);}
|
||||
}
|
||||
|
||||
.site-zfj-anim i{-webkit-animation-name: site-zfj; animation-name: site-zfj; -webkit-animation-duration: 5s; animation-duration: 5s; -webkit-animation-timing-function: linear; animation-timing-function: linear;}
|
||||
|
||||
|
||||
/* 描述字体 */
|
||||
@font-face {font-family: 'webfont-desc';
|
||||
src: url('//at.alicdn.com/t/webfont_eovt4pxxy5.eot'); /* IE9*/
|
||||
src: url('//at.alicdn.com/t/webfont_eovt4pxxy5.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('//at.alicdn.com/t/webfont_eovt4pxxy5.woff') format('woff'), /* chrome、firefox */
|
||||
url('//at.alicdn.com/t/webfont_eovt4pxxy5.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
|
||||
url('//at.alicdn.com/t/webfont_eovt4pxxy5.svg#思源黑体-极细') format('svg'); /* iOS 4.1- */
|
||||
}
|
||||
.web-font-desc{
|
||||
font-family:"webfont-desc" !important;
|
||||
font-size:16px;font-style:normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
|
||||
.site-desc{position: relative; height: 70px; margin-top: 20px;}
|
||||
.site-desc .web-font-desc{color: #fff; color: rgba(255,255,255,.8); font-size: 61px;}
|
||||
|
||||
.site-desc-anim{-webkit-animation-name: site-desc; animation-name: site-desc;}
|
||||
.site-desc cite{position: absolute; bottom: -40px; left: 0; width: 100%; color: #c2c2c2; font-style: normal;}
|
||||
|
||||
.site-download{margin-top: 80px; font-size: 0;}
|
||||
.site-download a{position: relative; padding: 0 55px 0 95px; height: 65px; line-height: 65px; border: 1px solid #c2c2c2; border-color: rgba(255,255,255,.2); font-size: 24px; color: #ccc; transition: all .5s; -webkit-transition: all .5s;}
|
||||
.site-download a:hover{border-color: rgba(255,255,255,.3); color: #fff; background-color: rgba(255,255,255,.05); border-radius: 30px;}
|
||||
.site-download a cite{position: absolute; left: 55px; top: 2px; font-size: 30px;}
|
||||
.site-version{position: relative; margin-top: 15px; color: #ccc; font-size: 12px;}
|
||||
.site-version span{padding: 0 3px;}
|
||||
.site-version *{font-style: normal;}
|
||||
.site-version a{color: #e2e2e2; text-decoration: underline;}
|
||||
|
||||
.site-banner-other{position: absolute; left: 0; bottom: 35px; width: 100%; text-align: center; font-size: 0;}
|
||||
.site-banner-other iframe{border: none;}
|
||||
.site-banner-other a{display: inline-block; vertical-align: middle; height: 28px; line-height: 28px; margin: 0 6px; padding: 0 10px; border-radius: 2px; color: #c2c2c2; color: rgba(255,255,255,.8); border: 1px solid #c2c2c2; border-color: rgba(255,255,255,.2); font-size: 14px; transition: all .5s; -webkit-transition: all .5s;}
|
||||
.site-banner-other a:hover{color: #fff; background-color: rgba(255,255,255,.1);}
|
||||
|
||||
|
||||
.site-idea{margin: 50px 0; font-size: 0; text-align: center; font-weight: 300;}
|
||||
.site-idea li{display: inline-block; vertical-align: top; *display: inline; *zoom:1; font-size: 14px; }
|
||||
.site-idea li{width: 298px; height: 150px; padding: 30px; line-height: 24px; margin-left: 30px; border: 1px solid #d2d2d2; text-align: left;}
|
||||
.site-idea li:first-child{margin-left: 0}
|
||||
.site-idea .layui-field-title{border-color: #d2d2d2}
|
||||
.site-idea .layui-field-title legend{margin: 0 20px 20px 0; padding: 0 20px; text-align: center;}
|
||||
|
||||
/* 赞助商 */
|
||||
.site-sponsor-home{margin-top: 40px; text-align: center;}
|
||||
.site-sponsor-home .layui-btn{position: relative; width: 248px; height: 60px; line-height: 60px; background: none; border-color: #212121; font-size: 20px; border-radius: 6px;}
|
||||
.site-sponsor-home .layui-btn:hover{background: #4A4855; color: #BAB8C3;}
|
||||
|
||||
.site-sponsor-home p{position: relative; padding-top: 15px; font-size: 22px; color: #212121;}
|
||||
.site-sponsor-home p:before{content: ''; position: relative; top: -2px; display: inline-block; vertical-align: middle; width: 30px; height: 30px; margin-right: 10px; background: url(http://cdn.layui.com/upload/2018_1/168_1514869467160_26113.png) center; background-repeat: no-repeat; background-size: contain;}
|
||||
@media screen and (max-width: 750px) {
|
||||
.site-sponsor-home .layui-btn{width: 180px; height: 45px; line-height: 45px; font-size: 20px;}
|
||||
.site-sponsor-home p{font-size: 16px;}
|
||||
.site-sponsor-home p:before{width: 20px; height: 20px;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 辅助 */
|
||||
.site-tips{margin-bottom: 10px; padding: 15px; line-height: 22px; border-left: 5px solid #0078AD; background-color: #f2f2f2;}
|
||||
body .site-tips p{margin: 0;}
|
||||
body .layui-layer-notice .layui-layer-content{padding: 20px; line-height: 26px; background-color: #393D49; color: #fff; font-weight: 300;}
|
||||
.layui-layer-notice .layui-text{color: #f8f8f8;}
|
||||
.layui-layer-notice .layui-text a{color: #009688;}
|
||||
|
||||
/* 目录 */
|
||||
.site-dir{display: none;}
|
||||
.site-dir li{line-height: 26px; margin-left: 20px; overflow: visible; list-style-type: disc;}
|
||||
.site-dir li a{display: block;}
|
||||
.site-dir li a:active{color: #01AAED;}
|
||||
.site-dir li a.layui-this{color: #01AAED;}
|
||||
body .layui-layer-dir{box-shadow: none; border: 1px solid #d2d2d2;}
|
||||
body .layui-layer-dir .layui-layer-content{padding: 10px;}
|
||||
.site-dir a em{padding-left: 5px; font-size: 12px; color: #c2c2c2; font-style: normal;}
|
||||
|
||||
/* 文档 */
|
||||
.site-tree{border-right: 1px solid #eee; }
|
||||
.site-tree .layui-tree{line-height: 32px;}
|
||||
.site-tree .layui-tree li i{position: relative; font-size: 22px; color: #000}
|
||||
.site-tree .layui-tree li a cite{padding: 0 8px;}
|
||||
.site-tree .layui-tree .site-tree-noicon a cite{padding-left: 15px;}
|
||||
.site-tree .layui-tree li a em{font-size: 12px; color: #bbb; padding-right: 5px; font-style: normal;}
|
||||
.site-tree .layui-tree li h2{line-height: 36px; border-left: 5px solid #009E94; margin: 15px 0 5px; padding: 0 10px; background-color: #f2f2f2;}
|
||||
.site-tree .layui-tree li ul{margin-left: 27px; line-height: 28px;}
|
||||
.site-tree .layui-tree li ul a,
|
||||
.site-tree .layui-tree li ul a i{color: #777;}
|
||||
.site-tree .layui-tree li ul a:hover{color: #333;}
|
||||
.site-tree .layui-tree li ul li{margin-left: 25px; overflow: visible; list-style-type: disc; /*list-style-position: inside;*/}
|
||||
.site-tree .layui-tree li ul li cite,
|
||||
.site-tree .layui-tree .site-tree-noicon ul li cite{padding-left: 0;}
|
||||
|
||||
.site-tree .layui-tree .layui-this a{color: #01AAED;}
|
||||
.site-tree .layui-tree .layui-this .layui-icon{color: #01AAED;}
|
||||
|
||||
.site-fix .site-tree{position: fixed; top: 0; bottom: 0; z-index: 666; min-height: 0; overflow: auto; background-color: #fff;}
|
||||
.site-fix .site-content{margin-left: 220px;}
|
||||
.site-fix-footer .site-tree{/*margin-bottom: 120px;*/}
|
||||
|
||||
|
||||
.site-title{ margin: 30px 0 20px;}
|
||||
.site-title fieldset{border: none; padding: 0; border-top: 1px solid #eee;}
|
||||
.site-title fieldset legend{margin-left: 20px; padding: 0 10px; font-size: 22px; font-weight: 300;}
|
||||
|
||||
.site-text a{color: #01AAED;}
|
||||
.site-h1{margin-bottom: 20px; line-height: 60px; padding-bottom: 10px; color: #393D49; border-bottom: 1px solid #eee; font-size: 28px; font-weight: 300;}
|
||||
.site-h1 .layui-icon{position: relative; top: 5px; font-size: 35px; margin-right: 10px;}
|
||||
.site-text{position:relative;}
|
||||
.site-text p{margin-bottom: 10px; line-height:22px;}
|
||||
.site-text em{padding: 0 3px; font-weight: 500; font-style: italic; color: #666;}
|
||||
.site-text code{margin:0 5px; padding: 3px 10px; border: 1px solid #e2e2e2; background-color: #fbfbfb; color: #666; border-radius: 2px;}
|
||||
|
||||
|
||||
.site-table{width: 100%; margin: 10px 0;}
|
||||
.site-table thead{background-color:#f2f2f2; }
|
||||
.site-table th,
|
||||
.site-table td{padding: 6px 15px; min-height: 20px; line-height: 20px; border:1px solid #ddd; font-size: 14px; font-weight: 400;}
|
||||
.site-table tr:nth-child(even){background: #fbfbfb;}
|
||||
|
||||
.site-block{padding: 20px; border: 1px solid #eee;}
|
||||
.site-block .layui-form{margin-right: 200px;}
|
||||
|
||||
/* 更新日志 */
|
||||
.site-changelog .layui-timeline-title h2{display: inline-block;}
|
||||
.site-changelog .layui-timeline-title .layui-badge-rim{top: -2px; left: 10px;}
|
||||
|
||||
/* 颜色 */
|
||||
.site-doc-color{font-size: 0;}
|
||||
.site-doc-color li{display: inline-block; vertical-align: middle; width: 180px; margin-left: 20px; margin-bottom: 20px; padding: 20px 10px; color: #fff; text-align: center; border-radius: 2px; line-height: 22px; font-size: 14px;}
|
||||
.site-doc-color li p[tips]{opacity: 0.8; font-size: 12px;}
|
||||
|
||||
.site-doc-necolor li{width: 108px; margin-top: 15px; margin-left: 0; border-radius: 0;}
|
||||
|
||||
.site-doc-bgcolor li{padding: 10px;}
|
||||
|
||||
/* 宫格 */
|
||||
.site-doc-icon{margin-bottom: 50px; font-size: 0;}
|
||||
.site-doc-icon li{display: inline-block; vertical-align: middle; width: 127px; height: 105px; line-height: 25px; padding: 20px 0; margin-right: -1px; margin-bottom: -1px; border: 1px solid #e2e2e2; font-size: 14px; text-align: center; color: #666; transition: all .3s; -webkit-transition: all .3s;}
|
||||
.site-doc-anim li{height: auto;}
|
||||
.site-doc-icon li .layui-icon{display: inline-block; font-size: 36px;}
|
||||
|
||||
.site-doc-icon li .doc-icon-name,
|
||||
.site-doc-icon li .doc-icon-code{color: #c2c2c2;}
|
||||
.site-doc-icon li .doc-icon-fontclass{height: 40px; line-height: 20px; padding: 0 5px; font-size: 13px; color: #333; }
|
||||
.site-doc-icon li:hover{background-color: #f2f2f2; color: #000;}
|
||||
|
||||
/* 栅格示例 */
|
||||
.grid-demo{padding: 10px; line-height: 50px; text-align: center; background-color: #79C48C; color: #fff;}
|
||||
.grid-demo-bg1{background-color: #63BA79;}
|
||||
.grid-demo-bg2{background-color: #49A761;}
|
||||
.grid-demo-bg3{background-color: #38814A;}
|
||||
|
||||
|
||||
/* 演示 */
|
||||
body .layui-layout-admin .site-demo{bottom: 60px; padding: 0;}
|
||||
body .site-demo-nav .layui-nav-item{line-height: 40px}
|
||||
.layui-nav-item .layui-icon{position: relative; font-size: 20px;}
|
||||
.layui-nav-item a cite{padding: 0 10px;}
|
||||
.site-demo .layui-main{margin: 15px; line-height: 22px;}
|
||||
.site-demo-editor{position: absolute; top: 0; bottom: 0; left: 0; width: 50%; }
|
||||
.site-demo-area{position: absolute; top: 0; bottom: 0; width: 100%;}
|
||||
.site-demo-editor textarea{position: absolute; width: 100%; height: 100%; padding: 10px; border: none; resize: none; background-color: #F7FBFF; background-color: #13151A; color: #999; font-family: Courier New; font-size: 12px; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}
|
||||
.site-demo-btn{position: absolute; bottom: 15px; right: 20px;}
|
||||
.site-demo-zanzhu{position: absolute; bottom: 0; left: 0; width: 100%; height: 90px; text-align: center; background-color: #e2e2e2; overflow: hidden;}
|
||||
.site-demo-zanzhu>*{position: relative; z-index: 1;}
|
||||
.site-demo-zanzhu:before{content: ""; position: absolute; z-index: 0; top: 50%; left: 50%; width: 120px; margin: -10px 0px 0px -60px; text-align: center; color: rgb(170, 170, 170); font-size: 18px; font-weight: 300; }
|
||||
|
||||
.site-demo-result{position: absolute; right: 0; top: 0; bottom: 0; width: 50%;}
|
||||
.site-demo-result iframe{position: absolute; width: 100%; height: 100%;}
|
||||
|
||||
.site-demo-button{margin-bottom: 30px;}
|
||||
.site-demo-button div{margin: 20px 30px 10px;}
|
||||
.site-demo-button .layui-btn+.layui-btn{margin-left: 0;}
|
||||
.site-demo-button .layui-btn{margin: 0 7px 10px 0; }
|
||||
|
||||
.site-demo-text a{color: #01AAED;}
|
||||
|
||||
.site-demo-laytpl{text-align: center;}
|
||||
.site-demo-laytpl textarea,
|
||||
.site-demo-laytpl div span{width: 40%; padding: 15px; margin: 0 15px;}
|
||||
.site-demo-laytpl textarea{height: 300px; border: none; background-color: #3F3F3F; color: #E3CEAB; font-family: Courier New; resize: none;}
|
||||
.site-demo-laytpl div span{display: inline-block; text-align: center; background: #101010; color: #fff;}
|
||||
.site-demo-tplres{margin: 10px 0; text-align: center}
|
||||
.site-demo-tplres .site-demo-tplh2,
|
||||
.site-demo-tplres .site-demo-tplview{display: inline-block; width: 50%;}
|
||||
.site-demo-tplres h2{padding: 15px; background: #e2e2e2;}
|
||||
.site-demo-tplres h3{font-weight: 700;}
|
||||
.site-demo-tplres div{padding: 14px; border: 1px solid #e2e2e2; text-align: left;}
|
||||
|
||||
.site-demo-upload,
|
||||
.site-demo-upload img{width: 200px; height: 200px; border-radius: 100%;}
|
||||
.site-demo-upload{position: relative; background: #e2e2e2;}
|
||||
.site-demo-upload .site-demo-upbar{position: absolute; top: 50%; left: 50%; margin: -18px 0 0 -56px;}
|
||||
.site-demo-upload .layui-upload-button{background-color: rgba(0,0,0,.2); color: rgba(255,255,255,1);}
|
||||
|
||||
.site-demo-util{position: relative; width: 300px;}
|
||||
.site-demo-util img{width: 300px; border-radius: 100%;}
|
||||
.site-demo-util span{position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: #333; cursor: pointer;}
|
||||
@-webkit-keyframes demo-fengjie {
|
||||
0% {-webkit-filter: blur(0); opacity: 1; background: #fff; height: 300px; border-radius: 100%;}
|
||||
80% {-webkit-filter: blur(50px); opacity: 0.95;}
|
||||
100% {-webkit-filter: blur(20px); opacity: 0; background: #fff;}
|
||||
}
|
||||
@keyframes demo-fengjie {
|
||||
0% {filter: blur(0); opacity: 1; background: #fff; height: 300px; border-radius: 100%;}
|
||||
80% {filter: blur(50px); opacity: 0.95;}
|
||||
100% {filter: blur(20px); opacity: 0; background: #fff;}
|
||||
}
|
||||
.site-demo-fengjie{-webkit-animation-name: demo-fengjie; animation-name: demo-fengjie; -webkit-animation-duration: 5s; animation-duration: 5s;}
|
||||
|
||||
.layui-layout-admin .site-demo-body{top: 106px;}
|
||||
.site-demo-title{position: fixed; left: 200px; right: 0; top: 65px;}
|
||||
.site-demo-code{position: absolute; left: 0; top: 0; width: 100%; height: 100%; border: none; padding: 10px; resize: none; font-size: 12px; background-color: #F7FBFF; color: #881280; font-family: Courier New;}
|
||||
|
||||
.site-demo-overflow{overflow: hidden;}
|
||||
|
||||
/* 其它 */
|
||||
#trans-tooltip,
|
||||
#tip-arrow-bottom,
|
||||
#tip-arrow-top{display: none !important;}
|
||||
|
||||
|
||||
/* 独立组件 与 主页 */
|
||||
.alone{text-align: center; background-color: #009688; color: #fff; font-weight: 300; transition: all .3s; -webkit-transition: all .3s;}
|
||||
.alone:hover{background-color: #5FB878;}
|
||||
.alone a{display: block; padding: 50px 20px; color: #fff; font-size: 30px;}
|
||||
.alone a cite{display: block; padding-top: 10px; font-size: 14px;}
|
||||
|
||||
|
||||
.alone-banner{height: 190px; text-align: center; font-weight: 300; background-color: #009688; color:#fff;}
|
||||
.alone-banner h1{padding-top: 60px; line-height: 32px; font-size: 30px; font-weight: 300;}
|
||||
.alone-banner p{padding-top: 20px; color: #e2e2e2; color: rgba(255,255,255,.8);}
|
||||
|
||||
.alone-nav .layui-tab-title li{margin-right: 30px; padding: 0; color: #666;}
|
||||
.alone-nav .layui-tab-title li a{ padding: 0 20px;}
|
||||
|
||||
.alone-download{margin: 30px 0;}
|
||||
.alone-download .layui-btn{margin-right: 10px;}
|
||||
.alone-download span{display: inline-block; line-height: 44px; padding-right: 20px;}
|
||||
.alone-download span em{color: #999;}
|
||||
|
||||
.alone-title{margin-top: 20px;}
|
||||
|
||||
.alone-download-btn{text-align: center; margin-top: 50px; font-size: 0;}
|
||||
.alone-download-btn .layui-btn{position: relative; width: 206px; height: 60px; line-height: 60px; font-size: 26px; font-weight: 300;}
|
||||
.alone-download-btn .layui-btn+.layui-btn{margin: 0;}
|
||||
.alone-download-btn .alone-download-right{margin-left: 20px !important; border-color: #009688; background: none; color: #009688;}
|
||||
.alone-download-btn .layui-btn img{position: relative; top: -3px; width: 118px;}
|
||||
|
||||
|
||||
|
||||
/* 适配多设备 */
|
||||
@media screen and (max-width: 750px) {
|
||||
.layui-main{width: auto; margin: 0 10px;}
|
||||
.logo,
|
||||
.header-demo .logo{left: 10px;}
|
||||
.component{display: none}
|
||||
|
||||
.header .layui-nav-child{left: auto!important; right: 0!important;}
|
||||
.site-demo-overflow{overflow: auto;}
|
||||
|
||||
.site-nav-layim{display: none !important;}
|
||||
.header .layui-nav .layui-nav-item{margin: 0;}
|
||||
.header .layui-nav .layui-nav-item a{padding: 0 20px;}
|
||||
.header .layui-nav .layui-nav-item[pc]{display: none;}
|
||||
.header .layui-nav .layui-nav-item[mobile]{display: inline-block;}
|
||||
.site-banner{height: 300px;}
|
||||
.site-banner-bg{background-size: cover;}
|
||||
.site-zfj{height: 100px; padding-top: 5px;}
|
||||
.site-zfj i{top: 10px; width: 100px; height: 100px; margin-left: -50px; font-size: 100px;}
|
||||
.site-desc{background-size: 70%; margin: 0;}
|
||||
.site-desc .web-font-desc{padding-top: 20px; font-size: 30px;}
|
||||
.site-desc cite{display: none;}
|
||||
.site-download{margin-top: 0; }
|
||||
.site-download a{height: 40px; line-height: 40px; padding: 0 25px 0 60px; border-radius: 30px; color: #fff; font-size: 16px;}
|
||||
.site-download a cite{left: 20px;}
|
||||
.site-banner-other{bottom: 10px;}
|
||||
|
||||
.site-idea{margin: 20px 0;}
|
||||
.site-idea li{margin: 0 0 20px 0; width: 100%; height: auto; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}
|
||||
.site-hengfu img{max-width: 100%}
|
||||
|
||||
.site-block .layui-form{margin-right: 0;}
|
||||
|
||||
.layui-layer-dir{display: none;}
|
||||
.site-tree{position: fixed; top: 0; bottom: 0; min-height: 0; overflow: auto; z-index: 1000; left: -260px; background-color: #fff; transition: all .3s; -webkit-transition: all .3s;}
|
||||
.site-content{width: 100%; padding: 0; overflow: auto;}
|
||||
.site-content img{max-width: 100%;}
|
||||
.site-tree-mobile{display: block!important; position: fixed; z-index: 100000; bottom: 15px; left: 15px; width: 50px; height: 50px; line-height: 50px; border-radius: 2px; text-align: center; background-color: rgba(0,0,0,.7); color: #fff;}
|
||||
.site-home .site-tree-mobile{display: none!important;}
|
||||
.site-mobile .site-tree-mobile{display: none !important;}
|
||||
.site-mobile .site-tree{left: 0;}
|
||||
.site-mobile .site-mobile-shade{content: ''; position: fixed; top: 0; bottom: 0; left: 0; right: 0; background-color: rgba(0,0,0,.8); z-index: 999;}
|
||||
.site-tree-mobile i{font-size: 20px;}
|
||||
.layui-code-view{-webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}
|
||||
|
||||
.layui-layout-admin .layui-side{position: fixed; top: 0; left: -260px; transition: all .3s; -webkit-transition: all .3s; z-index: 10000;}
|
||||
.layui-body{position: static; bottom: 0; left: 0;}
|
||||
.site-mobile .layui-side{left: 0;}
|
||||
.site-mobile .layui-side-child{top: 50%; left: 200px; height: 300px; margin-top: -100px;}
|
||||
|
||||
body .layui-layout-admin .footer-demo{position: static; height: auto; padding: 15px 0; line-height: 30px;}
|
||||
.footer-demo p,
|
||||
.footer-demo .site-union{height: auto; padding-right: 0;}
|
||||
.footer-demo .site-union{top: 0;}
|
||||
.footer-demo .site-union span{top:0 ;}
|
||||
|
||||
.site-demo-area,
|
||||
.site-demo-editor,
|
||||
.site-demo-result,
|
||||
.site-demo-editor textarea,
|
||||
.site-demo-result iframe{position: static; width: 100%;}
|
||||
.site-demo-editor textarea{height: 350px;}
|
||||
.site-demo-zanzhu{display: none;}
|
||||
.site-demo-btn{bottom: auto; top: 370px;}
|
||||
.site-demo-result iframe{height: 500px;}
|
||||
|
||||
.site-demo-laytpl textarea, .site-demo-laytpl div span{margin: 0;}
|
||||
.site-demo-tplres .site-demo-tplh2, .site-demo-tplres .site-demo-tplview{width: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}
|
||||
|
||||
.site-demo-title{position: static; left: 0;}
|
||||
body .layui-layout-admin .site-demo{position: static;}
|
||||
.site-demo-code{position: static; height: 350px;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@-webkit-keyframes site-anim-closeup{ /* 特写 */
|
||||
from {-webkit-transform: translate3d(0, 0, 0) scale(1); opacity: 1;}
|
||||
to { -webkit-transform: translate3d(0, 400px, 0) scale(2); opacity: 0.5;}
|
||||
}
|
||||
@keyframes site-anim-closeup{
|
||||
from {transform: translate3d(0, 0, 0) scale(1); opacity: 1;}
|
||||
to {transform: translate3d(0, 400px, 0) scale(2); opacity: 0.5;}
|
||||
}
|
||||
.site-out-up{-webkit-animation-duration: 3s; animation-duration: 3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-name: site-anim-closeup; animation-name: site-anim-closeup; overflow: hidden;}
|
||||
2
src/main/resources/static/layui/css/layui.css
Normal file
2
src/main/resources/static/layui/css/layui.mobile.css
Normal file
2
src/main/resources/static/layui/css/modules/code.css
Normal file
@ -0,0 +1,2 @@
|
||||
/** layui-v2.5.7 MIT License */
|
||||
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}
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 701 B |
|
After Width: | Height: | Size: 1.7 KiB |
BIN
src/main/resources/static/layui/font/iconfont.eot
Normal file
554
src/main/resources/static/layui/font/iconfont.svg
Normal file
|
After Width: | Height: | Size: 299 KiB |
BIN
src/main/resources/static/layui/font/iconfont.ttf
Normal file
BIN
src/main/resources/static/layui/font/iconfont.woff
Normal file
BIN
src/main/resources/static/layui/font/iconfont.woff2
Normal file
BIN
src/main/resources/static/layui/images/face/0.gif
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/main/resources/static/layui/images/face/1.gif
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
src/main/resources/static/layui/images/face/10.gif
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/main/resources/static/layui/images/face/11.gif
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
src/main/resources/static/layui/images/face/12.gif
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/main/resources/static/layui/images/face/13.gif
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
src/main/resources/static/layui/images/face/14.gif
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/main/resources/static/layui/images/face/15.gif
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/main/resources/static/layui/images/face/16.gif
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
src/main/resources/static/layui/images/face/17.gif
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
src/main/resources/static/layui/images/face/18.gif
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/main/resources/static/layui/images/face/19.gif
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
src/main/resources/static/layui/images/face/2.gif
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
src/main/resources/static/layui/images/face/20.gif
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
src/main/resources/static/layui/images/face/21.gif
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
src/main/resources/static/layui/images/face/22.gif
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
src/main/resources/static/layui/images/face/23.gif
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
src/main/resources/static/layui/images/face/24.gif
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
src/main/resources/static/layui/images/face/25.gif
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
src/main/resources/static/layui/images/face/26.gif
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/main/resources/static/layui/images/face/27.gif
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
src/main/resources/static/layui/images/face/28.gif
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/main/resources/static/layui/images/face/29.gif
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
src/main/resources/static/layui/images/face/3.gif
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src/main/resources/static/layui/images/face/30.gif
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/main/resources/static/layui/images/face/31.gif
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/main/resources/static/layui/images/face/32.gif
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src/main/resources/static/layui/images/face/33.gif
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/main/resources/static/layui/images/face/34.gif
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
src/main/resources/static/layui/images/face/35.gif
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/main/resources/static/layui/images/face/36.gif
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/main/resources/static/layui/images/face/37.gif
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/main/resources/static/layui/images/face/38.gif
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
src/main/resources/static/layui/images/face/39.gif
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
src/main/resources/static/layui/images/face/4.gif
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
src/main/resources/static/layui/images/face/40.gif
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
src/main/resources/static/layui/images/face/41.gif
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
src/main/resources/static/layui/images/face/42.gif
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
src/main/resources/static/layui/images/face/43.gif
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/main/resources/static/layui/images/face/44.gif
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
src/main/resources/static/layui/images/face/45.gif
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/main/resources/static/layui/images/face/46.gif
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/main/resources/static/layui/images/face/47.gif
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/main/resources/static/layui/images/face/48.gif
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/main/resources/static/layui/images/face/49.gif
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/main/resources/static/layui/images/face/5.gif
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
src/main/resources/static/layui/images/face/50.gif
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
src/main/resources/static/layui/images/face/51.gif
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/main/resources/static/layui/images/face/52.gif
Normal file
|
After Width: | Height: | Size: 777 B |
BIN
src/main/resources/static/layui/images/face/53.gif
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/main/resources/static/layui/images/face/54.gif
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/main/resources/static/layui/images/face/55.gif
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
src/main/resources/static/layui/images/face/56.gif
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/main/resources/static/layui/images/face/57.gif
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/main/resources/static/layui/images/face/58.gif
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/main/resources/static/layui/images/face/59.gif
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
src/main/resources/static/layui/images/face/6.gif
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/main/resources/static/layui/images/face/60.gif
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/main/resources/static/layui/images/face/61.gif
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/main/resources/static/layui/images/face/62.gif
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/main/resources/static/layui/images/face/63.gif
Normal file
|
After Width: | Height: | Size: 5.7 KiB |