From f22c4b9230808fed4fec80c435eccb4c833349a0 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期五, 21 十月 2022 18:36:38 +0800
Subject: [PATCH] 2022.10.21 1.环境守法小程序后台功能首发版本完成

---
 src/main/kotlin/cn/flightfeather/supervision/common/wx/WxConfig.kt                                  |   23 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/LedgerServiceImpl.kt           |   19 
 src/main/kotlin/cn/flightfeather/supervision/domain/mapper/LogMsgSubscribeWxMapper.kt               |    8 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/AuthServiceImpl.kt             |  224 ++++
 src/main/kotlin/cn/flightfeather/supervision/SupervisionApplication.kt                              |    5 
 src/main/kotlin/cn/flightfeather/supervision/domain/entity/BaseInfo.java                            |  160 ++
 src/main/kotlin/cn/flightfeather/supervision/domain/entity/MsgSubscribeWx.java                      |  206 +++
 src/main/kotlin/cn/flightfeather/supervision/common/wx/SHA1.java                                    |   61 +
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/NotificationService.kt              |    3 
 src/main/kotlin/cn/flightfeather/supervision/common/wx/PKCS7Encoder.java                            |   67 +
 src/main/resources/mapper/LogMsgSubscribeWxMapper.xml                                               |   27 
 src/main/kotlin/cn/flightfeather/supervision/common/wx/AesException.java                            |   59 +
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/UserinfoServiceImpl.kt         |   31 
 src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskFetchVOC.kt                             |    4 
 src/main/kotlin/cn/flightfeather/supervision/domain/mapper/MsgSubscribeWxMapper.kt                  |    8 
 src/test/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImplTest.kt |   31 
 src/main/kotlin/cn/flightfeather/supervision/domain/enumeration/AuthenticationStatus.kt             |    9 
 src/main/kotlin/cn/flightfeather/supervision/domain/entity/Userinfo.kt                              |   11 
 src/main/resources/mapper/BaseInfoMapper.xml                                                        |   16 
 src/test/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImplTest.kt       |   25 
 src/main/kotlin/cn/flightfeather/supervision/domain/entity/LogMsgSubscribeWx.java                   |  195 +++
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImpl.kt           |  313 ++++
 src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/UserBaseInfo.kt                          |    4 
 src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskController.kt                           |    6 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/UserinfoService.kt                  |    4 
 src/main/kotlin/cn/flightfeather/supervision/common/wx/TemplateManager.kt                           |  188 +++
 src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AuthSceneVo.kt                           |   64 +
 src/main/kotlin/cn/flightfeather/supervision/common/wx/MessageWxVo.kt                               |   13 
 src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskLedgerRemind.kt                         |   39 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/web/WxUserController.kt                     |   28 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AuthSceneRestVo.kt                       |  104 +
 src/main/resources/templates/commitment-restaurant.ftl                                              |   15 
 src/main/kotlin/cn/flightfeather/supervision/common/wx/XMLParse.java                                |   78 +
 src/main/kotlin/cn/flightfeather/supervision/lightshare/web/NotificationController.kt               |    8 
 src/main/kotlin/cn/flightfeather/supervision/domain/entity/RestaurantBaseInfo.java                  |   77 +
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/AuthService.kt                      |   33 
 src/test/kotlin/cn/flightfeather/supervision/timingtask/PushFumeTest.kt                             |    4 
 pom.xml                                                                                             |    6 
 src/main/kotlin/cn/flightfeather/supervision/domain/entity/UserInfoWx.java                          |  127 +
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/LedgerService.kt                    |    2 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AccessToken.kt                           |    2 
 src/main/resources/generator/generatorConfig.xml                                                    |   14 
 src/test/kotlin/cn/flightfeather/supervision/CommonTest.kt                                          |    6 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/web/LedgerController.kt                     |    2 
 src/main/resources/mapper/MsgSubscribeWxMapper.xml                                                  |   26 
 src/main/kotlin/cn/flightfeather/supervision/common/net/WXHttpService.kt                            |   88 +
 src/main/kotlin/cn/flightfeather/supervision/domain/mapper/PersonalInfoMapper.kt                    |    8 
 src/main/kotlin/cn/flightfeather/supervision/common/wx/WxTokenManager.kt                            |   98 +
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/WxUserService.kt                    |   12 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/web/AuthController.kt                       |   45 
 src/main/kotlin/cn/flightfeather/supervision/common/wx/WXBizMsgCrypt.java                           |  289 +++++
 src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImpl.kt     |   18 
 src/main/kotlin/cn/flightfeather/supervision/lightshare/web/UserinfoController.kt                   |    7 
 src/main/kotlin/cn/flightfeather/supervision/timingtask/BaseTimingTask.kt                           |    2 
 src/main/resources/mapper/PersonalInfoMapper.xml                                                    |   27 
 src/main/resources/mapper/RestaurantBaseInfoMapper.xml                                              |    8 
 src/main/kotlin/cn/flightfeather/supervision/common/wx/ByteGroup.java                               |   26 
 src/main/resources/mapper/UserInfoWxMapper.xml                                                      |    6 
 src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskPushFume.kt                             |    9 
 src/main/kotlin/cn/flightfeather/supervision/domain/entity/PersonalInfo.java                        |  243 ++++
 src/test/kotlin/cn/flightfeather/supervision/common/wx/TemplateManagerTest.kt                       |   25 
 src/main/kotlin/cn/flightfeather/supervision/infrastructure/utils/PinYin.kt                         |   58 +
 62 files changed, 3,177 insertions(+), 147 deletions(-)

diff --git a/pom.xml b/pom.xml
index f5bbd96..8cde2c3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -363,6 +363,12 @@
             <artifactId>freemarker</artifactId>
             <version>2.3.31</version>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/com.belerweb/pinyin4j -->
+        <dependency>
+            <groupId>com.belerweb</groupId>
+            <artifactId>pinyin4j</artifactId>
+            <version>2.5.1</version>
+        </dependency>
 
     </dependencies>
 
diff --git a/src/main/kotlin/cn/flightfeather/supervision/SupervisionApplication.kt b/src/main/kotlin/cn/flightfeather/supervision/SupervisionApplication.kt
index c339a5a..518e7c5 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/SupervisionApplication.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/SupervisionApplication.kt
@@ -1,5 +1,6 @@
 package cn.flightfeather.supervision
 
+import cn.flightfeather.supervision.common.wx.WxTokenManager
 import cn.flightfeather.supervision.timingtask.TaskController
 import cn.flightfeather.supervision.websocket.VMRoomWebSocketServer
 import org.springframework.beans.factory.annotation.Autowired
@@ -18,10 +19,14 @@
     @Autowired
     lateinit var taskController: TaskController
 
+    @Autowired
+    lateinit var wxTokenManager: WxTokenManager
+
     @Bean
     fun runner() = ApplicationRunner {
         webSocketServer.start()
 //        taskController.run()
+        wxTokenManager.run()
     }
 }
 
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/net/WXHttpService.kt b/src/main/kotlin/cn/flightfeather/supervision/common/net/WXHttpService.kt
index bb20893..39bd1b8 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/common/net/WXHttpService.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/net/WXHttpService.kt
@@ -1,5 +1,13 @@
 package cn.flightfeather.supervision.common.net
 
+import cn.flightfeather.supervision.common.wx.MessageWxVo
+import cn.flightfeather.supervision.common.wx.WxConfig
+import com.alibaba.fastjson.JSON
+import com.alibaba.fastjson.JSONObject
+import com.google.gson.Gson
+import com.google.gson.JsonObject
+import com.google.gson.JsonParser
+
 /**
  * @author riku
  * Date: 2020/10/15
@@ -7,17 +15,87 @@
  */
 object WXHttpService {
 
-    private const val APP_ID=""
-    private const val SECRET = ""
     private val httpMethod = HttpMethod("api.weixin.qq.com", 443, true)
 
     /**
      * 寰俊鐧诲綍鍑瘉鏍¢獙
      */
-    fun code2Session(code: String): HttpMethod.MyResponse =
-        httpMethod.get(
+    fun code2Session(code: String): Pair<String, String>? {
+        val res =httpMethod.get(
             "/sns/jscode2session", listOf(
-                Pair("appid", APP_ID), Pair("secret", SECRET), Pair("js_code", code), Pair("grant_type", "authorization_code")
+                Pair("appid", WxConfig.APP_ID), Pair("secret", WxConfig.SECRET), Pair("js_code", code), Pair("grant_type", "authorization_code")
             )
         )
+        return if (res.success) {
+            val json = JSONObject.parseObject(res.m.responseBodyAsString)
+            val errCode = json["errcode"]
+            if (errCode == 0 || errCode == null) {
+                val openid = json["openid"] as String
+                val unionid = json["session_key"] as String
+                Pair(openid, unionid)
+            } else {
+                null
+            }
+        } else {
+            null
+        }
+    }
+
+    /**
+     * 寰俊鍙戦�佽闃呮秷鎭�
+     */
+    fun sendMsg(accessToken:String, msgWxV0: MessageWxVo): Boolean {
+        val data = Gson().toJson(msgWxV0)
+        val response = httpMethod.post("/cgi-bin/message/subscribe/send?access_token=${accessToken}", data)
+        if (response.success) {
+            val json = JsonParser.parseString(response.m.responseBodyAsString)
+            if (json.isJsonObject) {
+                val jo = json.asJsonObject
+                val eMsg = jo["errmsg"]?.asString
+                when (jo["errcode"]?.asInt) {
+                    40003 -> {
+                        throw IllegalStateException("寰俊璁㈤槄娑堟伅锛宼ouser瀛楁openid涓虹┖鎴栬�呬笉姝g‘锛岄敊璇俊鎭細${eMsg}")
+                    }
+                    40037 -> {
+                        throw IllegalStateException("寰俊璁㈤槄娑堟伅锛岃闃呮ā鏉縤d涓虹┖涓嶆纭紝閿欒淇℃伅锛�${eMsg}")
+                    }
+                    43101 -> {
+                        throw IllegalStateException("寰俊璁㈤槄娑堟伅锛岀敤鎴锋嫆缁濇帴鏀舵秷鎭紝閿欒淇℃伅锛�${eMsg}")
+                    }
+                    47003 -> {
+                        throw IllegalStateException("寰俊璁㈤槄娑堟伅锛屾ā鏉垮弬鏁颁笉鍑嗙‘锛屽叿浣撻敊璇細${eMsg}")
+                    }
+                    41030 -> {
+                        throw IllegalStateException("寰俊璁㈤槄娑堟伅锛宲age璺緞涓嶆纭紝閿欒淇℃伅锛�${eMsg}")
+                    }
+                }
+            }
+            return true
+        } else {
+            return false
+        }
+    }
+
+    /**
+     * 鑾峰彇灏忕▼搴忓叏灞�鍚庡彴鎺ュ彛璋冪敤鍑嵁
+     */
+    fun getAccessToken(): JsonObject? {
+        val res = httpMethod.get(
+            "/cgi-bin/token", listOf(
+                Pair("grant_type", "client_credential"),
+                Pair("appid", WxConfig.APP_ID),
+                Pair("secret", WxConfig.SECRET)
+            )
+        )
+        return if (res.success) {
+            val json = JsonParser.parseString(res.m.responseBodyAsString)
+            if (json.isJsonObject) {
+                json.asJsonObject
+            } else {
+                null
+            }
+        } else {
+            null
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/AesException.java b/src/main/kotlin/cn/flightfeather/supervision/common/wx/AesException.java
new file mode 100644
index 0000000..6b439d5
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/AesException.java
@@ -0,0 +1,59 @@
+package cn.flightfeather.supervision.common.wx;
+
+@SuppressWarnings("serial")
+public class AesException extends Exception {
+
+	public final static int OK = 0;
+	public final static int ValidateSignatureError = -40001;
+	public final static int ParseXmlError = -40002;
+	public final static int ComputeSignatureError = -40003;
+	public final static int IllegalAesKey = -40004;
+	public final static int ValidateAppidError = -40005;
+	public final static int EncryptAESError = -40006;
+	public final static int DecryptAESError = -40007;
+	public final static int IllegalBuffer = -40008;
+	//public final static int EncodeBase64Error = -40009;
+	//public final static int DecodeBase64Error = -40010;
+	//public final static int GenReturnXmlError = -40011;
+
+	private int code;
+
+	private static String getMessage(int code) {
+		switch (code) {
+		case ValidateSignatureError:
+			return "绛惧悕楠岃瘉閿欒";
+		case ParseXmlError:
+			return "xml瑙f瀽澶辫触";
+		case ComputeSignatureError:
+			return "sha鍔犲瘑鐢熸垚绛惧悕澶辫触";
+		case IllegalAesKey:
+			return "SymmetricKey闈炴硶";
+		case ValidateAppidError:
+			return "appid鏍¢獙澶辫触";
+		case EncryptAESError:
+			return "aes鍔犲瘑澶辫触";
+		case DecryptAESError:
+			return "aes瑙e瘑澶辫触";
+		case IllegalBuffer:
+			return "瑙e瘑鍚庡緱鍒扮殑buffer闈炴硶";
+//		case EncodeBase64Error:
+//			return "base64鍔犲瘑閿欒";
+//		case DecodeBase64Error:
+//			return "base64瑙e瘑閿欒";
+//		case GenReturnXmlError:
+//			return "xml鐢熸垚澶辫触";
+		default:
+			return null; // cannot be
+		}
+	}
+
+	public int getCode() {
+		return code;
+	}
+
+	AesException(int code) {
+		super(getMessage(code));
+		this.code = code;
+	}
+
+}
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/ByteGroup.java b/src/main/kotlin/cn/flightfeather/supervision/common/wx/ByteGroup.java
new file mode 100644
index 0000000..142420c
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/ByteGroup.java
@@ -0,0 +1,26 @@
+package cn.flightfeather.supervision.common.wx;
+
+import java.util.ArrayList;
+
+class ByteGroup {
+	ArrayList<Byte> byteContainer = new ArrayList<Byte>();
+
+	public byte[] toBytes() {
+		byte[] bytes = new byte[byteContainer.size()];
+		for (int i = 0; i < byteContainer.size(); i++) {
+			bytes[i] = byteContainer.get(i);
+		}
+		return bytes;
+	}
+
+	public ByteGroup addBytes(byte[] bytes) {
+		for (byte b : bytes) {
+			byteContainer.add(b);
+		}
+		return this;
+	}
+
+	public int size() {
+		return byteContainer.size();
+	}
+}
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/MessageWxVo.kt b/src/main/kotlin/cn/flightfeather/supervision/common/wx/MessageWxVo.kt
new file mode 100644
index 0000000..ef94771
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/MessageWxVo.kt
@@ -0,0 +1,13 @@
+package cn.flightfeather.supervision.common.wx
+
+import kotlin.reflect.jvm.internal.impl.load.kotlin.JvmType
+
+data class MessageWxVo(
+    //鎺ユ敹鑰咃紙鐢ㄦ埛锛夌殑openid
+    val touser: String,
+    val template_id: String,
+    val page: String,
+    val miniprogram_state: String,
+    val lang: String,
+    var data: Any? = null
+)
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/PKCS7Encoder.java b/src/main/kotlin/cn/flightfeather/supervision/common/wx/PKCS7Encoder.java
new file mode 100644
index 0000000..2603a3f
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/PKCS7Encoder.java
@@ -0,0 +1,67 @@
+/**
+ * 瀵瑰叕浼楀钩鍙板彂閫佺粰鍏紬璐﹀彿鐨勬秷鎭姞瑙e瘑绀轰緥浠g爜.
+ * 
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+// ------------------------------------------------------------------------
+
+package cn.flightfeather.supervision.common.wx;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+/**
+ * 鎻愪緵鍩轰簬PKCS7绠楁硶鐨勫姞瑙e瘑鎺ュ彛.
+ */
+class PKCS7Encoder {
+	static Charset CHARSET = Charset.forName("utf-8");
+	static int BLOCK_SIZE = 32;
+
+	/**
+	 * 鑾峰緱瀵规槑鏂囪繘琛岃ˉ浣嶅~鍏呯殑瀛楄妭.
+	 * 
+	 * @param count 闇�瑕佽繘琛屽~鍏呰ˉ浣嶆搷浣滅殑鏄庢枃瀛楄妭涓暟
+	 * @return 琛ラ綈鐢ㄧ殑瀛楄妭鏁扮粍
+	 */
+	static byte[] encode(int count) {
+		// 璁$畻闇�瑕佸~鍏呯殑浣嶆暟
+		int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
+		if (amountToPad == 0) {
+			amountToPad = BLOCK_SIZE;
+		}
+		// 鑾峰緱琛ヤ綅鎵�鐢ㄧ殑瀛楃
+		char padChr = chr(amountToPad);
+		String tmp = new String();
+		for (int index = 0; index < amountToPad; index++) {
+			tmp += padChr;
+		}
+		return tmp.getBytes(CHARSET);
+	}
+
+	/**
+	 * 鍒犻櫎瑙e瘑鍚庢槑鏂囩殑琛ヤ綅瀛楃
+	 * 
+	 * @param decrypted 瑙e瘑鍚庣殑鏄庢枃
+	 * @return 鍒犻櫎琛ヤ綅瀛楃鍚庣殑鏄庢枃
+	 */
+	static byte[] decode(byte[] decrypted) {
+		int pad = (int) decrypted[decrypted.length - 1];
+		if (pad < 1 || pad > 32) {
+			pad = 0;
+		}
+		return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
+	}
+
+	/**
+	 * 灏嗘暟瀛楄浆鍖栨垚ASCII鐮佸搴旂殑瀛楃锛岀敤浜庡鏄庢枃杩涜琛ョ爜
+	 * 
+	 * @param a 闇�瑕佽浆鍖栫殑鏁板瓧
+	 * @return 杞寲寰楀埌鐨勫瓧绗�
+	 */
+	static char chr(int a) {
+		byte target = (byte) (a & 0xFF);
+		return (char) target;
+	}
+
+}
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/SHA1.java b/src/main/kotlin/cn/flightfeather/supervision/common/wx/SHA1.java
new file mode 100644
index 0000000..fa703c9
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/SHA1.java
@@ -0,0 +1,61 @@
+/**
+ * 瀵瑰叕浼楀钩鍙板彂閫佺粰鍏紬璐﹀彿鐨勬秷鎭姞瑙e瘑绀轰緥浠g爜.
+ * 
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+// ------------------------------------------------------------------------
+
+package cn.flightfeather.supervision.common.wx;
+
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+/**
+ * SHA1 class
+ *
+ * 璁$畻鍏紬骞冲彴鐨勬秷鎭鍚嶆帴鍙�.
+ */
+public class SHA1 {
+
+	/**
+	 * 鐢⊿HA1绠楁硶鐢熸垚瀹夊叏绛惧悕
+	 * @param token 绁ㄦ嵁
+	 * @param timestamp 鏃堕棿鎴�
+	 * @param nonce 闅忔満瀛楃涓�
+	 * @param encrypt 瀵嗘枃
+	 * @return 瀹夊叏绛惧悕
+	 * @throws AesException
+	 */
+	public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException
+			  {
+		try {
+			String[] array = new String[] { token, timestamp, nonce, encrypt };
+			StringBuffer sb = new StringBuffer();
+			// 瀛楃涓叉帓搴�
+			Arrays.sort(array);
+			for (int i = 0; i < 4; i++) {
+				sb.append(array[i]);
+			}
+			String str = sb.toString();
+			// SHA1绛惧悕鐢熸垚
+			MessageDigest md = MessageDigest.getInstance("SHA-1");
+			md.update(str.getBytes());
+			byte[] digest = md.digest();
+
+			StringBuffer hexstr = new StringBuffer();
+			String shaHex = "";
+			for (int i = 0; i < digest.length; i++) {
+				shaHex = Integer.toHexString(digest[i] & 0xFF);
+				if (shaHex.length() < 2) {
+					hexstr.append(0);
+				}
+				hexstr.append(shaHex);
+			}
+			return hexstr.toString();
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.ComputeSignatureError);
+		}
+	}
+}
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/TemplateManager.kt b/src/main/kotlin/cn/flightfeather/supervision/common/wx/TemplateManager.kt
new file mode 100644
index 0000000..29dbf57
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/TemplateManager.kt
@@ -0,0 +1,188 @@
+package cn.flightfeather.supervision.common.wx
+
+import cn.flightfeather.supervision.common.net.WXHttpService
+import cn.flightfeather.supervision.domain.entity.LogMsgSubscribeWx
+import cn.flightfeather.supervision.domain.mapper.LogMsgSubscribeWxMapper
+import com.alibaba.fastjson.JSON
+import com.google.gson.Gson
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Component
+import java.util.*
+import javax.annotation.PostConstruct
+
+/**
+ * 寰俊璁㈤槄娑堟伅妯℃澘绠$悊
+ */
+@Component
+class TemplateManager {
+
+    companion object {
+        private lateinit var instance: TemplateManager
+
+        //鎺ㄩ�佸皬绋嬪簭鐗堟湰
+        private const val PROGRAM_STATE_1 = "developer"//寮�鍙戠増
+        private const val PROGRAM_STATE_2 = "trial"//浣撻獙鐗�
+        private const val PROGRAM_STATE_3 = "formal"//姝e紡鐗�
+
+        const val TEMPLATE_1 = "6JQFOJ12yBvKfRg_duSdwKiH5_J3LpICmz3Li-L1Cr8"//鍊掕鏃跺埌鏈熸彁閱掞紝鍙拌处
+        const val TEMPLATE_2 = "zPNMzF5WsshniJyl83DD-lDZtNvx7JyqLbKgqDl0qvU"//浠e姙浜嬮」鎻愰啋锛岃嚜娴嬫櫤璇�
+        const val TEMPLATE_3 = "zPNMzF5WsshniJyl83DD-u7MyVoUozOc2kjK8dGZcSA"//浠e姙浜嬮」鎻愰啋锛岄噸瑕侀�氱煡锛屽浼氳銆佹斂搴滃叕鍛婏紙鏆傚畾锛�
+        const val TEMPLATE_4 = "dqREi7vAd03OOirTgBGcm5aCihZJKBjVpiA8Kbu4B8w"//澶囧繕浜嬮」鎻愰啋锛屾湭璁よ瘉鎻愰啋鎴栧叾浠�
+
+        //妯℃澘id鍜屽搴旂殑璺宠浆璺緞(宸叉湁椤哄簭灏介噺涓嶈淇敼锛屾柊妯℃澘寰�鍚庨『寤�)
+        val templateList = listOf(
+            Pair(TEMPLATE_1,"pages/m_user/userlogin/userlogin"),
+            Pair(TEMPLATE_2,"pages/m_user/userlogin/userlogin"),
+            Pair(TEMPLATE_3,"pages/m_user/userlogin/userlogin"),
+            Pair(TEMPLATE_4,"pages/m_user/userlogin/userlogin"),
+        )
+    }
+
+    @Autowired
+    lateinit var wxTokenManager: WxTokenManager
+
+    @Autowired
+    lateinit var logMsgSubscribeWxMapper: LogMsgSubscribeWxMapper
+
+    @PostConstruct
+    fun init() {
+        instance = this
+    }
+
+    fun sendMsg(templateId: Int, openId: String, dataList: List<String>): Boolean {
+        val token = wxTokenManager.getAccessToken()
+        val msg = newTemplate(templateId, openId, dataList)
+        val res = WXHttpService.sendMsg(token, msg)
+        return if (res) {
+            //鍙戦�佹垚鍔燂紝鍒欒褰曠浉搴旂殑鏃ュ織
+            val log = LogMsgSubscribeWx().apply {
+                lmsOpenId = msg.touser
+                lmsTemplateId = msg.template_id
+                lmsData = Gson().toJson(msg.data)
+                lmsTime = Date()
+                lmsResult = false
+            }
+            logMsgSubscribeWxMapper.insert(log)
+            true
+        } else {
+            false
+        }
+    }
+
+    fun newTemplate(templateId: Int, openId: String, dataList: List<String>): MessageWxVo {
+        val t = templateList[templateId]
+        val msg = MessageWxVo(openId, t.first, t.second, PROGRAM_STATE_3, "zh_CN")
+        when (templateId) {
+            0 -> {
+                val temp = Template1()
+                if (dataList.size == 4) {
+                    temp.thing1.value = dataList[0]
+                    temp.time2.value = dataList[1]
+                    temp.number3.value = dataList[2]
+                    temp.thing4.value = dataList[3]
+                }
+                msg.data = temp
+            }
+            1 -> {
+                val temp = Template2()
+                if (dataList.size == 5) {
+                    temp.thing15.value = dataList[0]
+                    temp.thing1.value = dataList[1]
+                    temp.thing4.value = dataList[2]
+                    temp.time10.value = dataList[3]
+                    temp.thing12.value = dataList[4]
+                }
+                msg.data = temp
+            }
+            2 -> {
+                val temp = Template3()
+                if (dataList.size == 4) {
+                    temp.thing1.value = dataList[0]
+                    temp.thing4.value = dataList[1]
+                    temp.time10.value = dataList[2]
+                    temp.thing12.value = dataList[3]
+                }
+                msg.data = temp
+            }
+        }
+        return msg
+    }
+
+
+
+    /**
+     * 鍙拌处鍊掕鏃舵彁閱�
+     */
+    inner class Template1 {
+        //鍊掕鏃跺悕绉�
+        val thing1: TValue = TValue("")
+
+        //鐩爣鏃堕棿
+        val time2: TValue = TValue("")
+
+        //鍓╀綑澶╂暟
+        val number3: TValue = TValue("")
+
+        //澶囨敞
+        val thing4: TValue = TValue("")
+    }
+
+    /**
+     * 鑷祴鏅鸿瘎鎻愰啋
+     */
+    inner class Template2 {
+        //浜嬮」绫诲瀷
+        val thing15: TValue = TValue("")
+
+        //浜嬮」涓婚
+        val thing1: TValue = TValue("")
+
+        //浜嬮」鎻忚堪
+        val thing4: TValue = TValue("")
+
+        //鎴鏃堕棿
+        val time10: TValue = TValue("")
+
+        //澶囨敞娑堟伅
+        val thing12: TValue = TValue("")
+    }
+
+    /**
+     * 閲嶈閫氱煡锛屽浼氳銆佹斂搴滃叕鍛婏紙鏆傚畾锛�
+     */
+    inner class Template3 {
+        //浜嬮」涓婚
+        val thing1: TValue = TValue("")
+
+        //浜嬮」鎻忚堪
+        val thing4: TValue = TValue("")
+
+        //鎴鏃堕棿
+        val time10: TValue = TValue("")
+
+        //澶囨敞娑堟伅
+        val thing12: TValue = TValue("")
+    }
+
+    /**
+     * 鏈璇佹彁閱掓垨鍏朵粬
+     */
+    inner class Template4 {
+        //娲诲姩浜嬩欢
+        val thing1: TValue = TValue("")
+
+        //澶囧繕浜嬮」
+        val thing3: TValue = TValue("")
+
+        //寮�濮嬫椂闂�
+        val time2: TValue = TValue("")
+
+        //娓╅Θ鎻愮ず
+        val thing5: TValue = TValue("")
+
+        //瀹屾垚杩涘害
+        val thing4: TValue = TValue("")
+    }
+
+    data class TValue(var value: String)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/WXBizMsgCrypt.java b/src/main/kotlin/cn/flightfeather/supervision/common/wx/WXBizMsgCrypt.java
new file mode 100644
index 0000000..cdd2c43
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/WXBizMsgCrypt.java
@@ -0,0 +1,289 @@
+/**
+ * 瀵瑰叕浼楀钩鍙板彂閫佺粰鍏紬璐﹀彿鐨勬秷鎭姞瑙e瘑绀轰緥浠g爜.
+ * 
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * 閽堝org.apache.commons.codec.binary.Base64锛�
+ * 闇�瑕佸鍏ユ灦鍖卌ommons-codec-1.9锛堟垨commons-codec-1.8绛夊叾浠栫増鏈級
+ * 瀹樻柟涓嬭浇鍦板潃锛歨ttp://commons.apache.org/proper/commons-codec/download_codec.cgi
+ */
+package cn.flightfeather.supervision.common.wx;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Random;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+
+/**
+ * 鎻愪緵鎺ユ敹鍜屾帹閫佺粰鍏紬骞冲彴娑堟伅鐨勫姞瑙e瘑鎺ュ彛(UTF8缂栫爜鐨勫瓧绗︿覆).
+ * <ol>
+ * 	<li>绗笁鏂瑰洖澶嶅姞瀵嗘秷鎭粰鍏紬骞冲彴</li>
+ * 	<li>绗笁鏂规敹鍒板叕浼楀钩鍙板彂閫佺殑娑堟伅锛岄獙璇佹秷鎭殑瀹夊叏鎬э紝骞跺娑堟伅杩涜瑙e瘑銆�</li>
+ * </ol>
+ * 璇存槑锛氬紓甯竕ava.security.InvalidKeyException:illegal Key Size鐨勮В鍐虫柟妗�
+ * <ol>
+ * 	<li>鍦ㄥ畼鏂圭綉绔欎笅杞絁CE鏃犻檺鍒舵潈闄愮瓥鐣ユ枃浠讹紙JDK7鐨勪笅杞藉湴鍧�锛�
+ *      http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html</li>
+ * 	<li>涓嬭浇鍚庤В鍘嬶紝鍙互鐪嬪埌local_policy.jar鍜孶S_export_policy.jar浠ュ強readme.txt</li>
+ * 	<li>濡傛灉瀹夎浜咼RE锛屽皢涓や釜jar鏂囦欢鏀惧埌%JRE_HOME%\lib\security鐩綍涓嬭鐩栧師鏉ョ殑鏂囦欢</li>
+ * 	<li>濡傛灉瀹夎浜咼DK锛屽皢涓や釜jar鏂囦欢鏀惧埌%JDK_HOME%\jre\lib\security鐩綍涓嬭鐩栧師鏉ユ枃浠�</li>
+ * </ol>
+ */
+public class WXBizMsgCrypt {
+	static Charset CHARSET = Charset.forName("utf-8");
+	Base64 base64 = new Base64();
+	byte[] aesKey;
+	String token;
+	String appId;
+
+	/**
+	 * 鏋勯�犲嚱鏁�
+	 * @param token 鍏紬骞冲彴涓婏紝寮�鍙戣�呰缃殑token
+	 * @param encodingAesKey 鍏紬骞冲彴涓婏紝寮�鍙戣�呰缃殑EncodingAESKey
+	 * @param appId 鍏紬骞冲彴appid
+	 * 
+	 * @throws AesException 鎵ц澶辫触锛岃鏌ョ湅璇ュ紓甯哥殑閿欒鐮佸拰鍏蜂綋鐨勯敊璇俊鎭�
+	 */
+	public WXBizMsgCrypt(String token, String encodingAesKey, String appId) throws AesException {
+		if (encodingAesKey.length() != 43) {
+			throw new AesException(AesException.IllegalAesKey);
+		}
+
+		this.token = token;
+		this.appId = appId;
+		aesKey = Base64.decodeBase64(encodingAesKey + "=");
+	}
+
+	// 鐢熸垚4涓瓧鑺傜殑缃戠粶瀛楄妭搴�
+	byte[] getNetworkBytesOrder(int sourceNumber) {
+		byte[] orderBytes = new byte[4];
+		orderBytes[3] = (byte) (sourceNumber & 0xFF);
+		orderBytes[2] = (byte) (sourceNumber >> 8 & 0xFF);
+		orderBytes[1] = (byte) (sourceNumber >> 16 & 0xFF);
+		orderBytes[0] = (byte) (sourceNumber >> 24 & 0xFF);
+		return orderBytes;
+	}
+
+	// 杩樺師4涓瓧鑺傜殑缃戠粶瀛楄妭搴�
+	int recoverNetworkBytesOrder(byte[] orderBytes) {
+		int sourceNumber = 0;
+		for (int i = 0; i < 4; i++) {
+			sourceNumber <<= 8;
+			sourceNumber |= orderBytes[i] & 0xff;
+		}
+		return sourceNumber;
+	}
+
+	// 闅忔満鐢熸垚16浣嶅瓧绗︿覆
+	String getRandomStr() {
+		String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+		Random random = new Random();
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < 16; i++) {
+			int number = random.nextInt(base.length());
+			sb.append(base.charAt(number));
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 瀵规槑鏂囪繘琛屽姞瀵�.
+	 * 
+	 * @param text 闇�瑕佸姞瀵嗙殑鏄庢枃
+	 * @return 鍔犲瘑鍚巄ase64缂栫爜鐨勫瓧绗︿覆
+	 * @throws AesException aes鍔犲瘑澶辫触
+	 */
+	String encrypt(String randomStr, String text) throws AesException {
+		ByteGroup byteCollector = new ByteGroup();
+		byte[] randomStrBytes = randomStr.getBytes(CHARSET);
+		byte[] textBytes = text.getBytes(CHARSET);
+		byte[] networkBytesOrder = getNetworkBytesOrder(textBytes.length);
+		byte[] appidBytes = appId.getBytes(CHARSET);
+
+		// randomStr + networkBytesOrder + text + appid
+		byteCollector.addBytes(randomStrBytes);
+		byteCollector.addBytes(networkBytesOrder);
+		byteCollector.addBytes(textBytes);
+		byteCollector.addBytes(appidBytes);
+
+		// ... + pad: 浣跨敤鑷畾涔夌殑濉厖鏂瑰紡瀵规槑鏂囪繘琛岃ˉ浣嶅~鍏�
+		byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());
+		byteCollector.addBytes(padBytes);
+
+		// 鑾峰緱鏈�缁堢殑瀛楄妭娴�, 鏈姞瀵�
+		byte[] unencrypted = byteCollector.toBytes();
+
+		try {
+			// 璁剧疆鍔犲瘑妯″紡涓篈ES鐨凜BC妯″紡
+			Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+			SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
+			IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
+			cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
+
+			// 鍔犲瘑
+			byte[] encrypted = cipher.doFinal(unencrypted);
+
+			// 浣跨敤BASE64瀵瑰姞瀵嗗悗鐨勫瓧绗︿覆杩涜缂栫爜
+			String base64Encrypted = base64.encodeToString(encrypted);
+
+			return base64Encrypted;
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.EncryptAESError);
+		}
+	}
+
+	/**
+	 * 瀵瑰瘑鏂囪繘琛岃В瀵�.
+	 * 
+	 * @param text 闇�瑕佽В瀵嗙殑瀵嗘枃
+	 * @return 瑙e瘑寰楀埌鐨勬槑鏂�
+	 * @throws AesException aes瑙e瘑澶辫触
+	 */
+	String decrypt(String text) throws AesException {
+		byte[] original;
+		try {
+			// 璁剧疆瑙e瘑妯″紡涓篈ES鐨凜BC妯″紡
+			Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+			SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
+			IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
+			cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
+
+			// 浣跨敤BASE64瀵瑰瘑鏂囪繘琛岃В鐮�
+			byte[] encrypted = Base64.decodeBase64(text);
+
+			// 瑙e瘑
+			original = cipher.doFinal(encrypted);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.DecryptAESError);
+		}
+
+		String xmlContent, from_appid;
+		try {
+			// 鍘婚櫎琛ヤ綅瀛楃
+			byte[] bytes = PKCS7Encoder.decode(original);
+
+			// 鍒嗙16浣嶉殢鏈哄瓧绗︿覆,缃戠粶瀛楄妭搴忓拰AppId
+			byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
+
+			int xmlLength = recoverNetworkBytesOrder(networkOrder);
+
+			xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
+			from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),
+					CHARSET);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.IllegalBuffer);
+		}
+
+		// appid涓嶇浉鍚岀殑鎯呭喌
+		if (!from_appid.equals(appId)) {
+			throw new AesException(AesException.ValidateAppidError);
+		}
+		return xmlContent;
+
+	}
+
+	/**
+	 * 灏嗗叕浼楀钩鍙板洖澶嶇敤鎴风殑娑堟伅鍔犲瘑鎵撳寘.
+	 * <ol>
+	 * 	<li>瀵硅鍙戦�佺殑娑堟伅杩涜AES-CBC鍔犲瘑</li>
+	 * 	<li>鐢熸垚瀹夊叏绛惧悕</li>
+	 * 	<li>灏嗘秷鎭瘑鏂囧拰瀹夊叏绛惧悕鎵撳寘鎴恱ml鏍煎紡</li>
+	 * </ol>
+	 * 
+	 * @param replyMsg 鍏紬骞冲彴寰呭洖澶嶇敤鎴风殑娑堟伅锛寈ml鏍煎紡鐨勫瓧绗︿覆
+	 * @param timeStamp 鏃堕棿鎴筹紝鍙互鑷繁鐢熸垚锛屼篃鍙互鐢║RL鍙傛暟鐨則imestamp
+	 * @param nonce 闅忔満涓诧紝鍙互鑷繁鐢熸垚锛屼篃鍙互鐢║RL鍙傛暟鐨刵once
+	 * 
+	 * @return 鍔犲瘑鍚庣殑鍙互鐩存帴鍥炲鐢ㄦ埛鐨勫瘑鏂囷紝鍖呮嫭msg_signature, timestamp, nonce, encrypt鐨剎ml鏍煎紡鐨勫瓧绗︿覆
+	 * @throws AesException 鎵ц澶辫触锛岃鏌ョ湅璇ュ紓甯哥殑閿欒鐮佸拰鍏蜂綋鐨勯敊璇俊鎭�
+	 */
+	public String encryptMsg(String replyMsg, String timeStamp, String nonce) throws AesException {
+		// 鍔犲瘑
+		String encrypt = encrypt(getRandomStr(), replyMsg);
+
+		// 鐢熸垚瀹夊叏绛惧悕
+		if (timeStamp == "") {
+			timeStamp = Long.toString(System.currentTimeMillis());
+		}
+
+		String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt);
+
+		// System.out.println("鍙戦�佺粰骞冲彴鐨勭鍚嶆槸: " + signature[1].toString());
+		// 鐢熸垚鍙戦�佺殑xml
+		String result = XMLParse.generate(encrypt, signature, timeStamp, nonce);
+		return result;
+	}
+
+	/**
+	 * 妫�楠屾秷鎭殑鐪熷疄鎬э紝骞朵笖鑾峰彇瑙e瘑鍚庣殑鏄庢枃.
+	 * <ol>
+	 * 	<li>鍒╃敤鏀跺埌鐨勫瘑鏂囩敓鎴愬畨鍏ㄧ鍚嶏紝杩涜绛惧悕楠岃瘉</li>
+	 * 	<li>鑻ラ獙璇侀�氳繃锛屽垯鎻愬彇xml涓殑鍔犲瘑娑堟伅</li>
+	 * 	<li>瀵规秷鎭繘琛岃В瀵�</li>
+	 * </ol>
+	 * 
+	 * @param msgSignature 绛惧悕涓诧紝瀵瑰簲URL鍙傛暟鐨刴sg_signature
+	 * @param timeStamp 鏃堕棿鎴筹紝瀵瑰簲URL鍙傛暟鐨則imestamp
+	 * @param nonce 闅忔満涓诧紝瀵瑰簲URL鍙傛暟鐨刵once
+	 * @param postData 瀵嗘枃锛屽搴擯OST璇锋眰鐨勬暟鎹�
+	 * 
+	 * @return 瑙e瘑鍚庣殑鍘熸枃
+	 * @throws AesException 鎵ц澶辫触锛岃鏌ョ湅璇ュ紓甯哥殑閿欒鐮佸拰鍏蜂綋鐨勯敊璇俊鎭�
+	 */
+	public String decryptMsg(String msgSignature, String timeStamp, String nonce, String postData)
+			throws AesException {
+
+		// 瀵嗛挜锛屽叕浼楄处鍙风殑app secret
+		// 鎻愬彇瀵嗘枃
+		Object[] encrypt = XMLParse.extract(postData);
+
+		// 楠岃瘉瀹夊叏绛惧悕
+		String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt[1].toString());
+
+		// 鍜孶RL涓殑绛惧悕姣旇緝鏄惁鐩哥瓑
+		// System.out.println("绗笁鏂规敹鍒癠RL涓殑绛惧悕锛�" + msg_sign);
+		// System.out.println("绗笁鏂规牎楠岀鍚嶏細" + signature);
+		if (!signature.equals(msgSignature)) {
+			throw new AesException(AesException.ValidateSignatureError);
+		}
+
+		// 瑙e瘑
+		String result = decrypt(encrypt[1].toString());
+		return result;
+	}
+
+	/**
+	 * 楠岃瘉URL
+	 * @param msgSignature 绛惧悕涓诧紝瀵瑰簲URL鍙傛暟鐨刴sg_signature
+	 * @param timeStamp 鏃堕棿鎴筹紝瀵瑰簲URL鍙傛暟鐨則imestamp
+	 * @param nonce 闅忔満涓诧紝瀵瑰簲URL鍙傛暟鐨刵once
+	 * @param echoStr 闅忔満涓诧紝瀵瑰簲URL鍙傛暟鐨別chostr
+	 * 
+	 * @return 瑙e瘑涔嬪悗鐨別chostr
+	 * @throws AesException 鎵ц澶辫触锛岃鏌ョ湅璇ュ紓甯哥殑閿欒鐮佸拰鍏蜂綋鐨勯敊璇俊鎭�
+	 */
+	public String verifyUrl(String msgSignature, String timeStamp, String nonce, String echoStr)
+			throws AesException {
+		String signature = SHA1.getSHA1(token, timeStamp, nonce, echoStr);
+
+		if (!signature.equals(msgSignature)) {
+			throw new AesException(AesException.ValidateSignatureError);
+		}
+
+		String result = decrypt(echoStr);
+		return result;
+	}
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/WxConfig.kt b/src/main/kotlin/cn/flightfeather/supervision/common/wx/WxConfig.kt
new file mode 100644
index 0000000..62419a4
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/WxConfig.kt
@@ -0,0 +1,23 @@
+package cn.flightfeather.supervision.common.wx
+
+object WxConfig {
+    /**灏忕▼搴忕敵璇蜂簡涓や釜鍏紬鍙凤紝閫夋嫨鍏朵腑涓�绉�*************************************************************/
+    //灏忕櫧鍜ㄨ
+//    const val APP_ID="wxffd1438dd373fcf6"
+//    const val SECRET = "83c5ecfb9b2ae882b577a5c04ff7c3bd"
+
+    //涓皬寰紒涓氱敓鎬佺幆澧冨畧娉曟櫤鑳芥湇鍔�
+    const val APP_ID="wx5758efcebb0774de"
+    const val SECRET = "444a906c37ae3f2eab609060d944f624"
+    const val USER_NAME = "gh_c60faa57000f"
+    /*********************************************************************************************/
+
+    //灏忕▼搴忔帹閫佹秷鎭獙璇乼oken
+    const val TOKEN = "ledger"
+
+    const val AES_KEY = "ou43VsUPRFNmEIoVXsy038z0NPLbPAiIAysGrg1YFlZ"
+
+    //鐢ㄦ埛鎺ユ敹鎴栨嫆鏀舵秷鎭帹閫佺殑鍏抽敭璇�
+    const val S_ACCEPT = "accept"
+    const val S_REJECT = "reject"
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/WxTokenManager.kt b/src/main/kotlin/cn/flightfeather/supervision/common/wx/WxTokenManager.kt
new file mode 100644
index 0000000..25f420f
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/WxTokenManager.kt
@@ -0,0 +1,98 @@
+package cn.flightfeather.supervision.common.wx
+
+import cn.flightfeather.supervision.common.net.WXHttpService
+import org.springframework.stereotype.Component
+import java.util.concurrent.Executors
+import java.util.concurrent.ScheduledExecutorService
+import java.util.concurrent.TimeUnit
+
+/**
+ * 灏忕▼搴忓叏灞�鍚庡彴鎺ュ彛璋冪敤鍑嵁绠$悊
+ */
+@Component
+class WxTokenManager {
+
+    companion object {
+        private const val TAG = "WxTokenManager"
+    }
+    private var schedule = Executors.newScheduledThreadPool(2)
+
+    private var token = ""
+
+    fun run(){
+        if (token.isBlank()) {
+            refreshToken(0)
+        }
+    }
+
+    /**
+     * 鍒锋柊鎺ュ彛璋冪敤鍑瘉
+     * @param delay 寤惰繜鎵ц鏃堕棿锛屽崟浣嶏細绉�
+     * @param force 鏄惁寮哄埗涓柇褰撳墠绾跨▼锛岄噸鏂版墽琛�
+     */
+    fun refreshToken(delay:Long, force:Boolean = false) {
+        if (force) {
+            schedule = closeThread(schedule)
+        }
+        schedule.schedule({
+            getTokenTask()
+        }, delay, TimeUnit.SECONDS)
+    }
+
+    fun getAccessToken(): String {
+        if (token.isBlank()) {
+            throw IllegalStateException("[${TAG}]鑾峰彇灏忕▼搴忔帴鍙h皟鐢ㄥ嚟鎹紝褰撳墠token杩樻湭鑾峰彇鍒�")
+        }
+        return token
+    }
+
+    private fun getTokenTask() {
+        val res = WXHttpService.getAccessToken()
+        if (res == null) {
+            //璇锋眰澶辫触锛�10s鍚庨噸璇�
+            refreshToken(10)
+        } else {
+            var nextDelay = 6900L//涓嬩竴娆¤幏鍙栧嚟璇佹椂闂撮棿闅旓紙绉掞級
+            when (res["errcode"]?.asInt) {
+                //璇锋眰鎴愬姛
+                null, 0 -> {
+                    val t = res["access_token"]?.asString
+                    if (t == null) {
+                        refreshToken(60)
+                    } else {
+                        token = t
+                        res["expires_in"]?.asLong?.let { nextDelay = it - 300 }
+                        refreshToken(nextDelay)
+                    }
+                }
+                //寰俊鏈嶅姟鍣ㄧ郴缁熺箒蹇欙紝绋嶅悗閲嶈瘯
+                -1 -> {
+                    refreshToken(60)
+                }
+                //AppSecret閿欒
+                40001 -> {
+                    throw IllegalStateException("[${TAG}]鑾峰彇灏忕▼搴忔帴鍙h皟鐢ㄥ嚟鎹紝AppSecret[${WxConfig.SECRET}]閿欒")
+                }
+                40002 -> {
+                    throw IllegalStateException("[${TAG}]鑾峰彇灏忕▼搴忔帴鍙h皟鐢ㄥ嚟鎹紝璇风‘淇漡rant_type瀛楁鍊间负client_credential")
+                }
+                40003 -> {
+                    throw IllegalStateException("[${TAG}]鑾峰彇灏忕▼搴忔帴鍙h皟鐢ㄥ嚟鎹紝AppID[${WxConfig.APP_ID}]閿欒")
+                }
+            }
+        }
+    }
+
+    private fun closeThread(s: ScheduledExecutorService): ScheduledExecutorService {
+        try {
+            s.shutdown()
+            if (s.awaitTermination(10, TimeUnit.SECONDS)) {
+                s.shutdownNow()
+            }
+        } catch (e: InterruptedException) {
+            e.printStackTrace()
+            s.shutdownNow()
+        }
+        return Executors.newScheduledThreadPool(2)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/common/wx/XMLParse.java b/src/main/kotlin/cn/flightfeather/supervision/common/wx/XMLParse.java
new file mode 100644
index 0000000..7ea25e3
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/common/wx/XMLParse.java
@@ -0,0 +1,78 @@
+/**
+ * 瀵瑰叕浼楀钩鍙板彂閫佺粰鍏紬璐﹀彿鐨勬秷鎭姞瑙e瘑绀轰緥浠g爜.
+ * 
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+// ------------------------------------------------------------------------
+
+package cn.flightfeather.supervision.common.wx;
+
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * XMLParse class
+ *
+ * 鎻愪緵鎻愬彇娑堟伅鏍煎紡涓殑瀵嗘枃鍙婄敓鎴愬洖澶嶆秷鎭牸寮忕殑鎺ュ彛.
+ */
+class XMLParse {
+
+	/**
+	 * 鎻愬彇鍑簒ml鏁版嵁鍖呬腑鐨勫姞瀵嗘秷鎭�
+	 * @param xmltext 寰呮彁鍙栫殑xml瀛楃涓�
+	 * @return 鎻愬彇鍑虹殑鍔犲瘑娑堟伅瀛楃涓�
+	 * @throws AesException 
+	 */
+	public static Object[] extract(String xmltext) throws AesException     {
+		Object[] result = new Object[3];
+		try {
+			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+			dbf.setXIncludeAware(false);
+			dbf.setExpandEntityReferences(false);
+			DocumentBuilder db = dbf.newDocumentBuilder();
+			StringReader sr = new StringReader(xmltext);
+			InputSource is = new InputSource(sr);
+			Document document = db.parse(is);
+
+			Element root = document.getDocumentElement();
+			NodeList nodelist1 = root.getElementsByTagName("Encrypt");
+			NodeList nodelist2 = root.getElementsByTagName("ToUserName");
+			result[0] = 0;
+			result[1] = nodelist1.item(0).getTextContent();
+			result[2] = nodelist2.item(0).getTextContent();
+			return result;
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.ParseXmlError);
+		}
+	}
+
+	/**
+	 * 鐢熸垚xml娑堟伅
+	 * @param encrypt 鍔犲瘑鍚庣殑娑堟伅瀵嗘枃
+	 * @param signature 瀹夊叏绛惧悕
+	 * @param timestamp 鏃堕棿鎴�
+	 * @param nonce 闅忔満瀛楃涓�
+	 * @return 鐢熸垚鐨剎ml瀛楃涓�
+	 */
+	public static String generate(String encrypt, String signature, String timestamp, String nonce) {
+
+		String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n"
+				+ "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n"
+				+ "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n" + "</xml>";
+		return String.format(format, encrypt, signature, timestamp, nonce);
+
+	}
+}
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/BaseInfo.java b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/BaseInfo.java
index 2c55e12..54a8c7a 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/BaseInfo.java
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/BaseInfo.java
@@ -19,6 +19,12 @@
     private String biName;
 
     /**
+     * 鐢ㄦ埛绠�绉�
+     */
+    @Column(name = "BI_Nick_Name")
+    private String biNickName;
+
+    /**
      * 鎵�灞炲叕鍙竔d
      */
     @Column(name = "CI_GUID")
@@ -29,6 +35,30 @@
      */
     @Column(name = "CI_Name")
     private String ciName;
+
+    @Column(name = "BI_Province_Code")
+    private String biProvinceCode;
+
+    @Column(name = "BI_Province_Name")
+    private String biProvinceName;
+
+    @Column(name = "BI_City_Code")
+    private String biCityCode;
+
+    @Column(name = "BI_City_Name")
+    private String biCityName;
+
+    @Column(name = "BI_District_Code")
+    private String biDistrictCode;
+
+    @Column(name = "BI_District_Name")
+    private String biDistrictName;
+
+    @Column(name = "BI_Town_Code")
+    private String biTownCode;
+
+    @Column(name = "BI_Town_Name")
+    private String biTownName;
 
     /**
      * 鎵�灞炵墿涓氬叕鍙稿悕绉癷d
@@ -115,6 +145,24 @@
     }
 
     /**
+     * 鑾峰彇鐢ㄦ埛绠�绉�
+     *
+     * @return BI_Nick_Name - 鐢ㄦ埛绠�绉�
+     */
+    public String getBiNickName() {
+        return biNickName;
+    }
+
+    /**
+     * 璁剧疆鐢ㄦ埛绠�绉�
+     *
+     * @param biNickName 鐢ㄦ埛绠�绉�
+     */
+    public void setBiNickName(String biNickName) {
+        this.biNickName = biNickName == null ? null : biNickName.trim();
+    }
+
+    /**
      * 鑾峰彇鎵�灞炲叕鍙竔d
      *
      * @return CI_GUID - 鎵�灞炲叕鍙竔d
@@ -151,6 +199,118 @@
     }
 
     /**
+     * @return BI_Province_Code
+     */
+    public String getBiProvinceCode() {
+        return biProvinceCode;
+    }
+
+    /**
+     * @param biProvinceCode
+     */
+    public void setBiProvinceCode(String biProvinceCode) {
+        this.biProvinceCode = biProvinceCode == null ? null : biProvinceCode.trim();
+    }
+
+    /**
+     * @return BI_Province_Name
+     */
+    public String getBiProvinceName() {
+        return biProvinceName;
+    }
+
+    /**
+     * @param biProvinceName
+     */
+    public void setBiProvinceName(String biProvinceName) {
+        this.biProvinceName = biProvinceName == null ? null : biProvinceName.trim();
+    }
+
+    /**
+     * @return BI_City_Code
+     */
+    public String getBiCityCode() {
+        return biCityCode;
+    }
+
+    /**
+     * @param biCityCode
+     */
+    public void setBiCityCode(String biCityCode) {
+        this.biCityCode = biCityCode == null ? null : biCityCode.trim();
+    }
+
+    /**
+     * @return BI_City_Name
+     */
+    public String getBiCityName() {
+        return biCityName;
+    }
+
+    /**
+     * @param biCityName
+     */
+    public void setBiCityName(String biCityName) {
+        this.biCityName = biCityName == null ? null : biCityName.trim();
+    }
+
+    /**
+     * @return BI_District_Code
+     */
+    public String getBiDistrictCode() {
+        return biDistrictCode;
+    }
+
+    /**
+     * @param biDistrictCode
+     */
+    public void setBiDistrictCode(String biDistrictCode) {
+        this.biDistrictCode = biDistrictCode == null ? null : biDistrictCode.trim();
+    }
+
+    /**
+     * @return BI_District_Name
+     */
+    public String getBiDistrictName() {
+        return biDistrictName;
+    }
+
+    /**
+     * @param biDistrictName
+     */
+    public void setBiDistrictName(String biDistrictName) {
+        this.biDistrictName = biDistrictName == null ? null : biDistrictName.trim();
+    }
+
+    /**
+     * @return BI_Town_Code
+     */
+    public String getBiTownCode() {
+        return biTownCode;
+    }
+
+    /**
+     * @param biTownCode
+     */
+    public void setBiTownCode(String biTownCode) {
+        this.biTownCode = biTownCode == null ? null : biTownCode.trim();
+    }
+
+    /**
+     * @return BI_Town_Name
+     */
+    public String getBiTownName() {
+        return biTownName;
+    }
+
+    /**
+     * @param biTownName
+     */
+    public void setBiTownName(String biTownName) {
+        this.biTownName = biTownName == null ? null : biTownName.trim();
+    }
+
+    /**
      * 鑾峰彇鎵�灞炵墿涓氬叕鍙稿悕绉癷d
      *
      * @return BI_Management_Company_Id - 鎵�灞炵墿涓氬叕鍙稿悕绉癷d
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/LogMsgSubscribeWx.java b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/LogMsgSubscribeWx.java
new file mode 100644
index 0000000..a136abe
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/LogMsgSubscribeWx.java
@@ -0,0 +1,195 @@
+package cn.flightfeather.supervision.domain.entity;
+
+import java.util.Date;
+import javax.persistence.*;
+
+@Table(name = "sys_log_msg_subscribe_wx")
+public class LogMsgSubscribeWx {
+    @Id
+    @Column(name = "LMS_ID")
+    private Integer lmsId;
+
+    @Column(name = "LMS_Open_Id")
+    private String lmsOpenId;
+
+    @Column(name = "LMS_Template_Id")
+    private String lmsTemplateId;
+
+    @Column(name = "LMS_Data")
+    private String lmsData;
+
+    @Column(name = "LMS_Time")
+    private Date lmsTime;
+
+    @Column(name = "LMS_Msg_Id")
+    private String lmsMsgId;
+
+    @Column(name = "LMS_Result")
+    private Boolean lmsResult;
+
+    @Column(name = "LMS_Extension1")
+    private String lmsExtension1;
+
+    @Column(name = "LMS_Extension2")
+    private String lmsExtension2;
+
+    @Column(name = "LMS_Extension3")
+    private String lmsExtension3;
+
+    @Column(name = "LMS_Remark")
+    private String lmsRemark;
+
+    /**
+     * @return LMS_ID
+     */
+    public Integer getLmsId() {
+        return lmsId;
+    }
+
+    /**
+     * @param lmsId
+     */
+    public void setLmsId(Integer lmsId) {
+        this.lmsId = lmsId;
+    }
+
+    /**
+     * @return LMS_Open_Id
+     */
+    public String getLmsOpenId() {
+        return lmsOpenId;
+    }
+
+    /**
+     * @param lmsOpenId
+     */
+    public void setLmsOpenId(String lmsOpenId) {
+        this.lmsOpenId = lmsOpenId == null ? null : lmsOpenId.trim();
+    }
+
+    /**
+     * @return LMS_Template_Id
+     */
+    public String getLmsTemplateId() {
+        return lmsTemplateId;
+    }
+
+    /**
+     * @param lmsTemplateId
+     */
+    public void setLmsTemplateId(String lmsTemplateId) {
+        this.lmsTemplateId = lmsTemplateId == null ? null : lmsTemplateId.trim();
+    }
+
+    /**
+     * @return LMS_Data
+     */
+    public String getLmsData() {
+        return lmsData;
+    }
+
+    /**
+     * @param lmsData
+     */
+    public void setLmsData(String lmsData) {
+        this.lmsData = lmsData == null ? null : lmsData.trim();
+    }
+
+    /**
+     * @return LMS_Time
+     */
+    public Date getLmsTime() {
+        return lmsTime;
+    }
+
+    /**
+     * @param lmsTime
+     */
+    public void setLmsTime(Date lmsTime) {
+        this.lmsTime = lmsTime;
+    }
+
+    /**
+     * @return LMS_Msg_Id
+     */
+    public String getLmsMsgId() {
+        return lmsMsgId;
+    }
+
+    /**
+     * @param lmsMsgId
+     */
+    public void setLmsMsgId(String lmsMsgId) {
+        this.lmsMsgId = lmsMsgId == null ? null : lmsMsgId.trim();
+    }
+
+    /**
+     * @return LMS_Result
+     */
+    public Boolean getLmsResult() {
+        return lmsResult;
+    }
+
+    /**
+     * @param lmsResult
+     */
+    public void setLmsResult(Boolean lmsResult) {
+        this.lmsResult = lmsResult;
+    }
+
+    /**
+     * @return LMS_Extension1
+     */
+    public String getLmsExtension1() {
+        return lmsExtension1;
+    }
+
+    /**
+     * @param lmsExtension1
+     */
+    public void setLmsExtension1(String lmsExtension1) {
+        this.lmsExtension1 = lmsExtension1 == null ? null : lmsExtension1.trim();
+    }
+
+    /**
+     * @return LMS_Extension2
+     */
+    public String getLmsExtension2() {
+        return lmsExtension2;
+    }
+
+    /**
+     * @param lmsExtension2
+     */
+    public void setLmsExtension2(String lmsExtension2) {
+        this.lmsExtension2 = lmsExtension2 == null ? null : lmsExtension2.trim();
+    }
+
+    /**
+     * @return LMS_Extension3
+     */
+    public String getLmsExtension3() {
+        return lmsExtension3;
+    }
+
+    /**
+     * @param lmsExtension3
+     */
+    public void setLmsExtension3(String lmsExtension3) {
+        this.lmsExtension3 = lmsExtension3 == null ? null : lmsExtension3.trim();
+    }
+
+    /**
+     * @return LMS_Remark
+     */
+    public String getLmsRemark() {
+        return lmsRemark;
+    }
+
+    /**
+     * @param lmsRemark
+     */
+    public void setLmsRemark(String lmsRemark) {
+        this.lmsRemark = lmsRemark == null ? null : lmsRemark.trim();
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/MsgSubscribeWx.java b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/MsgSubscribeWx.java
new file mode 100644
index 0000000..289911f
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/MsgSubscribeWx.java
@@ -0,0 +1,206 @@
+package cn.flightfeather.supervision.domain.entity;
+
+import java.util.Date;
+import javax.persistence.*;
+
+@Table(name = "ea_t_msg_subscribe_wx")
+public class MsgSubscribeWx {
+    @Id
+    @Column(name = "MS_ID")
+    private Integer msId;
+
+    /**
+     * 璁㈤槄鐨勬ā鏉縤d
+     */
+    @Column(name = "MS_Template_Id")
+    private String msTemplateId;
+
+    @Column(name = "MS_Open_Id")
+    private String msOpenId;
+
+    /**
+     * 鍓╀綑璁㈤槄娆℃暟
+     */
+    @Column(name = "MS_Count")
+    private Integer msCount;
+
+    /**
+     * 鏄惁鎺ユ敹鎺ㄩ��
+     */
+    @Column(name = "MS_Accept")
+    private Boolean msAccept;
+
+    /**
+     * 鏈�鏂版搷浣滄椂闂�
+     */
+    @Column(name = "MS_Update_Time")
+    private Date msUpdateTime;
+
+    @Column(name = "MS_Extension1")
+    private String msExtension1;
+
+    @Column(name = "MS_Extension2")
+    private String msExtension2;
+
+    @Column(name = "MS_Extension3")
+    private String msExtension3;
+
+    @Column(name = "MS_Remark")
+    private String msRemark;
+
+    /**
+     * @return MS_ID
+     */
+    public Integer getMsId() {
+        return msId;
+    }
+
+    /**
+     * @param msId
+     */
+    public void setMsId(Integer msId) {
+        this.msId = msId;
+    }
+
+    /**
+     * 鑾峰彇璁㈤槄鐨勬ā鏉縤d
+     *
+     * @return MS_Template_Id - 璁㈤槄鐨勬ā鏉縤d
+     */
+    public String getMsTemplateId() {
+        return msTemplateId;
+    }
+
+    /**
+     * 璁剧疆璁㈤槄鐨勬ā鏉縤d
+     *
+     * @param msTemplateId 璁㈤槄鐨勬ā鏉縤d
+     */
+    public void setMsTemplateId(String msTemplateId) {
+        this.msTemplateId = msTemplateId == null ? null : msTemplateId.trim();
+    }
+
+    /**
+     * @return MS_Open_Id
+     */
+    public String getMsOpenId() {
+        return msOpenId;
+    }
+
+    /**
+     * @param msOpenId
+     */
+    public void setMsOpenId(String msOpenId) {
+        this.msOpenId = msOpenId == null ? null : msOpenId.trim();
+    }
+
+    /**
+     * 鑾峰彇鍓╀綑璁㈤槄娆℃暟
+     *
+     * @return MS_Count - 鍓╀綑璁㈤槄娆℃暟
+     */
+    public Integer getMsCount() {
+        return msCount;
+    }
+
+    /**
+     * 璁剧疆鍓╀綑璁㈤槄娆℃暟
+     *
+     * @param msCount 鍓╀綑璁㈤槄娆℃暟
+     */
+    public void setMsCount(Integer msCount) {
+        this.msCount = msCount;
+    }
+
+    /**
+     * 鑾峰彇鏄惁鎺ユ敹鎺ㄩ��
+     *
+     * @return MS_Accept - 鏄惁鎺ユ敹鎺ㄩ��
+     */
+    public Boolean getMsAccept() {
+        return msAccept;
+    }
+
+    /**
+     * 璁剧疆鏄惁鎺ユ敹鎺ㄩ��
+     *
+     * @param msAccept 鏄惁鎺ユ敹鎺ㄩ��
+     */
+    public void setMsAccept(Boolean msAccept) {
+        this.msAccept = msAccept;
+    }
+
+    /**
+     * 鑾峰彇鏈�鏂版搷浣滄椂闂�
+     *
+     * @return MS_Update_Time - 鏈�鏂版搷浣滄椂闂�
+     */
+    public Date getMsUpdateTime() {
+        return msUpdateTime;
+    }
+
+    /**
+     * 璁剧疆鏈�鏂版搷浣滄椂闂�
+     *
+     * @param msUpdateTime 鏈�鏂版搷浣滄椂闂�
+     */
+    public void setMsUpdateTime(Date msUpdateTime) {
+        this.msUpdateTime = msUpdateTime;
+    }
+
+    /**
+     * @return MS_Extension1
+     */
+    public String getMsExtension1() {
+        return msExtension1;
+    }
+
+    /**
+     * @param msExtension1
+     */
+    public void setMsExtension1(String msExtension1) {
+        this.msExtension1 = msExtension1 == null ? null : msExtension1.trim();
+    }
+
+    /**
+     * @return MS_Extension2
+     */
+    public String getMsExtension2() {
+        return msExtension2;
+    }
+
+    /**
+     * @param msExtension2
+     */
+    public void setMsExtension2(String msExtension2) {
+        this.msExtension2 = msExtension2 == null ? null : msExtension2.trim();
+    }
+
+    /**
+     * @return MS_Extension3
+     */
+    public String getMsExtension3() {
+        return msExtension3;
+    }
+
+    /**
+     * @param msExtension3
+     */
+    public void setMsExtension3(String msExtension3) {
+        this.msExtension3 = msExtension3 == null ? null : msExtension3.trim();
+    }
+
+    /**
+     * @return MS_Remark
+     */
+    public String getMsRemark() {
+        return msRemark;
+    }
+
+    /**
+     * @param msRemark
+     */
+    public void setMsRemark(String msRemark) {
+        this.msRemark = msRemark == null ? null : msRemark.trim();
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/PersonalInfo.java b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/PersonalInfo.java
new file mode 100644
index 0000000..291f278
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/PersonalInfo.java
@@ -0,0 +1,243 @@
+package cn.flightfeather.supervision.domain.entity;
+
+import javax.persistence.*;
+
+@Table(name = "ea_t_personal_info")
+public class PersonalInfo {
+    /**
+     * 涓汉淇℃伅id
+     */
+    @Id
+    @Column(name = "PI_GUID")
+    private String piGuid;
+
+    /**
+     * 濮撳悕
+     */
+    @Column(name = "PI_Name")
+    private String piName;
+
+    /**
+     * 涓汉璇佷欢绫诲瀷id
+     */
+    @Column(name = "PI_ID_Type_Num")
+    private Byte piIdTypeNum;
+
+    /**
+     * 涓汉璇佷欢绫诲瀷
+     */
+    @Column(name = "PI_ID_Type")
+    private String piIdType;
+
+    /**
+     * 璇佷欢缂栧彿
+     */
+    @Column(name = "PI_ID")
+    private String piId;
+
+    /**
+     * 鑱屼綅缂栧彿
+     */
+    @Column(name = "PI_Position_Num")
+    private Byte piPositionNum;
+
+    /**
+     * 鑱屼綅
+     */
+    @Column(name = "PI_Position")
+    private String piPosition;
+
+    @Column(name = "PI_Extension1")
+    private String piExtension1;
+
+    @Column(name = "PI_Extension2")
+    private String piExtension2;
+
+    @Column(name = "PI_Extension3")
+    private String piExtension3;
+
+    @Column(name = "PI_Remark")
+    private String piRemark;
+
+    /**
+     * 鑾峰彇涓汉淇℃伅id
+     *
+     * @return PI_GUID - 涓汉淇℃伅id
+     */
+    public String getPiGuid() {
+        return piGuid;
+    }
+
+    /**
+     * 璁剧疆涓汉淇℃伅id
+     *
+     * @param piGuid 涓汉淇℃伅id
+     */
+    public void setPiGuid(String piGuid) {
+        this.piGuid = piGuid == null ? null : piGuid.trim();
+    }
+
+    /**
+     * 鑾峰彇濮撳悕
+     *
+     * @return PI_Name - 濮撳悕
+     */
+    public String getPiName() {
+        return piName;
+    }
+
+    /**
+     * 璁剧疆濮撳悕
+     *
+     * @param piName 濮撳悕
+     */
+    public void setPiName(String piName) {
+        this.piName = piName == null ? null : piName.trim();
+    }
+
+    /**
+     * 鑾峰彇涓汉璇佷欢绫诲瀷id
+     *
+     * @return PI_ID_Type_Num - 涓汉璇佷欢绫诲瀷id
+     */
+    public Byte getPiIdTypeNum() {
+        return piIdTypeNum;
+    }
+
+    /**
+     * 璁剧疆涓汉璇佷欢绫诲瀷id
+     *
+     * @param piIdTypeNum 涓汉璇佷欢绫诲瀷id
+     */
+    public void setPiIdTypeNum(Byte piIdTypeNum) {
+        this.piIdTypeNum = piIdTypeNum;
+    }
+
+    /**
+     * 鑾峰彇涓汉璇佷欢绫诲瀷
+     *
+     * @return PI_ID_Type - 涓汉璇佷欢绫诲瀷
+     */
+    public String getPiIdType() {
+        return piIdType;
+    }
+
+    /**
+     * 璁剧疆涓汉璇佷欢绫诲瀷
+     *
+     * @param piIdType 涓汉璇佷欢绫诲瀷
+     */
+    public void setPiIdType(String piIdType) {
+        this.piIdType = piIdType == null ? null : piIdType.trim();
+    }
+
+    /**
+     * 鑾峰彇璇佷欢缂栧彿
+     *
+     * @return PI_ID - 璇佷欢缂栧彿
+     */
+    public String getPiId() {
+        return piId;
+    }
+
+    /**
+     * 璁剧疆璇佷欢缂栧彿
+     *
+     * @param piId 璇佷欢缂栧彿
+     */
+    public void setPiId(String piId) {
+        this.piId = piId == null ? null : piId.trim();
+    }
+
+    /**
+     * 鑾峰彇鑱屼綅缂栧彿
+     *
+     * @return PI_Position_Num - 鑱屼綅缂栧彿
+     */
+    public Byte getPiPositionNum() {
+        return piPositionNum;
+    }
+
+    /**
+     * 璁剧疆鑱屼綅缂栧彿
+     *
+     * @param piPositionNum 鑱屼綅缂栧彿
+     */
+    public void setPiPositionNum(Byte piPositionNum) {
+        this.piPositionNum = piPositionNum;
+    }
+
+    /**
+     * 鑾峰彇鑱屼綅
+     *
+     * @return PI_Position - 鑱屼綅
+     */
+    public String getPiPosition() {
+        return piPosition;
+    }
+
+    /**
+     * 璁剧疆鑱屼綅
+     *
+     * @param piPosition 鑱屼綅
+     */
+    public void setPiPosition(String piPosition) {
+        this.piPosition = piPosition == null ? null : piPosition.trim();
+    }
+
+    /**
+     * @return PI_Extension1
+     */
+    public String getPiExtension1() {
+        return piExtension1;
+    }
+
+    /**
+     * @param piExtension1
+     */
+    public void setPiExtension1(String piExtension1) {
+        this.piExtension1 = piExtension1 == null ? null : piExtension1.trim();
+    }
+
+    /**
+     * @return PI_Extension2
+     */
+    public String getPiExtension2() {
+        return piExtension2;
+    }
+
+    /**
+     * @param piExtension2
+     */
+    public void setPiExtension2(String piExtension2) {
+        this.piExtension2 = piExtension2 == null ? null : piExtension2.trim();
+    }
+
+    /**
+     * @return PI_Extension3
+     */
+    public String getPiExtension3() {
+        return piExtension3;
+    }
+
+    /**
+     * @param piExtension3
+     */
+    public void setPiExtension3(String piExtension3) {
+        this.piExtension3 = piExtension3 == null ? null : piExtension3.trim();
+    }
+
+    /**
+     * @return PI_Remark
+     */
+    public String getPiRemark() {
+        return piRemark;
+    }
+
+    /**
+     * @param piRemark
+     */
+    public void setPiRemark(String piRemark) {
+        this.piRemark = piRemark == null ? null : piRemark.trim();
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/RestaurantBaseInfo.java b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/RestaurantBaseInfo.java
index eac6309..1227455 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/RestaurantBaseInfo.java
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/RestaurantBaseInfo.java
@@ -1,12 +1,9 @@
 package cn.flightfeather.supervision.domain.entity;
 
-import com.fasterxml.jackson.annotation.JsonInclude;
-
 import javax.persistence.*;
 
 @Table(name = "ea_t_restaurant_base_info")
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class RestaurantBaseInfo implements BaseSpecialInfo {
+public class RestaurantBaseInfo implements BaseSpecialInfo{
     @Id
     @Column(name = "RB_GUID")
     private String rbGuid;
@@ -118,6 +115,24 @@
      */
     @Column(name = "RB_Concentration_Area")
     private String rbConcentrationArea;
+
+    /**
+     * 鎺掑彛鏁伴噺
+     */
+    @Column(name = "RB_Outfall_Count")
+    private Integer rbOutfallCount;
+
+    /**
+     * 鎺掑彛浣嶇疆
+     */
+    @Column(name = "RB_Outfall_Location")
+    private String rbOutfallLocation;
+
+    /**
+     * 鎺掑彛缂栧彿
+     */
+    @Column(name = "RB_Outfall_Num")
+    private String rbOutfallNum;
 
     @Column(name = "RB_Extension1")
     private String rbExtension1;
@@ -470,6 +485,60 @@
     }
 
     /**
+     * 鑾峰彇鎺掑彛鏁伴噺
+     *
+     * @return RB_Outfall_Count - 鎺掑彛鏁伴噺
+     */
+    public Integer getRbOutfallCount() {
+        return rbOutfallCount;
+    }
+
+    /**
+     * 璁剧疆鎺掑彛鏁伴噺
+     *
+     * @param rbOutfallCount 鎺掑彛鏁伴噺
+     */
+    public void setRbOutfallCount(Integer rbOutfallCount) {
+        this.rbOutfallCount = rbOutfallCount;
+    }
+
+    /**
+     * 鑾峰彇鎺掑彛浣嶇疆
+     *
+     * @return RB_Outfall_Location - 鎺掑彛浣嶇疆
+     */
+    public String getRbOutfallLocation() {
+        return rbOutfallLocation;
+    }
+
+    /**
+     * 璁剧疆鎺掑彛浣嶇疆
+     *
+     * @param rbOutfallLocation 鎺掑彛浣嶇疆
+     */
+    public void setRbOutfallLocation(String rbOutfallLocation) {
+        this.rbOutfallLocation = rbOutfallLocation == null ? null : rbOutfallLocation.trim();
+    }
+
+    /**
+     * 鑾峰彇鎺掑彛缂栧彿
+     *
+     * @return RB_Outfall_Num - 鎺掑彛缂栧彿
+     */
+    public String getRbOutfallNum() {
+        return rbOutfallNum;
+    }
+
+    /**
+     * 璁剧疆鎺掑彛缂栧彿
+     *
+     * @param rbOutfallNum 鎺掑彛缂栧彿
+     */
+    public void setRbOutfallNum(String rbOutfallNum) {
+        this.rbOutfallNum = rbOutfallNum == null ? null : rbOutfallNum.trim();
+    }
+
+    /**
      * @return RB_Extension1
      */
     public String getRbExtension1() {
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/UserInfoWx.java b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/UserInfoWx.java
index a906aec..d88ce2b 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/UserInfoWx.java
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/UserInfoWx.java
@@ -4,13 +4,28 @@
 
 @Table(name = "sm_t_userinfo_wx")
 public class UserInfoWx {
-    @Column(name = "UI_GUID")
-    private String uiGuid;
-
+    /**
+     * 寰俊id
+     */
     @Id
     @Column(name = "UI_Open_Id")
     private String uiOpenId;
 
+    /**
+     * 鍦烘櫙id
+     */
+    @Column(name = "UI_GUID")
+    private String uiGuid;
+
+    /**
+     * 浼佷笟id
+     */
+    @Column(name = "CI_GUID")
+    private String ciGuid;
+
+    /**
+     * 寰俊鏄电О
+     */
     @Column(name = "UI_Nick_Name")
     private String uiNickName;
 
@@ -26,49 +41,91 @@
     @Column(name = "UI_City")
     private String uiCity;
 
+    /**
+     * 寰俊澶村儚
+     */
     @Column(name = "UI_Avatar_Url")
     private String uiAvatarUrl;
 
+    /**
+     * 寰俊浼氳瘽sessionId
+     */
     @Column(name = "UI_UnionId")
     private String uiUnionid;
 
     /**
-     * @return UI_GUID
+     * 涓汉淇℃伅id
      */
-    public String getUiGuid() {
-        return uiGuid;
-    }
+    @Column(name = "PI_GUID")
+    private String piGuid;
 
     /**
-     * @param uiGuid
-     */
-    public void setUiGuid(String uiGuid) {
-        this.uiGuid = uiGuid == null ? null : uiGuid.trim();
-    }
-
-    /**
-     * @return UI_Open_Id
+     * 鑾峰彇寰俊id
+     *
+     * @return UI_Open_Id - 寰俊id
      */
     public String getUiOpenId() {
         return uiOpenId;
     }
 
     /**
-     * @param uiOpenId
+     * 璁剧疆寰俊id
+     *
+     * @param uiOpenId 寰俊id
      */
     public void setUiOpenId(String uiOpenId) {
         this.uiOpenId = uiOpenId == null ? null : uiOpenId.trim();
     }
 
     /**
-     * @return UI_Nick_Name
+     * 鑾峰彇鍦烘櫙id
+     *
+     * @return UI_GUID - 鍦烘櫙id
+     */
+    public String getUiGuid() {
+        return uiGuid;
+    }
+
+    /**
+     * 璁剧疆鍦烘櫙id
+     *
+     * @param uiGuid 鍦烘櫙id
+     */
+    public void setUiGuid(String uiGuid) {
+        this.uiGuid = uiGuid == null ? null : uiGuid.trim();
+    }
+
+    /**
+     * 鑾峰彇浼佷笟id
+     *
+     * @return CI_GUID - 浼佷笟id
+     */
+    public String getCiGuid() {
+        return ciGuid;
+    }
+
+    /**
+     * 璁剧疆浼佷笟id
+     *
+     * @param ciGuid 浼佷笟id
+     */
+    public void setCiGuid(String ciGuid) {
+        this.ciGuid = ciGuid == null ? null : ciGuid.trim();
+    }
+
+    /**
+     * 鑾峰彇寰俊鏄电О
+     *
+     * @return UI_Nick_Name - 寰俊鏄电О
      */
     public String getUiNickName() {
         return uiNickName;
     }
 
     /**
-     * @param uiNickName
+     * 璁剧疆寰俊鏄电О
+     *
+     * @param uiNickName 寰俊鏄电О
      */
     public void setUiNickName(String uiNickName) {
         this.uiNickName = uiNickName == null ? null : uiNickName.trim();
@@ -131,30 +188,56 @@
     }
 
     /**
-     * @return UI_Avatar_Url
+     * 鑾峰彇寰俊澶村儚
+     *
+     * @return UI_Avatar_Url - 寰俊澶村儚
      */
     public String getUiAvatarUrl() {
         return uiAvatarUrl;
     }
 
     /**
-     * @param uiAvatarUrl
+     * 璁剧疆寰俊澶村儚
+     *
+     * @param uiAvatarUrl 寰俊澶村儚
      */
     public void setUiAvatarUrl(String uiAvatarUrl) {
         this.uiAvatarUrl = uiAvatarUrl == null ? null : uiAvatarUrl.trim();
     }
 
     /**
-     * @return UI_UnionId
+     * 鑾峰彇寰俊浼氳瘽sessionId
+     *
+     * @return UI_UnionId - 寰俊浼氳瘽sessionId
      */
     public String getUiUnionid() {
         return uiUnionid;
     }
 
     /**
-     * @param uiUnionid
+     * 璁剧疆寰俊浼氳瘽sessionId
+     *
+     * @param uiUnionid 寰俊浼氳瘽sessionId
      */
     public void setUiUnionid(String uiUnionid) {
         this.uiUnionid = uiUnionid == null ? null : uiUnionid.trim();
     }
+
+    /**
+     * 鑾峰彇涓汉淇℃伅id
+     *
+     * @return PI_GUID - 涓汉淇℃伅id
+     */
+    public String getPiGuid() {
+        return piGuid;
+    }
+
+    /**
+     * 璁剧疆涓汉淇℃伅id
+     *
+     * @param piGuid 涓汉淇℃伅id
+     */
+    public void setPiGuid(String piGuid) {
+        this.piGuid = piGuid == null ? null : piGuid.trim();
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/Userinfo.kt b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/Userinfo.kt
index d9390a1..9342e1b 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/domain/entity/Userinfo.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/entity/Userinfo.kt
@@ -1,13 +1,14 @@
 package cn.flightfeather.supervision.domain.entity
 
 import com.fasterxml.jackson.annotation.JsonInclude
+import java.util.*
 import javax.persistence.Column
 import javax.persistence.Id
 import javax.persistence.Table
 
 @Table(name = "sm_t_userinfo")
 @JsonInclude(JsonInclude.Include.NON_NULL)
-open class  Userinfo {
+open class Userinfo {
     @Id
     @Column(name = "UI_GUID")
     var guid: String? = null
@@ -28,7 +29,7 @@
     var password: String? = null
 
     /**
-     *
+     * 鍊煎煙琛ㄤ腑鑾峰彇锛�1锛氭垜鍙哥敤鎴凤紱2锛氳鐩戠瀵硅薄鍗曚綅鐢ㄦ埛锛�3锛氫富绠¢儴闂ㄧ敤鎴凤級
      */
     @Column(name = "UI_UserTypeID")
     var usertypeid: Byte? = null
@@ -57,6 +58,12 @@
     @Column(name = "UI_WechatID")
     var wechatid: String? = null
 
+    @Column(name = "UI_Create_Time")
+    var uiCreateTime: Date? = null
+
+    @Column(name = "UI_Login_Time")
+    var uiLoginTime: Date? = null
+
     @Column(name = "UI_Extension1")
     var extension1: String? = null
 
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/enumeration/AuthenticationStatus.kt b/src/main/kotlin/cn/flightfeather/supervision/domain/enumeration/AuthenticationStatus.kt
new file mode 100644
index 0000000..2ecd7a0
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/enumeration/AuthenticationStatus.kt
@@ -0,0 +1,9 @@
+package cn.flightfeather.supervision.domain.enumeration
+
+/**
+ * 鐢ㄦ埛璁よ瘉鐘舵��
+ */
+enum class AuthenticationStatus(val value: Byte, val des: String) {
+    YES(1, "authenticated"),
+    NO(0, "unauthorized")
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/LogMsgSubscribeWxMapper.kt b/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/LogMsgSubscribeWxMapper.kt
new file mode 100644
index 0000000..3410900
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/LogMsgSubscribeWxMapper.kt
@@ -0,0 +1,8 @@
+package cn.flightfeather.supervision.domain.mapper
+
+import cn.flightfeather.supervision.domain.entity.LogMsgSubscribeWx
+import cn.flightfeather.supervision.domain.util.MyMapper
+import org.apache.ibatis.annotations.Mapper
+
+@Mapper
+interface LogMsgSubscribeWxMapper : MyMapper<LogMsgSubscribeWx?>
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/MsgSubscribeWxMapper.kt b/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/MsgSubscribeWxMapper.kt
new file mode 100644
index 0000000..2645521
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/MsgSubscribeWxMapper.kt
@@ -0,0 +1,8 @@
+package cn.flightfeather.supervision.domain.mapper
+
+import cn.flightfeather.supervision.domain.entity.MsgSubscribeWx
+import cn.flightfeather.supervision.domain.util.MyMapper
+import org.apache.ibatis.annotations.Mapper
+
+@Mapper
+interface MsgSubscribeWxMapper : MyMapper<MsgSubscribeWx?>
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/PersonalInfoMapper.kt b/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/PersonalInfoMapper.kt
new file mode 100644
index 0000000..6f1201c
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/domain/mapper/PersonalInfoMapper.kt
@@ -0,0 +1,8 @@
+package cn.flightfeather.supervision.domain.mapper
+
+import cn.flightfeather.supervision.domain.entity.PersonalInfo
+import cn.flightfeather.supervision.domain.util.MyMapper
+import org.apache.ibatis.annotations.Mapper
+
+@Mapper
+interface PersonalInfoMapper : MyMapper<PersonalInfo?>
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/infrastructure/utils/PinYin.kt b/src/main/kotlin/cn/flightfeather/supervision/infrastructure/utils/PinYin.kt
new file mode 100644
index 0000000..e883c26
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/infrastructure/utils/PinYin.kt
@@ -0,0 +1,58 @@
+package cn.flightfeather.supervision.infrastructure.utils
+
+import net.sourceforge.pinyin4j.PinyinHelper
+
+class PinYin {
+
+    companion object{
+        fun getPinYinHeader(str: String): String {
+
+            val temp = str.trim()
+            val result = StringBuilder()
+            for (i in temp.indices) {
+                if (i >= 6) {
+                    break
+                }
+                val it = temp[i]
+                if (it in 'a'..'z' || it in 'A'..'Z' || it in '0'..'9') {
+                    result.append(it.toString()) //濡傛灉瀛楃涓叉槸鑻辨枃涓嶆敼鍙�
+                } else {
+                    PinyinHelper.toHanyuPinyinStringArray(it)?.let { pinyin ->
+                        result.append(pinyin[0].elementAt(0) + "")
+                    }
+                }
+            }
+
+            return result.toString()
+        }
+
+        /**
+         * 绗竴涓枃瀛楄幏鍙栧畬鏁存嫾闊筹紝涔嬪悗鐨勫彧鍙栭瀛楁瘝
+         */
+        fun getPinYinHeader2(str: String): Array<String>? {
+            val temp = str.trim()
+            val result = mutableListOf<String>()
+            var i = 0
+            temp.forEach {
+                //                if (i >= 6) {
+//                    return@forEach
+//                }
+                if (it in 'a'..'z' || it in 'A'..'Z' || it in '0'..'9') {
+                    result.add(it.toString()) //濡傛灉瀛楃涓叉槸鑻辨枃涓嶆敼鍙�
+                } else {
+                    PinyinHelper.toHanyuPinyinStringArray(it)?.let { pinyin ->
+                        if (i == 0) {
+                            result.add(pinyin[0].dropLast(1))
+                        } else {
+                            result.add(pinyin[0].elementAt(0) + "")
+                        }
+                    }
+                }
+                i++
+            }
+
+            return result.toTypedArray()
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/AuthService.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/AuthService.kt
new file mode 100644
index 0000000..40102da
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/AuthService.kt
@@ -0,0 +1,33 @@
+package cn.flightfeather.supervision.lightshare.service
+
+import cn.flightfeather.supervision.domain.entity.Company
+import cn.flightfeather.supervision.domain.entity.PersonalInfo
+import cn.flightfeather.supervision.domain.enumeration.SceneType
+import cn.flightfeather.supervision.lightshare.vo.AuthSceneVo
+import cn.flightfeather.supervision.lightshare.vo.BaseResponse
+
+interface AuthService {
+
+    fun authCompany(wxUserId: String, company: Company): BaseResponse<String>
+
+    /**
+     * 鐢ㄦ埛鍦烘櫙璁よ瘉
+     * @param wxUserId 寰俊鐢ㄦ埛openId
+     * @param sceneType 鍦烘櫙绫诲瀷锛孾SceneType.value]
+     * @param sceneInfo 鍦烘櫙淇℃伅锛孾AuthSceneVo]
+     * @see SceneType
+     * @see AuthSceneVo
+     * @return 璁よ瘉鎴愬姛涓庡惁
+     */
+    fun authScene(wxUserId: String, sceneType: Int, sceneInfo: String): BaseResponse<String>
+
+    fun authPersonal(wxUserId: String, personalInfo: PersonalInfo): BaseResponse<String>
+
+    /**
+     * 鑾峰彇鐢ㄦ埛璁よ瘉鐘舵��
+     * @param wxUserId 寰俊鐢ㄦ埛openId
+     * @param userId 鍦烘櫙鐢ㄦ埛id
+     * @return 璁よ瘉鐘舵�侊紝 [浼佷笟璁よ瘉鐘舵��, 鍦烘櫙璁よ瘉鐘舵��, 涓汉璁よ瘉鐘舵�乚
+     */
+    fun authStatus(wxUserId: String?, userId: String?): BaseResponse<List<Boolean>>
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/AuthServiceImpl.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/AuthServiceImpl.kt
new file mode 100644
index 0000000..7262457
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/AuthServiceImpl.kt
@@ -0,0 +1,224 @@
+package cn.flightfeather.supervision.lightshare.service.Impl
+
+import cn.flightfeather.supervision.domain.entity.*
+import cn.flightfeather.supervision.domain.enumeration.AuthenticationStatus
+import cn.flightfeather.supervision.domain.enumeration.SceneType
+import cn.flightfeather.supervision.domain.mapper.*
+import cn.flightfeather.supervision.infrastructure.utils.PinYin
+import cn.flightfeather.supervision.infrastructure.utils.UUIDGenerator
+import cn.flightfeather.supervision.lightshare.service.AuthService
+import cn.flightfeather.supervision.lightshare.vo.AuthSceneRestVo
+import cn.flightfeather.supervision.lightshare.vo.AuthSceneVo
+import cn.flightfeather.supervision.lightshare.vo.BaseResponse
+import com.google.gson.Gson
+import org.springframework.stereotype.Service
+import org.springframework.transaction.annotation.Transactional
+import tk.mybatis.mapper.entity.Example
+
+@Service
+class AuthServiceImpl(
+    private val userinfoMapper: UserinfoMapper,
+    private val userInfoWxMapper: UserInfoWxMapper,
+    private val companyMapper: CompanyMapper,
+    private val personalInfoMapper: PersonalInfoMapper,
+    private val baseInfoMapper: BaseInfoMapper,
+    private val fumePurifyDeviceMapper: FumePurifyDeviceMapper,
+    private val monitorDeviceMapper: MonitorDeviceMapper,
+    private val restaurantBaseInfoMapper: RestaurantBaseInfoMapper,
+    private val vehicleBaseInfoMapper: VehicleBaseInfoMapper
+): AuthService {
+
+    @Transactional
+    override fun authCompany(wxUserId: String, company: Company): BaseResponse<String> {
+        val wxUser = userInfoWxMapper.selectByPrimaryKey(wxUserId) ?: return BaseResponse(false, "鐢ㄦ埛寰俊id涓嶅瓨鍦�")
+        company.ciExtension3 = AuthenticationStatus.YES.des
+        if (company.ciGuid == null) {
+            company.ciGuid = UUIDGenerator.generate16ShortUUID()
+            companyMapper.insert(company)
+        } else {
+            companyMapper.updateByPrimaryKeySelective(company)
+        }
+        val bInfo = if (wxUser.uiGuid == null) null else baseInfoMapper.selectByPrimaryKey(wxUser.uiGuid)
+        if (bInfo != null && bInfo.ciGuid != company.ciGuid) {
+            bInfo.ciGuid = company.ciGuid
+            bInfo.ciName = company.ciName
+            baseInfoMapper.updateByPrimaryKeySelective(bInfo)
+        }
+        if (wxUser.ciGuid != company.ciGuid) {
+            wxUser.ciGuid = company.ciGuid
+            userInfoWxMapper.updateByPrimaryKeySelective(wxUser)
+        }
+        return BaseResponse(true)
+    }
+
+    @Transactional
+    override fun authScene(wxUserId: String, sceneType: Int, sceneInfo: String): BaseResponse<String> {
+//        val user = userinfoMapper.selectByPrimaryKey(userId) ?: return BaseResponse(false, "鐢ㄦ埛鍦烘櫙id涓嶅瓨鍦�")
+        val wxUser = userInfoWxMapper.selectByPrimaryKey(wxUserId) ?: return BaseResponse(false, "鐢ㄦ埛寰俊id涓嶅瓨鍦�")
+        val gson = Gson()
+        // 鎵�鏈夊満鏅粺涓�鐨勫熀纭�淇℃伅
+        val asVo = gson.fromJson(sceneInfo, AuthSceneVo::class.java)
+        var bInfo = if (wxUser.uiGuid == null) null else baseInfoMapper.selectByPrimaryKey(wxUser.uiGuid)
+        if (bInfo == null) {
+            val cInfo = if (wxUser.ciGuid == null) null else companyMapper.selectByPrimaryKey(wxUser.ciGuid)
+            val name = getUName(asVo.biName ?: "")
+            //鏂板缓鍦烘櫙璐﹀彿鍙婂満鏅俊鎭�
+            val newUser = Userinfo().apply {
+                guid = UUIDGenerator.generate16ShortUUID()
+                acountname = name
+                realname = asVo.biName
+                password = "123456"
+                usertypeid = 3
+                usertype = "浼佷笟"
+                isenable = true
+                if (asVo.biLocation.isNotEmpty()) extension1 = asVo.biLocation[2]
+                extension2 = sceneType.toString()
+            }
+            bInfo = asVo.toNewBaseInfo(newUser, cInfo)
+            userinfoMapper.insert(newUser)
+            baseInfoMapper.insert(bInfo)
+        } else {
+            val userInfo = userinfoMapper.selectByPrimaryKey(bInfo.biGuid)
+            userInfo.apply {
+                realname = asVo.biName
+                if (asVo.biLocation.isNotEmpty()) extension1 = asVo.biLocation[2]
+            }
+            asVo.updateBaseInfo(bInfo)
+            userinfoMapper.updateByPrimaryKeySelective(userInfo)
+            baseInfoMapper.updateByPrimaryKeySelective(bInfo)
+        }
+        val userId = bInfo.biGuid
+        when (sceneType) {
+            SceneType.Restaurant.value -> {
+                val info = gson.fromJson(sceneInfo, AuthSceneRestVo::class.java)
+                //椁愰ギ搴楀熀鏈俊鎭綍鍏�
+                var rbInfo = restaurantBaseInfoMapper.selectByPrimaryKey(userId)
+                if (rbInfo == null) {
+                    rbInfo = info.toNewRestInfo(userId)
+                    restaurantBaseInfoMapper.insert(rbInfo)
+                } else {
+                    info.updateRestInfo(rbInfo)
+                    restaurantBaseInfoMapper.updateByPrimaryKeySelective(rbInfo)
+                }
+                //椁愰ギ搴楁补鐑熷噣鍖栬缃俊鎭綍鍏�
+                var fpdInfo = fumePurifyDeviceMapper.selectByExample(Example(FumePurifyDevice::class.java).apply {
+                    createCriteria().andEqualTo("fpUserId", userId)
+                })?.takeIf { it.isNotEmpty() }?.get(0)
+                if (fpdInfo == null) {
+                    fpdInfo = info.toNewFpdInfo(bInfo)
+                    fumePurifyDeviceMapper.insert(fpdInfo)
+                } else {
+                    info.updateFpdInfo(fpdInfo)
+                    fumePurifyDeviceMapper.updateByPrimaryKeySelective(fpdInfo)
+                }
+                //椁愰ギ搴楁补鐑熺洃娴嬭澶囦俊鎭綍鍏�
+                var mdInfo = monitorDeviceMapper.selectByExample(Example(MonitorDevice::class.java).apply {
+                    createCriteria().andEqualTo("mdUserId", userId)
+                })?.takeIf { it.isNotEmpty() }?.get(0)
+                if (mdInfo == null) {
+                    mdInfo = info.toNewMdInfo(bInfo)
+                    monitorDeviceMapper.insert(mdInfo)
+                } else {
+                    info.updateMdInfo(mdInfo)
+                    monitorDeviceMapper.updateByPrimaryKeySelective(mdInfo)
+                }
+            }
+            SceneType.Construction.value -> {
+                val info = gson.fromJson(sceneInfo, AuthSceneVo::class.java)
+            }
+            SceneType.Wharf.value -> {
+                val info = gson.fromJson(sceneInfo, AuthSceneVo::class.java)
+            }
+            SceneType.StorageYard.value -> {
+                val info = gson.fromJson(sceneInfo, AuthSceneVo::class.java)
+            }
+            SceneType.MixingPlant.value -> {
+                val info = gson.fromJson(sceneInfo, AuthSceneVo::class.java)
+            }
+            SceneType.Industrial.value -> {
+                val info = gson.fromJson(sceneInfo, AuthSceneVo::class.java)
+            }
+            SceneType.VehicleRepair.value -> {
+                val info = gson.fromJson(sceneInfo, AuthSceneVo::class.java)
+            }
+            else-> return BaseResponse(false, "鐢ㄦ埛鍦烘櫙绫诲瀷閿欒")
+        }
+
+        return BaseResponse(true, "鍦烘櫙璁よ瘉瀹屾垚")
+    }
+
+    override fun authPersonal(wxUserId: String, personalInfo: PersonalInfo): BaseResponse<String> {
+        val wxUser = userInfoWxMapper.selectByPrimaryKey(wxUserId) ?: return BaseResponse(false, "鐢ㄦ埛寰俊id涓嶅瓨鍦�")
+        personalInfo.piExtension3 = AuthenticationStatus.YES.des
+        if (personalInfo.piGuid == null) {
+            personalInfo.piGuid = UUIDGenerator.generate16ShortUUID()
+            personalInfoMapper.insert(personalInfo)
+        } else {
+            personalInfoMapper.updateByPrimaryKeySelective(personalInfo)
+        }
+        if (wxUser.piGuid != personalInfo.piGuid) {
+            wxUser.piGuid = personalInfo.piGuid
+            userInfoWxMapper.updateByPrimaryKeySelective(wxUser)
+        }
+        return BaseResponse(true)
+    }
+
+    override fun authStatus(wxUserId: String?, userId: String?): BaseResponse<List<Boolean>> {
+        val status = mutableListOf(false, false, false)
+        if (wxUserId != null) {
+            val wxUser = userInfoWxMapper.selectByPrimaryKey(wxUserId) ?: return BaseResponse(false, "璇ュ井淇¤处鎴蜂笉瀛樺湪")
+            //鍒ゆ柇浼佷笟淇℃伅鏄惁璁よ瘉
+            if (wxUser.ciGuid != null) {
+                companyMapper.selectByPrimaryKey(wxUser.ciGuid)?.let { c ->
+                    if (c.ciExtension3 == AuthenticationStatus.YES.des) status[0] = true
+                }
+            }
+            //鍒ゆ柇鍦烘櫙淇℃伅鏄惁璁よ瘉
+            if (wxUser.uiGuid != null) {
+                baseInfoMapper.selectByPrimaryKey(wxUser.uiGuid)?.let {b ->
+                    if (b.biExtension3 == AuthenticationStatus.YES.des) status[1] = true
+                }
+            }
+            //鍒ゆ柇涓汉淇℃伅鏄惁璁よ瘉
+            if (wxUser.piGuid != null) {
+                personalInfoMapper.selectByPrimaryKey(wxUser.piGuid)?.let { p ->
+                    if (p.piExtension3 == AuthenticationStatus.YES.des) status[2] = true
+                }
+            }
+        }else if (userId != null) {
+            val user = userinfoMapper.selectByPrimaryKey(userId) ?: return BaseResponse(false, "璇ュ満鏅处鎴蜂笉瀛樺湪")
+            val baseInfo = baseInfoMapper.selectByPrimaryKey(userId)
+            //鍒ゆ柇浼佷笟淇℃伅鏄惁璁よ瘉
+            if (baseInfo?.ciGuid != null) {
+                companyMapper.selectByPrimaryKey(baseInfo.ciGuid)?.let { c ->
+                    if (c.ciExtension3 == AuthenticationStatus.YES.des) status[0] = true
+                }
+            }
+            //鍒ゆ柇鍦烘櫙淇℃伅鏄惁璁よ瘉
+            if (baseInfo?.biExtension3 == AuthenticationStatus.YES.des) status[1] = true
+            //鍒ゆ柇涓汉淇℃伅鏄惁璁よ瘉
+            // TODO: 2022/10/11 姝ゅ垎鏀笅鏆傛椂鏃犱釜浜鸿璇�
+        }
+
+        return BaseResponse(true, data = status)
+    }
+
+    private fun getUName(sceneName: String): String {
+        var uName = if (sceneName.isNotBlank()) PinYin.getPinYinHeader(sceneName) else UUIDGenerator.generateShortUUID()
+        var repeated = false
+        var i = 1
+        do {
+            userinfoMapper.selectByExample(Example(Userinfo::class.java).apply {
+                createCriteria().andEqualTo("acountname", uName)
+            }).let {
+                repeated = it.isNotEmpty()
+                if (repeated) {
+                    uName += i
+                }
+            }
+            i++
+        } while (repeated && i < 20)
+        if (repeated) uName = UUIDGenerator.generateShortUUID()
+        return uName
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/LedgerServiceImpl.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/LedgerServiceImpl.kt
index f05ae65..76a8350 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/LedgerServiceImpl.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/LedgerServiceImpl.kt
@@ -60,6 +60,7 @@
             if (sceneType != SceneType.NoType.value) {
                 createCriteria().andEqualTo("lScenetype", sceneType)
             }
+            orderBy("lTypeid")
         })
         val records = getLedgerRecords(userId, null, sceneType, time)
         val resultList = mutableListOf<LedgerSubTypeVo>()
@@ -170,8 +171,19 @@
 
     }
 
-    override fun getLedgerDetail2(userId: String, ledgerSubTypeId: Int?, sceneType: Int, time: String): List<LedgerVo> {
-        val records = getLedgerRecords(userId, ledgerSubTypeId, sceneType, time)
+    override fun getLedgerDetail2(userId: String, ledgerSubTypeId: Int?, sceneType: Int, time: String?): List<LedgerVo> {
+        val records = if (time != null) {
+            getLedgerRecords(userId, ledgerSubTypeId, sceneType, time)
+        } else {
+            // FIXME: 2022/10/13 鏆傛椂鍙敮鎸乴edgerSubTypeId涓嶄负null鐨勬儏鍐�
+            if (ledgerSubTypeId == null) return emptyList()
+            PageHelper.startPage<LedgerRecord>(1, 1)
+            ledgerRecordMapper.selectByExample(Example(LedgerRecord::class.java).apply {
+                createCriteria().andEqualTo("lrSubmitid", userId)
+                    .andEqualTo("lsSubtypeid", ledgerSubTypeId)
+                orderBy("lrSubmitdate").desc()
+            })
+        }
         val result = ArrayList<LedgerVo>()
         records.forEach {
             val media = ledgerMediaFileMapper.selectByExample(
@@ -387,6 +399,7 @@
     override fun copyLedger(userId: String, time: String, copyLedgerList: List<CopyLedgerVo>): BaseResponse<String> {
         val year = time.split("-")[0]
         val month = time.split("-")[1]
+        val date = DateUtil.StringToDate(time, DateUtil.DateStyle.YYYY_MM)
         copyLedgerList.forEach {
             //鍘婚噸鍒ゆ柇
             val r = ledgerRecordMapper.selectByExample(Example(LedgerRecord::class.java).apply {
@@ -419,7 +432,7 @@
                 lr.lrYear = year.toInt()
                 lr.lrMonth = month.toByte()
                 lr.lrIssubmitontime = true
-                lr.lrSubmitdate = Date()
+                lr.lrSubmitdate = date
                 lr.lrExtension2 = "copy"//琛ㄦ槑鏄鍒剁殑鍙拌处
                 ledgerRecordMapper.insert(lr)
 
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImpl.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImpl.kt
index 78a5550..be4bb2b 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImpl.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImpl.kt
@@ -1,12 +1,12 @@
 package cn.flightfeather.supervision.lightshare.service.Impl
 
+import cn.flightfeather.supervision.common.net.WXHttpService
+import cn.flightfeather.supervision.common.wx.MessageWxVo
+import cn.flightfeather.supervision.common.wx.TemplateManager
+import cn.flightfeather.supervision.common.wx.WxTokenManager
 import cn.flightfeather.supervision.domain.entity.*
 import cn.flightfeather.supervision.domain.enumeration.DistrictType
 import cn.flightfeather.supervision.domain.enumeration.UserType
-import cn.flightfeather.supervision.domain.mapper.NoticeMapper
-import cn.flightfeather.supervision.domain.mapper.NoticeReadStateMapper
-import cn.flightfeather.supervision.domain.mapper.NotificationMapper
-import cn.flightfeather.supervision.domain.mapper.UserinfoMapper
 import cn.flightfeather.supervision.lightshare.repository.MeetingParticipantRepository
 import cn.flightfeather.supervision.lightshare.service.NotificationService
 import cn.flightfeather.supervision.lightshare.vo.NoticeReadStateVo
@@ -14,7 +14,9 @@
 import cn.flightfeather.supervision.push.PushService
 import cn.flightfeather.supervision.domain.enumeration.ParticipantType
 import cn.flightfeather.supervision.domain.enumeration.SceneType
+import cn.flightfeather.supervision.domain.mapper.*
 import cn.flightfeather.supervision.infrastructure.utils.UUIDGenerator
+import com.alibaba.fastjson.JSON
 import com.flightfeather.taizhang.model.enumeration.NotificationType
 import com.flightfeather.taizhang.model.enumeration.WorkSubType
 import com.github.pagehelper.PageHelper
@@ -31,7 +33,8 @@
         val noticeMapper: NoticeMapper,
         val noticeReadStateMapper: NoticeReadStateMapper,
         val userinfoMapper: UserinfoMapper,
-        val meetingParticipantRepository: MeetingParticipantRepository
+        val meetingParticipantRepository: MeetingParticipantRepository,
+        val templateManager: TemplateManager
 ) : NotificationService {
 
     override fun getNotificationUnRead(userId: String, page: Int, per_page: Int, response: HttpServletResponse): List<NotificationVo> {
@@ -288,4 +291,9 @@
         }
         return noticeMapper.insert(notice) == 1
     }
+
+    override fun pushMsgWx(templateId: Int): String {
+        val res = templateManager.sendMsg(templateId, "otZkc5VRlwauEMPqMluQYdVa4zuE", listOf("鍙拌处涓婁紶", "2022骞�10鏈�10鏃�", "3", "璇烽噸鐐瑰叧娉ㄧ幇鍦鸿嚜瀵绘煡閮ㄥ垎"))
+        return if (res) "success" else "fail"
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/UserinfoServiceImpl.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/UserinfoServiceImpl.kt
index 1ff3939..c371dc0 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/UserinfoServiceImpl.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/UserinfoServiceImpl.kt
@@ -1,18 +1,14 @@
 package cn.flightfeather.supervision.lightshare.service.Impl
 
-import cn.flightfeather.supervision.common.net.WXHttpService
 import cn.flightfeather.supervision.domain.entity.BaseInfo
 import cn.flightfeather.supervision.domain.entity.Company
-import cn.flightfeather.supervision.domain.entity.UserInfoWx
 import cn.flightfeather.supervision.domain.entity.Userinfo
 import cn.flightfeather.supervision.domain.enumeration.SceneType
-import cn.flightfeather.supervision.domain.enumeration.UserType
 import cn.flightfeather.supervision.domain.mapper.*
 import cn.flightfeather.supervision.infrastructure.utils.FileUtil
 import cn.flightfeather.supervision.infrastructure.utils.UUIDGenerator
 import cn.flightfeather.supervision.lightshare.service.UserinfoService
 import cn.flightfeather.supervision.lightshare.vo.*
-import com.alibaba.fastjson.JSONObject
 import com.github.pagehelper.PageHelper
 import org.springframework.beans.BeanUtils
 import org.springframework.stereotype.Service
@@ -30,6 +26,8 @@
     val restaurantBaseInfoMapper: RestaurantBaseInfoMapper,
     val vehicleBaseInfoMapper: VehicleBaseInfoMapper,
     val userMapMapper: UserMapMapper,
+    val personalInfoMapper: PersonalInfoMapper,
+    val userInfoWxMapper: UserInfoWxMapper
 ) : UserinfoService {
 
     //鏍规嵁userinfo鏉′欢鏌ヨ
@@ -45,7 +43,7 @@
         }
     }
 
-    override fun findOne(id: String): Userinfo{
+    override fun findOne(id: String): Userinfo {
         val userInfo = userinfoMapper.selectByPrimaryKey(id)
         userMapMapper.selectByPrimaryKey(id)?.let {
             userInfo?.extension3 = it.svUserId
@@ -206,16 +204,21 @@
         }
     }
 
-    override fun changePassword(userId: String, oldPassword: String, newPassword: String): Int {
+    override fun changePassword(userId: String, oldPassword: String, newPassword: String): BaseResponse<String> {
+        if (newPassword.trim() == "") return BaseResponse(false, "鏂板瘑鐮佷笉鑳戒负绌�")
+        if (oldPassword == newPassword) return BaseResponse(false, "鏂板瘑鐮佷笉鑳藉拰鍘熷瘑鐮佺浉鍚�")
+
         val userInfo = findOne(userId)
         return if (oldPassword != userInfo.password) {
-            0
+            BaseResponse(false, "鍘熷瘑鐮侀敊璇�")
         } else {
             val newUserInfo = Userinfo().apply {
                 guid = userInfo.guid
                 password = newPassword
+                remark = "pwChanged"
             }
             update(newUserInfo)
+            BaseResponse(true, "瀵嗙爜淇敼鎴愬姛")
         }
     }
 
@@ -249,20 +252,22 @@
         return result
     }
 
-    override fun getBaseInfo(userId: String): UserBaseInfo {
+    override fun getBaseInfo(userId: String, wxUserId: String?): UserBaseInfo {
         val userInfo = userinfoMapper.selectByPrimaryKey(userId) ?: return UserBaseInfo(userId)
-        val baseInfo = baseInfoMapper.selectByPrimaryKey(userId) ?: return UserBaseInfo(userId)
+        val baseInfo = baseInfoMapper.selectByPrimaryKey(userId)
+        val wxUser = if (wxUserId != null) userInfoWxMapper.selectByPrimaryKey(wxUserId) else null
 
         val mapper = when (userInfo.extension2) {
             SceneType.Restaurant.value.toString() -> restaurantBaseInfoMapper
             SceneType.VehicleRepair.value.toString() -> vehicleBaseInfoMapper
-            else -> restaurantBaseInfoMapper
+            else -> null
         }
 
-        val specialInfo = mapper.selectByPrimaryKey(baseInfo.biGuid)
-        val companyInfo = companyMapper.selectByPrimaryKey(baseInfo.ciGuid)
+        val specialInfo = mapper?.selectByPrimaryKey(baseInfo?.biGuid)
+        val companyInfo = companyMapper.selectByPrimaryKey(if (baseInfo?.ciGuid != null) baseInfo.ciGuid else wxUser?.ciGuid)
+        val personalInfo = personalInfoMapper.selectByPrimaryKey(wxUser?.piGuid)
 
-        return UserBaseInfo(userId, userInfo.realname, baseInfo, companyInfo, specialInfo)
+        return UserBaseInfo(userId, userInfo.realname, baseInfo, companyInfo, specialInfo, personalInfo)
     }
 
     override fun search(district: String?, sceneType: Int?, userType: Int?, page: Int, perPage: Int): BaseResponse<List<Userinfo>> {
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImpl.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImpl.kt
index 0cde9e7..d3961f6 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImpl.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImpl.kt
@@ -1,53 +1,58 @@
 package cn.flightfeather.supervision.lightshare.service.Impl
 
 import cn.flightfeather.supervision.common.net.WXHttpService
+import cn.flightfeather.supervision.common.wx.SHA1
+import cn.flightfeather.supervision.common.wx.WxConfig
+import cn.flightfeather.supervision.domain.entity.LogMsgSubscribeWx
+import cn.flightfeather.supervision.domain.entity.MsgSubscribeWx
 import cn.flightfeather.supervision.domain.entity.UserInfoWx
 import cn.flightfeather.supervision.domain.entity.Userinfo
-import cn.flightfeather.supervision.domain.entity.Version
-import cn.flightfeather.supervision.domain.enumeration.UserType
-import cn.flightfeather.supervision.domain.mapper.UserInfoWxMapper
-import cn.flightfeather.supervision.domain.mapper.UserinfoMapper
-import cn.flightfeather.supervision.domain.mapper.VersionMapper
-import cn.flightfeather.supervision.infrastructure.utils.FileUtil
-import cn.flightfeather.supervision.infrastructure.utils.UUIDGenerator
-import cn.flightfeather.supervision.lightshare.service.VersionService
+import cn.flightfeather.supervision.domain.mapper.*
 import cn.flightfeather.supervision.lightshare.service.WxUserService
+import cn.flightfeather.supervision.lightshare.vo.AccessToken
 import cn.flightfeather.supervision.lightshare.vo.AccessTokenPW
 import cn.flightfeather.supervision.lightshare.vo.AccessTokenWX
 import cn.flightfeather.supervision.lightshare.vo.BaseResponse
-import cn.flightfeather.supervision.lightshare.vo.VersionVo
+import com.alibaba.fastjson.JSON
+import com.alibaba.fastjson.JSONArray
 import com.alibaba.fastjson.JSONObject
+import org.slf4j.LoggerFactory
 import org.springframework.stereotype.Service
-import org.springframework.web.multipart.MultipartFile
 import tk.mybatis.mapper.entity.Example
+import java.util.*
 
 @Service
-class WxUserServiceImpl(val userinfoMapper: UserinfoMapper, val userInfoWxMapper: UserInfoWxMapper): WxUserService {
+class WxUserServiceImpl(
+        val userinfoMapper: UserinfoMapper,
+        val userInfoWxMapper: UserInfoWxMapper,
+        val userMapMapper: UserMapMapper,
+        val baseInfoMapper: BaseInfoMapper,
+        private val msgSubscribeWxMapper: MsgSubscribeWxMapper,
+        private val logMsgSubscribeWxMapper: LogMsgSubscribeWxMapper
+): WxUserService {
+
+    private val LOGGER = LoggerFactory.getLogger(WxUserServiceImpl::class.java)
 
     override fun loginWx(accessTokenWX: AccessTokenWX): BaseResponse<Userinfo> {
         accessTokenWX.code ?: return BaseResponse(false, "鐧诲綍鍑瘉涓嶈兘涓虹┖")
 
-        val res = WXHttpService.code2Session(accessTokenWX.code!!)
-
 //        return BaseResponse(false)
-        if (res.success) {
-            val json = JSONObject.parseObject(res.m.responseBodyAsString)
-            if (json["errcode"] == 0 || json["errcode"] == null) {
-                val openid = json["openid"] as String
-                val unionid = json["unionid"] as String
-                val user = userInfoWxMapper.selectByPrimaryKey(openid)
-                return if (user.uiOpenId == null) {
-                    val newUserWx = UserInfoWx().apply {
+        WXHttpService.code2Session(accessTokenWX.code!!)?.let {
+            val openid = it.first
+            val unionid = it.second
+            val user = userInfoWxMapper.selectByPrimaryKey(openid)
+            return if (user == null || user.uiOpenId == null) {
+                val newUserWx = UserInfoWx().apply {
 //                        uiGuid = UUIDGenerator.generate16ShortUUID()
-                        uiOpenId = openid
-                        uiNickName = accessTokenWX.nickName
-                        uiGender
-                        uiCountry
-                        uiProvince
-                        uiCity
-                        uiAvatarUrl = accessTokenWX.avatarUrl
-                        uiUnionid = unionid
-                    }
+                    uiOpenId = openid
+                    uiNickName = accessTokenWX.nickName
+                    uiGender
+                    uiCountry
+                    uiProvince
+                    uiCity
+                    uiAvatarUrl = accessTokenWX.avatarUrl
+                    uiUnionid = unionid
+                }
 //                    val newUser = Userinfo().apply {
 //                        guid = newUserWx.uiGuid
 //                        headIconUrl = newUserWx.uiAvatarUrl
@@ -59,30 +64,246 @@
 //                        isenable = true
 //                        wechatid = newUserWx.uiOpenId
 //                    }
-                    var r = userInfoWxMapper.insert(newUserWx)
+                var r = userInfoWxMapper.insert(newUserWx)
 //                    r += userinfoMapper.insert(newUser)
-                    return if (r == 1) {
-                        BaseResponse(true, "寰俊鐢ㄦ埛娉ㄥ唽鎴愬姛")
-                    } else {
-                        BaseResponse(false, "寰俊鐢ㄦ埛娉ㄥ唽澶辫触")
-                    }
+                return if (r == 1) {
+                    BaseResponse(true, "寰俊鐢ㄦ埛娉ㄥ唽鎴愬姛")
                 } else {
-                    if (user.uiGuid != null) {
-                        val userinfo = userinfoMapper.selectByPrimaryKey(user.uiGuid)
-                        BaseResponse(true, "寰俊鐢ㄦ埛鐧诲綍鎴愬姛", data = userinfo)
-                    } else {
-                        BaseResponse(true, "寰俊鐢ㄦ埛鏈粦瀹氫紒涓�")
-                    }
+                    BaseResponse(false, "寰俊鐢ㄦ埛娉ㄥ唽澶辫触")
                 }
             } else {
-                return BaseResponse(false, "璇锋眰澶辫触锛歟rrcode=${json["errcode"]}")
+                if (user.uiGuid != null) {
+                    val userinfo = userinfoMapper.selectByPrimaryKey(user.uiGuid)
+                    BaseResponse(true, "寰俊鐢ㄦ埛鐧诲綍鎴愬姛", data = userinfo)
+                } else {
+                    BaseResponse(true, "寰俊鐢ㄦ埛鏈粦瀹氫紒涓�")
+                }
             }
+        }
+
+        return BaseResponse(false, "璇锋眰澶辫触, 鏃犳硶璁块棶寰俊鎺ュ彛")
+    }
+
+    override fun loginPw(accessTokenPW: AccessTokenPW): AccessToken {
+        //1. 璐﹀彿瀵嗙爜鐧诲綍鏃讹紝灏嗛檮甯︾殑寰俊id涓庤处鍙风粦瀹�
+        if (!accessTokenPW.userName.isNullOrBlank() && !accessTokenPW.password.isNullOrBlank()) {
+            val user = userinfoMapper.selectByExample(Example(Userinfo::class.java).apply {
+                createCriteria().andEqualTo("acountname", accessTokenPW.userName)
+                        .andEqualTo("password",accessTokenPW.password)
+            })
+            if (user.isEmpty()) return AccessToken()
+
+            val result = AccessToken()
+            //1.1 寰俊id涓虹┖锛岀洿鎺ョ櫥褰�; 寰俊id涓嶄负绌猴紝缁戝畾鑷宠处鍙�
+            if (!accessTokenPW.code.isNullOrBlank()) {
+                val baseInfo = baseInfoMapper.selectByPrimaryKey(user[0].guid)
+                WXHttpService.code2Session(accessTokenPW.code!!)?.let {
+                    val openid = it.first
+                    val unionid = it.second
+                    val userWx = userInfoWxMapper.selectByPrimaryKey(openid)
+                    result.openId = openid
+                    return@let if (userWx == null || userWx.uiOpenId == null) {
+                        val newUserWx = UserInfoWx().apply {
+                            uiGuid = user[0].guid
+                            ciGuid = baseInfo?.ciGuid
+                            uiOpenId = openid
+                            uiNickName = accessTokenPW.nickName
+                            uiGender
+                            uiCountry
+                            uiProvince
+                            uiCity
+                            uiAvatarUrl = accessTokenPW.avatarUrl
+                            uiUnionid = unionid
+                        }
+                        userInfoWxMapper.insert(newUserWx)
+                    } else if (userWx.uiGuid != user[0].guid) {
+                        userWx.uiGuid = user[0].guid
+                        userWx.ciGuid = baseInfo?.ciGuid
+                        userInfoWxMapper.updateByPrimaryKey(userWx)
+                    } else {
+                        return@let
+                    }
+                }
+            }
+            return result.apply {
+                userId = user[0].guid
+                val sUser = userMapMapper.selectByPrimaryKey(userId)
+                sUserId = sUser?.svUserId
+                success = true
+            }
+        }
+        //2. 褰撳井淇′竴閿櫥褰曟椂锛屽垽鏂处鍙风粦瀹氭儏鍐�
+        else if (!accessTokenPW.code.isNullOrBlank()) {
+            WXHttpService.code2Session(accessTokenPW.code!!)?.let {
+                val openid = it.first
+                val unionid = it.second
+                val userWx = userInfoWxMapper.selectByPrimaryKey(openid)
+                return if (userWx == null || userWx.uiOpenId == null) {
+                    AccessToken()
+                } else {
+                    val user = userinfoMapper.selectByPrimaryKey(userWx.uiGuid)
+                    AccessToken().apply {
+                        if (user?.guid == null) {
+                            success = false
+                        } else {
+                            userId = user.guid
+                            val sUser = userMapMapper.selectByPrimaryKey(userId)
+                            sUserId = sUser?.svUserId
+                            openId = openid
+                            success = true
+                        }
+                    }
+                }
+            }
+            return AccessToken()
         } else {
-            return BaseResponse(false, "璇锋眰澶辫触, 鏃犳硶璁块棶寰俊鎺ュ彛")
+            return AccessToken()
         }
     }
 
-    override fun loginPw(accessTokenPW: AccessTokenPW): BaseResponse<Userinfo> {
-        TODO("Not yet implemented")
+    override fun subscribeCheck(signature: String, timestamp: String, nonce: String, echostr: String): String {
+        val s = SHA1.getSHA1(WxConfig.TOKEN, timestamp, nonce, "")
+        LOGGER.info("寰俊鏈嶅姟鍣ㄩ獙璇侊紝sha1锛�${s}")
+        return if (signature == s) {
+            LOGGER.info("success")
+            echostr
+        } else {
+            LOGGER.info("fail")
+            "fail"
+        }
+    }
+
+    override fun subscribeResult(msg: String): String{
+        println(msg)
+
+        val json = JSON.parseObject(msg)
+        //灏忕▼搴忓師濮媔d锛屼笉鏄疉PP_ID
+        val appName = (json["ToUserName"] as String?) ?: throw NullPointerException("寰俊鏈嶅姟鍣ㄥ彂閫佺殑璁㈤槄杩斿洖娑堟伅ToUserName瀛楁涓簄ull")
+        if (appName != WxConfig.USER_NAME) throw IllegalStateException("灏忕▼搴忓師濮婭D涓嶅尮閰嶏紝寰俊[${appName}]锛屾湇鍔″櫒璁板綍[${WxConfig.USER_NAME}]")
+        //鐢ㄦ埛openid
+        val openId = (json["FromUserName"] as String?) ?: throw NullPointerException("寰俊鏈嶅姟鍣ㄥ彂閫佺殑璁㈤槄杩斿洖娑堟伅FromUserName瀛楁涓簄ull")
+        //鏃堕棿鎴�
+        val createTime = (json["CreateTime"] as Int?) ?: throw NullPointerException("寰俊鏈嶅姟鍣ㄥ彂閫佺殑璁㈤槄杩斿洖娑堟伅CreateTime瀛楁涓簄ull")
+        //浜嬩欢绫诲瀷锛屾澶勫簲璇ラ兘鏄痚vent
+        val msgType = json["MsgType"] as String?
+
+        //鍚勬秷鎭ā鏉胯繑鍥炵粨鏋�
+        val results = mutableListOf<JSONObject>()
+        val list = json["List"]
+        if (list is JSONArray) {
+            list.forEach {
+                if (it is JSONObject) {
+                    results.add(it)
+                }
+            }
+        } else if (list is JSONObject) {
+            results.add(list)
+        }
+        val event = json["Event"]
+        if (event is String) {
+            when (event) {
+                //鐢ㄦ埛瑙﹀彂璁㈤槄娑堟伅寮规鍚庣殑琛屼负鏃堕棿缁撴灉
+                //鐢ㄦ埛鍦ㄦ墜鏈虹鏈嶅姟閫氱煡娑堟伅鍗$墖鍙充笂瑙掔鐞嗘秷鎭椂鐨勬搷浣滅粨鏋�
+                "subscribe_msg_popup_event" ,
+                "subscribe_msg_change_event" -> {
+                    results.forEach {
+                        val templateId = it["TemplateId"] as String?
+                        val sStatus = it["SubscribeStatusString"] as String?
+                        //鏍规嵁鏃堕棿鍜岀敤鎴穙penId锛屽垽鏂娆℃搷浣滄槸鍚﹂噸澶�
+                        val time = Date(createTime.toLong() * 1000)
+                        val records = msgSubscribeWxMapper.selectByExample(Example(MsgSubscribeWx::class.java).apply {
+                            createCriteria().andEqualTo("msOpenId", openId)
+                                .andEqualTo("msTemplateId", templateId)
+                        })
+                        //鐢ㄦ埛鏃犺闃呰褰�
+                        if (records.isEmpty()) {
+                            val m = MsgSubscribeWx().apply {
+                                msTemplateId = templateId
+                                msOpenId = openId
+                                msUpdateTime = time
+                                if (sStatus == WxConfig.S_ACCEPT) {
+                                    msCount = 1
+                                    msAccept = true
+                                }else if (sStatus == WxConfig.S_REJECT) {
+                                    msCount = 0
+                                    msAccept = false
+                                }
+                            }
+                            msgSubscribeWxMapper.insert(m)
+                        }
+                        //鐢ㄦ埛鏈夎闃呰褰�
+                        else if (records.size == 1) {
+                            //鍏堟帓閲�
+                            val r = records[0]
+                            if (r != null && createTime > (r.msUpdateTime?.time ?: 0)) {
+                                r.msUpdateTime = time
+                                if (sStatus == WxConfig.S_ACCEPT) {
+                                    r.msCount += 1
+                                    r.msAccept = true
+                                } else if (sStatus == WxConfig.S_REJECT) {
+                                    r.msAccept = false
+                                }
+                                msgSubscribeWxMapper.updateByPrimaryKey(r)
+                            }
+                        }
+                        //鐢ㄦ埛鍗曚釜妯℃澘鏈夊鏉¤褰曪紝閿欒
+                        else {
+                            throw IllegalStateException("鐢ㄦ埛[${openId}]寰俊璁㈤槄鍗曟潯娑堟伅璁板綍澶т簬1")
+                        }
+                    }
+                }
+                //鍙戦�佺粰鐢ㄦ埛璁㈤槄娑堟伅鐨勮繑鍥炵粨鏋�
+                "subscribe_msg_sent_event" -> {
+                    results.forEach {
+                        val templateId = it["TemplateId"] as String?
+                        val msgId = it["MsgID"] as String?
+                        val eCode = it["ErrorCode"] as String?
+                        val eStatus = it["ErrorStatus"] as String?
+                        //鎺ㄩ�佹垚鍔熷悗锛岃鐢ㄦ埛璇ユ潯妯℃澘鍙敤娆℃暟鍑忎竴锛屽苟涓旇褰曟帹閫佹棩蹇�
+                        if (eCode == "0") {
+                            val records = msgSubscribeWxMapper.selectByExample(Example(MsgSubscribeWx::class.java).apply {
+                                createCriteria().andEqualTo("msOpenId", openId)
+                                    .andEqualTo("msTemplateId", templateId)
+                            })
+                            if (records.size != 1) throw IllegalStateException("寰俊鐢ㄦ埛[${openId}]妯℃澘[${templateId}]璁㈤槄娆℃暟璁板綍缂哄け")
+                            records[0]?.let { ms ->
+                                ms.msCount--
+                                msgSubscribeWxMapper.updateByPrimaryKey(ms)
+                            }
+
+                            //鏌ユ壘杩斿洖娑堟伅24灏忔椂涔嬪唴鐨勮褰�
+                            // 涓�鑸儏鍐典笅锛屼富鍔ㄦ帹閫佹秷鎭悗锛屽井淇℃湇鍔″櫒浼氱珛鍗宠繑鍥炲搴旂殑鎺ㄩ�佺粨鏋滐紝鎵�浠ュ簲璇ュ彧鏌ヨ鍒颁竴鏉℃病鏈塴msMsgId鐨勮褰曪紝
+                            // 鎴栬�呭湪寰俊鏈嶅姟鍣ㄩ噸澶嶅彂閫佺殑鎯呭喌涓嬶紝鍙煡璇㈠埌涓�鏉℃湁瀵瑰簲lmsMsgId鐨勮褰曪紝
+                            val logs = logMsgSubscribeWxMapper.selectByExample(Example(LogMsgSubscribeWx::class.java).apply {
+                                createCriteria().andEqualTo("lmsOpenId", openId)
+                                    .andEqualTo("lmsTemplateId", templateId)
+                                and(
+                                    createCriteria().orIsNull("lmsMsgId").orEqualTo("lmsMsgId", msgId)
+                                )
+                            }).let { list->
+                                var result = list
+                                for (l in list) {
+                                    if (l?.lmsMsgId == msgId) {
+                                        result = emptyList()
+                                        break
+                                    }
+                                }
+                                result
+                            }
+                            if (logs.isNotEmpty()) {
+                                val l = logs[0]
+                                l?.lmsTime = Date()
+                                l?.lmsMsgId = msgId
+                                l?.lmsResult = true
+                                logMsgSubscribeWxMapper.updateByPrimaryKey(l)
+                            }
+                        }
+                    }
+                }
+            }
+            return "success"
+        } else {
+            return "fail"
+        }
     }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/LedgerService.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/LedgerService.kt
index 7dca21d..a049cf7 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/LedgerService.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/LedgerService.kt
@@ -15,7 +15,7 @@
 
     fun getLedgerDetail(userId: String, ledgerSubTypeId: Int? = null, sceneType: Int, startTime: String, endTime: String, page: Int? = null, perPage: Int, response: HttpServletResponse): ArrayList<LedgerVo>
 
-    fun getLedgerDetail2(userId: String, ledgerSubTypeId: Int? = null, sceneType: Int, time: String): List<LedgerVo>
+    fun getLedgerDetail2(userId: String, ledgerSubTypeId: Int? = null, sceneType: Int, time: String?): List<LedgerVo>
 
     fun uploadLedger(userId: String, ledgerVoList: String, files: Array<MultipartFile>): Boolean
 
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/NotificationService.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/NotificationService.kt
index 876e36b..bd6839c 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/NotificationService.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/NotificationService.kt
@@ -1,5 +1,6 @@
 package cn.flightfeather.supervision.lightshare.service
 
+import cn.flightfeather.supervision.common.wx.MessageWxVo
 import cn.flightfeather.supervision.domain.entity.MeetingInfo
 import cn.flightfeather.supervision.domain.entity.VMRoom
 import cn.flightfeather.supervision.lightshare.vo.LedgerSubTypeVo
@@ -26,4 +27,6 @@
     fun pushMeetingReleaseNotification(meetingVo: MeetingInfo, roomVo: VMRoom?, userId: String, title: String, body: String)
 
     fun releaseNotice(userId: String, noticeVo: NotificationVo): Boolean
+
+    fun pushMsgWx(templateId: Int): String
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/UserinfoService.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/UserinfoService.kt
index 0d7b9c4..7e23222 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/UserinfoService.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/UserinfoService.kt
@@ -29,11 +29,11 @@
 
     fun upLoadAccountPic(userId: String, files: Array<MultipartFile>): String
 
-    fun changePassword(userId: String, oldPassword: String, newPassword: String): Int
+    fun changePassword(userId: String, oldPassword: String, newPassword: String): BaseResponse<String>
 
     fun searchUser(userId: String,condition: UserSearchCondition, page: Int, perPage: Int, response: HttpServletResponse): List<Userinfo>
 
-    fun getBaseInfo(userId: String): UserBaseInfo
+    fun getBaseInfo(userId: String, wxUserId: String?): UserBaseInfo
 
     fun search(district: String?, sceneType: Int?, userType: Int?, page: Int, perPage: Int): BaseResponse<List<Userinfo>>
 
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/WxUserService.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/WxUserService.kt
index de6779f..1654ea7 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/WxUserService.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/service/WxUserService.kt
@@ -1,6 +1,7 @@
 package cn.flightfeather.supervision.lightshare.service
 
 import cn.flightfeather.supervision.domain.entity.Userinfo
+import cn.flightfeather.supervision.lightshare.vo.AccessToken
 import cn.flightfeather.supervision.lightshare.vo.AccessTokenPW
 import cn.flightfeather.supervision.lightshare.vo.AccessTokenWX
 import cn.flightfeather.supervision.lightshare.vo.BaseResponse
@@ -12,5 +13,14 @@
      */
     fun loginWx(accessTokenWX: AccessTokenWX): BaseResponse<Userinfo>
 
-    fun loginPw(accessTokenPW: AccessTokenPW): BaseResponse<Userinfo>
+    /**
+     * 鐢ㄦ埛鍚嶅瘑鐮佺櫥褰曪紝鍚屾椂缁戝畾寰俊鐢ㄦ埛
+     */
+    // FIXME: 2022/9/25 鏆傚畾
+    fun loginPw(accessTokenPW: AccessTokenPW): AccessToken
+
+
+    fun subscribeCheck(signature: String, timestamp: String, nonce: String, echostr: String): String
+
+    fun subscribeResult(msg: String): String
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AccessToken.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AccessToken.kt
index c6ca2e7..ab8a248 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AccessToken.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AccessToken.kt
@@ -10,5 +10,7 @@
     var userId: String? = null
     // 瀵瑰簲椋炵窘鐩戠涓殑鐢ㄦ埛id
     var sUserId: String? = null
+    // 寰俊鐢ㄦ埛id
+    var openId: String? = null
     var success: Boolean = false
 }
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AuthSceneRestVo.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AuthSceneRestVo.kt
new file mode 100644
index 0000000..2687db7
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AuthSceneRestVo.kt
@@ -0,0 +1,104 @@
+package cn.flightfeather.supervision.lightshare.vo
+
+import cn.flightfeather.supervision.domain.entity.BaseInfo
+import cn.flightfeather.supervision.domain.entity.FumePurifyDevice
+import cn.flightfeather.supervision.domain.entity.MonitorDevice
+import cn.flightfeather.supervision.domain.entity.RestaurantBaseInfo
+import cn.flightfeather.supervision.infrastructure.utils.UUIDGenerator
+import org.springframework.beans.BeanUtils
+import java.util.*
+
+/**
+ * 椁愰ギ搴楄璇佷俊鎭�
+ */
+class AuthSceneRestVo : AuthSceneVo() {
+    //缁忚惀鑿滅郴
+    var rbCuisine: String? = null
+    //灏遍浣嶆�绘暟
+    var rbTotalSeating: Int? = null
+    //鐏跺ご鏁�
+    var rbCookingRangeNum: Int? = null
+    //骞村潎鐢ㄦ补閲忥紙鏁版嵁搴撹褰曚负鏈堝害鐢ㄦ补閲忥級
+    var rbCookingOilCapacity: Int? = null
+    //鐢ㄦ补绫诲瀷
+    var rbCookingOilType: String? = null
+    //鎵�灞為泦涓尯
+    var rbConcentrationArea: String? = null
+    //鎺掑彛鏁伴噺
+    var rbOutfallCount: Int? = null
+    //鎺掑彛浣嶇疆
+    var rbOutfallLocation: String? = null
+    //鎺掑彛缂栧彿
+    var rbOutfallNum: String? = null
+
+    //鍑�鍖栬澶囨暟閲�
+    var fpNum: String? = null
+    //鐩戞祴璁惧鏁伴噺
+    var mdNum: String? = null
+
+    /**
+     * 鐢熸垚鏂扮殑椁愰ギ淇℃伅瀵硅薄
+     */
+    fun toNewRestInfo(userId: String) = RestaurantBaseInfo().apply {
+        rbGuid = userId
+        updateRestInfo(this)
+    }
+
+    /**
+     * 鏇存柊鑷抽楗俊鎭�
+     */
+    fun updateRestInfo(restInfo: RestaurantBaseInfo) {
+        restInfo.apply {
+//            rbCuisine = rbCuisine
+//            rbTotalSeating = rbTotalSeating
+//            rbCookingRangeNum = rbCookingRangeNum
+//            rbCookingOilType = rbCookingOilType
+//            rbConcentrationArea = rbConcentrationArea
+//            rbOutfallCount = rbOutfallCount
+//            rbOutfallLocation = rbOutfallLocation
+//            rbOutfallNum = rbOutfallNum
+            BeanUtils.copyProperties(this@AuthSceneRestVo, this)
+            rbCookingOilCapacity = this@AuthSceneRestVo.rbCookingOilCapacity?.div(12).toString()
+        }
+    }
+
+    /**
+     * 鐢熸垚鏂扮殑椁愰ギ娌圭儫鍑�鍖栬缃俊鎭璞�
+     */
+    fun toNewFpdInfo(baseInfo: BaseInfo) = FumePurifyDevice().apply {
+        fpGuid = UUIDGenerator.generate16ShortUUID()
+        fpUserId = baseInfo.biGuid
+        fpUserName = baseInfo.biName
+        fpUpdatingTime = Date()
+        updateFpdInfo(this)
+    }
+
+    /**
+     * 鏇存柊鑷抽楗补鐑熷噣鍖栬缃俊鎭�
+     */
+    fun updateFpdInfo(fpdInfo: FumePurifyDevice) {
+        fpdInfo.apply {
+            fpNum = this@AuthSceneRestVo.fpNum
+        }
+    }
+
+    /**
+     * 鐢熸垚鏂扮殑椁愰ギ娌圭儫鐩戞祴璁惧淇℃伅瀵硅薄
+     */
+    fun toNewMdInfo(baseInfo: BaseInfo) = MonitorDevice().apply {
+        mdGuid = UUIDGenerator.generate16ShortUUID()
+        mdUserId = baseInfo.biGuid
+        mdUserName = baseInfo.biName
+        mdUpdatingTime = Date()
+        updateMdInfo(this)
+    }
+
+    /**
+     * 鏇存柊鑷抽楗补鐑熺洃娴嬭澶囦俊鎭�
+     */
+    fun updateMdInfo(mdInfo: MonitorDevice) {
+        mdInfo.apply {
+            mdNum = this@AuthSceneRestVo.mdNum
+        }
+    }
+}
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AuthSceneVo.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AuthSceneVo.kt
new file mode 100644
index 0000000..f42a973
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/AuthSceneVo.kt
@@ -0,0 +1,64 @@
+package cn.flightfeather.supervision.lightshare.vo
+
+import cn.flightfeather.supervision.domain.entity.BaseInfo
+import cn.flightfeather.supervision.domain.entity.Company
+import cn.flightfeather.supervision.domain.entity.Userinfo
+import cn.flightfeather.supervision.domain.enumeration.AuthenticationStatus
+import org.springframework.beans.BeanUtils
+import java.util.*
+
+/**
+ * 鍦烘櫙璁よ瘉淇℃伅
+ */
+open class AuthSceneVo {
+    //鍦烘櫙鍚嶇О
+    var biName: String? = null
+    //鍦烘櫙绠�绉�
+    var biNickName: String? = null
+    //鍦烘櫙鑱旂郴浜�
+    var biContact: String? = null
+    //鍦烘櫙鑱旂郴鐢佃瘽
+    var biTelephone: String? = null
+    //鍦烘櫙鍦板潃
+    var biAddress: String? = null
+    //鍦烘櫙鎵�灞炶鏀垮尯鍩�
+    var biLocation: Array<String> = emptyArray()
+
+    /**
+     * 鐢熸垚鏂扮殑鍦烘櫙鍩虹淇℃伅瀵硅薄
+     */
+    fun toNewBaseInfo(newUser: Userinfo, cInfo:Company?) = BaseInfo().apply {
+        biGuid = newUser.guid
+        ciGuid = cInfo?.ciGuid
+        ciName = cInfo?.ciName
+        biCreateTime = Date()
+        biExtension1 = newUser.acountname
+        updateBaseInfo(this)
+    }
+
+    /**
+     * 鏇存柊鑷冲満鏅熀纭�淇℃伅
+     */
+    fun updateBaseInfo(baseInfo: BaseInfo) {
+        baseInfo.apply {
+//            biName = biName
+//            biNickName = biNickName
+//            biContact = biContact
+//            biTelephone = biTelephone
+//            biAddress = biAddress
+            if (biLocation.isNotEmpty()) {
+                biProvinceName = biLocation[0]
+                biCityName = biLocation[1]
+                biDistrictName = biLocation[2]
+                biTownName = biLocation[3]
+                biProvinceCode = biLocation[4]
+                biCityCode = biLocation[5]
+                biDistrictCode = biLocation[6]
+                biTownCode = biLocation[7]
+            }
+            biUpdateTime = Date()
+            biExtension3 = AuthenticationStatus.YES.des
+            BeanUtils.copyProperties(this@AuthSceneVo, this)
+        }
+    }
+}
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/UserBaseInfo.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/UserBaseInfo.kt
index 989b9ed..f795b96 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/UserBaseInfo.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/vo/UserBaseInfo.kt
@@ -3,6 +3,7 @@
 import cn.flightfeather.supervision.domain.entity.BaseInfo
 import cn.flightfeather.supervision.domain.entity.BaseSpecialInfo
 import cn.flightfeather.supervision.domain.entity.Company
+import cn.flightfeather.supervision.domain.entity.PersonalInfo
 import com.fasterxml.jackson.annotation.JsonInclude
 
 /**
@@ -15,5 +16,6 @@
         val name: String? = null,
         val baseInfo: BaseInfo? = null,
         val company: Company? = null,
-        val specialInfo: BaseSpecialInfo? = null
+        val specialInfo: BaseSpecialInfo? = null,
+        val personalInfo: PersonalInfo? = null
 )
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/AuthController.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/AuthController.kt
new file mode 100644
index 0000000..6f00f35
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/AuthController.kt
@@ -0,0 +1,45 @@
+package cn.flightfeather.supervision.lightshare.web
+
+import cn.flightfeather.supervision.domain.entity.Company
+import cn.flightfeather.supervision.domain.entity.PersonalInfo
+import cn.flightfeather.supervision.lightshare.service.AuthService
+import cn.flightfeather.supervision.lightshare.vo.AuthSceneVo
+import io.swagger.annotations.Api
+import io.swagger.annotations.ApiOperation
+import io.swagger.annotations.ApiParam
+import org.springframework.web.bind.annotation.*
+
+@Api(tags = ["鐢ㄦ埛璁よ瘉鐩稿叧API鎺ュ彛"])
+@RestController
+@RequestMapping("/auth")
+class AuthController(val authService: AuthService) {
+
+    @ApiOperation(value = "浼佷笟淇℃伅璁よ瘉")
+    @PostMapping("/company")
+    fun authCompany(
+        @ApiParam("鐢ㄦ埛寰俊id") @RequestParam("wxUserId") wxUserId: String,
+        @ApiParam("浼佷笟淇℃伅") @RequestBody company: Company,
+    ) = authService.authCompany(wxUserId, company)
+
+    @ApiOperation(value = "鍦烘櫙淇℃伅璁よ瘉")
+    @PostMapping("/scene")
+    fun authScene(
+        @ApiParam("鐢ㄦ埛寰俊id") @RequestParam("wxUserId") wxUserId: String,
+        @ApiParam("鐢ㄦ埛鍦烘櫙绫诲瀷缂栧彿") @RequestParam("sceneType") sceneType: Int,
+        @ApiParam("鍦烘櫙淇℃伅") @RequestBody sceneInfo: String,
+    ) = authService.authScene(wxUserId, sceneType, sceneInfo)
+
+    @ApiOperation(value = "涓汉淇℃伅璁よ瘉")
+    @PostMapping("/personal")
+    fun authPersonal(
+        @ApiParam("鐢ㄦ埛寰俊id") @RequestParam("wxUserId") wxUserId: String,
+        @ApiParam("涓汉淇℃伅") @RequestBody personalInfo: PersonalInfo
+    ) = authService.authPersonal(wxUserId, personalInfo)
+
+    @ApiOperation(value = "鑾峰彇鐢ㄦ埛璁よ瘉鐘舵��")
+    @GetMapping("/status")
+    fun authStatus(
+        @ApiParam("鐢ㄦ埛寰俊id") @RequestParam(value = "wxUserId", required = false) wxUserId: String?,
+        @ApiParam("鐢ㄦ埛鍦烘櫙id") @RequestParam(value = "userId", required = false) userId: String?,
+    ) = authService.authStatus(wxUserId, userId)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/LedgerController.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/LedgerController.kt
index 4ddc139..172a37d 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/LedgerController.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/LedgerController.kt
@@ -52,7 +52,7 @@
         @ApiParam("鐢ㄦ埛id") @PathVariable userId: String,
         @ApiParam(value = "鍙拌处瀛愮被鍨媔d锛� 濡傛灉涓嶄紶锛屽垯榛樿鏍规嵁鍦烘櫙绫诲瀷鑾峰彇鎵�鏈夊彴璐�", required = false) @RequestParam(value = "ledgerSubTypeId", required = false) ledgerSubTypeId: Int?,
         @ApiParam("鍦烘櫙绫诲瀷id") @RequestParam(value = "sceneType") sceneType: Int,
-        @ApiParam(value = "鏃堕棿", example = "yyyy-MM-dd") @RequestParam(value = "time") time: String
+        @ApiParam(value = "鏃堕棿", example = "yyyy-MM-dd") @RequestParam(value = "time", required = false) time: String?
     ) = ledgerService.getLedgerDetail2(userId, ledgerSubTypeId, sceneType, time)
 
     @ApiOperation(value = "涓婁紶鍙拌处淇℃伅")
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/NotificationController.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/NotificationController.kt
index 0382f15..f7f9453 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/NotificationController.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/NotificationController.kt
@@ -43,9 +43,15 @@
     ) = notificationService.getUnReadNoticeNum(userId)
 
     @ApiOperation(value = "鍙戝竷閫氱煡")
-    @PostMapping("{userId}/release")
+    @PostMapping("/{userId}/release")
     fun releaseNotice(
         @ApiParam("鐢ㄦ埛id") @PathVariable("userId") userId: String,
         @ApiParam("閫氱煡") @RequestBody notice: NotificationVo
     ) = notificationService.releaseNotice(userId, notice)
+
+    @ApiOperation(value = "鎺ㄩ�佷竴鏉″井淇¤闃呮秷鎭�")
+    @GetMapping("/wx/message/subscribe/send")
+    fun pushMsgWx(
+        @ApiParam("妯℃澘id") @RequestParam("templateId") templateId: Int
+    ) = notificationService.pushMsgWx(templateId)
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/UserinfoController.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/UserinfoController.kt
index 95f390a..d69f90d 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/UserinfoController.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/UserinfoController.kt
@@ -71,7 +71,7 @@
     ) = userinfoService.upLoadAccountPic(userId, files)
 
     @ApiOperation(value = "淇敼瀵嗙爜")
-    @PostMapping("/password/change/{userId}")
+    @PostMapping("/password/change")
     fun changePassword(
         @ApiParam("鐢ㄦ埛id") @RequestParam("userId") userId: String,
         @ApiParam("鏃у瘑鐮�") @RequestParam("oldPassword") oldPassword: String,
@@ -91,8 +91,9 @@
     @ApiOperation(value = "鑾峰彇鐢ㄦ埛鍩烘湰淇℃伅")
     @GetMapping("/baseInfo")
     fun getBaseInfo(
-        @ApiParam("鐢ㄦ埛id") @RequestParam("userId") userId: String
-    ) = userinfoService.getBaseInfo(userId)
+        @ApiParam("鐢ㄦ埛id") @RequestParam("userId") userId: String,
+        @ApiParam("寰俊鐢ㄦ埛id") @RequestParam(value = "wxUserId", required = false) wxUserId: String?
+    ) = userinfoService.getBaseInfo(userId, wxUserId)
 
     @ApiOperation(value = "鏍规嵁缁欏畾鏉′欢锛屾悳绱㈢敤鎴�")
     @GetMapping("/search")
diff --git a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/WxUserController.kt b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/WxUserController.kt
index 9dc1b94..b196366 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/WxUserController.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/lightshare/web/WxUserController.kt
@@ -1,14 +1,12 @@
 package cn.flightfeather.supervision.lightshare.web
 
 import cn.flightfeather.supervision.lightshare.service.WxUserService
+import cn.flightfeather.supervision.lightshare.vo.AccessTokenPW
 import cn.flightfeather.supervision.lightshare.vo.AccessTokenWX
 import io.swagger.annotations.Api
 import io.swagger.annotations.ApiOperation
 import io.swagger.annotations.ApiParam
-import org.springframework.web.bind.annotation.PostMapping
-import org.springframework.web.bind.annotation.RequestBody
-import org.springframework.web.bind.annotation.RequestMapping
-import org.springframework.web.bind.annotation.RestController
+import org.springframework.web.bind.annotation.*
 
 @Api(tags = ["寰俊鐢ㄦ埛淇℃伅API鎺ュ彛"])
 @RestController
@@ -20,4 +18,26 @@
     fun loginWx(
         @ApiParam("鐧诲綍淇℃伅") @RequestBody accessTokenWX: AccessTokenWX
     ) = wxUserService.loginWx(accessTokenWX)
+
+
+    @ApiOperation(value = "鐧诲綍")
+    @PostMapping("/loginPW")
+    fun loginPW(
+            @ApiParam("鐧诲綍淇℃伅") @RequestBody accessTokenPW: AccessTokenPW
+    ) = wxUserService.loginPw(accessTokenPW)
+
+    @ApiOperation(value = "寰俊鎺ュ叆楠岃瘉")
+    @GetMapping("/message/subscribe/result")
+    fun subscribeCheck(
+        @ApiParam("寰俊鍔犲瘑绛惧悕") @RequestParam signature: String,
+        @ApiParam("鏃堕棿鎴�") @RequestParam timestamp: String,
+        @ApiParam("闅忔満鏁�") @RequestParam nonce: String,
+        @ApiParam("闅忔満瀛楃涓�") @RequestParam echostr: String,
+    ) = wxUserService.subscribeCheck(signature, timestamp, nonce, echostr)
+
+    @ApiOperation(value = "寰俊鐢ㄦ埛璁㈤槄娑堟伅缁撴灉鎺ㄩ��", notes = "寰俊浼氬皢鐢ㄦ埛璁㈤槄娑堟伅銆佹秷鎭帹閫佹儏鍐电瓑淇℃伅閫氳繃姝ゆ帴鍙e彂閫佽繃鏉�")
+    @PostMapping("/message/subscribe/result")
+    fun subscribeResult(
+        @ApiParam("娑堟伅") @RequestBody msg: String
+    ) = wxUserService.subscribeResult(msg)
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/timingtask/BaseTimingTask.kt b/src/main/kotlin/cn/flightfeather/supervision/timingtask/BaseTimingTask.kt
index d755127..b9fa2ce 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/timingtask/BaseTimingTask.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/timingtask/BaseTimingTask.kt
@@ -19,7 +19,7 @@
     // 浠诲姟鎵ц鍛ㄦ湡锛屽崟浣嶏細鍒嗛挓
     abstract val period: Long
 
-    fun execute(localtime:LocalDateTime) {
+    open fun execute(localtime:LocalDateTime) {
         val now = LocalDateTime.now()
         if (now.minusSeconds(period * 60 - 5) >= lastTime) {
             lastTime = now
diff --git a/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskController.kt b/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskController.kt
index 04d81f5..0a26809 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskController.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskController.kt
@@ -14,7 +14,7 @@
  */
 @Component
 class TaskController(
-        fetchVOC: FetchVOC, pushFume: PushFume
+    fetchVOC: TaskFetchVOC, pushFume: TaskPushFume
 ) {
 
     companion object {
@@ -32,8 +32,8 @@
     init {
         LOGGER.info("娣诲姞瀹氭椂浠诲姟")
         timeTask.clear()
-        timeTask.add(fetchVOC)
-        timeTask.add(pushFume)
+//        timeTask.add(fetchVOC)
+//        timeTask.add(pushFume)
         LOGGER.info("娣诲姞瀹氭椂浠诲姟瀹屾垚锛屼换鍔℃�昏${timeTask.size}涓�")
     }
 
diff --git a/src/main/kotlin/cn/flightfeather/supervision/timingtask/FetchVOC.kt b/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskFetchVOC.kt
similarity index 98%
rename from src/main/kotlin/cn/flightfeather/supervision/timingtask/FetchVOC.kt
rename to src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskFetchVOC.kt
index 5e4c86b..788b89e 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/timingtask/FetchVOC.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskFetchVOC.kt
@@ -19,9 +19,9 @@
  * 鑾峰彇voc鐩戞祴鏁版嵁
  */
 @Component
-class FetchVOC : BaseTimingTask() {
+class TaskFetchVOC : BaseTimingTask() {
     companion object {
-        private lateinit var instance: FetchVOC
+        private lateinit var instance: TaskFetchVOC
     }
 
     @Autowired
diff --git a/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskLedgerRemind.kt b/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskLedgerRemind.kt
new file mode 100644
index 0000000..8fc78f4
--- /dev/null
+++ b/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskLedgerRemind.kt
@@ -0,0 +1,39 @@
+package cn.flightfeather.supervision.timingtask
+
+import cn.flightfeather.supervision.common.wx.TemplateManager
+import cn.flightfeather.supervision.domain.entity.MsgSubscribeWx
+import cn.flightfeather.supervision.domain.mapper.MsgSubscribeWxMapper
+import org.springframework.stereotype.Component
+import tk.mybatis.mapper.entity.Example
+import java.time.LocalDateTime
+
+/**
+ * 鍙拌处涓婁紶鍊掕鏃舵彁閱�
+ */
+@Component
+class TaskLedgerRemind(
+    private val msgSubscribeWxMapper: MsgSubscribeWxMapper
+) : BaseTimingTask() {
+
+    override val period: Long
+        get() = 1440L
+
+    override fun doTask(localtime: LocalDateTime) {
+        //1.閫夋嫨宸茶闃呬簡璇ユ潯鎻愰啋鐨勫井淇$敤鎴�
+        val ms = msgSubscribeWxMapper.selectByExample(Example(MsgSubscribeWx::class.java).apply {
+            createCriteria().andEqualTo("msTemplateId", TemplateManager.TEMPLATE_1)
+                .andGreaterThan("msCount", 0)
+        })
+        //2.鏌ユ壘寰俊鐢ㄦ埛缁戝畾鐨勫満鏅彴璐︿笂浼犳儏鍐�
+        //3.鏍规嵁缁熻缁撴灉鍐冲畾鏄惁鍙戦�佹彁閱掓帹閫�
+    }
+
+    /**
+     * 鍙拌处鎻愰啋浠诲姟瀹氫负姣忔湀5鍙锋棭涓�10鐐规彁閱掑綋鏈�10鍙蜂箣鍓嶆彁浜ゅ彴璐�
+     */
+    override fun execute(localtime: LocalDateTime) {
+        if (localtime.dayOfMonth == 5) {
+            doTask(localtime)
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/flightfeather/supervision/timingtask/PushFume.kt b/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskPushFume.kt
similarity index 95%
rename from src/main/kotlin/cn/flightfeather/supervision/timingtask/PushFume.kt
rename to src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskPushFume.kt
index b2e4007..55d4069 100644
--- a/src/main/kotlin/cn/flightfeather/supervision/timingtask/PushFume.kt
+++ b/src/main/kotlin/cn/flightfeather/supervision/timingtask/TaskPushFume.kt
@@ -8,29 +8,24 @@
 import cn.flightfeather.supervision.domain.mapper.DeviceInfoMapper
 import cn.flightfeather.supervision.domain.mapper.FumeMinuteValueMapper
 import cn.flightfeather.supervision.infrastructure.utils.DateUtil
-import com.github.pagehelper.PageHelper
 import org.slf4j.LoggerFactory
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Component
 import tk.mybatis.mapper.entity.Example
 import java.time.LocalDateTime
-import java.time.LocalTime
 import java.time.ZoneId
-import java.time.ZoneOffset
-import java.time.format.DateTimeFormatter
 import java.util.*
-import javax.annotation.PostConstruct
 import kotlin.math.round
 
 /**
  * 涓婁紶娌圭儫鐩戞祴鏁版嵁
  */
 @Component
-class PushFume : BaseTimingTask() {
+class TaskPushFume : BaseTimingTask() {
 
     companion object {
 //        private lateinit var instance: PushFume
-        val LOGGER = LoggerFactory.getLogger(PushFume::class.java)
+        val LOGGER = LoggerFactory.getLogger(TaskPushFume::class.java)
     }
 
     @Autowired
diff --git a/src/main/resources/generator/generatorConfig.xml b/src/main/resources/generator/generatorConfig.xml
index a1ffdec..65354ff 100644
--- a/src/main/resources/generator/generatorConfig.xml
+++ b/src/main/resources/generator/generatorConfig.xml
@@ -92,7 +92,17 @@
 <!--               selectByExampleQueryId="false"/>-->
 <!--        <table tableName="epk_t_enforcecase" domainObjectName="EnforceCase" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"-->
 <!--               selectByExampleQueryId="false"/>-->
-        <table tableName="sm_t_userinfo_wx" domainObjectName="UserInfoWx" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
-               selectByExampleQueryId="false"/>
+<!--        <table tableName="sm_t_userinfo_wx" domainObjectName="UserInfoWx" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"-->
+<!--               selectByExampleQueryId="false"/>-->
+<!--        <table tableName="ea_t_personal_info" domainObjectName="PersonalInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"-->
+<!--               selectByExampleQueryId="false"/>-->
+<!--        <table tableName="ea_t_msg_subscribe_wx" domainObjectName="MsgSubscribeWx" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false"-->
+<!--               enableSelectByExample="false"-->
+<!--               selectByExampleQueryId="false"/>-->
+<!--        <table tableName="sys_log_msg_subscribe_wx" domainObjectName="LogMsgSubscribeWx" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false"-->
+<!--               enableSelectByExample="false"-->
+<!--               selectByExampleQueryId="false"/>-->
+                <table tableName="sm_t_userinfo" domainObjectName="Userinfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
+                       selectByExampleQueryId="false"/>
     </context>
 </generatorConfiguration>
\ No newline at end of file
diff --git a/src/main/resources/mapper/BaseInfoMapper.xml b/src/main/resources/mapper/BaseInfoMapper.xml
index b692b1d..88f9e98 100644
--- a/src/main/resources/mapper/BaseInfoMapper.xml
+++ b/src/main/resources/mapper/BaseInfoMapper.xml
@@ -7,8 +7,17 @@
     -->
     <id column="BI_GUID" property="biGuid" jdbcType="VARCHAR" />
     <result column="BI_Name" property="biName" jdbcType="VARCHAR" />
+    <result column="BI_Nick_Name" property="biNickName" jdbcType="VARCHAR" />
     <result column="CI_GUID" property="ciGuid" jdbcType="VARCHAR" />
     <result column="CI_Name" property="ciName" jdbcType="VARCHAR" />
+    <result column="BI_Province_Code" property="biProvinceCode" jdbcType="VARCHAR" />
+    <result column="BI_Province_Name" property="biProvinceName" jdbcType="VARCHAR" />
+    <result column="BI_City_Code" property="biCityCode" jdbcType="VARCHAR" />
+    <result column="BI_City_Name" property="biCityName" jdbcType="VARCHAR" />
+    <result column="BI_District_Code" property="biDistrictCode" jdbcType="VARCHAR" />
+    <result column="BI_District_Name" property="biDistrictName" jdbcType="VARCHAR" />
+    <result column="BI_Town_Code" property="biTownCode" jdbcType="VARCHAR" />
+    <result column="BI_Town_Name" property="biTownName" jdbcType="VARCHAR" />
     <result column="BI_Management_Company_Id" property="biManagementCompanyId" jdbcType="VARCHAR" />
     <result column="BI_Management_Company" property="biManagementCompany" jdbcType="VARCHAR" />
     <result column="BI_Contact" property="biContact" jdbcType="VARCHAR" />
@@ -25,8 +34,9 @@
     <!--
       WARNING - @mbg.generated
     -->
-    BI_GUID, BI_Name, CI_GUID, CI_Name, BI_Management_Company_Id, BI_Management_Company, 
-    BI_Contact, BI_Telephone, BI_Address, BI_Create_Time, BI_Update_Time, BI_Extension1, 
-    BI_Extension2, BI_Extension3, BI_Remark
+    BI_GUID, BI_Name, BI_Nick_Name, CI_GUID, CI_Name, BI_Province_Code, BI_Province_Name, 
+    BI_City_Code, BI_City_Name, BI_District_Code, BI_District_Name, BI_Town_Code, BI_Town_Name, 
+    BI_Management_Company_Id, BI_Management_Company, BI_Contact, BI_Telephone, BI_Address, 
+    BI_Create_Time, BI_Update_Time, BI_Extension1, BI_Extension2, BI_Extension3, BI_Remark
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/LogMsgSubscribeWxMapper.xml b/src/main/resources/mapper/LogMsgSubscribeWxMapper.xml
new file mode 100644
index 0000000..188cdb7
--- /dev/null
+++ b/src/main/resources/mapper/LogMsgSubscribeWxMapper.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="cn.flightfeather.supervision.domain.mapper.LogMsgSubscribeWxMapper" >
+  <resultMap id="BaseResultMap" type="cn.flightfeather.supervision.domain.entity.LogMsgSubscribeWx" >
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="LMS_ID" property="lmsId" jdbcType="INTEGER" />
+    <result column="LMS_Open_Id" property="lmsOpenId" jdbcType="VARCHAR" />
+    <result column="LMS_Template_Id" property="lmsTemplateId" jdbcType="VARCHAR" />
+    <result column="LMS_Data" property="lmsData" jdbcType="VARCHAR" />
+    <result column="LMS_Time" property="lmsTime" jdbcType="TIMESTAMP" />
+    <result column="LMS_Msg_Id" property="lmsMsgId" jdbcType="VARCHAR" />
+    <result column="LMS_Result" property="lmsResult" jdbcType="BIT" />
+    <result column="LMS_Extension1" property="lmsExtension1" jdbcType="VARCHAR" />
+    <result column="LMS_Extension2" property="lmsExtension2" jdbcType="VARCHAR" />
+    <result column="LMS_Extension3" property="lmsExtension3" jdbcType="VARCHAR" />
+    <result column="LMS_Remark" property="lmsRemark" jdbcType="VARCHAR" />
+  </resultMap>
+  <sql id="Base_Column_List" >
+    <!--
+      WARNING - @mbg.generated
+    -->
+    LMS_ID, LMS_Open_Id, LMS_Template_Id, LMS_Data, LMS_Time, LMS_Msg_Id, LMS_Result, 
+    LMS_Extension1, LMS_Extension2, LMS_Extension3, LMS_Remark
+  </sql>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/MsgSubscribeWxMapper.xml b/src/main/resources/mapper/MsgSubscribeWxMapper.xml
new file mode 100644
index 0000000..c26c3c3
--- /dev/null
+++ b/src/main/resources/mapper/MsgSubscribeWxMapper.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="cn.flightfeather.supervision.domain.mapper.MsgSubscribeWxMapper" >
+  <resultMap id="BaseResultMap" type="cn.flightfeather.supervision.domain.entity.MsgSubscribeWx" >
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="MS_ID" property="msId" jdbcType="INTEGER" />
+    <result column="MS_Template_Id" property="msTemplateId" jdbcType="VARCHAR" />
+    <result column="MS_Open_Id" property="msOpenId" jdbcType="VARCHAR" />
+    <result column="MS_Count" property="msCount" jdbcType="INTEGER" />
+    <result column="MS_Accept" property="msAccept" jdbcType="BIT" />
+    <result column="MS_Update_Time" property="msUpdateTime" jdbcType="TIMESTAMP" />
+    <result column="MS_Extension1" property="msExtension1" jdbcType="VARCHAR" />
+    <result column="MS_Extension2" property="msExtension2" jdbcType="VARCHAR" />
+    <result column="MS_Extension3" property="msExtension3" jdbcType="VARCHAR" />
+    <result column="MS_Remark" property="msRemark" jdbcType="VARCHAR" />
+  </resultMap>
+  <sql id="Base_Column_List" >
+    <!--
+      WARNING - @mbg.generated
+    -->
+    MS_ID, MS_Template_Id, MS_Open_Id, MS_Count, MS_Accept, MS_Update_Time, MS_Extension1, 
+    MS_Extension2, MS_Extension3, MS_Remark
+  </sql>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/PersonalInfoMapper.xml b/src/main/resources/mapper/PersonalInfoMapper.xml
new file mode 100644
index 0000000..a920f0d
--- /dev/null
+++ b/src/main/resources/mapper/PersonalInfoMapper.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="cn.flightfeather.supervision.domain.mapper.PersonalInfoMapper" >
+  <resultMap id="BaseResultMap" type="cn.flightfeather.supervision.domain.entity.PersonalInfo" >
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="PI_GUID" property="piGuid" jdbcType="VARCHAR" />
+    <result column="PI_Name" property="piName" jdbcType="VARCHAR" />
+    <result column="PI_ID_Type_Num" property="piIdTypeNum" jdbcType="TINYINT" />
+    <result column="PI_ID_Type" property="piIdType" jdbcType="VARCHAR" />
+    <result column="PI_ID" property="piId" jdbcType="VARCHAR" />
+    <result column="PI_Position_Num" property="piPositionNum" jdbcType="TINYINT" />
+    <result column="PI_Position" property="piPosition" jdbcType="VARCHAR" />
+    <result column="PI_Extension1" property="piExtension1" jdbcType="VARCHAR" />
+    <result column="PI_Extension2" property="piExtension2" jdbcType="VARCHAR" />
+    <result column="PI_Extension3" property="piExtension3" jdbcType="VARCHAR" />
+    <result column="PI_Remark" property="piRemark" jdbcType="VARCHAR" />
+  </resultMap>
+  <sql id="Base_Column_List" >
+    <!--
+      WARNING - @mbg.generated
+    -->
+    PI_GUID, PI_Name, PI_ID_Type_Num, PI_ID_Type, PI_ID, PI_Position_Num, PI_Position, 
+    PI_Extension1, PI_Extension2, PI_Extension3, PI_Remark
+  </sql>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/RestaurantBaseInfoMapper.xml b/src/main/resources/mapper/RestaurantBaseInfoMapper.xml
index 4aef661..509559f 100644
--- a/src/main/resources/mapper/RestaurantBaseInfoMapper.xml
+++ b/src/main/resources/mapper/RestaurantBaseInfoMapper.xml
@@ -24,6 +24,9 @@
     <result column="RB_Cooking_Oil_Type" property="rbCookingOilType" jdbcType="VARCHAR" />
     <result column="RB_Cooking_Oil_Capacity" property="rbCookingOilCapacity" jdbcType="VARCHAR" />
     <result column="RB_Concentration_Area" property="rbConcentrationArea" jdbcType="VARCHAR" />
+    <result column="RB_Outfall_Count" property="rbOutfallCount" jdbcType="INTEGER" />
+    <result column="RB_Outfall_Location" property="rbOutfallLocation" jdbcType="VARCHAR" />
+    <result column="RB_Outfall_Num" property="rbOutfallNum" jdbcType="VARCHAR" />
     <result column="RB_Extension1" property="rbExtension1" jdbcType="VARCHAR" />
     <result column="RB_Extension2" property="rbExtension2" jdbcType="VARCHAR" />
     <result column="RB_Extension3" property="rbExtension3" jdbcType="VARCHAR" />
@@ -36,7 +39,8 @@
     RB_GUID, RB_Cuisine, RB_Cooking_Fumes_Type, RB_Peak_Period, RB_Indoor_Seating, RB_Outdoor_Seating, 
     RB_Total_Seating, RB_Outdoor_Barbecue, RB_Open_Kitchen, RB_Environment, RB_Cooking_Range_Num, 
     RB_Electric_Oven_Num, RB_Other_Cooker_Num, RB_Fresh_Air, RB_Air_Conditioner, RB_Exhaust_Fan, 
-    RB_Cooking_Oil_Type, RB_Cooking_Oil_Capacity, RB_Concentration_Area, RB_Extension1, 
-    RB_Extension2, RB_Extension3, RB_Remark
+    RB_Cooking_Oil_Type, RB_Cooking_Oil_Capacity, RB_Concentration_Area, RB_Outfall_Count, 
+    RB_Outfall_Location, RB_Outfall_Num, RB_Extension1, RB_Extension2, RB_Extension3, 
+    RB_Remark
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/UserInfoWxMapper.xml b/src/main/resources/mapper/UserInfoWxMapper.xml
index e51ef0b..ab69f66 100644
--- a/src/main/resources/mapper/UserInfoWxMapper.xml
+++ b/src/main/resources/mapper/UserInfoWxMapper.xml
@@ -7,6 +7,7 @@
     -->
     <id column="UI_Open_Id" property="uiOpenId" jdbcType="VARCHAR" />
     <result column="UI_GUID" property="uiGuid" jdbcType="VARCHAR" />
+    <result column="CI_GUID" property="ciGuid" jdbcType="VARCHAR" />
     <result column="UI_Nick_Name" property="uiNickName" jdbcType="VARCHAR" />
     <result column="UI_Gender" property="uiGender" jdbcType="VARCHAR" />
     <result column="UI_Country" property="uiCountry" jdbcType="VARCHAR" />
@@ -14,12 +15,13 @@
     <result column="UI_City" property="uiCity" jdbcType="VARCHAR" />
     <result column="UI_Avatar_Url" property="uiAvatarUrl" jdbcType="VARCHAR" />
     <result column="UI_UnionId" property="uiUnionid" jdbcType="VARCHAR" />
+    <result column="PI_GUID" property="piGuid" jdbcType="VARCHAR" />
   </resultMap>
   <sql id="Base_Column_List" >
     <!--
       WARNING - @mbg.generated
     -->
-    UI_GUID, UI_Open_Id, UI_Nick_Name, UI_Gender, UI_Country, UI_Province, UI_City, UI_Avatar_Url, 
-    UI_UnionId
+    UI_Open_Id, UI_GUID, CI_GUID, UI_Nick_Name, UI_Gender, UI_Country, UI_Province, UI_City, 
+    UI_Avatar_Url, UI_UnionId, PI_GUID
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/templates/commitment-restaurant.ftl b/src/main/resources/templates/commitment-restaurant.ftl
index 2089527..b9e8fcc 100644
--- a/src/main/resources/templates/commitment-restaurant.ftl
+++ b/src/main/resources/templates/commitment-restaurant.ftl
@@ -38,18 +38,18 @@
                         <p style="margin:0pt; orphans:0; text-align:center; widows:0"><span
                                 style=" font-size:12pt">缁熶竴绀句細淇$敤浠g爜</span></p>
                     </td>
-                    <td
+                    <td colspan="3"
                         style="border-bottom-color:#000000; border-bottom-style:solid; border-bottom-width:0.75pt; border-right-color:#000000; border-right-style:solid; border-right-width:0.75pt; border-top-color:#000000; border-top-style:solid; border-top-width:0.75pt; padding-left:5.4pt; padding-right:5.03pt; vertical-align:middle; width:133.55pt">
                         <p style="margin:0pt; orphans:0; text-align:center; widows:0"><span
                                 style=" font-size:12pt">${SocialCode}</span></p>
                     </td>
                     <td
-                        style="border-bottom-color:#000000; border-bottom-style:solid; border-bottom-width:0.75pt; border-right-color:#000000; border-right-style:solid; border-right-width:0.75pt; border-top-color:#000000; border-top-style:solid; border-top-width:0.75pt; padding-left:5.4pt; padding-right:5.03pt; vertical-align:middle; width:97.8pt">
+                        style="display:none;border-bottom-color:#000000; border-bottom-style:solid; border-bottom-width:0.75pt; border-right-color:#000000; border-right-style:solid; border-right-width:0.75pt; border-top-color:#000000; border-top-style:solid; border-top-width:0.75pt; padding-left:5.4pt; padding-right:5.03pt; vertical-align:middle; width:97.8pt">
                         <p style="margin:0pt; orphans:0; text-align:center; widows:0"><span
                                 style=" font-size:12pt">鐜瘎瀹℃壒鏂囧彿</span></p>
                     </td>
                     <td
-                        style="border-bottom-color:#000000; border-bottom-style:solid; border-bottom-width:0.75pt; border-right-color:#000000; border-right-style:solid; border-right-width:0.75pt; border-top-color:#000000; border-top-style:solid; border-top-width:0.75pt; padding-left:5.4pt; padding-right:5.03pt; vertical-align:middle; width:119.55pt">
+                        style="display:none;border-bottom-color:#000000; border-bottom-style:solid; border-bottom-width:0.75pt; border-right-color:#000000; border-right-style:solid; border-right-width:0.75pt; border-top-color:#000000; border-top-style:solid; border-top-width:0.75pt; padding-left:5.4pt; padding-right:5.03pt; vertical-align:middle; width:119.55pt">
                         <p style="margin:0pt; orphans:0; text-align:center; widows:0"><span
                                 style=" font-size:12pt">${Number}</span></p>
                     </td>
@@ -80,7 +80,7 @@
                                 style=" font-size:12pt">${IdNo}</span></p>
                     </td>
                 </tr>
-                <tr style="height:42.7pt">
+                <tr style="height:42.7pt;display:none;">
                     <td colspan="2"
                         style="border-bottom-color:#000000; border-bottom-style:solid; border-bottom-width:0.75pt; border-left-color:#000000; border-left-style:solid; border-left-width:0.75pt; border-right-color:#000000; border-right-style:solid; border-right-width:0.75pt; border-top-color:#000000; border-top-style:solid; border-top-width:0.75pt; padding-left:5.03pt; padding-right:5.03pt; vertical-align:middle; width:106.85pt">
                         <p style="line-height:20pt; margin:0pt; orphans:0; text-align:center; widows:0"><span
@@ -128,13 +128,14 @@
                         </p>
                         <p
                             style="line-height:20pt; margin:0pt; orphans:0; text-align:justify; text-indent:21pt; widows:0">
-                            <span style=" font-size:12pt">涓夈�佸畨瑁呮补鐑熷噣鍖栧拰寮傚懗澶勭悊璁炬柦锛屾补鐑熸帓鏀炬祿搴︾鍚�&lt;涓婃捣甯傞楗笟娌圭儫鎺掓斁鏍囧噯銆�(DB
-                                31/844 -2014)锛屽苟濮旀墭绗﹀悎銆婃竻娲佽涓氱粡钀ユ湇鍔¤鑼冦�嬬殑鏈嶅姟鍗曚綅瀹氭湡杩涜缁存姢娓呮礂锛屽強鏃惰褰曠浉鍏冲彴璐︼紝纭繚鍏舵甯镐娇鐢紝闃叉瀵瑰懆杈瑰眳姘戦�犳垚鐢熸椿鐜姹℃煋銆� </span>
+                            <span style=" font-size:12pt">涓夈�佸畨瑁呮补鐑熷噣鍖栧拰寮傚懗澶勭悊璁炬柦锛屾补鐑熸帓鏀炬祿搴︾鍚堛�婁笂娴峰競椁愰ギ涓氭补鐑熸帓鏀炬爣鍑嗐��(DB
+                                31/844 -2014)锛屽苟濮旀墭瑙勮寖鏈嶅姟鍗曚綅鍙傜収銆婃帓娌圭儫璁炬柦娓呮礂鎶�鏈鑼冦��(T/SHXFXH 002-2021)瀹氭湡杩涜缁存姢娓呮礂锛屽強鏃惰褰曠浉鍏冲彴璐︼紝纭繚鍏舵甯镐娇鐢紝闃叉瀵瑰懆杈瑰眳姘戦�犳垚鐢熸椿鐜姹℃煋銆� </span>
                         </p>
                         <p
                             style="line-height:20pt; margin:0pt; orphans:0; text-align:justify; text-indent:21pt; widows:0">
                             <span
-                                style=" font-size:12pt">鍥涖�佸畨瑁呯鍚堛�奀CAEPI-RG-Y-020-2011銆嬬殑娌圭儫鍦ㄧ嚎鐩戞祴瑁呯疆锛屽苟鍙婃椂涓庣敓鎬佺幆绔熼儴闂╙娌圭儫鐩戞帶绯荤粺鑱旂綉锛屽鎵樿鑼冩湇鍔″崟浣嶅畾鏈熻繍缁达紝鍙婃椂璁板綍鐩稿叧鍙拌处锛岀‘淇濆叾姝e父浣跨敤锛屼笉瓒呮爣鎺掓斁銆�
+                                style=" font-size:12pt">鍥涖�佸畨瑁呯鍚堛�奀CAEPI-RG-Y-020-2011銆嬬殑娌圭儫鍦ㄧ嚎鐩戞祴瑁呯疆锛屾牴鎹�婇楗补鐑熷湪绾跨洃娴嬶紙鍏夋暎灏勬硶锛変笌鐩戞帶鎶�鏈鑼冦��(T/SHAEPI 003-2022)锛屽強鏃朵笌鐢熸�佺幆澧冮儴闂ㄦ补鐑熺洃鎺ф暟鎹钩鍙拌仈缃戯紝
+                                濮旀墭瑙勮寖鏈嶅姟鍗曚綅瀹氭湡杩愮淮锛屽強鏃惰褰曠浉鍏冲彴璐︼紝纭繚鍏舵甯镐娇鐢紝涓嶈秴鏍囨帓鏀俱��
                             </span>
                         </p>
                         <p
diff --git a/src/test/kotlin/cn/flightfeather/supervision/CommonTest.kt b/src/test/kotlin/cn/flightfeather/supervision/CommonTest.kt
index 194d5ab..0c5c79a 100644
--- a/src/test/kotlin/cn/flightfeather/supervision/CommonTest.kt
+++ b/src/test/kotlin/cn/flightfeather/supervision/CommonTest.kt
@@ -6,6 +6,7 @@
 import com.google.gson.Gson
 import org.junit.Test
 import org.springframework.boot.json.GsonJsonParser
+import java.util.*
 import java.util.regex.Pattern
 
 /**
@@ -65,6 +66,9 @@
 
     @Test
     fun foo4() {
-
+        val d = Date()
+        println(d.time)
+        d.time = 1666262747
+        println(d)
     }
 }
\ No newline at end of file
diff --git a/src/test/kotlin/cn/flightfeather/supervision/common/wx/TemplateManagerTest.kt b/src/test/kotlin/cn/flightfeather/supervision/common/wx/TemplateManagerTest.kt
new file mode 100644
index 0000000..1330873
--- /dev/null
+++ b/src/test/kotlin/cn/flightfeather/supervision/common/wx/TemplateManagerTest.kt
@@ -0,0 +1,25 @@
+package cn.flightfeather.supervision.common.wx
+
+import org.junit.Test
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.extension.ExtendWith
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.junit.jupiter.SpringExtension
+import org.springframework.test.context.junit4.SpringRunner
+
+@RunWith(SpringRunner::class)
+@ExtendWith(SpringExtension::class)
+@SpringBootTest
+class TemplateManagerTest{
+
+    @Autowired
+    lateinit var templateManager: TemplateManager
+
+    @Test
+    fun newTemplate() {
+        val msg = templateManager.newTemplate(0, "otZkc5cC55BtV2AFZdXMvBw0oJo8", listOf("value1", "value2", "value3", "value4"))
+        println(msg)
+    }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImplTest.kt b/src/test/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImplTest.kt
new file mode 100644
index 0000000..3d630ec
--- /dev/null
+++ b/src/test/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/NotificationServiceImplTest.kt
@@ -0,0 +1,31 @@
+package cn.flightfeather.supervision.lightshare.service.Impl
+
+import cn.flightfeather.supervision.lightshare.service.NotificationService
+import org.junit.Test
+import org.junit.jupiter.api.extension.ExtendWith
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.junit.jupiter.SpringExtension
+import org.springframework.test.context.junit4.SpringRunner
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+
+@RunWith(SpringRunner::class)
+@ExtendWith(SpringExtension::class)
+@SpringBootTest
+class NotificationServiceImplTest{
+
+    @Autowired
+    lateinit var notificationService: NotificationService
+
+    @Test
+    fun pushMsgWx() {
+        Thread.sleep(10000)
+        notificationService.pushMsgWx(0)
+        val input = BufferedReader(InputStreamReader(System.`in`))
+        val reader = input.readLine()
+    }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImplTest.kt b/src/test/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImplTest.kt
new file mode 100644
index 0000000..5055805
--- /dev/null
+++ b/src/test/kotlin/cn/flightfeather/supervision/lightshare/service/Impl/WxUserServiceImplTest.kt
@@ -0,0 +1,25 @@
+package cn.flightfeather.supervision.lightshare.service.Impl
+
+import cn.flightfeather.supervision.lightshare.service.WxUserService
+import org.junit.Test
+import org.junit.jupiter.api.extension.ExtendWith
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.junit.jupiter.SpringExtension
+import org.springframework.test.context.junit4.SpringRunner
+
+@RunWith(SpringRunner::class)
+@ExtendWith(SpringExtension::class)
+@SpringBootTest
+class WxUserServiceImplTest {
+
+    @Autowired
+    lateinit var wxUserService: WxUserService
+
+    @Test
+    fun subscribeResult() {
+        val msg = "{\"ToUserName\":\"gh_213453153\", \"List\": [{\"TemplateId\":\"sadaihdfjhsadoaiwhfefe\", \"SubscribeStatusString\":\"accept\"}]}"
+        wxUserService.subscribeResult(msg)
+    }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/cn/flightfeather/supervision/timingtask/PushFumeTest.kt b/src/test/kotlin/cn/flightfeather/supervision/timingtask/PushFumeTest.kt
index 9307b92..30aac88 100644
--- a/src/test/kotlin/cn/flightfeather/supervision/timingtask/PushFumeTest.kt
+++ b/src/test/kotlin/cn/flightfeather/supervision/timingtask/PushFumeTest.kt
@@ -1,7 +1,6 @@
 package cn.flightfeather.supervision.timingtask
 
 import cn.flightfeather.supervision.SupervisionApplication
-import cn.flightfeather.supervision.common.net.FumeHttpService
 import cn.flightfeather.supervision.domain.entity.AvgFumeMinuteValue
 import cn.flightfeather.supervision.domain.entity.FumeMinuteValue
 import cn.flightfeather.supervision.domain.mapper.AvgFumeMinuteValueMapper
@@ -21,14 +20,13 @@
 import java.util.*
 import java.util.concurrent.Executors
 import java.util.concurrent.TimeUnit
-import kotlin.math.round
 
 @RunWith(SpringJUnit4ClassRunner::class)
 @SpringBootTest(classes = [SupervisionApplication::class])
 class PushFumeTest {
 
     @Autowired
-    lateinit var pushFume: PushFume
+    lateinit var pushFume: TaskPushFume
 
     @Autowired
     lateinit var fumeMinuteValueMapper: FumeMinuteValueMapper

--
Gitblit v1.9.3