diff --git a/.gitignore b/.gitignore
index 40c92d4d2b5dd6a891c13617b53903b99820eb30..fdfdab7028a7395759056fc4a8eaba8d692e1902 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,27 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
.idea
-target
+*.iws
*.iml
-/view/flutter/**/gen/*
-**/*.log
-dist
+*.ipr
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+### Mac files ###
+.DS_Store
diff --git a/core/captcha-solon-plugin/pom.xml b/core/captcha-solon-plugin/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5300d62583e9a5152cbd7c60a23d49752670138c
--- /dev/null
+++ b/core/captcha-solon-plugin/pom.xml
@@ -0,0 +1,156 @@
+
+
+ 4.0.0
+
+ com.anji-plus
+ captcha-solon-plugin
+ 1.3.0
+
+ captcha-spring-boot-starter
+ anji-plus captcha captcha-spring-boot-starter
+ https://github.com/anji-plus/captcha
+ jar
+
+
+ 1.8
+ 1.5.27
+ 1.7.25
+
+
+
+
+ com.anji-plus
+ captcha
+ 1.3.0
+
+
+
+ org.noear
+ solon
+ ${solon.version}
+
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+ provided
+
+
+
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+ scm:git:git://github.com/anji-plus/OSSRH-56732.git
+ scm:git:ssh://github.com/anji-plus/OSSRH-56732.git
+ https://github.com/anji-plus/OSSRH-56732/tree/master
+
+
+
+
+ develop.anji-plus.com
+ MS@anji-plus.com
+ https://github.com/anji-plus
+
+
+ noear
+ noear@live.cn
+ https://github.com/noear
+
+
+
+
+
+ snapshots
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.3
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 2.4
+
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.2.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.9.1
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+ UTF-8
+ -Xdoclint:none
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.5
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
+
+ releases
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ releases
+ https://oss.sonatype.org/service/local/staging/deploy/maven2
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core/captcha-solon-plugin/src/main/java/com/anji/captcha/XPluginImp.java b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/XPluginImp.java
new file mode 100644
index 0000000000000000000000000000000000000000..2590334e23e1a57ba15228bebcbe55f9d892a74c
--- /dev/null
+++ b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/XPluginImp.java
@@ -0,0 +1,22 @@
+package com.anji.captcha;
+
+import com.anji.captcha.config.AjCaptchaServiceConfiguration;
+import com.anji.captcha.config.AjCaptchaStorageConfiguration;
+import com.anji.captcha.properties.AjCaptchaProperties;
+import org.noear.solon.SolonApp;
+import org.noear.solon.core.Plugin;
+import com.anji.captcha.controller.CaptchaController;
+
+/**
+ * @author noear
+ * @since 1.5
+ */
+public class XPluginImp implements Plugin {
+ @Override
+ public void start(SolonApp app) {
+ app.beanMake(AjCaptchaProperties.class);
+ app.beanMake(AjCaptchaServiceConfiguration.class);
+ app.beanMake(AjCaptchaStorageConfiguration.class);
+ app.beanMake(CaptchaController.class);
+ }
+}
diff --git a/core/captcha-solon-plugin/src/main/java/com/anji/captcha/config/AjCaptchaServiceConfiguration.java b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/config/AjCaptchaServiceConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b7f25284ab2a5dbd581c1823e342572b9b82636
--- /dev/null
+++ b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/config/AjCaptchaServiceConfiguration.java
@@ -0,0 +1,99 @@
+package com.anji.captcha.config;
+
+import com.anji.captcha.properties.AjCaptchaProperties;
+import com.anji.captcha.service.CaptchaService;
+import com.anji.captcha.service.impl.CaptchaServiceFactory;
+import com.anji.captcha.util.Base64Utils;
+import com.anji.captcha.util.FileCopyUtils;
+import com.anji.captcha.util.ImageUtils;
+import com.anji.captcha.util.StringUtils;
+import org.noear.solon.Utils;
+import org.noear.solon.annotation.Bean;
+import org.noear.solon.annotation.Configuration;
+import org.noear.solon.core.util.ResourceScaner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.net.URL;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author noear
+ * @since 1.5
+ */
+@Configuration
+public class AjCaptchaServiceConfiguration {
+ private static Logger logger = LoggerFactory.getLogger(AjCaptchaServiceConfiguration.class);
+
+ public AjCaptchaServiceConfiguration() {
+ }
+
+ @Bean
+ public CaptchaService captchaService(AjCaptchaProperties prop) {
+ logger.info("自定义配置项:{}", prop.toString());
+
+ Properties config = new Properties();
+ config.put("captcha.cacheType", prop.getCacheType().name());
+ config.put("captcha.water.mark", prop.getWaterMark());
+ config.put("captcha.font.type", prop.getFontType());
+ config.put("captcha.type", prop.getType().getCodeValue());
+ config.put("captcha.interference.options", prop.getInterferenceOptions());
+ config.put("captcha.captchaOriginalPath.jigsaw", prop.getJigsaw());
+ config.put("captcha.captchaOriginalPath.pic-click", prop.getPicClick());
+ config.put("captcha.slip.offset", prop.getSlipOffset());
+ config.put("captcha.aes.status", String.valueOf(prop.getAesStatus()));
+ config.put("captcha.water.font", prop.getWaterFont());
+ config.put("captcha.cache.number", prop.getCacheNumber());
+ config.put("captcha.timing.clear", prop.getTimingClear());
+ config.put("captcha.history.data.clear.enable", prop.isHistoryDataClearEnable() ? "1" : "0");
+ config.put("captcha.req.frequency.limit.enable", prop.getReqFrequencyLimitEnable() ? "1" : "0");
+ config.put("captcha.req.get.lock.limit", prop.getReqGetLockLimit() + "");
+ config.put("captcha.req.get.lock.seconds", prop.getReqGetLockSeconds() + "");
+ config.put("captcha.req.get.minute.limit", prop.getReqGetMinuteLimit() + "");
+ config.put("captcha.req.check.minute.limit", prop.getReqCheckMinuteLimit() + "");
+ config.put("captcha.req.verify.minute.limit", prop.getReqVerifyMinuteLimit() + "");
+ if (StringUtils.isNotBlank(prop.getJigsaw()) && prop.getJigsaw().startsWith("classpath:") || StringUtils.isNotBlank(prop.getPicClick()) && prop.getPicClick().startsWith("classpath:")) {
+ config.put("captcha.init.original", "true");
+ initializeBaseMap(prop.getJigsaw(), prop.getPicClick());
+ }
+
+ CaptchaService s = CaptchaServiceFactory.getInstance(config);
+ return s;
+ }
+
+ private static void initializeBaseMap(String jigsaw, String picClick) {
+ jigsaw = jigsaw.substring(10);
+ picClick = picClick.substring(10);
+
+ Map originalMap = getResourcesImagesFile(jigsaw + "/original");
+ Map slidingBlockMap = getResourcesImagesFile(jigsaw + "/slidingBlock");
+ Map picClickMap = getResourcesImagesFile(picClick + "");
+
+ ImageUtils.cacheBootImage(originalMap, slidingBlockMap, picClickMap);
+ }
+
+ public static Map getResourcesImagesFile(String path) {
+ Map imgMap = new HashMap();
+
+ //todo: 这里可能会有问题
+ try {
+ List resources = ResourceScaner.scan(path, n -> n.endsWith(".png"))
+ .stream()
+ .map(k -> Utils.getResource(k))
+ .collect(Collectors.toList());
+
+ for (URL resource : resources) {
+ byte[] bytes = FileCopyUtils.copyToByteArray(resource.openStream());
+ String string = Base64Utils.encodeToString(bytes);
+ String filename = new File(resource.getFile()).getName();
+ imgMap.put(filename, string);
+ }
+ } catch (Exception var11) {
+ var11.printStackTrace();
+ }
+
+ return imgMap;
+ }
+}
diff --git a/core/captcha-solon-plugin/src/main/java/com/anji/captcha/config/AjCaptchaStorageConfiguration.java b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/config/AjCaptchaStorageConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..3988f1c3acd0b26fab6dd9ec1a300e9b6849b82b
--- /dev/null
+++ b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/config/AjCaptchaStorageConfiguration.java
@@ -0,0 +1,22 @@
+package com.anji.captcha.config;
+
+import com.anji.captcha.properties.AjCaptchaProperties;
+import com.anji.captcha.service.CaptchaCacheService;
+import com.anji.captcha.service.impl.CaptchaServiceFactory;
+import org.noear.solon.annotation.Bean;
+import org.noear.solon.annotation.Configuration;
+
+/**
+ * @author noear
+ * @since 1.5
+ */
+@Configuration
+public class AjCaptchaStorageConfiguration {
+ public AjCaptchaStorageConfiguration() {
+ }
+
+ @Bean("AjCaptchaCacheService")
+ public CaptchaCacheService captchaCacheService(AjCaptchaProperties ajCaptchaProperties) {
+ return CaptchaServiceFactory.getCache(ajCaptchaProperties.getCacheType().name());
+ }
+}
diff --git a/core/captcha-solon-plugin/src/main/java/com/anji/captcha/controller/CaptchaController.java b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/controller/CaptchaController.java
new file mode 100644
index 0000000000000000000000000000000000000000..12167dce83bc2486201177305f1fc2fee845ba4b
--- /dev/null
+++ b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/controller/CaptchaController.java
@@ -0,0 +1,42 @@
+package com.anji.captcha.controller;
+
+import com.anji.captcha.model.common.ResponseModel;
+import com.anji.captcha.model.vo.CaptchaVO;
+import com.anji.captcha.service.CaptchaService;
+import org.noear.solon.annotation.*;
+import org.noear.solon.core.handle.Context;
+
+/**
+ * @author noear
+ * @since 1.5
+ */
+@Controller
+@Mapping("/captcha")
+public class CaptchaController {
+ @Inject
+ private CaptchaService captchaService;
+
+ @Post
+ @Mapping("/get")
+ public ResponseModel get(CaptchaVO data, Context request) {
+ assert request.realIp() != null;
+
+ data.setBrowserInfo(getRemoteId(request));
+ return this.captchaService.get(data);
+ }
+
+ @Post
+ @Mapping("/check")
+ public ResponseModel check(CaptchaVO data, Context request) {
+ data.setBrowserInfo(getRemoteId(request));
+ return this.captchaService.check(data);
+ }
+
+ public ResponseModel verify( CaptchaVO data, Context request) {
+ return this.captchaService.verification(data);
+ }
+
+ public static final String getRemoteId(Context ctx) {
+ return ctx.realIp() + ctx.userAgent();
+ }
+}
diff --git a/core/captcha-solon-plugin/src/main/java/com/anji/captcha/properties/AjCaptchaProperties.java b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/properties/AjCaptchaProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..49e8185919b1ca6551041f5bf76087add99fa299
--- /dev/null
+++ b/core/captcha-solon-plugin/src/main/java/com/anji/captcha/properties/AjCaptchaProperties.java
@@ -0,0 +1,229 @@
+package com.anji.captcha.properties;
+
+import com.anji.captcha.model.common.CaptchaTypeEnum;
+import org.noear.solon.annotation.Configuration;
+import org.noear.solon.annotation.Inject;
+
+/**
+ * @author noear
+ * @since 1.5
+ */
+@Inject("${aj.captcha}")
+@Configuration
+public class AjCaptchaProperties {
+ public static final String PREFIX = "aj.captcha";
+ private CaptchaTypeEnum type;
+ private String jigsaw;
+ private String picClick;
+ private String waterMark;
+ private String waterFont;
+ private String fontType;
+ private String slipOffset;
+ private Boolean aesStatus;
+ private String interferenceOptions;
+ private String cacheNumber;
+ private String timingClear;
+ private StorageType cacheType;
+ private boolean historyDataClearEnable;
+ private boolean reqFrequencyLimitEnable;
+ private int reqGetLockLimit;
+ private int reqGetLockSeconds;
+ private int reqGetMinuteLimit;
+ private int reqCheckMinuteLimit;
+ private int reqVerifyMinuteLimit;
+
+ public AjCaptchaProperties() {
+ this.type = CaptchaTypeEnum.DEFAULT;
+ this.jigsaw = "";
+ this.picClick = "";
+ this.waterMark = "我的水印";
+ this.waterFont = "WenQuanZhengHei.ttf";
+ this.fontType = "WenQuanZhengHei.ttf";
+ this.slipOffset = "5";
+ this.aesStatus = true;
+ this.interferenceOptions = "0";
+ this.cacheNumber = "1000";
+ this.timingClear = "180";
+ this.cacheType = StorageType.local;
+ this.historyDataClearEnable = false;
+ this.reqFrequencyLimitEnable = false;
+ this.reqGetLockLimit = 5;
+ this.reqGetLockSeconds = 300;
+ this.reqGetMinuteLimit = 100;
+ this.reqCheckMinuteLimit = 100;
+ this.reqVerifyMinuteLimit = 100;
+ }
+
+ public boolean isHistoryDataClearEnable() {
+ return this.historyDataClearEnable;
+ }
+
+ public void setHistoryDataClearEnable(boolean historyDataClearEnable) {
+ this.historyDataClearEnable = historyDataClearEnable;
+ }
+
+ public boolean isReqFrequencyLimitEnable() {
+ return this.reqFrequencyLimitEnable;
+ }
+
+ public boolean getReqFrequencyLimitEnable() {
+ return this.reqFrequencyLimitEnable;
+ }
+
+ public void setReqFrequencyLimitEnable(boolean reqFrequencyLimitEnable) {
+ this.reqFrequencyLimitEnable = reqFrequencyLimitEnable;
+ }
+
+ public int getReqGetLockLimit() {
+ return this.reqGetLockLimit;
+ }
+
+ public void setReqGetLockLimit(int reqGetLockLimit) {
+ this.reqGetLockLimit = reqGetLockLimit;
+ }
+
+ public int getReqGetLockSeconds() {
+ return this.reqGetLockSeconds;
+ }
+
+ public void setReqGetLockSeconds(int reqGetLockSeconds) {
+ this.reqGetLockSeconds = reqGetLockSeconds;
+ }
+
+ public int getReqGetMinuteLimit() {
+ return this.reqGetMinuteLimit;
+ }
+
+ public void setReqGetMinuteLimit(int reqGetMinuteLimit) {
+ this.reqGetMinuteLimit = reqGetMinuteLimit;
+ }
+
+ public int getReqCheckMinuteLimit() {
+ return this.reqGetMinuteLimit;
+ }
+
+ public void setReqCheckMinuteLimit(int reqCheckMinuteLimit) {
+ this.reqCheckMinuteLimit = reqCheckMinuteLimit;
+ }
+
+ public int getReqVerifyMinuteLimit() {
+ return this.reqVerifyMinuteLimit;
+ }
+
+ public void setReqVerifyMinuteLimit(int reqVerifyMinuteLimit) {
+ this.reqVerifyMinuteLimit = reqVerifyMinuteLimit;
+ }
+
+ public static String getPREFIX() {
+ return "aj.captcha";
+ }
+
+ public CaptchaTypeEnum getType() {
+ return this.type;
+ }
+
+ public void setType(CaptchaTypeEnum type) {
+ this.type = type;
+ }
+
+ public String getJigsaw() {
+ return this.jigsaw;
+ }
+
+ public void setJigsaw(String jigsaw) {
+ this.jigsaw = jigsaw;
+ }
+
+ public String getPicClick() {
+ return this.picClick;
+ }
+
+ public void setPicClick(String picClick) {
+ this.picClick = picClick;
+ }
+
+ public String getWaterMark() {
+ return this.waterMark;
+ }
+
+ public void setWaterMark(String waterMark) {
+ this.waterMark = waterMark;
+ }
+
+ public String getWaterFont() {
+ return this.waterFont;
+ }
+
+ public void setWaterFont(String waterFont) {
+ this.waterFont = waterFont;
+ }
+
+ public String getFontType() {
+ return this.fontType;
+ }
+
+ public void setFontType(String fontType) {
+ this.fontType = fontType;
+ }
+
+ public String getSlipOffset() {
+ return this.slipOffset;
+ }
+
+ public void setSlipOffset(String slipOffset) {
+ this.slipOffset = slipOffset;
+ }
+
+ public Boolean getAesStatus() {
+ return this.aesStatus;
+ }
+
+ public void setAesStatus(Boolean aesStatus) {
+ this.aesStatus = aesStatus;
+ }
+
+ public StorageType getCacheType() {
+ return this.cacheType;
+ }
+
+ public void setCacheType(AjCaptchaProperties.StorageType cacheType) {
+ this.cacheType = cacheType;
+ }
+
+ public String getInterferenceOptions() {
+ return this.interferenceOptions;
+ }
+
+ public void setInterferenceOptions(String interferenceOptions) {
+ this.interferenceOptions = interferenceOptions;
+ }
+
+ public String getCacheNumber() {
+ return this.cacheNumber;
+ }
+
+ public void setCacheNumber(String cacheNumber) {
+ this.cacheNumber = cacheNumber;
+ }
+
+ public String getTimingClear() {
+ return this.timingClear;
+ }
+
+ public void setTimingClear(String timingClear) {
+ this.timingClear = timingClear;
+ }
+
+ public String toString() {
+ return "\nAjCaptchaProperties{type=" + this.type + ", jigsaw='" + this.jigsaw + '\'' + ", picClick='" + this.picClick + '\'' + ", waterMark='" + this.waterMark + '\'' + ", waterFont='" + this.waterFont + '\'' + ", fontType='" + this.fontType + '\'' + ", slipOffset='" + this.slipOffset + '\'' + ", aesStatus=" + this.aesStatus + ", interferenceOptions='" + this.interferenceOptions + '\'' + ", cacheNumber='" + this.cacheNumber + '\'' + ", timingClear='" + this.timingClear + '\'' + ", cacheType=" + this.cacheType + ", reqFrequencyLimitEnable=" + this.reqFrequencyLimitEnable + ", reqGetLockLimit=" + this.reqGetLockLimit + ", reqGetLockSeconds=" + this.reqGetLockSeconds + ", reqGetMinuteLimit=" + this.reqGetMinuteLimit + ", reqCheckMinuteLimit=" + this.reqCheckMinuteLimit + ", reqVerifyMinuteLimit=" + this.reqVerifyMinuteLimit + '}';
+ }
+
+ public static enum StorageType {
+ local,
+ redis,
+ other;
+
+ private StorageType() {
+ }
+ }
+}
diff --git a/core/captcha-solon-plugin/src/main/resources/META-INF/solon/com-anji-captcha-solon-plugin.properties b/core/captcha-solon-plugin/src/main/resources/META-INF/solon/com-anji-captcha-solon-plugin.properties
new file mode 100644
index 0000000000000000000000000000000000000000..7da0890b7bd31d761dfbd5d311873e6829377a49
--- /dev/null
+++ b/core/captcha-solon-plugin/src/main/resources/META-INF/solon/com-anji-captcha-solon-plugin.properties
@@ -0,0 +1 @@
+solon.plugin=com.anji.captcha.XPluginImp
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index ac7634024984c73afaf739069040fd8a0b2fea68..69b9c33f0041b6376723328951cd5a68b7d64ef2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,9 @@
core/captcha
core/captcha-spring-boot-starter
+ core/captcha-solon-plugin
service/springmvc
service/springboot
+ service/solon
\ No newline at end of file
diff --git a/service/solon/README.md b/service/solon/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a22cca8ab0c9ebee967f1587759f53c63f54c703
--- /dev/null
+++ b/service/solon/README.md
@@ -0,0 +1,253 @@
+# 2 对接流程
+## 2.1 接入流程
+### 2.1.1 后端接入
+ 用户提交表单会携带验证码相关参数,产品应用在相关接口处将该参数传给 集成jar包相关接口做二次校验,以确保该次验证是正确有效的。
+### 2.1.2 前端接入
+ 引入相关组件,调用初始化函数,通过配置的一些参数信息。将行为验证码渲染出来。
+## 2.2 后端接入
+### 2.2.1 引入maven依赖
+目前已上传maven仓库,源码已分享
+```java
+
+ com.github.anji-plus
+ captcha
+ 1.2.6
+
+```
+### 2.2.2 缓存实现
+```java
+#分布式环境要自己实现,参考service\springboot示例中CaptchaCacheServiceRedisImpl。默认使用内存。
+public interface CaptchaCacheService {
+
+ void set(String key, String value, long expiresInSeconds);
+
+ boolean exists(String key);
+
+ void delete(String key);
+
+ String get(String key);
+
+ /**
+ * 缓存类型-local/redis/memcache/..
+ * 通过java SPI机制,接入方可自定义实现类
+ * @return
+ */
+ String type();
+}
+```
+
+### 2.2.3 二次校验接口
+登录为例,用户在提交表单到产品应用后台,会携带一个验证码相关的参数。产品应用会在登录接口login中将该参数传给集成jar包中相关接口做二次校验。
+接口地址:https://****/captcha/verify
+### 2.2.4 请求方式
+HTTP POST, 接口仅支持POST请求, 且仅接受 application/json 编码的参数
+### 2.2.5 请求参数
+| 参数 | 类型 | 必填 | 备注 |
+| ------------ | ------------ | ------------ | ------------ |
+| captchaVerification | String | Y | 验证数据,aes加密,数据在前端success函数回调参数中获取 |
+
+
+### 2.2.6 响应参数
+| 参数 | 类型 | 必填 | 备注 |
+| ------------ | ------------ | ------------ | ------------ |
+| repCode | String | Y | 异常代号 |
+| success | Boolean | Y | 成功或者失败 |
+| error | Boolean | Y | 接口报错 |
+| repMsg | String | Y | 错误信息 |
+
+
+### 2.2.7 异常代号
+
+| error | 说明 |
+| ------------ | ------------ |
+| 0000 | 无异常,代表成功 |
+| 9999 | 服务器内部异常 |
+| 0011 | 参数不能为空 |
+| 6110 | 验证码已失效,请重新获取 |
+| 6111 | 验证失败 |
+| 6112 | 获取验证码失败,请联系管理员 |
+
+## 2.3 前端接入
+### 2.3.1 兼容性
+IE8+、Chrome、Firefox.(其他未测试)
+### 2.3.2 初始化组件
+引入前端vue组件, npm install axios crypto-js -S
+// 基础用例
+
+```javascript
+
+
+
+
+```
+
+### 2.3.3 事件
+
+| 参数 | 说明 |
+| ------------ | ------------ |
+| success | 验证码匹配成功后的回调函数 |
+| error | 验证码匹配失败后的回调函数 |
+| ready | 验证码初始化成功的回调函数 |
+
+### 2.3.4 验证码参数
+
+| 参数 | 说明 |
+| ------------ | ------------ |
+| captchaType | 1)滑动拼图 blockPuzzle 2)文字点选 clickWord |
+| mode | 验证码的显示方式,弹出式pop,固定fixed,默认是:mode : ‘pop’ |
+| vSpace | 验证码图片和移动条容器的间隔,默认单位是px。如:间隔为5px,设置vSpace:5 |
+| explain | 滑动条内的提示,不设置默认是:'向右滑动完成验证' |
+| imgSize | 其中包含了width、height两个参数,分别代表图片的宽度和高度,支持百分比方式设置 如:{width:'100%',height:'200px'} |
+| blockSize | 其中包含了width、height两个参数,分别代表拼图块的宽度和高度,如:{width:'40px',height:'40px'} |
+| barSize | 其中包含了width、height两个参数,分别代表滑动条的宽度和高度,支持百分比方式设置,如:{width:'100%',height:'40px'} |
+
+### 2.3.5 获取验证码接口详情
+#### 接口地址:http://*:*/captcha/get
+##### 请求参数:
+```json
+{
+ "captchaType": "blockPuzzle" //验证码类型 clickWord
+}
+```
+##### 响应参数:
+```json
+{
+ "repCode": "0000",
+ "repData": {
+ "originalImageBase64": "底图base64",
+ "point": { //默认不返回的,校验的就是该坐标信息,允许误差范围
+ "x": 205,
+ "y": 5
+ },
+ "jigsawImageBase64": "滑块图base64",
+ "token": "71dd26999e314f9abb0c635336976635", //一次校验唯一标识
+ "result": false,
+ "opAdmin": false
+ },
+ "success": true,
+ "error": false
+}
+```
+### 2.3.6 核对验证码接口详情
+#### 请求接口:http://*:*/captcha/check
+##### 请求参数:
+```json
+{
+ "captchaType": "blockPuzzle",
+ "pointJson": "QxIVdlJoWUi04iM+65hTow==", //aes加密坐标信息
+ "token": "71dd26999e314f9abb0c635336976635" //get请求返回的token
+}
+```
+##### 响应参数:
+```json
+{
+ "repCode": "0000",
+ "repData": {
+ "captchaType": "blockPuzzle",
+ "token": "71dd26999e314f9abb0c635336976635",
+ "result": true,
+ "opAdmin": false
+ },
+ "success": true,
+ "error": false
+}
+```
+## 2.4 IOS接入
+待接入
+## 2.5 Android
+待接入
+
+# 3 Q & A
+## 3.1 linux部署注意事项点选文字
+### 3.1.1 字体乱码问题
+点选文字中所用字体默认为思源黑体,Windows\Linux服务器均正常显示中文。需指定自己特殊字体,linux不支持的,可能会出现以下图中情况,如图3-1所示。
+
+
+
+图3-1 点选文字字体乱码
+### 3.1.2 乱码解决方案
+从1.2.6+开始,我们在核心包中内置了开源中文字体[思源黑体],无需安装配置就可正常显示。支持两种自定义字体方式:
+##### 方式一:自定义特定字体,请将字体放到工程resources下fonts文件夹,支持ttf\ttc\otf字体,通过配置项water-font和font-type激活。
+```
+# 水印字体
+aj.captcha.water-font=SourceHanSansCN-Normal.otf
+# 点选文字验证码的文字字体(思源黑体)
+aj.captcha.font-type=SourceHanSansCN-Normal.otf
+```
+##### 方式二:直接配置OS层的现有的字体名称,比如:宋体,因宋体等商业使用需要授权,请开发人员在取得授权后使用,Linux安装字体步骤如下:
+```
+# 水印字体
+aj.captcha.water-font=宋体
+# 点选文字验证码的文字字体
+aj.captcha.font-type=宋体
+```
+#### 1、安装字体库
+在CentOS 4.x开始用fontconfig来安装字体库,所以输入以下命令即可:
+```shell
+sudo yum -y install fontconfig
+```
+这时在/usr/shared目录就可以看到fonts和fontconfig目录了(之前是没有的):
+接下来就可以给我们的字体库中添加中文字体了。
+#### 2、首先在/usr/shared/fonts目录下新建一个目录chinese:
+CentOS中,字体库的存放位置正是上图中看到的fonts目录,所以我们首先要做的就是找到中文字体文件放到该目录下,而中文字体文件在我们的windows系统中就可以找到,打开c盘下的Windows/Fonts目录:
+#### 3、紧接着需要修改chinese目录的权限:
+```shell
+sudo chmod -R 755 /usr/share/fonts/chinese
+```
+接下来需要安装ttmkfdir来搜索目录中所有的字体信息,并汇总生成fonts.scale文件,输入命令:
+```shell
+sudo yum -y install ttmkfdir
+```
+然后执行ttmkfdir命令即可:
+```shell
+ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir
+```
+#### 4、最后一步就是修改字体配置文件了,首先通过编辑器打开配置文件 :
+```shell
+vim /etc/fonts/fonts.conf
+```
+可以看到一个Font list,即字体列表,在这里需要把我们添加的中文字体位置加进去:
+```shell
+/usr/share/fonts/chinese
+```
+#### 5、然后输入:wq保存退出,最后别忘了刷新内存中的字体缓存,这样就不用reboot重启了:
+```shell
+fc-cache
+```
+#### 6、这样所有的步骤就算完成了,最后再次通过fc-list看一下字体列表:
+```shell
+fc-list
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/service/solon/pom.xml b/service/solon/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8461414aa1f1e5317438ea8d33a5987a75433249
--- /dev/null
+++ b/service/solon/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+
+ com.anji.captcha
+ captcha-solon
+ 0.0.1-SNAPSHOT
+
+ captcha-solon-demo
+ anji-plus captcha demo
+ https://github.com/anji-plus/captcha
+ jar
+
+
+ org.noear
+ solon-parent
+ 1.5.27
+
+
+
+
+
+
+ org.noear
+ solon-web
+
+
+
+ org.noear
+ solon.extend.cors
+
+
+
+ com.anji-plus
+ captcha-solon-plugin
+ 1.3.0
+
+
+
+ ch.qos.logback
+ logback-classic
+ 1.1.7
+
+
+
+ org.noear
+ solon-test
+ test
+
+
+
+
+
+
diff --git a/service/solon/src/main/java/com/anji/captcha/demo/App.java b/service/solon/src/main/java/com/anji/captcha/demo/App.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4f07e60aa0349ad30d8571e424009a73e32c945
--- /dev/null
+++ b/service/solon/src/main/java/com/anji/captcha/demo/App.java
@@ -0,0 +1,24 @@
+package com.anji.captcha.demo;
+
+import org.noear.solon.SolonBuilder;
+import org.noear.solon.core.handle.Handler;
+import org.noear.solon.extend.cors.CrossHandler;
+
+
+/**
+ * @author noear 2021/9/2 created
+ */
+public class App {
+ public static void main(String[] args) {
+ new SolonBuilder()
+ .onError(e -> e.printStackTrace())
+ .start(App.class, args, app->{
+ Handler handler = new CrossHandler()
+ .allowHeaders("*")
+ .allowMethods("*")
+ .allowCredentials(true);
+
+ app.before(handler);
+ });
+ }
+}
diff --git a/service/solon/src/main/java/com/anji/captcha/demo/controller/LoginController.java b/service/solon/src/main/java/com/anji/captcha/demo/controller/LoginController.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c796bc07440c4f2829d380fd2ba67d39797da11
--- /dev/null
+++ b/service/solon/src/main/java/com/anji/captcha/demo/controller/LoginController.java
@@ -0,0 +1,40 @@
+package com.anji.captcha.demo.controller;
+
+import com.anji.captcha.model.common.ResponseModel;
+import com.anji.captcha.model.vo.CaptchaVO;
+import com.anji.captcha.service.CaptchaService;
+import org.noear.solon.annotation.Controller;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.annotation.Mapping;
+import org.noear.solon.annotation.Post;
+import org.noear.solon.extend.cors.annotation.CrossOrigin;
+
+/**
+ * 后端二次校验接口示例
+ */
+@Controller
+@Mapping("/auth")
+public class LoginController {
+
+ @Inject
+ private CaptchaService captchaService;
+
+ @Post
+ @Mapping("/login")
+ public ResponseModel get(String captchaVerification) {
+ CaptchaVO captchaVO = new CaptchaVO();
+ captchaVO.setCaptchaVerification(captchaVerification);
+ ResponseModel response = captchaService.verification(captchaVO);
+ if (response.isSuccess() == false) {
+ //验证码校验失败,返回信息告诉前端
+ //repCode 0000 无异常,代表成功
+ //repCode 9999 服务器内部异常
+ //repCode 0011 参数不能为空
+ //repCode 6110 验证码已失效,请重新获取
+ //repCode 6111 验证失败
+ //repCode 6112 获取验证码失败,请联系管理员
+ }
+ return response;
+ }
+
+}
diff --git a/service/solon/src/main/resources/app.properties b/service/solon/src/main/resources/app.properties
new file mode 100644
index 0000000000000000000000000000000000000000..66d9412160d2d9484fd4a7b5841dd0aef0e760c4
--- /dev/null
+++ b/service/solon/src/main/resources/app.properties
@@ -0,0 +1,39 @@
+solon.name=captcha-service
+
+server.port=8080
+
+# ?????????????????????CaptchaCacheService????Redis??memcache?
+# ??CaptchaCacheServiceRedisImpl.java
+# ??????????????redis?????????
+# ??????????????????????????????????????????
+# ??? ???????????spring-boot-starter-data-redis?
+# ???CaptchaCacheServiceRedisImpl.java???
+aj.captcha.cache-type=local
+# local?????,??????????
+aj.captcha.cache-number=1000
+# local????????(???),???0?????
+aj.captcha.timing-clear=3600
+#spring.redis.host=10.108.11.46
+#spring.redis.port=6379
+#spring.redis.password=
+#spring.redis.database=2
+#spring.redis.timeout=6000
+
+aj.captcha.jigsaw=classpath:images/jigsaw
+aj.captcha.pic-click=classpath:images/pic-click
+# ?????default???????
+aj.captcha.type=default
+# ??????Unicode,??????@value????????????????
+# https://tool.chinaz.com/tools/unicode.aspx ???Unicode
+# ???????(????)
+aj.captcha.water-mark=\u6211\u7684\u6c34\u5370
+# ???????(??)
+aj.captcha.water-font=\u5b8b\u4f53
+# ????????????(??)
+aj.captcha.font-type=\u5b8b\u4f53
+# ?????????????(??5??)
+aj.captcha.slip-offset=5
+# aes??????????(true|false)
+aj.captcha.aes-status=true
+# ?????(0/1/2)
+aj.captcha.interference-options=1
\ No newline at end of file
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg1.png b/service/solon/src/main/resources/images/jigsaw/original/bg1.png
new file mode 100644
index 0000000000000000000000000000000000000000..028073aed11bdb66cb43d1274d892414fae9e940
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg1.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg10.png b/service/solon/src/main/resources/images/jigsaw/original/bg10.png
new file mode 100644
index 0000000000000000000000000000000000000000..022aabf93c273244165aa410ff0d62a46e7d684b
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg10.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg11.png b/service/solon/src/main/resources/images/jigsaw/original/bg11.png
new file mode 100644
index 0000000000000000000000000000000000000000..914908e8979d4a1604c8f58a5c637108ef11b870
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg11.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg12.png b/service/solon/src/main/resources/images/jigsaw/original/bg12.png
new file mode 100644
index 0000000000000000000000000000000000000000..f0f3ce581b624e3821b2e5249a3dc5bd8e9690e3
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg12.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg13.png b/service/solon/src/main/resources/images/jigsaw/original/bg13.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5697f3cb45e6da7ea069dee4f9e3c43479a3b5b
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg13.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg14.png b/service/solon/src/main/resources/images/jigsaw/original/bg14.png
new file mode 100644
index 0000000000000000000000000000000000000000..e29e7a3c1b0b733e150df993877b3ca34d245b30
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg14.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg15.png b/service/solon/src/main/resources/images/jigsaw/original/bg15.png
new file mode 100644
index 0000000000000000000000000000000000000000..2425f412df6f861b627a73ec68907dcb65fef09b
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg15.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg16.png b/service/solon/src/main/resources/images/jigsaw/original/bg16.png
new file mode 100644
index 0000000000000000000000000000000000000000..c1730ad2d1076d732bc67a6dc1040b1ccaaaca4e
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg16.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg17.png b/service/solon/src/main/resources/images/jigsaw/original/bg17.png
new file mode 100644
index 0000000000000000000000000000000000000000..10ea85b0cf8375291d94bc26f885c355fc525cee
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg17.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg18.png b/service/solon/src/main/resources/images/jigsaw/original/bg18.png
new file mode 100644
index 0000000000000000000000000000000000000000..a63f0ac7aac2ecdbfd16a3102289b63521d7182b
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg18.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg19.png b/service/solon/src/main/resources/images/jigsaw/original/bg19.png
new file mode 100644
index 0000000000000000000000000000000000000000..fe9c4cc84d05df11ebc1bfaa5568108d542ebf18
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg19.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg2.png b/service/solon/src/main/resources/images/jigsaw/original/bg2.png
new file mode 100644
index 0000000000000000000000000000000000000000..7167036eace5463038358c14f3dfaa9531eb1ab8
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg2.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg20.png b/service/solon/src/main/resources/images/jigsaw/original/bg20.png
new file mode 100644
index 0000000000000000000000000000000000000000..7db9563ca82db9c0bbb8141c0b7a1735f6b5231a
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg20.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg3.png b/service/solon/src/main/resources/images/jigsaw/original/bg3.png
new file mode 100644
index 0000000000000000000000000000000000000000..e932d2c7abe651873c3281d0346b02e02663d973
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg3.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg4.png b/service/solon/src/main/resources/images/jigsaw/original/bg4.png
new file mode 100644
index 0000000000000000000000000000000000000000..63b2005896522bedae38e8827bacaddab1603555
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg4.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg5.png b/service/solon/src/main/resources/images/jigsaw/original/bg5.png
new file mode 100644
index 0000000000000000000000000000000000000000..4281ad4556608338ffbd4d32f40a6b54371c5013
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg5.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg6.png b/service/solon/src/main/resources/images/jigsaw/original/bg6.png
new file mode 100644
index 0000000000000000000000000000000000000000..ac544e3b5bd27d263fc8352204145251ed39331d
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg6.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg7.png b/service/solon/src/main/resources/images/jigsaw/original/bg7.png
new file mode 100644
index 0000000000000000000000000000000000000000..c6df4f7763cfcc55e1f3ce0db8460b97888ae46e
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg7.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg8.png b/service/solon/src/main/resources/images/jigsaw/original/bg8.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b07dcd8ee920c0b6e92fe08df4df6df2c38dc38
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg8.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/original/bg9.png b/service/solon/src/main/resources/images/jigsaw/original/bg9.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b9844a362ffcaacfa78d19dc35696778e8f1899
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/original/bg9.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/1.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/1.png
new file mode 100644
index 0000000000000000000000000000000000000000..1905026606d04c80eba0d7e03a5e286519257b9b
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/1.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/10.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/10.png
new file mode 100644
index 0000000000000000000000000000000000000000..e651cf466a80074177376067a3c6cb174c9865ea
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/10.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/11.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/11.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a33509afdc6330a257783c71d97da5d353b608e
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/11.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/2.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/2.png
new file mode 100644
index 0000000000000000000000000000000000000000..b1482d48b4f2f323979ead105e074fbcc6c0e6d9
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/2.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/3.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/3.png
new file mode 100644
index 0000000000000000000000000000000000000000..cdbb0b18c46c25c9d4573f60ad6031d70b99b872
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/3.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/4.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/4.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc69c96224d02597aa7c34d122bde3a563727dc6
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/4.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/5.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/5.png
new file mode 100644
index 0000000000000000000000000000000000000000..0080a54650950b41e6b5bb1be4d50cb506498d93
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/5.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/6.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/6.png
new file mode 100644
index 0000000000000000000000000000000000000000..b07c3b404654eb8e42c3824819fc9b7b325b64c1
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/6.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/7.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/7.png
new file mode 100644
index 0000000000000000000000000000000000000000..3be019a65e071a656a735a8db75fdb9355a834e7
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/7.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/8.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/8.png
new file mode 100644
index 0000000000000000000000000000000000000000..96d3c76cd8281cb7156f39b3fe25491c091dda5a
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/8.png differ
diff --git a/service/solon/src/main/resources/images/jigsaw/slidingBlock/9.png b/service/solon/src/main/resources/images/jigsaw/slidingBlock/9.png
new file mode 100644
index 0000000000000000000000000000000000000000..524c9404f9629cfe06c30861adbca06bc3a3bca0
Binary files /dev/null and b/service/solon/src/main/resources/images/jigsaw/slidingBlock/9.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg1.png b/service/solon/src/main/resources/images/pic-click/bg1.png
new file mode 100644
index 0000000000000000000000000000000000000000..51573a0c4e1e72a0566fa1ba57422b5f06cd90d8
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg1.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg2.png b/service/solon/src/main/resources/images/pic-click/bg2.png
new file mode 100644
index 0000000000000000000000000000000000000000..909dc39ef60eae026a09a82fde781ccc44858bd4
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg2.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg3.png b/service/solon/src/main/resources/images/pic-click/bg3.png
new file mode 100644
index 0000000000000000000000000000000000000000..59bc59c0b4181c512677c09460ca377e40120da7
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg3.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg4.png b/service/solon/src/main/resources/images/pic-click/bg4.png
new file mode 100644
index 0000000000000000000000000000000000000000..c856f4d97e3f939230a461d3f9f8c22b92d64e0c
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg4.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg5.png b/service/solon/src/main/resources/images/pic-click/bg5.png
new file mode 100644
index 0000000000000000000000000000000000000000..4594fcf65bb6e615dda6b2a1f705d969b9c712c6
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg5.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg6.png b/service/solon/src/main/resources/images/pic-click/bg6.png
new file mode 100644
index 0000000000000000000000000000000000000000..0f28d820b414c07f91399bc27c4d5c8c9e7d819d
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg6.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg7.png b/service/solon/src/main/resources/images/pic-click/bg7.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e04492979a234b9d1999634e8d671b2fcf827e6
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg7.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg8.png b/service/solon/src/main/resources/images/pic-click/bg8.png
new file mode 100644
index 0000000000000000000000000000000000000000..f11545fd3e1879ee204dd2887c868188140cea36
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg8.png differ
diff --git a/service/solon/src/main/resources/images/pic-click/bg9.png b/service/solon/src/main/resources/images/pic-click/bg9.png
new file mode 100644
index 0000000000000000000000000000000000000000..2f3a86dabb192a11ffffedb19ada8fbe2b444767
Binary files /dev/null and b/service/solon/src/main/resources/images/pic-click/bg9.png differ
diff --git a/service/solon/src/main/resources/logback.xml b/service/solon/src/main/resources/logback.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9f62adb1fee817f72b995085e7e3094e50d2da30
--- /dev/null
+++ b/service/solon/src/main/resources/logback.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+ %d{MM-dd HH:mm:ss.SSS} | %thread |-%-5level %logger{36}:%L - %msg%n
+
+
+ INFO
+
+
+
+
+
+ ${LOG_HOME}/${LOG_NAME}.log
+
+ ${LOG_HOME}/%d{yyyy-MM-dd}/${LOG_NAME}-%i.log
+ 50MB
+ 30
+
+
+ %d{MM-dd HH:mm:ss.SSS} |-%-5level %logger{36}:%L - %m%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/view/html/index.html b/view/html/index.html
index c89bfa644f84fb37652638ee155f68ef0b4a9bc2..857eb66c34fa322bb38e8329226624641e27b251 100644
--- a/view/html/index.html
+++ b/view/html/index.html
@@ -60,9 +60,9 @@