admin
2021-11-19 4daec329f36cc9d86911c08b8ec8e00270792189
自动化代码中的service优化
14个文件已修改
96个文件已添加
9284 ■■■■■ 已修改文件
src/main/java/com/ks/codegenerator/utils/ServiceBuilder.java 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/pom.xml 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/Application.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/AdminApiFilter.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/SignValidate.java 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/config/WebSecurityConfig.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/AlipayController.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/WXController.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/SystemController.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/user/UserInfoAdminController.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/user/UserLoginRecordAdminController.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/vip/VIPPriceAdminController.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/SMSController.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/UserController.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/VIPController.java 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/config/SystemConfigDao.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/QQUserInfoDao.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/UserInfoDao.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/UserLoginRecordDao.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/WXUserInfoDao.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/OrderRecordDao.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/UserVIPInfoDao.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/VIPPriceDao.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/user/LoginInfoDTO.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/vip/OrderPaySuccessForm.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/vip/PayWayInfoDTO.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/APPPlatform.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/SystemEnum.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfig.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfigKey.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/QQUserInfo.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/UserInfo.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/UserLoginRecord.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/WXUserInfo.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/OrderRecord.java 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/OrderType.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/UserVIPInfo.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/VIPPrice.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/VIPPriceType.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/goldcorn/GoldCornException.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/user/LoginException.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/vip/OrderException.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/vip/PayException.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/vip/VIPException.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/AdminUserServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/config/SystemConfigServiceImpl.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/QQUserInfoServiceImpl.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserAccountServiceImpl.java 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserInfoServiceImpl.java 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserLoginRecordServiceImpl.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/WXUserInfoServiceImpl.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/OrderServiceImpl.java 527 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/VIPPriceServiceImpl.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/VIPServiceImpl.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/AdminUserService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/config/SystemConfigService.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/QQUserInfoService.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserAccountService.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserInfoService.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserLoginRecordService.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/WXUserInfoService.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/vip/IPaySuccess.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/vip/OrderService.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/vip/VIPPriceService.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/vip/VIPService.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/manager/GoldCornManager.java 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/manager/VerifyCodeManager.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/VIPPriceQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/config/SystemConfigQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/user/QQUserInfoQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/user/UserInfoQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/user/UserLoginRecordQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/user/WXUserInfoQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/vip/VIPPriceQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/AliyunOneKeyLoginUtil.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/ApiCodeConstant.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/Constant.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/PayConstant.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/SystemInfoUtil.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/vip/VIPOrderUtil.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/vip/VipUtil.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/AcceptAdminData.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/AcceptData.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/SystemVO.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/user/UserInfoVO.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/vip/OrderInfoVO.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/alipay.properties 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/application-dev.yml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/ehcache.xml 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/BaseMapper.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/OrderRecordMapper.xml 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/QQUserInfoMapper.xml 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/UserInfoMapper.xml 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/UserVIPInfoMapper.xml 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/WXUserInfoMapper.xml 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/css/login.css 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/index.html 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/js/http.js 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/js/xadmin.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/login.html 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/user/user_info_list.html 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/user/user_login_record_list.html 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/vip/vipprice_add.html 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/vip/vipprice_list.html 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/vip/vipprice_update.html 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/welcome.html 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/wx/apiclient_key.pem 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/wxpay.properties 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/test/java/test/GeneratorTest.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/pom.xml 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ks/codegenerator/utils/ServiceBuilder.java
@@ -1,12 +1,19 @@
package com.ks.codegenerator.utils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.yeshi.utils.FileUtil;
import org.yeshi.utils.StringUtil;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -66,7 +73,7 @@
        //修改文件名称与文件夹名称
        renameDir(destPath);
        //重新命名包名
        renamePackage(destPath + "/app/src/main/java/com/ks/app");
        renamePackage(destPath + "/app/src/main/java/" + subpks.replace(".", "/"));
        replaceSettings(destPath);
        //压缩文件夹
        File zip = new File(new File(destPath).getParent(), new File(destPath).getName() + ".zip");
@@ -81,8 +88,35 @@
        FileUtils.replaceFileContent(path + "/pom.xml", "<groupId>com.ks</groupId>", String.format("<groupId>%s</groupId>", getGroupId(pks)));
        FileUtils.replaceFileContent(path + "/pom.xml", "<artifactId>demo</artifactId>", String.format("<artifactId>%s</artifactId>", getArtifactId(pks)));
        FileUtils.replaceFileContent(path + "/app/pom.xml", "<groupId>com.ks</groupId>", String.format("<groupId>%s</groupId>", getGroupId(subpks)));
        FileUtils.replaceFileContent(path + "/app/pom.xml", "<artifactId>demo</artifactId>", String.format("<artifactId>%s</artifactId>", getArtifactId(subpks)));
        //更改parent以及artifactId
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(path + "/app/pom.xml");
        NodeList list = doc.getElementsByTagName("project").item(0).getChildNodes();
        for (int i = 0; i < list.getLength(); i++) {
            if (list.item(i).getNodeName().equalsIgnoreCase("parent")) {
                NodeList parent = list.item(i).getChildNodes();
                for (int j = 0; j < parent.getLength(); j++) {
                    Node node = parent.item(j);
                    switch (node.getNodeName()) {
                        case "artifactId":
                            node.setTextContent(getArtifactId(pks));
                            break;
                        case "groupId":
                            node.setTextContent(getGroupId(pks));
                            break;
                    }
                }
            } else if (list.item(i).getNodeName().equalsIgnoreCase("artifactId")) {
                list.item(i).setTextContent(getArtifactId(subpks));
            }
        }
        //保存
        Transformer ts = TransformerFactory.newInstance().newTransformer();
        ts.transform(new DOMSource(doc), new StreamResult(path + "/app/pom.xml"));
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-dev.yml", "com.ks.app", subpks);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-pro.yml", "com.ks.app", subpks);
@@ -93,7 +127,7 @@
        FileUtils.renameFile(path + "/service.iml", name + ".iml");
        //更改java文件的路径
        FileUtils.copyFileDir(path + "/app/src/main/java/com/ks/app", path + "/app/src/main/java/" + subpks.replace(".", "/"));
        new File(path + "/app/src/main/java/com/ks/app").delete();
        FileUtil.deleteFileDir(new File(path + "/app/src/main/java/com/ks/app"));
    }
src/main/resources/code/service/app/pom.xml
@@ -20,16 +20,22 @@
        <seata.version>1.4.1</seata.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.ks</groupId>
            <artifactId>facade-goldcorn</artifactId>
            <version>0.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.yeshi</groupId>
            <artifactId>utils</artifactId>
            <version>0.1.5</version>
            <groupId>com.ks</groupId>
            <artifactId>lib-common</artifactId>
            <version>0.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
@@ -187,10 +193,31 @@
            <version>3.8.1</version>
        </dependency>
        <!-- 阿里云 -->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.4.6</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dypnsapi</artifactId>
            <version>1.0.5</version>
        </dependency>
        <!-- 支付宝相关 -->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.9.71.ALL</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>app</finalName>
        <plugins>
src/main/resources/code/service/app/src/main/java/com/ks/app/Application.java
@@ -1,13 +1,10 @@
package com.ks.app;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -15,9 +12,9 @@
//不引入数据库
//@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class,DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class
//        , DruidDataSourceAutoConfigure.class, HibernateJpaAutoConfiguration.class})
//@MapperScan(basePackages = "com.ks.app.mapper")
@MapperScan(basePackages = "com.ks.app.dao")
@SpringBootApplication
//@EnableTransactionManagement
@EnableTransactionManagement
//@EnableDubbo(scanBasePackages = "com.ks.push.service.remote")
public class Application implements ApplicationListener<ContextRefreshedEvent> {
    private final static Logger logger = LoggerFactory.getLogger(Application.class);
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/AdminApiFilter.java
New file
@@ -0,0 +1,64 @@
package com.ks.app.aop;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.utils.ApiCodeConstant;
import com.ks.app.utils.SystemInfoUtil;
import com.ks.app.vo.AcceptAdminData;
import com.ks.app.vo.AcceptData;
import net.sf.json.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
//后台接口监控
@Component
@Aspect
@Order(2)
public class AdminApiFilter {
    public static final String EDP = "execution(* com.ks.app.controller.admin..*.*(..))";
    @Around(EDP)
    public Object around(ProceedingJoinPoint joinPoint) throws IOException {
        Object[] args = joinPoint.getArgs();
        ServletRequestAttributes servletContainer = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        AcceptAdminData acceptAdminData = null;
        for (Object obj : args) {
            if (obj instanceof AcceptAdminData) {
                acceptAdminData = (AcceptAdminData) obj;
                break;
            }
        }
        if (acceptAdminData != null) {
            acceptAdminData.setSystem(SystemInfoUtil.getAdminSelectedSystem(servletContainer.getRequest().getSession()));
        }
        try {
            return joinPoint.proceed(args);
        } catch (Throwable e) {
            PrintWriter out = servletContainer.getResponse().getWriter();
            out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_ERROR_IN_SERVER, "服务器内部错误"));
            out.close();
        }
        return null;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/SignValidate.java
New file
@@ -0,0 +1,157 @@
package com.ks.app.aop;
import com.ks.app.entity.APPPlatform;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.utils.ApiCodeConstant;
import com.ks.app.utils.SystemInfoUtil;
import com.ks.app.vo.AcceptData;
import net.sf.json.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.util.*;
//客户端接口签名验证
@Component
@Aspect
@Order(2)
public class SignValidate {
    public static final String EDP = "execution(* com.ks.app.controller.client..*.*(..))";
    @Resource
    private SystemConfigService systemConfigService;
    @Around(EDP)
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        PrintWriter out = null;
        ServletRequestAttributes servletContainer = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        out = servletContainer.getResponse().getWriter();
        HttpServletRequest request = servletContainer.getRequest();
        AcceptData acceptData = null;
        for (Object obj : args) {
            if (obj instanceof AcceptData) {
                acceptData = (AcceptData) obj;
            } else if (obj instanceof HttpServletRequest) {
                request = (HttpServletRequest) obj;
            }
        }
        if (acceptData == null) {
            out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_FAIL_SIGN_ERROR, "签名错误"));
            return null;
        }
        boolean isRight = signIsRight(request, acceptData);
        // 签名是否正确
        if (isRight) {
            // 判断签名超时
            if (Math.abs((acceptData.getTimestamp() - System.currentTimeMillis())) > 1000 * 60 * 10) {
                out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_FAIL_OUT_TIME, "时间错误"));
                return null;
            }
            if (acceptData != null) {
                acceptData.setSystem(SystemInfoUtil.getSystem(acceptData.getPlatform(), acceptData.getPackages()));
            }
//            final String url = request.getRequestURI();
//            final Map<String, String[]> params = request.getParameterMap();
//            ThreadUtil.run(new Runnable() {
//                @Override
//                public void run() {
//                    // 记录请求日志
//                    LogHelper.requestInfo(url, params);
//                }
//            });
            Object obj = null;
            try {
                long startTime = System.currentTimeMillis();
                obj = joinPoint.proceed(args);
            } catch (Throwable e) {
                out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_ERROR_IN_SERVER, "服务器内部错误"));
                return null;
            }
            return obj;
        } else {
            out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_FAIL_SIGN_ERROR, "签名错误"));
            return null;
        }
    }
    private String getHttpServletParams(HttpServletRequest request) {
        if (request == null) {
            return "";
        }
        Map map = request.getParameterMap();
        if (map != null) {
            Iterator<String> its = map.keySet().iterator();
            JSONObject json = new JSONObject();
            while (its.hasNext()) {
                String next = its.next();
                if (map.get(next) != null) {
                    Object[] objects = (Object[]) map.get(next);
                    if (objects != null && objects.length > 0) {
                        json.put(next, objects[0].toString());
                    }
                }
            }
            return json.toString();
        }
        return "";
    }
    /**
     * 判断签名的正确性 Android version>50
     *
     * @param request
     * @return
     */
    private boolean signIsRight(HttpServletRequest request, AcceptData acceptData) {
        Map<String, String[]> map = request.getParameterMap();
        Iterator<String> its = map.keySet().iterator();
        List<String> list = new ArrayList<>();
        while (its.hasNext()) {
            String key = its.next();
            if (key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("callback") || key.equalsIgnoreCase("_")) {
                continue;
            }
            String[] values = map.get(key);
            list.add(key + "=" + values[0]);
        }
        Collections.sort(list);
        String str = "";
        for (String st : list) {
            str += st + "&";
        }
        String key = systemConfigService.getValueCache(acceptData.getSystem(), SystemConfigKey.signKey);
        String sign = StringUtil.Md5(str + key);
        if (sign.equalsIgnoreCase(request.getParameter("sign") + "")) {
            return true;
        } else {
            return false;
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/config/WebSecurityConfig.java
@@ -10,6 +10,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
@@ -23,11 +24,13 @@
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.web.filter.OncePerRequestFilter;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
@@ -170,11 +173,13 @@
            @Override
            public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                logger.info("onLogoutSuccess");
                httpServletResponse.getWriter().print(JsonUtil.loadTrueResult(""));
            }
        })
                .and()
                .csrf().disable()
                .rememberMe().userDetailsService(new MyUserDetailsService());
                .rememberMe().userDetailsService(new MyUserDetailsService())
                .and().exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint());
        http.addFilterBefore(new VerificationCodeFilter(), UsernamePasswordAuthenticationFilter.class);
    }
@@ -235,4 +240,20 @@
        }
    }
    //自定义未授权返回
    class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response,
                             AuthenticationException authException) throws IOException, ServletException {
            String url = request.getRequestURI().toString();
            if (url.contains("/admin/api/")) {
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
            } else {
                response.sendRedirect("/login.html");
            }
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/AlipayController.java
New file
@@ -0,0 +1,98 @@
package com.ks.app.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.google.gson.Gson;
import com.ks.app.service.inter.vip.OrderService;
import com.ks.app.utils.vip.VIPOrderUtil;
import com.ks.app.utils.vip.VipUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.entity.alipay.AlipayAppInfo;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@Controller
@RequestMapping("alipay")
public class AlipayController {
    Logger logger = LoggerFactory.getLogger(AlipayController.class);
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private OrderService orderService;
    @RequestMapping("printPayForm")
    public void printPayForm(String formId, HttpServletResponse response) {
        String form = redisTemplate.opsForValue().get(formId);
        if (StringUtil.isNullOrEmpty(form)) {
            form = "出错了,请稍后再试";
        }
        response.setContentType("text/html;charset=GBK");
        try {
            response.getWriter().write(form);//直接将完整的表单html输出到页面
            response.getWriter().flush();
            response.getWriter().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @RequestMapping("pay")
    public void pay(HttpServletRequest request, HttpServletResponse response) {
        try {
            request.setCharacterEncoding("GBK");
            response.setCharacterEncoding("GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Map<String, String[]> params = request.getParameterMap();
        Map<String, String> map = new HashMap<>();
        for (Iterator<String> its = params.keySet().iterator(); its.hasNext(); ) {
            String key = its.next();
            map.put(key, params.get(key)[0]);
        }
        String outTradeNo = map.get("out_trade_no") + "";
        String tradeStatus = map.get("trade_status") + "";
        logger.info("支付回调:" + new Gson().toJson(map));
        AlipayAppInfo app = VipUtil.getAlipayApp();
        try {
            boolean right = AlipaySignature.rsaCheckV1(map, app.getAlipayPublicKey(), "GBK", map.get("sign_type"));
            if (right) {
                //支付成功
                if ("TRADE_SUCCESS".equalsIgnoreCase(tradeStatus)) {
                    Long id = VIPOrderUtil.getIdFromOutOrderNo(outTradeNo);
                    logger.info("订单ID:{}", id);
                    orderService.checkOrderPayState(id);
                }
                response.getWriter().print("success");
                response.getWriter().close();
            }
            logger.info("签名是否正确:" + right);
        } catch (AlipayApiException | IOException e) {
            e.printStackTrace();
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/WXController.java
New file
@@ -0,0 +1,173 @@
package com.ks.app.controller;
import com.ks.app.service.inter.vip.OrderService;
import com.ks.app.utils.vip.VIPOrderUtil;
import com.ks.app.utils.vip.VipUtil;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.entity.wx.WXAPPInfo;
import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
@Controller
@RequestMapping("wx")
public class WXController {
    Logger logger = LoggerFactory.getLogger(WXController.class);
    @Resource
    private OrderService orderService;
    private static String decryptToString(String apiV3Key, String associatedData, String nonce, String ciphertext)
            throws GeneralSecurityException, IOException {
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            SecretKeySpec key = new SecretKeySpec(apiV3Key.getBytes("UTF-8"), "AES");
            GCMParameterSpec spec = new GCMParameterSpec(128, nonce.getBytes("UTF-8"));
            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData.getBytes("UTF-8"));
            return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(e);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw new IllegalArgumentException(e);
        }
    }
    /**
     * 处理通知结果
     *
     * @param request
     * @throws Exception
     */
    private void process(HttpServletRequest request) throws Exception {
        WXAPPInfo wxappInfo = VipUtil.getWXAPP();
        //验证证书序列号
        String mchSerialNo = request.getHeader("Wechatpay-Serial");
        logger.debug("微信支付mchSerialNo:{}", mchSerialNo);
//        if (!mchSerialNo.equalsIgnoreCase(wxappInfo.getMchSerialNo())) {
//            throw new Exception("证书序列号不一致");
//        }
        String timeStamp = request.getHeader("Wechatpay-Timestamp");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String signature = request.getHeader("Wechatpay-Signature");
        String data = null;
        try {
            if (request.getInputStream() != null) {
                String entity = IOUtils.toString(request.getInputStream(), "UTF-8");
                data = entity;
                logger.debug("微信支付回调entity:{}", entity);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (StringUtil.isNullOrEmpty(data)) {
            throw new Exception("通知的内容为空");
        }
        JSONObject resultJson = JSONObject.fromObject(data);
        String eventType = resultJson.optString("event_type");
        switch (eventType) {
            //支付成功
            case "TRANSACTION.SUCCESS":
                JSONObject resource = resultJson.optJSONObject("resource");
                String ciphertext = resource.optString("ciphertext");
                String r = decryptToString(wxappInfo.getApiV3Key(), resource.optString("associated_data"), resource.optString("nonce"), ciphertext);
                //解密格式如下 {"mchid":"1520950211","appid":"wxa99686bb65a9f466","out_trade_no":"buwan-vip-8","transaction_id":"4200000796202101259681241680","trade_type":"MWEB","trade_state":"SUCCESS","trade_state_desc":"支付成功","bank_type":"OTHERS","attach":"","success_time":"2021-01-25T16:18:33+08:00","payer":{"openid":"oq7R20lxhKF8qSnkszxFJHViyKEY"},"amount":{"total":10,"payer_total":10,"currency":"CNY","payer_currency":"CNY"}}
                logger.debug("数据解码:{}", r);
                JSONObject decript = JSONObject.fromObject(r);
                String outTradeNo = decript.optString("out_trade_no");
                String appId = decript.optString("appid");
                String mchId = decript.optString("mchid");
                String tradeState = decript.optString("trade_state");
                //支付成功
                if (tradeState.equalsIgnoreCase("SUCCESS")) {
                    Long id = VIPOrderUtil.getIdFromOutOrderNo(outTradeNo);
                    orderService.checkOrderPayState(id);
                }
                break;
        }
    }
    /**
     * 微信支付结果通知
     *
     * @param request
     * @param response
     */
    @RequestMapping("pay/vip")
    public void vipPay(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            process(request);
            JSONObject data = new JSONObject();
            data.put("code", "SUCCESS");
            data.put("message", "处理成功");
            response.sendError(200, data.toString());
        } catch (Exception e) {
            logger.error("微信支付回调处理出错:", e);
            e.printStackTrace();
            JSONObject data = new JSONObject();
            data.put("code", "FAIL");
            data.put("message", e.getMessage());
            response.sendError(500, data.toString());
        }
    }
    public static void main(String[] args) {
        String result = "{\n" +
                "    \"id\":\"c86a0485-0b56-5c6a-b449-d2a17fbb98ea\",\n" +
                "    \"create_time\":\"2021-01-25T16:18:33+08:00\",\n" +
                "    \"resource_type\":\"encrypt-resource\",\n" +
                "    \"event_type\":\"TRANSACTION.SUCCESS\",\n" +
                "    \"summary\":\"支付成功\",\n" +
                "    \"resource\":{\n" +
                "        \"original_type\":\"transaction\",\n" +
                "        \"algorithm\":\"AEAD_AES_256_GCM\",\n" +
                "        \"ciphertext\":\"UG6kFmJ4z+zCyOldYZLa/y+jzWwyLLMjc8usFqum0Yh08qR0nGPhLYyXCyIGi6DvnG33Ju7t1grKBA5VP0nLqw8NrITwajCK+Ph6avkxSz6lv7ObenIGp6tg+SJe/UxS9rToLH0sDVUB4L6XvawHw5ite/40G0lrdVCbZlJZCm4NxfnH3iRMnBZBw3QaUlySRoKugMIc2WzloHueq7K4bc7tCln4uro3eNDEHe++p2QWuiHmDm6s+aMLHKdQj723aVPhmZLc1kWqUAua6QJx77Jn3eYy8I0PksTKh1EdK3DV4+Fl4+UBZ86aqHdIHy+7gj0vRyDXXIUdfHYHQPMkYr46KfjoVSbA/Jop+2uH610a8jBRP4aP/3YJ2XBJbvw/DSupTJ7z8k1e9xCNJUfN3SeycvFIyaQI/mYi8jpe2F6ek2wexGUAXB5bDmoNGMGkIbbLE9NjJazF8O1WtQilqMIeJ/CiW6Pnrn0N/BibK1EuJxyr2dXmHt+aA+jpvwI8pTWBXn8ZeYG9CeMM0Ml+mBQcPzYdPx1ZsrKylJoIlvwSZTy4cRGSQlC/0w==\",\n" +
                "        \"associated_data\":\"transaction\",\n" +
                "        \"nonce\":\"2pIZSvqoRYYu\"\n" +
                "    }\n" +
                "}";
        WXAPPInfo wxappInfo = new WXAPPInfo("wxa99686bb65a9f466", "1520950211", "454328C324C6CC21355D064B44D6524CD7506DD0", "", "XYJkJ2018FAfaodCCx899mLl138rfGVd");
        JSONObject resultJson = JSONObject.fromObject(result);
        JSONObject resource = resultJson.optJSONObject("resource");
        String ciphertext = resource.optString("ciphertext");
        try {
            String r = decryptToString(wxappInfo.getApiV3Key(), resource.optString("associated_data"), resource.optString("nonce"), ciphertext);
            System.out.println(r);
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/SystemController.java
New file
@@ -0,0 +1,61 @@
package com.ks.app.controller.admin;
import com.ks.app.entity.SystemEnum;
import com.ks.app.service.inter.AdminUserService;
import com.ks.app.utils.SystemInfoUtil;
import com.ks.app.vo.SystemVO;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping("/admin/api/system")
public class SystemController {
    @Resource
    private AdminUserService adminUserService;
    @ResponseBody
    @RequestMapping("systemList")
    public String systemList(HttpSession session) {
        List<SystemVO> systemVOList = new ArrayList<>();
        SystemVO selected = null;
        for (SystemEnum system : SystemEnum.values()) {
            SystemVO systemVO = new SystemVO(system.getName(), system.name(), system == SystemInfoUtil.getAdminSelectedSystem(session));
            if (systemVO.isSelected()) {
                selected = systemVO;
            }
            systemVOList.add(systemVO);
        }
        if (selected == null) {
            systemVOList.get(0).setSelected(true);
            SystemInfoUtil.saveAdminSelectedSystem(session, SystemEnum.valueOf(systemVOList.get(0).getKey()));
        }
        JSONObject data = new JSONObject();
        data.put("count", systemVOList.size());
        data.put("list", systemVOList);
        return JsonUtil.loadTrueResult(data);
    }
    @ResponseBody
    @RequestMapping("selectSystem")
    public String selectSystem(String key, HttpSession session) {
        if (SystemEnum.valueOf(key) == null) {
            return JsonUtil.loadFalseResult("选择失败,系统不存在");
        }
        SystemInfoUtil.saveAdminSelectedSystem(session, SystemEnum.valueOf(key));
        return JsonUtil.loadTrueResult("");
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/user/UserInfoAdminController.java
New file
@@ -0,0 +1,142 @@
package com.ks.app.controller.admin.user;
import com.google.gson.*;
import com.ks.app.vo.AcceptAdminData;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.TimeUtil;
import com.google.gson.reflect.TypeToken;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.service.inter.user.UserInfoService;
import com.ks.app.service.query.user.UserInfoQuery;
import org.yeshi.utils.statistic.BaseStatisticTimeQuery;
import org.yeshi.utils.statistic.StatisticNumberResult;
import org.yeshi.utils.statistic.StatisticResulterFilterUtil;
import org.yeshi.utils.statistic.StatisticTimeSpan;
@Controller
@RequestMapping("admin/api/user")
public class UserInfoAdminController {
    @Resource
    private UserInfoService userInfoService;
    private String loadPrint(String callback, String root) {
        return root;
    }
    @ResponseBody
    @RequestMapping("list")
    public String list(UserInfoQuery query, int page, int limit, String callback) {
        List<UserInfo> list = userInfoService.list(query, page, limit);
        //获取详情
        if (list != null) {
            List<Long> idList = new ArrayList<>();
            for (UserInfo user : list) {
                idList.add(user.getId());
            }
            list = userInfoService.getDetailList(idList);
        }
        long count = userInfoService.count(query);
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).create();
        data.put("list", gson.toJson(list));
        data.put("count", count);
        return loadPrint(callback, JsonUtil.loadTrueResult(data));
    }
    @ResponseBody
    @RequestMapping("delete")
    public String delete(String ids, String callback) {
        Type type = new TypeToken<List<Long>>() {
        }.getType();
        List<Long> idList = new Gson().fromJson(ids, type);
        userInfoService.delete(idList);
        return loadPrint(callback, JsonUtil.loadTrueResult(""));
    }
    @ResponseBody
    @RequestMapping("add")
    public String add(UserInfo bean, HttpSession session, String callback) {
        try {
            userInfoService.add(bean);
            return loadPrint(callback, JsonUtil.loadTrueResult(""));
        } catch (Exception e) {
            return loadPrint(callback, JsonUtil.loadFalseResult(e.getMessage()));
        }
    }
    @ResponseBody
    @RequestMapping("get")
    public String get(Long id, HttpSession session, String callback) {
        UserInfo entity = userInfoService.get(id);
        if (entity != null) {
            return loadPrint(callback, JsonUtil.loadTrueResult(entity));
        } else {
            return loadPrint(callback, JsonUtil.loadFalseResult("ID不存在"));
        }
    }
    @ResponseBody
    @RequestMapping("update")
    public String update(UserInfo bean, HttpSession session, String callback) {
        if (bean.getId() == null) {
            return loadPrint(callback, JsonUtil.loadFalseResult("ID不能为空"));
        }
        try {
            userInfoService.update(bean);
        } catch (Exception e) {
            return loadPrint(callback, JsonUtil.loadFalseResult(e.getMessage()));
        }
        return loadPrint(callback, JsonUtil.loadTrueResult(""));
    }
    @ResponseBody
    @RequestMapping("statisticRegisterUser")
    public String statisticRegisterUser(AcceptAdminData acceptAdminData, long startTime, long endTime, String span, String callback) {
        if (endTime < startTime) {
            return JsonUtil.loadFalseResult("开始时间不能大于结束时间");
        }
        if (StatisticTimeSpan.valueOf(span) == null) {
            return JsonUtil.loadFalseResult("时间间隔不存在");
        }
        BaseStatisticTimeQuery timeQuery = new BaseStatisticTimeQuery();
        timeQuery.setStartTime(new Date(startTime));
        timeQuery.setEndTime(new Date(endTime));
        timeQuery.setTimeSpan(StatisticTimeSpan.valueOf(span));
        List<StatisticNumberResult> list = userInfoService.statisticRegisterUser(acceptAdminData.getSystem(), timeQuery);
        list = StatisticResulterFilterUtil.filterNumberResult(list, timeQuery);
        JSONObject data = new JSONObject();
        data.put("list", new Gson().toJson(list));
        data.put("count", list.size());
        return loadPrint(callback, JsonUtil.loadTrueResult(data));
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/user/UserLoginRecordAdminController.java
New file
@@ -0,0 +1,64 @@
package com.ks.app.controller.admin.user;
import com.google.gson.*;
import com.ks.app.entity.user.UserLoginRecord;
import com.ks.app.service.inter.user.UserLoginRecordService;
import com.ks.app.service.query.user.UserLoginRecordQuery;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.TimeUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("admin/api/user/loginrecord")
public class UserLoginRecordAdminController {
    @Resource
    private UserLoginRecordService userLoginRecordService;
    private String loadPrint(String callback, String root) {
        return root;
    }
    @ResponseBody
    @RequestMapping("list")
    public String list(UserLoginRecordQuery query, int page, int limit, String callback) {
        List<UserLoginRecord> list = userLoginRecordService.list(query, page, limit);
        long count = userLoginRecordService.count(query);
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).create();
        data.put("list", gson.toJson(list));
        data.put("count", count);
        return loadPrint(callback, JsonUtil.loadTrueResult(data));
    }
    @ResponseBody
    @RequestMapping("get")
    public String get(String id, HttpSession session, String callback) {
        UserLoginRecord entity = userLoginRecordService.get(id);
        if (entity != null) {
            return loadPrint(callback, JsonUtil.loadTrueResult(entity));
        } else {
            return loadPrint(callback, JsonUtil.loadFalseResult("ID不存在"));
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/vip/VIPPriceAdminController.java
New file
@@ -0,0 +1,111 @@
package com.ks.app.controller.admin.vip;
import com.google.gson.*;
import com.ks.app.entity.vip.VIPPriceType;
import com.ks.app.vo.AcceptAdminData;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.TimeUtil;
import com.google.gson.reflect.TypeToken;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
import com.ks.app.entity.vip.VIPPrice;
import com.ks.app.service.inter.vip.VIPPriceService;
import com.ks.app.service.query.vip.VIPPriceQuery;
@Controller
@RequestMapping("admin/api/vip/vipprice")
public class VIPPriceAdminController {
    @Resource
    private VIPPriceService vIPPriceService;
    private String loadPrint(String callback, String root) {
        return root;
    }
    @ResponseBody
    @RequestMapping("list")
    public String list(VIPPriceQuery query, int page, int limit, String callback) {
        List<VIPPrice> list = vIPPriceService.list(query, page, limit);
        long count = vIPPriceService.count(query);
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(TimeUtil.getGernalTime(date.getTime(), "yyyy.MM.dd HH:mm"));
            }
        }).registerTypeAdapter(VIPPriceType.class, new JsonSerializer<VIPPriceType>() {
            @Override
            public JsonElement serialize(VIPPriceType date, Type type, JsonSerializationContext jsonSerializationContext) {
                return date == null ? new JsonPrimitive("") : new JsonPrimitive(date.getName());
            }
        }).create();
        data.put("list", gson.toJson(list));
        data.put("count", count);
        return loadPrint(callback, JsonUtil.loadTrueResult(data));
    }
    @ResponseBody
    @RequestMapping("delete")
    public String delete(String ids, String callback) {
        Type type = new TypeToken<List<String>>() {
        }.getType();
        List<String> idList = new Gson().fromJson(ids, type);
        vIPPriceService.delete(idList);
        return loadPrint(callback, JsonUtil.loadTrueResult(""));
    }
    @ResponseBody
    @RequestMapping("add")
    public String add(AcceptAdminData acceptData, VIPPrice bean, HttpSession session, String callback) {
        try {
            bean.setSystem(acceptData.getSystem());
            vIPPriceService.add(bean);
            return loadPrint(callback, JsonUtil.loadTrueResult(""));
        } catch (Exception e) {
            return loadPrint(callback, JsonUtil.loadFalseResult(e.getMessage()));
        }
    }
    @ResponseBody
    @RequestMapping("get")
    public String get(String id, HttpSession session, String callback) {
        VIPPrice entity = vIPPriceService.get(id);
        if (entity != null) {
            return loadPrint(callback, JsonUtil.loadTrueResult(entity));
        } else {
            return loadPrint(callback, JsonUtil.loadFalseResult("ID不存在"));
        }
    }
    @ResponseBody
    @RequestMapping("update")
    public String update(VIPPrice bean, HttpSession session, String callback) {
        if (bean.getId() == null) {
            return loadPrint(callback, JsonUtil.loadFalseResult("ID不能为空"));
        }
        try {
            vIPPriceService.update(bean);
        } catch (Exception e) {
            return loadPrint(callback, JsonUtil.loadFalseResult(e.getMessage()));
        }
        return loadPrint(callback, JsonUtil.loadTrueResult(""));
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/SMSController.java
New file
@@ -0,0 +1,71 @@
package com.ks.app.controller.client.api;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.manager.VerifyCodeManager;
import com.ks.app.vo.AcceptData;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.sms.TencentSMSUtil;
import org.yeshi.utils.sms.VerifyCodeFactory;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
/**
 * @author hxh
 * @title: UserController
 * @description: 用户接口
 * @date 2021/11/16 17:37
 */
@Controller
@RequestMapping("api/v1/sms")
public class SMSController {
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    private VerifyCodeManager verifyCodeManager;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    /**
     * @return java.lang.String
     * @author hxh
     * @description 发送验证码
     * @date 18:31 2021/11/16
     * @param: acceptData
     * @param: phone
     **/
    @ResponseBody
    @RequestMapping("sendSMS")
    public String sendSMS(AcceptData acceptData, String phone) {
        if (StringUtil.isMobile(phone)) {
            return JsonUtil.loadFalseResult("手机号格式错误");
        }
        String key = "sendsms-" + phone;
        if (redisTemplate.opsForValue().setIfAbsent(key, "1", 60, TimeUnit.SECONDS)) {
            String code = VerifyCodeFactory.createNumber(6);
            String msg = systemConfigService.getValueCache(acceptData.getSystem(), SystemConfigKey.tencentVerifySMSTemplate);
            String appId = systemConfigService.getValueCache(acceptData.getSystem(), SystemConfigKey.tencentSMSAppId);
            String appKey = systemConfigService.getValueCache(acceptData.getSystem(), SystemConfigKey.tencentSMSAppKey);
            //  SmsSingleSenderResult result=
//            TencentSMSUtil.sendSingleMsg(Integer.parseInt(appId), appKey, phone, msg.replace("{验证码}", code));
            verifyCodeManager.sendSMSSuccess(phone, code);
            return JsonUtil.loadTrueResult("");
        } else {
            return JsonUtil.loadFalseResult("服务器繁忙,请稍后再试");
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/UserController.java
New file
@@ -0,0 +1,59 @@
package com.ks.app.controller.client.api;
import com.ks.app.dto.user.LoginInfoDTO;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.entity.user.UserLoginRecord;
import com.ks.app.exception.user.LoginException;
import com.ks.app.service.inter.user.UserAccountService;
import com.ks.app.vo.AcceptData;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
/**
 * @author hxh
 * @title: UserController
 * @description: 用户接口
 * @date 2021/11/16 17:37
 */
@Controller
@RequestMapping("api/v1/user")
public class UserController {
    @Resource
    private UserAccountService userAccountService;
    @ResponseBody
    @RequestMapping("loginPhone")
    public String loginPhone(AcceptData acceptData, String phone, String vcode, String token) {
        LoginInfoDTO loginInfo = new LoginInfoDTO();
        loginInfo.setLoginType(UserLoginRecord.TYPE_LOGIN_PHONE);
        if (!StringUtil.isNullOrEmpty(phone)) {
            if (StringUtil.isNullOrEmpty(vcode)) {
                return JsonUtil.loadFalseResult("请上传验证码");
            }
            loginInfo.setPhone(phone);
            loginInfo.setVcode(vcode);
        } else if (StringUtil.isNullOrEmpty(token)) {
            loginInfo.setPhoneAuthInfo(token);
        } else {
            return JsonUtil.loadFalseResult("信息不完整");
        }
        loginInfo.setSystem(acceptData.getSystem());
        try {
            UserInfo userInfo = userAccountService.login(loginInfo);
            return JsonUtil.loadTrueResult(JsonUtil.getApiCommonGson().toJson(userInfo));
        } catch (LoginException e) {
            return JsonUtil.loadFalseResult(e.getMessage());
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/VIPController.java
New file
@@ -0,0 +1,253 @@
package com.ks.app.controller.client.api;
import com.google.gson.*;
import com.ks.app.dto.vip.PayWayInfoDTO;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.entity.vip.*;
import com.ks.app.exception.goldcorn.GoldCornException;
import com.ks.app.exception.vip.OrderException;
import com.ks.app.exception.vip.PayException;
import com.ks.app.exception.vip.VIPException;
import com.ks.app.service.inter.user.UserInfoService;
import com.ks.app.service.inter.vip.OrderService;
import com.ks.app.service.inter.vip.VIPPriceService;
import com.ks.app.service.inter.vip.VIPService;
import com.ks.app.utils.Constant;
import com.ks.app.vo.AcceptData;
import com.ks.app.vo.user.UserInfoVO;
import com.ks.app.vo.vip.OrderInfoVO;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.IPUtil;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.TimeUtil;
import org.yeshi.utils.annotation.RequestSerializableByKey;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("api/v1/vip")
public class VIPController {
    Logger logger = LoggerFactory.getLogger(VIPController.class);
    @Resource
    private VIPService vipService;
    @Resource
    private OrderService orderService;
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private VIPPriceService vipPriceService;
    @RequestMapping("getVIPPriceList")
    @ResponseBody
    public String getVIPPriceList(AcceptData acceptData, Long uid) {
        Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().registerTypeAdapter(VIPPriceType.class, new JsonSerializer<VIPPriceType>() {
            @Override
            public JsonElement serialize(VIPPriceType value, Type theType, JsonSerializationContext context) {
                if (value == null) {
                    return new JsonPrimitive("");
                } else {
                    return new JsonPrimitive(value.getName());
                }
            }
        }).create();
        JSONObject root = new JSONObject();
        if (uid != null) {
            UserInfo user = userInfoService.getAvaiableUser(uid);
            if (user == null) {
                return JsonUtil.loadFalseResult("用户不存在");
            }
            UserVIPInfo vipInfo = vipService.getVIPInfo(uid);
            UserInfoVO userInfoVO = new UserInfoVO();
            userInfoVO.setId(user.getId() + "");
            userInfoVO.setNickName(user.getNickName());
            userInfoVO.setPortrait(user.getPortrait());
            if (vipInfo != null && vipInfo.getExpireDate() != null) {
                userInfoVO.setVipExpireTime(vipInfo.getExpireDate().getTime());
            }
            root.put("user", new Gson().toJson(userInfoVO));
        }
        List<VIPPrice> vipPriceList = vipPriceService.listValidPrice(acceptData.getSystem());
        root.put("list", gson.toJson(vipPriceList));
        return JsonUtil.loadTrueResult(root.toString());
    }
    @RequestMapping("getOrderList")
    @ResponseBody
    public String getOrderList(AcceptData acceptData, Long uid, String type, int page) {
        if (uid == null) {
            return JsonUtil.loadFalseResult("尚未登录");
        }
        Gson gson = new GsonBuilder().registerTypeAdapter(VIPPriceType.class, new JsonSerializer<VIPPriceType>() {
            @Override
            public JsonElement serialize(VIPPriceType value, Type theType, JsonSerializationContext context) {
                if (value == null) {
                    return new JsonPrimitive("");
                } else {
                    return new JsonPrimitive(value.getName());
                }
            }
        }).registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
            @Override
            public JsonElement serialize(Date value, Type theType, JsonSerializationContext context) {
                if (value == null) {
                    return new JsonPrimitive("");
                } else {
                    return new JsonPrimitive(TimeUtil.getGernalTime(value.getTime(), "yyyy.MM.dd HH:mm"));
                }
            }
        }).create();
        JSONObject root = new JSONObject();
        List<OrderRecord> list = orderService.listOrderRecord(uid, type == null ? null : OrderType.valueOf(type), null, page, Constant.PAGE_SIZE);
        List<OrderInfoVO> voList = new ArrayList<>();
        for (OrderRecord record : list) {
            voList.add(OrderInfoVO.create(record));
        }
        long count = orderService.countOrderRecord(uid, type == null ? null : OrderType.valueOf(type), null);
        root.put("list", gson.toJson(voList));
        root.put("count", count);
        return JsonUtil.loadTrueResult(root.toString());
    }
    /**
     * 生成订单
     *
     * @param acceptData
     * @param uid
     * @return
     */
    @RequestMapping("createOrder")
    @ResponseBody
    public String createOrder(AcceptData acceptData, HttpServletRequest request, Long uid, String priceId, Integer goldCorn, int payWay) {
        if (uid == null) {
            return JsonUtil.loadFalseResult("用户未登录");
        }
        UserInfo user = userInfoService.getAvaiableUser(uid);
        if (user == null) {
            return JsonUtil.loadFalseResult("用户不存在");
        }
        if (StringUtil.isNullOrEmpty(user.getPhone()) && payWay != OrderRecord.PAY_WAY_IAPP) {
            return JsonUtil.loadFalseResult(10001, "请绑定电话号码");
        }
        if (goldCorn == null) {
            goldCorn = 0;
        }
        OrderType orderType = OrderType.vip;
        OrderRecord record = new OrderRecord();
        VIPPrice vipPrice = null;
        vipPrice = vipPriceService.selectByPrimaryKey(priceId);
        if (vipPrice == null) {
            return JsonUtil.loadFalseResult("套餐不存在");
        }
        record.setUid(uid);
        if (vipPrice != null) {
            record.setType(vipPrice.getType());
            record.setMoney(vipPrice.getActualPrice());
        }
        record.setOrderType(orderType);
        record.setGoldCorn(goldCorn);
        record.setPayWay(payWay);
        record.setState(OrderRecord.STATE_NOT_PAY);
        record.setIpInfo(IPUtil.getRemotIP(request) + ":" + request.getRemotePort());
        try {
            orderService.createOrder(record);
        } catch (OrderException e) {
            logger.error("生成订单出错", e);
            return JsonUtil.loadFalseResult("生成订单出错");
        }
        PayWayInfoDTO payResult = null;
        try {
            payResult = orderService.payOrder(record);
        } catch (OrderException e) {
            return JsonUtil.loadFalseResult(e.getMessage());
        } catch (GoldCornException e) {
            e.printStackTrace();
            return JsonUtil.loadFalseResult(e.getMessage());
        } catch (PayException e) {
            e.printStackTrace();
            return JsonUtil.loadFalseResult(e.getMessage());
        } catch (VIPException e) {
            return JsonUtil.loadFalseResult(e.getMessage());
        }
        if (payResult.getPayWay() == OrderRecord.PAY_WAY_IAPP) {
            //苹果内购
            JSONObject root = new JSONObject();
            root.put("orderNo", record.getId());
            root.put("productId", vipPrice.getIosProductId());
            return JsonUtil.loadTrueResult(root.toString());
        } else {
            return JsonUtil.loadTrueResult(new Gson().toJson(payResult));
        }
    }
    /**
     * 检查是否支付
     *
     * @param acceptData
     * @param uid
     * @param id
     * @param receipt    -ios支付结果receipt
     * @return
     */
    @RequestMapping("checkPay")
    @ResponseBody
    @RequestSerializableByKey(key = "'vip-checkPay-'+#id")
    public String checkPay(AcceptData acceptData, Long uid, Long id, String receipt) {
        OrderRecord record = orderService.getOrderRecord(id);
        if (record == null || record.getUid().longValue() != uid) {
            return JsonUtil.loadFalseResult("记录不存在/不是您的订单");
        }
        if (record.getPayWay() == OrderRecord.PAY_WAY_IAPP) {
            try {
                orderService.checkApplePay(record.getId(), receipt);
                JSONObject data = new JSONObject();
                return JsonUtil.loadTrueResult(data.toString());
            } catch (Exception e) {
                return JsonUtil.loadFalseResult(e.getMessage());
            }
        } else {
            record = orderService.checkOrderPayState(id);
            //未支付
            if (record != null && record.getState() != OrderRecord.STATE_PAY) {
                return JsonUtil.loadFalseResult(1, "支付未完成");
            }
            JSONObject data = new JSONObject();
            data.put("money", record.getPayMoney() == null ? record.getMoney() : record.getPayMoney());
            return JsonUtil.loadTrueResult(data.toString());
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/config/SystemConfigDao.java
New file
@@ -0,0 +1,96 @@
package com.ks.app.dao.config;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import java.util.List;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.entity.SystemEnum;
import java.util.Date;
import org.yeshi.utils.mongo.MongodbBaseDao;
import java.lang.String;
import com.ks.app.entity.config.SystemConfig;
import java.util.ArrayList;
@Repository
public class SystemConfigDao extends MongodbBaseDao<SystemConfig>{
  public void updateSelective(SystemConfig bean) {
        Query query = new Query();
        Update update=new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if(bean.getName() != null) {
            update.set("name", bean.getName());
        }
        if(bean.getKey() != null) {
            update.set("key", bean.getKey());
        }
        if(bean.getSystem() != null) {
            update.set("system", bean.getSystem());
        }
        if(bean.getValue() != null) {
            update.set("value", bean.getValue());
        }
        if(bean.getRemarks() != null) {
            update.set("remarks", bean.getRemarks());
        }
        if(bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
  }
  public List<SystemConfig> list(DaoQuery daoQuery){
        Query query = getQuery(daoQuery);
        if (daoQuery.sortList!=null && daoQuery.sortList.size()>0){
            query.with(Sort.by(daoQuery.sortList));
        }
        query.skip(daoQuery.start);
        query.limit(daoQuery.count);
        return findList(query);
  }
  public long count(DaoQuery daoQuery){
        Query query=getQuery(daoQuery);
        return count(query);
  }
  private Query getQuery(DaoQuery daoQuery){
        List<Criteria> andList=new ArrayList<>();
        if(daoQuery.name!=null){
            andList.add(Criteria.where("name").regex(daoQuery.name));
        }
        if(daoQuery.key!=null){
            andList.add(Criteria.where("key").is(daoQuery.key));
        }
        if(daoQuery.system!=null){
            andList.add(Criteria.where("system").is(daoQuery.system));
        }
        if(daoQuery.value!=null){
            andList.add(Criteria.where("value").regex(daoQuery.value));
        }
        Query query=new Query();
        Criteria[]  ands=new Criteria[andList.size()];
        andList.toArray(ands);
        if(ands.length>0){
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
  }
  public static class DaoQuery{
        public String name;
        public SystemConfigKey key;
        public SystemEnum system;
        public String value;
        public int start;
        public int count;
        public List<Sort.Order> sortList;
  }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/QQUserInfoDao.java
New file
@@ -0,0 +1,31 @@
package com.ks.app.dao.user;
import com.ks.app.entity.SystemEnum;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Date;
import org.apache.ibatis.annotations.Param;
import org.yeshi.utils.mybatis.BaseMapper;
import com.ks.app.entity.user.QQUserInfo;
@Repository
public interface QQUserInfoDao extends BaseMapper<QQUserInfo> {
    QQUserInfo selectByPrimaryKeyForUpdate(@Param("id") Long id);
    List<QQUserInfo> list(@Param("query") DaoQuery query);
    long count(@Param("query") DaoQuery query);
    public static class DaoQuery {
        public SystemEnum system;
        public String openId;
        public long start;
        public int count;
        public List<String> sortList;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/UserInfoDao.java
New file
@@ -0,0 +1,48 @@
package com.ks.app.dao.user;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.user.UserInfo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import org.yeshi.utils.mybatis.BaseMapper;
import org.yeshi.utils.statistic.BaseStatisticMySQLTimeQuery;
import org.yeshi.utils.statistic.StatisticNumberResult;
import java.util.Date;
import java.util.List;
@Repository
public interface UserInfoDao extends BaseMapper<UserInfo> {
    UserInfo selectByPrimaryKeyForUpdate(@Param("id") java.lang.Long id);
    List<UserInfo> list(@Param("query") DaoQuery query);
    long count(@Param("query") DaoQuery query);
    /**
     * @author hxh
     * @description 根据创建时间统计用户数量
     * @date 18:58 2021/11/18
     * @param: system
     * @param: timeQuery
     * @return java.util.List<org.yeshi.utils.statistic.http.StatisticNumberResult>
     **/
    List<StatisticNumberResult> statisticByCreateTime(@Param("system") SystemEnum system, @Param("timeQuery") BaseStatisticMySQLTimeQuery timeQuery);
    public static class DaoQuery {
        public SystemEnum system;
        public Long wxId;
        public Long qqId;
        public String nickName;
        public String phone;
        public String email;
        public Date maxCreateTime;
        public Date minCreateTime;
        public Integer status;
        public long start;
        public int count;
        public List<String> sortList;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/UserLoginRecordDao.java
New file
@@ -0,0 +1,90 @@
package com.ks.app.dao.user;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import com.ks.app.entity.user.UserLoginRecord;
import java.util.List;
import java.lang.Long;
import java.util.Date;
import org.yeshi.utils.mongo.MongodbBaseDao;
import java.lang.String;
import java.lang.Integer;
import java.util.ArrayList;
@Repository
public class UserLoginRecordDao extends MongodbBaseDao<UserLoginRecord>{
  public void updateSelective(UserLoginRecord bean) {
        Query query = new Query();
        Update update=new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if(bean.getUid() != null) {
            update.set("uid", bean.getUid());
        }
        if(bean.getLoginIPInfo() != null) {
            update.set("loginIPInfo", bean.getLoginIPInfo());
        }
        if(bean.getLoginType() != null) {
            update.set("loginType", bean.getLoginType());
        }
        if(bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
  }
  public List<UserLoginRecord> list(DaoQuery daoQuery){
        Query query = getQuery(daoQuery);
        if (daoQuery.sortList!=null && daoQuery.sortList.size()>0){
            query.with(Sort.by(daoQuery.sortList));
        }
        query.skip(daoQuery.start);
        query.limit(daoQuery.count);
        return findList(query);
  }
  public long count(DaoQuery daoQuery){
        Query query=getQuery(daoQuery);
        return count(query);
  }
  private Query getQuery(DaoQuery daoQuery){
        List<Criteria> andList=new ArrayList<>();
        if(daoQuery.uid!=null){
            andList.add(Criteria.where("uid").is(daoQuery.uid));
        }
        if(daoQuery.loginType!=null){
            andList.add(Criteria.where("loginType").is(daoQuery.loginType));
        }
        if(daoQuery.maxCreateTime!=null){
            andList.add(Criteria.where("createTime").lt(daoQuery.maxCreateTime));
        }
        if(daoQuery.minCreateTime!=null){
            andList.add(Criteria.where("createTime").gte(daoQuery.minCreateTime));
        }
        Query query=new Query();
        Criteria[]  ands=new Criteria[andList.size()];
        andList.toArray(ands);
        if(ands.length>0){
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
  }
  public static class DaoQuery{
        public Long uid;
        public Integer loginType;
        public Date maxCreateTime;
        public Date minCreateTime;
        public int start;
        public int count;
        public List<Sort.Order> sortList;
  }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/WXUserInfoDao.java
New file
@@ -0,0 +1,31 @@
package com.ks.app.dao.user;
import com.ks.app.entity.SystemEnum;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Date;
import org.apache.ibatis.annotations.Param;
import org.yeshi.utils.mybatis.BaseMapper;
import com.ks.app.entity.user.WXUserInfo;
@Repository
public interface WXUserInfoDao extends BaseMapper<WXUserInfo> {
    WXUserInfo selectByPrimaryKeyForUpdate(@Param("id") java.lang.Long id);
    List<WXUserInfo> list(@Param("query") DaoQuery query);
    long count(@Param("query") DaoQuery query);
    public static class DaoQuery {
        public SystemEnum system;
        public String unionId;
        public long start;
        public int count;
        public List<String> sortList;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/OrderRecordDao.java
New file
@@ -0,0 +1,34 @@
package com.ks.app.dao.vip;
import com.ks.app.entity.vip.OrderType;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Date;
import org.apache.ibatis.annotations.Param;
import org.yeshi.utils.mybatis.BaseMapper;
import com.ks.app.entity.vip.OrderRecord;
@Repository
public interface OrderRecordDao extends BaseMapper<OrderRecord> {
  OrderRecord selectByPrimaryKeyForUpdate(@Param("id") java.lang.Long id);
  List<OrderRecord> list(@Param("query") DaoQuery query);
  long count(@Param("query") DaoQuery query);
  int insertPaySuccess(@Param("id")Long id);
  public static class DaoQuery{
        public long start;
        public int count;
        public Integer state;
        public OrderType orderType;
        public Date minCreateTime;
        public Date maxCreateTime;
        public Long uid;
        public List<String> sortList;
  }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/UserVIPInfoDao.java
New file
@@ -0,0 +1,30 @@
package com.ks.app.dao.vip;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Date;
import org.apache.ibatis.annotations.Param;
import org.yeshi.utils.mybatis.BaseMapper;
import com.ks.app.entity.vip.UserVIPInfo;
@Repository
public interface UserVIPInfoDao extends BaseMapper<UserVIPInfo> {
    UserVIPInfo selectByPrimaryKeyForUpdate(@Param("id") java.lang.Long id);
    List<UserVIPInfo> list(@Param("query") DaoQuery query);
    long count(@Param("query") DaoQuery query);
    public static class DaoQuery {
        public long start;
        public int count;
        public Date minExpireDate;
        public Date maxExpireDate;
        public List<String> sortList;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/VIPPriceDao.java
New file
@@ -0,0 +1,112 @@
package com.ks.app.dao.vip;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.List;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.vip.VIPPriceType;
import java.util.Date;
import org.yeshi.utils.mongo.MongodbBaseDao;
import java.lang.Boolean;
import java.lang.String;
import java.lang.Integer;
import java.util.ArrayList;
import com.ks.app.entity.vip.VIPPrice;
@Repository
public class VIPPriceDao extends MongodbBaseDao<VIPPrice> {
    public void updateSelective(VIPPrice bean) {
        Query query = new Query();
        Update update = new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if (bean.getType() != null) {
            update.set("type", bean.getType());
        }
        if (bean.getSystem() != null) {
            update.set("system", bean.getSystem());
        }
        if (bean.getPrice() != null) {
            update.set("price", bean.getPrice());
        }
        if (bean.getActualPrice() != null) {
            update.set("actualPrice", bean.getActualPrice());
        }
        if (bean.getIosProductId() != null) {
            update.set("iosProductId", bean.getIosProductId());
        }
        if (bean.getShow() != null) {
            update.set("show", bean.getShow());
        }
        if (bean.getOrder() != null) {
            update.set("order", bean.getOrder());
        }
        if (bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
    }
    public List<VIPPrice> list(DaoQuery daoQuery) {
        Query query = getQuery(daoQuery);
        if (daoQuery.sortList != null && daoQuery.sortList.size() > 0) {
            query.with(Sort.by(daoQuery.sortList));
        }
        query.skip(daoQuery.start);
        query.limit(daoQuery.count);
        return findList(query);
    }
    public long count(DaoQuery daoQuery) {
        Query query = getQuery(daoQuery);
        return count(query);
    }
    private Query getQuery(DaoQuery daoQuery) {
        List<Criteria> andList = new ArrayList<>();
        if (daoQuery.type != null) {
            andList.add(Criteria.where("type").is(daoQuery.type));
        }
        if (daoQuery.system != null) {
            andList.add(Criteria.where("system").is(daoQuery.system));
        }
        if (daoQuery.show != null) {
            andList.add(Criteria.where("show").is(daoQuery.show));
        }
        if (daoQuery.iosProductId != null) {
            andList.add(Criteria.where("iosProductId").is(daoQuery.iosProductId));
        }
        Query query = new Query();
        Criteria[] ands = new Criteria[andList.size()];
        andList.toArray(ands);
        if (ands.length > 0) {
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
    }
    public static class DaoQuery {
        public VIPPriceType type;
        public SystemEnum system;
        public Boolean show;
        public String iosProductId;
        public int start;
        public int count;
        public List<Sort.Order> sortList;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/user/LoginInfoDTO.java
New file
@@ -0,0 +1,104 @@
package com.ks.app.dto.user;
import com.ks.app.entity.SystemEnum;
/**
 * @author hxh
 * @title: LoginInfo
 * @description: 登录信息
 * @date 2021/11/15 17:59
 */
public class LoginInfoDTO {
    private int loginType;
    private SystemEnum system;
    private String ipInfo;
    private String phone;
    private String vcode;
    //号码认证信息
    private String phoneAuthInfo;
    private String email;
    private String pwd;
    private String wxCode;
    private String qqCode;
    public int getLoginType() {
        return loginType;
    }
    public void setLoginType(int loginType) {
        this.loginType = loginType;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getVcode() {
        return vcode;
    }
    public void setVcode(String vcode) {
        this.vcode = vcode;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
    public String getWxCode() {
        return wxCode;
    }
    public void setWxCode(String wxCode) {
        this.wxCode = wxCode;
    }
    public String getQqCode() {
        return qqCode;
    }
    public void setQqCode(String qqCode) {
        this.qqCode = qqCode;
    }
    public String getIpInfo() {
        return ipInfo;
    }
    public void setIpInfo(String ipInfo) {
        this.ipInfo = ipInfo;
    }
    public String getPhoneAuthInfo() {
        return phoneAuthInfo;
    }
    public void setPhoneAuthInfo(String phoneAuthInfo) {
        this.phoneAuthInfo = phoneAuthInfo;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/vip/OrderPaySuccessForm.java
New file
@@ -0,0 +1,78 @@
package com.ks.app.dto.vip;
import java.math.BigDecimal;
import java.util.Date;
public class OrderPaySuccessForm {
    private Long id;
    private int payWay;
    private BigDecimal payMoney;
    private Date payTime;
    private String appleTransactionId;
    private String appleOriginalTransactionId;
    public OrderPaySuccessForm(Long id, int payWay, BigDecimal payMoney, Date payTime) {
        this.id = id;
        this.payWay = payWay;
        this.payMoney = payMoney;
        this.payTime = payTime;
    }
    public OrderPaySuccessForm(Long id, int payWay, BigDecimal payMoney, Date payTime, String appleTransactionId, String appleOriginalTransactionId) {
        this.id = id;
        this.payWay = payWay;
        this.payMoney = payMoney;
        this.payTime = payTime;
        this.appleTransactionId = appleTransactionId;
        this.appleOriginalTransactionId = appleOriginalTransactionId;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public int getPayWay() {
        return payWay;
    }
    public void setPayWay(int payWay) {
        this.payWay = payWay;
    }
    public BigDecimal getPayMoney() {
        return payMoney;
    }
    public void setPayMoney(BigDecimal payMoney) {
        this.payMoney = payMoney;
    }
    public Date getPayTime() {
        return payTime;
    }
    public void setPayTime(Date payTime) {
        this.payTime = payTime;
    }
    public String getAppleTransactionId() {
        return appleTransactionId;
    }
    public void setAppleTransactionId(String appleTransactionId) {
        this.appleTransactionId = appleTransactionId;
    }
    public String getAppleOriginalTransactionId() {
        return appleOriginalTransactionId;
    }
    public void setAppleOriginalTransactionId(String appleOriginalTransactionId) {
        this.appleOriginalTransactionId = appleOriginalTransactionId;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/vip/PayWayInfoDTO.java
New file
@@ -0,0 +1,28 @@
package com.ks.app.dto.vip;
public class PayWayInfoDTO {
    //0-表示支付成功
    private int payWay;
    private String payUrl;
    public PayWayInfoDTO(int payWay, String payUrl) {
        this.payWay = payWay;
        this.payUrl = payUrl;
    }
    public int getPayWay() {
        return payWay;
    }
    public void setPayWay(int payWay) {
        this.payWay = payWay;
    }
    public String getPayUrl() {
        return payUrl;
    }
    public void setPayUrl(String payUrl) {
        this.payUrl = payUrl;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/APPPlatform.java
New file
@@ -0,0 +1,12 @@
package com.ks.app.entity;
/**
 * @author hxh
 * @title: Platform
 * @description: 应用平台
 * @date 2021/11/16 17:59
 */
public enum APPPlatform {
    android, ios, web, wxxcx;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/SystemEnum.java
New file
@@ -0,0 +1,34 @@
package com.ks.app.entity;
/**
 * @author hxh
 * @title: SystemEnum
 * @description: TODO
 * @date 2021/11/15 11:17
 */
public enum SystemEnum {
    location("定位追踪轨迹", "com.dw.zzql", "");
    private String name;
    private String packageName;
    private String bundleId;
    private SystemEnum(String name, String packageName, String bundleId) {
        this.name = name;
        this.packageName = packageName;
        this.bundleId = bundleId;
    }
    public String getName() {
        return name;
    }
    public String getPackageName() {
        return packageName;
    }
    public String getBundleId() {
        return bundleId;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfig.java
New file
@@ -0,0 +1,97 @@
package com.ks.app.entity.config;
import com.ks.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
import java.io.Serializable;
import java.util.Date;
/**
 * @author hxh
 * @title: SystemConfig
 * @description: 系统配置文件
 * @date 2021/11/16 10:39
 */
@Document(collection = "systemConfig")
public class SystemConfig implements Serializable {
    @Id
    private String id;
    @DaoQueryCondition(queryType = DaoQueryCondition.QueryType.contains)
    private String name;
    @DaoQueryCondition
    private SystemConfigKey key;
    @DaoQueryCondition
    private SystemEnum system;
    @DaoQueryCondition(queryType = DaoQueryCondition.QueryType.contains)
    private String value;
    private String remarks;
    private Date createTime;
    private Date updateTime;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public SystemConfigKey getKey() {
        return key;
    }
    public void setKey(SystemConfigKey key) {
        this.key = key;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public String getRemarks() {
        return remarks;
    }
    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfigKey.java
New file
@@ -0,0 +1,33 @@
package com.ks.app.entity.config;
/**
 * @author hxh
 * @title: SystemConfigKey
 * @description: key值
 * @date 2021/11/16 11:22
 */
public enum SystemConfigKey {
    signKey("签名Key"),
    defaultPortrait("默认头像"),
    defaultNickNamePrefix("默认昵称前缀"),
    wxAppId("微信开放平台APPId"),
    wxAppSecret("微信开放平台APPSecret"),
    aliyunOneKeyAuthAcessKey("阿里云一键登录appId"),
    aliyunOneKeyAuthAcessSecret("阿里云一键登录appSecret"),
    tencentSMSAppId("腾讯云短信APPID"),
    tencentSMSAppKey("腾讯云短信APPKey"),
    tencentVerifySMSTemplate("腾讯云验证码短信模板");
    private String desc;
    public String getDesc() {
        return desc;
    }
    private SystemConfigKey(String desc) {
        this.desc = desc;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/QQUserInfo.java
New file
@@ -0,0 +1,88 @@
package com.ks.app.entity.user;
import com.ks.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.io.Serializable;
import java.util.Date;
/**
 * @author hxh
 * @title: QQUserInfo
 * @description: TODO
 * @date 2021/11/15 11:39
 */
@Table("lt_user_qq")
public class QQUserInfo implements Serializable {
    @Id
    private Long id;
    private SystemEnum system;
    @Column(name="nick_name")
    private String nickName;
    private String portrait;
    @Column(name="open_id")
    private String openId;
    @Column(name="create_time")
    private Date createTime;
    @Column(name="update_time")
    private Date updateTime;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public String getNickName() {
        return nickName;
    }
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    public String getPortrait() {
        return portrait;
    }
    public void setPortrait(String portrait) {
        this.portrait = portrait;
    }
    public String getOpenId() {
        return openId;
    }
    public void setOpenId(String openId) {
        this.openId = openId;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/UserInfo.java
New file
@@ -0,0 +1,176 @@
package com.ks.app.entity.user;
import com.google.gson.annotations.Expose;
import com.ks.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.yeshi.utils.generater.annotation.admin.AdminController;
import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
import org.yeshi.utils.generater.annotation.admin.Show;
import org.yeshi.utils.generater.entity.CommonSearchForm;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.io.Serializable;
import java.util.Date;
/**
 * @author hxh
 * @title: UserInfo
 * @description: 用户信息
 * @date 2021/11/15 11:16
 */
@Table("lt_user")
@AdminController(mapping = "admin/api/user", title = "用户信息", searchForm = CommonSearchForm.class)
public class UserInfo implements Serializable {
    //正常状态
    public final static int STATUS_NORMAL = 0;
    //主动删除
    public final static int STATUS_OWN_DELETE = 1;
    //被封禁
    public final static int STATUS_FORBIDDEN = 3;
    @Expose
    @Id
    @Show(title = "用户ID")
    private Long id;
    private SystemEnum system;
    @Expose
    @Show(title = "昵称")
    @Column(name = "nick_name")
    @DaoQueryCondition(queryType = DaoQueryCondition.QueryType.contains)
    private String nickName;
    @Expose
    @Show(title = "头像", showType = Show.ShowType.IMG)
    private String portrait;
    //手机号
    @Show(title = "电话")
    @DaoQueryCondition
    private String phone;
    //邮箱
    @Show(title = "邮箱")
    @DaoQueryCondition
    private String email;
    //密码
    private String pwd;
    //微信用户信息
    @Show(title = "微信用户信息")
    @Column(name = "wx_id")
    private WXUserInfo wxUser;
    //QQ用户信息
    @Show(title = "QQ用户信息")
    @Column(name = "qq_id")
    private QQUserInfo qqUser;
    //状态
    @Column(name = "status")
    private Integer status;
    @Show(title = "创建时间")
    @DaoQueryCondition
    @Column(name = "create_time")
    private Date createTime;
    @Show(title = "修改时间")
    @Column(name = "update_time")
    private Date updateTime;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public String getNickName() {
        return nickName;
    }
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    public String getPortrait() {
        return portrait;
    }
    public void setPortrait(String portrait) {
        this.portrait = portrait;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public WXUserInfo getWxUser() {
        return wxUser;
    }
    public void setWxUser(WXUserInfo wxUser) {
        this.wxUser = wxUser;
    }
    public QQUserInfo getQqUser() {
        return qqUser;
    }
    public void setQqUser(QQUserInfo qqUser) {
        this.qqUser = qqUser;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/UserLoginRecord.java
New file
@@ -0,0 +1,82 @@
package com.ks.app.entity.user;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.yeshi.utils.generater.annotation.admin.AdminController;
import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
import org.yeshi.utils.generater.annotation.admin.Show;
import org.yeshi.utils.generater.entity.CommonSearchForm;
import java.io.Serializable;
import java.util.Date;
/**
 * @author hxh
 * @title: UserLoginInfo
 * @description: 用户登录记录
 * @date 2021/11/15 11:48
 */
@Document(collection = "userLoginRecord")
@AdminController(mapping = "admin/api/user/loginrecord", title = "用户登录记录",delete=false,edit = false,searchForm= CommonSearchForm.class)
public class UserLoginRecord implements Serializable {
    public final static int TYPE_LOGIN_PHONE = 1;
    public final static int TYPE_LOGIN_WX = 2;
    public final static int TYPE_LOGIN_QQ = 3;
    public final static int TYPE_LOGIN_EMAIL = 4;
    @Id
    @Show(title = "ID")
    private String id;
    @Show(title = "用户ID")
    @DaoQueryCondition
    private Long uid;
    @Show(title = "登录IP信息")
    private String loginIPInfo;
    @Show(title = "登录类型")
    @DaoQueryCondition
    private Integer loginType;
    @Show(title = "登录时间")
    @DaoQueryCondition
    private Date createTime;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public Long getUid() {
        return uid;
    }
    public void setUid(Long uid) {
        this.uid = uid;
    }
    public String getLoginIPInfo() {
        return loginIPInfo;
    }
    public void setLoginIPInfo(String loginIPInfo) {
        this.loginIPInfo = loginIPInfo;
    }
    public Integer getLoginType() {
        return loginType;
    }
    public void setLoginType(Integer loginType) {
        this.loginType = loginType;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/WXUserInfo.java
New file
@@ -0,0 +1,148 @@
package com.ks.app.entity.user;
import com.ks.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.yeshi.utils.entity.wx.WeiXinUser;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.io.Serializable;
import java.util.Date;
/**
 * @author hxh
 * @title: WXUserInfo
 * @description: 微信用户信息
 * @date 2021/11/15 11:35
 */
@Table("lt_user_wx")
public class WXUserInfo implements Serializable {
    @Id
    private Long id;
    private SystemEnum system;
    @Column(name = "nick_name")
    private String nickName;
    private Integer sex;
    private String province;
    private String city;
    private String country;
    @Column(name = "head_img_url")
    private String headImgUrl;
    @Column(name = "open_id")
    private String openId;
    @Column(name = "union_id")
    private String unionId;
    @Column(name = "create_time")
    private Date createTime;
    @Column(name = "update_time")
    private Date updateTime;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public String getNickName() {
        return nickName;
    }
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    public int getSex() {
        return sex;
    }
    public void setSex(int sex) {
        this.sex = sex;
    }
    public String getProvince() {
        return province;
    }
    public void setProvince(String province) {
        this.province = province;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }
    public String getHeadImgUrl() {
        return headImgUrl;
    }
    public void setHeadImgUrl(String headImgUrl) {
        this.headImgUrl = headImgUrl;
    }
    public String getOpenId() {
        return openId;
    }
    public void setOpenId(String openId) {
        this.openId = openId;
    }
    public String getUnionId() {
        return unionId;
    }
    public void setUnionId(String unionId) {
        this.unionId = unionId;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public static WXUserInfo create(WeiXinUser weiXinUser) {
        WXUserInfo wxUserInfo = new WXUserInfo();
        wxUserInfo.setCity(weiXinUser.getCity());
        wxUserInfo.setCountry(weiXinUser.getCountry());
        wxUserInfo.setHeadImgUrl(weiXinUser.getHeadimgurl());
        wxUserInfo.setNickName(weiXinUser.getNickname());
        wxUserInfo.setOpenId(weiXinUser.getOpenid());
        wxUserInfo.setProvince(weiXinUser.getProvince());
        wxUserInfo.setSex(weiXinUser.getSex());
        wxUserInfo.setUnionId(weiXinUser.getUnionid());
        return wxUserInfo;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/OrderRecord.java
New file
@@ -0,0 +1,270 @@
package com.ks.app.entity.vip;
import org.springframework.data.annotation.Id;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.math.BigDecimal;
import java.util.Date;
/**
 * @author hxh
 * @description 会员订单记录
 * @date 14:29 2021/11/17
 * @return
 **/
@Table("lt_vip_order_record")
public class OrderRecord {
    //未支付
    public final static int STATE_NOT_PAY = 0;
    //已支付
    public final static int STATE_PAY = 1;
    //订单已取消
    public final static int STATE_CANCEL = -1;
    //支付宝
    public final static int PAY_WAY_ALIPAY = 1;
    //微信
    public final static int PAY_WAY_WX = 2;
    //金币支付
    public final static int PAY_WAY_GOLDCORN = 3;
    //苹果支付
    public final static int PAY_WAY_IAPP = 4;
    //支付宝+金币
    public final static int PAY_WAY_ALIPAY_GOLDCORN = 13;
    //微信+金币
    public final static int PAY_WAY_WX_GOLDCORN = 23;
    @Id
    private Long id;
    //订单类型
    @Column(name = "order_type")
    private OrderType orderType;
    //用户ID
    private Long uid;
    //状态
    private Integer state;
    //资金支付状态
    @Column(name = "money_pay")
    private Boolean moneyPay;
    //资金支付状态
    @Column(name = "gold_corn_pay")
    private Boolean goldCornPay;
    //金币
    @Column(name = "gold_corn")
    private Integer goldCorn;
    //类型
    private VIPPriceType type;
    //资金
    private BigDecimal money;
    //支付方式
    @Column(name = "pay_way")
    private Integer payWay;
    //支付金额
    @Column(name = "pay_money")
    private BigDecimal payMoney;
    @Column(name = "ip_info")
    private String ipInfo;
    //付款时间
    @Column(name = "pay_time")
    private Date payTime;
    @Column(name = "create_time")
    private Date createTime;
    @Column(name = "update_time")
    private Date updateTime;
    //会员开始时间
    @Column(name = "vip_start_time")
    private Date vipStartTime;
    //会员结束时间
    @Column(name = "vip_end_time")
    private Date vipEndTime;
    //备注
    private String remarks;
    @Column(name = "apple_transaction_id")
    private String appleTransactionId;
    @Column(name = "apple_original_transaction_id")
    private String appleOriginalTransactionId;
    public String getAppleTransactionId() {
        return appleTransactionId;
    }
    public void setAppleTransactionId(String appleTransactionId) {
        this.appleTransactionId = appleTransactionId;
    }
    public String getAppleOriginalTransactionId() {
        return appleOriginalTransactionId;
    }
    public void setAppleOriginalTransactionId(String appleOriginalTransactionId) {
        this.appleOriginalTransactionId = appleOriginalTransactionId;
    }
    public Boolean getMoneyPay() {
        return moneyPay;
    }
    public void setMoneyPay(Boolean moneyPay) {
        this.moneyPay = moneyPay;
    }
    public Boolean getGoldCornPay() {
        return goldCornPay;
    }
    public void setGoldCornPay(Boolean goldCornPay) {
        this.goldCornPay = goldCornPay;
    }
    public Date getVipStartTime() {
        return vipStartTime;
    }
    public void setVipStartTime(Date vipStartTime) {
        this.vipStartTime = vipStartTime;
    }
    public Date getVipEndTime() {
        return vipEndTime;
    }
    public void setVipEndTime(Date vipEndTime) {
        this.vipEndTime = vipEndTime;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Long getUid() {
        return uid;
    }
    public void setUid(Long uid) {
        this.uid = uid;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    public VIPPriceType getType() {
        return type;
    }
    public void setType(VIPPriceType type) {
        this.type = type;
    }
    public BigDecimal getMoney() {
        return money;
    }
    public void setMoney(BigDecimal money) {
        this.money = money;
    }
    public Integer getPayWay() {
        return payWay;
    }
    public void setPayWay(Integer payWay) {
        this.payWay = payWay;
    }
    public BigDecimal getPayMoney() {
        return payMoney;
    }
    public void setPayMoney(BigDecimal payMoney) {
        this.payMoney = payMoney;
    }
    public Date getPayTime() {
        return payTime;
    }
    public void setPayTime(Date payTime) {
        this.payTime = payTime;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public String getIpInfo() {
        return ipInfo;
    }
    public void setIpInfo(String ipInfo) {
        this.ipInfo = ipInfo;
    }
    public Integer getGoldCorn() {
        return goldCorn;
    }
    public void setGoldCorn(Integer goldCorn) {
        this.goldCorn = goldCorn;
    }
    public OrderType getOrderType() {
        return orderType;
    }
    public void setOrderType(OrderType orderType) {
        this.orderType = orderType;
    }
    public String getRemarks() {
        return remarks;
    }
    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/OrderType.java
New file
@@ -0,0 +1,8 @@
package com.ks.app.entity.vip;
public enum OrderType {
    //VIP
    vip;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/UserVIPInfo.java
New file
@@ -0,0 +1,52 @@
package com.ks.app.entity.vip;
import org.springframework.data.annotation.Id;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.util.Date;
@Table("lt_user_vip_info")
public class UserVIPInfo {
    @Id
    private Long uid;
    //到期时间
    @Column(name = "expire_date")
    private Date expireDate;
    @Column(name = "create_time")
    private Date createTime;
    @Column(name = "update_time")
    private Date updateTime;
    public Long getUid() {
        return uid;
    }
    public void setUid(Long uid) {
        this.uid = uid;
    }
    public Date getExpireDate() {
        return expireDate;
    }
    public void setExpireDate(Date expireDate) {
        this.expireDate = expireDate;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/VIPPrice.java
New file
@@ -0,0 +1,142 @@
package com.ks.app.entity.vip;
import com.google.gson.annotations.Expose;
import com.ks.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.yeshi.utils.generater.annotation.admin.AdminController;
import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
import org.yeshi.utils.generater.annotation.admin.Show;
import org.yeshi.utils.generater.annotation.admin.form.*;
import java.math.BigDecimal;
import java.util.Date;
@Document(collection = "vipPrice")
@AdminController(mapping = "admin/api/vip/vipprice", title = "会员套餐")
public class VIPPrice {
    @Id
    @Expose
    private String id;
    @DaoQueryCondition
    @Expose
    @Show(title = "套餐类型")
    @Select(title = "套餐类型", disable = true,values = {"day:包天","week:包周","month:包月","season:包季","halfYear:半年","year:1年"})
    private VIPPriceType type;
    @DaoQueryCondition
    private SystemEnum system;
    @Expose
    @Show(title = "价格")
    @Text(title = "价格")
    private BigDecimal price;
    //原始价格
    @Text(title = "原价")
    @Show(title = "原价")
    @Expose
    private BigDecimal actualPrice;
    //苹果的内购商品ID
    @Text(title = "APPStore内购ID")
    @Show(title = "APPStore内购ID")
    @Expose
    private String iosProductId;
    @DaoQueryCondition
    @Switch(title = "是否显示")
    @Show(title = "是否显示")
    private Boolean show;
    //排序值
    @Text(title = "排序值")
    @Show(title = "排序值")
    private Integer order;
    @Show(title = "创建时间")
    private Date createTime;
    @Show(title = "更新时间")
    private Date updateTime;
    public Boolean getShow() {
        return show;
    }
    public void setShow(Boolean show) {
        this.show = show;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public VIPPriceType getType() {
        return type;
    }
    public void setType(VIPPriceType type) {
        this.type = type;
    }
    public BigDecimal getPrice() {
        return price;
    }
    public void setPrice(BigDecimal price) {
        this.price = price;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public Integer getOrder() {
        return order;
    }
    public void setOrder(Integer order) {
        this.order = order;
    }
    public BigDecimal getActualPrice() {
        return actualPrice;
    }
    public void setActualPrice(BigDecimal actualPrice) {
        this.actualPrice = actualPrice;
    }
    public String getIosProductId() {
        return iosProductId;
    }
    public void setIosProductId(String iosProductId) {
        this.iosProductId = iosProductId;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/vip/VIPPriceType.java
New file
@@ -0,0 +1,16 @@
package com.ks.app.entity.vip;
public enum VIPPriceType {
    day("包天"), week("包周"), month("包月"), season("包季"), halfYear("半年"), year("包年");
    private String name;
    private VIPPriceType(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/goldcorn/GoldCornException.java
New file
@@ -0,0 +1,14 @@
package com.ks.app.exception.goldcorn;
public class GoldCornException extends Exception {
    private int code;
    private String msg;
    public GoldCornException(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/user/LoginException.java
New file
@@ -0,0 +1,15 @@
package com.ks.app.exception.user;
/**
 * @author hxh
 * @title: LoginException
 * @description: 登录异常
 * @date 2021/11/16 18:23
 */
public class LoginException extends Exception {
    public LoginException(String msg) {
        super(msg);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/vip/OrderException.java
New file
@@ -0,0 +1,14 @@
package com.ks.app.exception.vip;
public class OrderException extends Exception {
    private int code;
    private String msg;
    public OrderException(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/vip/PayException.java
New file
@@ -0,0 +1,14 @@
package com.ks.app.exception.vip;
public class PayException extends Exception {
    private int code;
    private String msg;
    public PayException(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/vip/VIPException.java
New file
@@ -0,0 +1,14 @@
package com.ks.app.exception.vip;
public class VIPException extends Exception {
    private int code;
    private String msg;
    public VIPException(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/AdminUserServiceImpl.java
@@ -1,8 +1,11 @@
package com.ks.app.service.impl;
import com.ks.app.dao.admin.AdminUserDao;
import com.ks.app.entity.AdminUser;
import com.ks.app.service.inter.AdminUserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
 * @author hxh
@@ -13,8 +16,19 @@
@Service
public class AdminUserServiceImpl implements AdminUserService {
    @Resource
    private AdminUserDao adminUserDao;
    @Override
    public AdminUser selectByAccount(String account) {
        return null;
        return adminUserDao.selectByAccount(account);
    }
    @Override
    public void add(AdminUser adminUser) throws Exception {
        if (selectByAccount(adminUser.getAccount()) != null) {
            throw new Exception("账号已存在");
        }
        adminUserDao.save(adminUser);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/config/SystemConfigServiceImpl.java
New file
@@ -0,0 +1,123 @@
package com.ks.app.service.impl.config;
import com.ks.app.dao.config.SystemConfigDao;
import com.ks.app.dao.config.SystemConfigDao.DaoQuery;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.config.SystemConfig;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.query.config.SystemConfigQuery;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.yeshi.utils.bean.BeanUtil;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Service
public class SystemConfigServiceImpl implements SystemConfigService {
    @Resource
    private SystemConfigDao systemConfigDao;
    @Cacheable(key = "configKey", value = "'getValueCache-'+#system+'-'+#key")
    @Override
    public String getValueCache(SystemEnum system, SystemConfigKey key) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.system = system;
        daoQuery.key = key;
        daoQuery.count = 1;
        List<SystemConfig> list = systemConfigDao.list(daoQuery);
        if (list == null || list.size() == 0) {
            return null;
        }
        return list.get(0).getValue();
    }
    @Override
    public List<SystemConfig> list(SystemConfigQuery systemConfigQuery, int page, int pageSize) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(systemConfigQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        return systemConfigDao.list(daoQuery);
    }
    @Override
    public long count(SystemConfigQuery systemConfigQuery) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(systemConfigQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return systemConfigDao.count(daoQuery);
    }
    @Override
    public SystemConfig get(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        return systemConfigDao.findOne(query);
    }
    @Override
    public void add(SystemConfig systemConfig) throws Exception {
        if (systemConfig.getId() == null) {
            systemConfig.setId(systemConfig.getSystem().name() + "-" + systemConfig.getKey().name());
        }
        //查询主键ID是否存在
        if (systemConfigDao.get(systemConfig.getId()) != null) {
            throw new Exception("已存在");
        }
        if (systemConfig.getCreateTime() == null) {
            systemConfig.setCreateTime(new Date());
        }
        //保存
        systemConfigDao.save(systemConfig);
    }
    @Override
    public void save(SystemConfig config) {
        if (config.getId() == null) {
            config.setId(config.getSystem().name() + "-" + config.getKey().name());
        }
        if (systemConfigDao.get(config.getId()) != null) {
            update(config);
        } else {
            if (config.getCreateTime() == null) {
                config.setCreateTime(new Date());
            }
            systemConfigDao.save(config);
        }
    }
    @Override
    public void update(SystemConfig systemConfig) {
        if (systemConfig.getUpdateTime() == null) {
            systemConfig.setUpdateTime(new Date());
        }
        //更新
        systemConfigDao.updateSelective(systemConfig);
    }
    @Override
    public void delete(List<String> idList) {
        for (String id : idList) {
            systemConfigDao.delete(id);
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/QQUserInfoServiceImpl.java
New file
@@ -0,0 +1,95 @@
package com.ks.app.service.impl.user;
import java.lang.Exception;
import javax.annotation.Resource;
import com.ks.app.entity.SystemEnum;
import org.springframework.stereotype.Service;
import java.util.Date;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.dao.user.QQUserInfoDao;
import com.ks.app.entity.user.QQUserInfo;
import com.ks.app.service.inter.user.QQUserInfoService;
import com.ks.app.service.query.user.QQUserInfoQuery;
import com.ks.app.dao.user.QQUserInfoDao.DaoQuery;
@Service
public class QQUserInfoServiceImpl implements QQUserInfoService {
    @Resource
    private QQUserInfoDao qQUserInfoMapper;
    @Override
    public List<QQUserInfo> list(QQUserInfoQuery qQUserInfoQuery, int page, int pageSize) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(qQUserInfoQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        return qQUserInfoMapper.list(daoQuery);
    }
    @Override
    public long count(QQUserInfoQuery qQUserInfoQuery) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(qQUserInfoQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return qQUserInfoMapper.count(daoQuery);
    }
    @Override
    public QQUserInfo get(Long id) {
        return qQUserInfoMapper.selectByPrimaryKey(id);
    }
    @Override
    public void add(QQUserInfo qQUserInfo) throws Exception {
        if (qQUserInfo.getCreateTime() == null) {
            qQUserInfo.setCreateTime(new Date());
        }
        //保存
        qQUserInfoMapper.insertSelective(qQUserInfo);
    }
    @Override
    public void update(QQUserInfo qQUserInfo) {
        if (qQUserInfo.getUpdateTime() == null) {
            qQUserInfo.setUpdateTime(new Date());
        }
        //保存
        qQUserInfoMapper.updateByPrimaryKey(qQUserInfo);
    }
    @Override
    public void delete(List<Long> idList) {
        for (Long id : idList) {
            qQUserInfoMapper.deleteByPrimaryKey(id);
        }
    }
    @Override
    public QQUserInfo selectBySystemAndOpenId(SystemEnum system, String openId) {
        if (system == null || StringUtil.isNullOrEmpty(openId)) {
            return null;
        }
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.count = 1;
        daoQuery.openId = openId;
        daoQuery.system = system;
        return null;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserAccountServiceImpl.java
New file
@@ -0,0 +1,172 @@
package com.ks.app.service.impl.user;
import com.ks.app.dto.user.LoginInfoDTO;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.entity.user.UserLoginRecord;
import com.ks.app.entity.user.WXUserInfo;
import com.ks.app.exception.user.LoginException;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.inter.user.*;
import com.ks.app.service.manager.VerifyCodeManager;
import com.ks.app.utils.AliyunOneKeyLoginUtil;
import org.apache.zookeeper.Login;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yeshi.utils.PropertiesUtil;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.entity.wx.WXAPPInfo;
import org.yeshi.utils.entity.wx.WeiXinUser;
import org.yeshi.utils.wx.WXAppLoginUtil;
import org.yeshi.utils.wx.WXUtil;
import javax.annotation.Resource;
import java.util.Properties;
import java.util.UUID;
@Service
public class UserAccountServiceImpl implements UserAccountService {
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private UserLoginRecordService userLoginRecordService;
    @Resource
    private VerifyCodeManager verifyCodeManager;
    @Resource
    private WXUserInfoService wxUserInfoService;
    @Resource
    private QQUserInfoService qqUserInfoService;
    @Resource
    private SystemConfigService systemConfigService;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserInfo login(LoginInfoDTO loginInfo) throws LoginException {
        if (loginInfo == null) {
            throw new LoginException("登录信息为空");
        }
        UserInfo user = null;
        switch (loginInfo.getLoginType()) {
            case UserLoginRecord
                    .TYPE_LOGIN_PHONE: {
                if (!StringUtil.isNullOrEmpty(loginInfo.getPhoneAuthInfo())) {
                    //一键登录
                    //获取电话号码
                    String mobile = AliyunOneKeyLoginUtil.getMobile(loginInfo.getPhoneAuthInfo(), UUID.randomUUID().toString(), systemConfigService.getValueCache(loginInfo.getSystem(), SystemConfigKey.aliyunOneKeyAuthAcessKey), systemConfigService.getValueCache(loginInfo.getSystem(), SystemConfigKey.aliyunOneKeyAuthAcessSecret));
                    if (StringUtil.isNullOrEmpty(mobile)) {
                        throw new LoginException("电话号码获取失败");
                    }
                    loginInfo.setPhone(mobile);
                } else {
                    //验证码登录
                    if (!verifyCodeManager.isPhoneCodeRight(loginInfo.getPhone(), loginInfo.getVcode())) {
                        throw new LoginException("验证码出错");
                    }
                }
                //执行登录操作
                user = userInfoService.selectByPhoneAndSystemAndStatus(loginInfo.getPhone(), loginInfo.getSystem(), UserInfo.STATUS_NORMAL);
                if (user == null) {
                    //创建用户
                    UserInfo newUser = new UserInfo();
                    newUser.setPhone(loginInfo.getPhone());
                    newUser.setSystem(loginInfo.getSystem());
                    newUser.setNickName("");
                    newUser.setPortrait(systemConfigService.getValueCache(loginInfo.getSystem(), SystemConfigKey.defaultPortrait));
                    try {
                        userInfoService.add(newUser);
                    } catch (Exception e) {
                        throw new LoginException("注册用户失败");
                    }
                    //更改昵称
                    UserInfo updateUser = new UserInfo();
                    updateUser.setId(newUser.getId());
                    updateUser.setNickName(systemConfigService.getValueCache(loginInfo.getSystem(), SystemConfigKey.defaultNickNamePrefix) + newUser.getId());
                    userInfoService.update(updateUser);
                    user = newUser;
                }
            }
            break;
            case UserLoginRecord
                    .TYPE_LOGIN_WX: {
                String appId = systemConfigService.getValueCache(loginInfo.getSystem(), SystemConfigKey.wxAppId);
                String appSecret = systemConfigService.getValueCache(loginInfo.getSystem(), SystemConfigKey.wxAppSecret);
                WeiXinUser weiXinUser = WXAppLoginUtil.getWeiXinUser(loginInfo.getWxCode(), appId, appSecret);
                if (weiXinUser == null) {
                    throw new LoginException("微信授权信息获取失败");
                }
                //保存微信用户信息
                WXUserInfo wxUserInfo = null;
                try {
                    wxUserInfo = wxUserInfoService.save(WXUserInfo.create(weiXinUser));
                } catch (Exception e) {
                    throw new LoginException("保存微信授权信息失败");
                }
                wxUserInfo.setSystem(loginInfo.getSystem());
                user = userInfoService.selectByWXIdAndSystemAndStatus(wxUserInfo.getId(), wxUserInfo.getSystem(), UserInfo.STATUS_NORMAL);
                if (user == null) {
                    //新建用户
                    UserInfo newUser = new UserInfo();
                    newUser.setWxUser(wxUserInfo);
                    newUser.setSystem(loginInfo.getSystem());
                    newUser.setNickName(wxUserInfo.getNickName());
                    newUser.setPortrait(wxUserInfo.getHeadImgUrl());
                    try {
                        userInfoService.add(newUser);
                    } catch (Exception e) {
                        throw new LoginException("注册用户失败");
                    }
                    user = newUser;
                }
            }
            break;
            case UserLoginRecord
                    .TYPE_LOGIN_QQ:
                //保存QQ信息
                break;
            case UserLoginRecord
                    .TYPE_LOGIN_EMAIL:
                //验证密码是否正确
                UserInfo oldUser = userInfoService.selectByEmailAndSystemAndStatus(loginInfo.getEmail(), loginInfo.getSystem(), UserInfo.STATUS_NORMAL);
                if (oldUser == null) {
                    throw new LoginException("邮箱未注册");
                }
                if (!StringUtil.Md5(loginInfo.getPwd()).equalsIgnoreCase(oldUser.getPwd())) {
                    throw new LoginException("密码错误");
                }
                user = oldUser;
                break;
            default:
                throw new LoginException("登录方式不存在");
        }
        loginSuccess(user.getId(), loginInfo);
        return null;
    }
    /**
     * @return void
     * @author hxh
     * @description 登录成功
     * @date 18:21 2021/11/15
     **/
    private void loginSuccess(Long uid, LoginInfoDTO dto) {
        UserLoginRecord record = new UserLoginRecord();
        record.setLoginIPInfo(dto.getIpInfo());
        record.setLoginType(dto.getLoginType());
        record.setUid(uid);
        userLoginRecordService.addUserLoginRecord(record);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserInfoServiceImpl.java
New file
@@ -0,0 +1,208 @@
package com.ks.app.service.impl.user;
import java.lang.Exception;
import javax.annotation.Resource;
import com.ks.app.entity.SystemEnum;
import com.ks.app.service.inter.user.QQUserInfoService;
import com.ks.app.service.inter.user.WXUserInfoService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.dao.user.UserInfoDao;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.service.inter.user.UserInfoService;
import com.ks.app.service.query.user.UserInfoQuery;
import com.ks.app.dao.user.UserInfoDao.DaoQuery;
import org.yeshi.utils.statistic.BaseStatisticMySQLTimeQuery;
import org.yeshi.utils.statistic.BaseStatisticTimeQuery;
import org.yeshi.utils.statistic.StatisticNumberResult;
@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Resource
    private UserInfoDao userInfoMapper;
    @Resource
    private WXUserInfoService wxUserInfoService;
    @Resource
    private QQUserInfoService qqUserInfoService;
    @Override
    public List<UserInfo> list(UserInfoQuery userInfoQuery, int page, int pageSize) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(userInfoQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        return userInfoMapper.list(daoQuery);
    }
    @Override
    public long count(UserInfoQuery userInfoQuery) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(userInfoQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userInfoMapper.count(daoQuery);
    }
    @Override
    public UserInfo get(Long id) {
        return userInfoMapper.selectByPrimaryKey(id);
    }
    @Override
    public void add(UserInfo userInfo) throws Exception {
        if (userInfo.getCreateTime() == null) {
            userInfo.setCreateTime(new Date());
        }
        if (userInfo.getStatus() == null) {
            userInfo.setStatus(UserInfo.STATUS_NORMAL);
        }
        //保存
        userInfoMapper.insertSelective(userInfo);
    }
    @Override
    public void update(UserInfo userInfo) {
        if (userInfo.getUpdateTime() == null) {
            userInfo.setUpdateTime(new Date());
        }
        //保存
        userInfoMapper.updateByPrimaryKey(userInfo);
    }
    @Override
    public void delete(List<Long> idList) {
        for (Long id : idList) {
            userInfoMapper.deleteByPrimaryKey(id);
        }
    }
    @Override
    public UserInfo getDetail(Long uid) {
        UserInfo user = get(uid);
        if (user == null) {
            return null;
        }
        if (user.getWxUser() != null && user.getWxUser().getId() != null) {
            //装载微信信息
            user.setWxUser(wxUserInfoService.get(user.getWxUser().getId()));
        }
        if (user.getQqUser() != null && user.getQqUser().getId() != null) {
            //装载QQ信息
            user.setQqUser(qqUserInfoService.get(user.getQqUser().getId()));
        }
        return user;
    }
    @Override
    public List<UserInfo> getDetailList(List<Long> uidList) {
        if (uidList == null) {
            return null;
        }
        List<UserInfo> userInfoList = new ArrayList<>();
        for (Long id : uidList) {
            userInfoList.add(getDetail(id));
        }
        return userInfoList;
    }
    @Override
    public UserInfo selectByPhoneAndSystemAndStatus(String phone, SystemEnum system, Integer status) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.phone = phone;
        daoQuery.system = system;
        daoQuery.status = status;
        daoQuery.count = 1;
        List<UserInfo> list = userInfoMapper.list(daoQuery);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
    @Override
    public UserInfo selectByWXIdAndSystemAndStatus(Long wxId, SystemEnum system, Integer status) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.wxId = wxId;
        daoQuery.system = system;
        daoQuery.status = status;
        daoQuery.count = 1;
        List<UserInfo> list = userInfoMapper.list(daoQuery);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
    @Override
    public UserInfo selectByQQIdAndSystemAndStatus(Long qqId, SystemEnum system, Integer status) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.qqId = qqId;
        daoQuery.system = system;
        daoQuery.status = status;
        daoQuery.count = 1;
        List<UserInfo> list = userInfoMapper.list(daoQuery);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
    @Override
    public UserInfo selectByEmailAndSystemAndStatus(String email, SystemEnum system, Integer status) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.email = email;
        daoQuery.system = system;
        daoQuery.status = status;
        daoQuery.count = 1;
        List<UserInfo> list = userInfoMapper.list(daoQuery);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
    @Override
    public SystemEnum getSystem(Long uid) {
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(uid);
        if (userInfo == null) {
            return null;
        }
        return userInfo.getSystem();
    }
    @Override
    public UserInfo getAvaiableUser(Long uid) {
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(uid);
        if (userInfo != null && userInfo.getStatus() == UserInfo.STATUS_NORMAL) {
            return userInfo;
        }
        return null;
    }
    @Override
    public List<StatisticNumberResult> statisticRegisterUser(SystemEnum system, BaseStatisticTimeQuery timeQuery) {
       return userInfoMapper.statisticByCreateTime(system, BaseStatisticMySQLTimeQuery.create(timeQuery));
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserLoginRecordServiceImpl.java
New file
@@ -0,0 +1,73 @@
package com.ks.app.service.impl.user;
import com.ks.app.dao.user.UserLoginRecordDao;
import com.ks.app.dao.user.UserLoginRecordDao.DaoQuery;
import com.ks.app.entity.user.UserLoginRecord;
import com.ks.app.service.inter.user.UserLoginRecordService;
import com.ks.app.service.query.user.UserLoginRecordQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.yeshi.utils.TimeUtil;
import org.yeshi.utils.bean.BeanUtil;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Service
public class UserLoginRecordServiceImpl implements UserLoginRecordService {
    @Resource
    private UserLoginRecordDao userLoginRecordDao;
    @Override
    public void addUserLoginRecord(UserLoginRecord record) {
        if (record == null)
            return;
        if (record.getUid() == null)
            return;
        if (record.getCreateTime() == null) {
            record.setCreateTime(new Date());
        }
        if (record.getId() == null) {
            record.setId(TimeUtil.getGernalTime(System.currentTimeMillis(), "yyyyMMddHHmmssSSS") + "_" + record.getUid());
        }
        userLoginRecordDao.save(record);
    }
    @Override
    public List<UserLoginRecord> list(UserLoginRecordQuery userLoginRecordQuery, int page, int pageSize) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(userLoginRecordQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        return userLoginRecordDao.list(daoQuery);
    }
    @Override
    public long count(UserLoginRecordQuery userLoginRecordQuery) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(userLoginRecordQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userLoginRecordDao.count(daoQuery);
    }
    @Override
    public UserLoginRecord get(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        return userLoginRecordDao.findOne(query);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/WXUserInfoServiceImpl.java
New file
@@ -0,0 +1,120 @@
package com.ks.app.service.impl.user;
import java.lang.Exception;
import javax.annotation.Resource;
import com.ks.app.entity.SystemEnum;
import org.springframework.stereotype.Service;
import java.util.Date;
import org.springframework.transaction.annotation.Transactional;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.dao.user.WXUserInfoDao;
import com.ks.app.entity.user.WXUserInfo;
import com.ks.app.service.inter.user.WXUserInfoService;
import com.ks.app.service.query.user.WXUserInfoQuery;
import com.ks.app.dao.user.WXUserInfoDao.DaoQuery;
@Service
public class WXUserInfoServiceImpl implements WXUserInfoService {
    @Resource
    private WXUserInfoDao wXUserInfoMapper;
    @Override
    public List<WXUserInfo> list(WXUserInfoQuery wXUserInfoQuery, int page, int pageSize) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(wXUserInfoQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        return wXUserInfoMapper.list(daoQuery);
    }
    @Override
    public long count(WXUserInfoQuery wXUserInfoQuery) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(wXUserInfoQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return wXUserInfoMapper.count(daoQuery);
    }
    @Override
    public WXUserInfo get(Long id) {
        return wXUserInfoMapper.selectByPrimaryKey(id);
    }
    @Override
    public void add(WXUserInfo wXUserInfo) throws Exception {
        if (wXUserInfo.getCreateTime() == null) {
            wXUserInfo.setCreateTime(new Date());
        }
        //保存
        wXUserInfoMapper.insertSelective(wXUserInfo);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public WXUserInfo save(WXUserInfo wXUserInfo) throws Exception {
        if (wXUserInfo == null || StringUtil.isNullOrEmpty(wXUserInfo.getUnionId()) || wXUserInfo.getSystem() == null) {
            throw new Exception("信息不完整");
        }
        if (wXUserInfo.getCreateTime() == null) {
            wXUserInfo.setCreateTime(new Date());
        }
        WXUserInfo userInfo = selectBySystemAndUnionId(wXUserInfo.getSystem(), wXUserInfo.getUnionId());
        if (userInfo == null) {
            add(wXUserInfo);
        } else {
            //更新
            wXUserInfo.setId(userInfo.getId());
            wXUserInfoMapper.updateByPrimaryKeySelective(wXUserInfo);
        }
        return wXUserInfo;
    }
    public void update(WXUserInfo wXUserInfo) {
        if (wXUserInfo.getUpdateTime() == null) {
            wXUserInfo.setUpdateTime(new Date());
        }
        //保存
        wXUserInfoMapper.updateByPrimaryKey(wXUserInfo);
    }
    @Override
    public void delete(List<Long> idList) {
        for (Long id : idList) {
            wXUserInfoMapper.deleteByPrimaryKey(id);
        }
    }
    @Override
    public WXUserInfo selectBySystemAndUnionId(SystemEnum system, String unionId) {
        if (system == null || StringUtil.isNullOrEmpty(unionId)) {
            return null;
        }
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.system = system;
        daoQuery.unionId = unionId;
        daoQuery.count = 1;
        List<WXUserInfo> list = wXUserInfoMapper.list(daoQuery);
        if (list == null || list.size() == 0) {
            return null;
        }
        return list.get(0);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/OrderServiceImpl.java
New file
@@ -0,0 +1,527 @@
package com.ks.app.service.impl.vip;
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.ks.app.dao.vip.OrderRecordDao;
import com.ks.app.dao.vip.UserVIPInfoDao;
import com.ks.app.dto.vip.OrderPaySuccessForm;
import com.ks.app.dto.vip.PayWayInfoDTO;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.vip.*;
import com.ks.app.exception.goldcorn.GoldCornException;
import com.ks.app.exception.vip.OrderException;
import com.ks.app.exception.vip.PayException;
import com.ks.app.exception.vip.VIPException;
import com.ks.app.service.inter.user.UserInfoService;
import com.ks.app.service.inter.vip.IPaySuccess;
import com.ks.app.service.inter.vip.OrderService;
import com.ks.app.service.inter.vip.VIPPriceService;
import com.ks.app.service.manager.GoldCornManager;
import com.ks.app.utils.PayConstant;
import com.ks.app.utils.vip.VIPOrderUtil;
import com.ks.app.utils.vip.VipUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.alipay.AlipayH5PayUtil;
import org.yeshi.utils.entity.wx.WXPayOrderInfoV3;
import org.yeshi.utils.ios.pay.IOSPayVerifyUtil;
import org.yeshi.utils.ios.pay.vo.IOSAPPBuyVerifyResult;
import org.yeshi.utils.wx.WXPayV3Util;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 * @author hxh
 * @title: OrderServiceImpl
 * @description: TODO
 * @date 2021/11/17 14:52
 */
@Service
public class OrderServiceImpl implements OrderService {
    private static Logger logger = LoggerFactory.getLogger("OrderService");
    private static Logger orderLogger = LoggerFactory.getLogger("order");
    @Resource
    private OrderRecordDao OrderRecordDao;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private GoldCornManager goldCornManager;
    @Resource
    private VIPPriceService vipPriceService;
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private UserVIPInfoDao userVIPInfoDao;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OrderRecord createOrder(OrderRecord record) throws OrderException {
        if (record.getMoney() == null || record.getOrderType() == null || record.getUid() == null) {
            throw new OrderException(1, "参数不完整");
        }
        if (record.getState() == null) {
            record.setState(OrderRecord.STATE_NOT_PAY);
        }
        if (record.getCreateTime() == null) {
            record.setCreateTime(new Date());
        }
        if (record.getPayWay() == OrderRecord.PAY_WAY_WX) {
            if (record.getGoldCorn() != null && record.getGoldCorn() > 0) {
                if (record.getMoney().compareTo(new BigDecimal("0")) == 0) {
                    record.setPayWay(OrderRecord.PAY_WAY_GOLDCORN);
                } else {
                    record.setPayWay(OrderRecord.PAY_WAY_WX_GOLDCORN);
                }
            }
        } else if (record.getPayWay() == OrderRecord.PAY_WAY_ALIPAY) {
            if (record.getGoldCorn() != null && record.getGoldCorn() > 0) {
                if (record.getMoney().compareTo(new BigDecimal("0")) == 0) {
                    record.setPayWay(OrderRecord.PAY_WAY_GOLDCORN);
                } else {
                    record.setPayWay(OrderRecord.PAY_WAY_ALIPAY_GOLDCORN);
                }
            }
        }
        record.setMoneyPay(false);
        record.setGoldCornPay(false);
        OrderRecordDao.insertSelective(record);
        orderLogger.info("订单创建成功:id-{} 类型-{}", record.getId(), record.getOrderType().name());
        return record;
    }
    @Transactional(rollbackFor = Exception.class)
//    @GlobalTransactional(timeoutMills = 30000, name = "buwan-order", rollbackFor = Exception.class)
    @Override
    public PayWayInfoDTO payOrder(OrderRecord record) throws OrderException, GoldCornException, PayException, VIPException {
        String orderNo = VIPOrderUtil.getOutOrderNo(userInfoService.getSystem(record.getUid()), record.getOrderType(), record.getId());
        switch (record.getPayWay()) {
            case OrderRecord
                    .PAY_WAY_ALIPAY_GOLDCORN:
                try {
                    goldCornManager.consumeGoldCorn(record, record.getGoldCorn());
                } catch (Exception e) {
                    throw new GoldCornException(1, "影视豆扣除出错");
                }
                paySuccess(new OrderPaySuccessForm(record.getId(), OrderRecord.PAY_WAY_GOLDCORN, null, new Date()));
                orderLogger.info("订单影视豆支付成功:id-{}", record.getId());
            case OrderRecord
                    .PAY_WAY_ALIPAY: {
                if (record.getMoney() != null && record.getMoney().compareTo(new BigDecimal(0)) == 0) {
                    return new PayWayInfoDTO(0, VipUtil.getPaySuccessUrl(record.getId()));
                }
                //生成支付宝支付订单
                String form = VipUtil.getVipChargeAlipayForm(record.getId(), record.getOrderType(), orderNo, record.getMoney());
                //暂存2分钟
                String id = StringUtil.Md5(UUID.randomUUID().toString() + "#" + System.currentTimeMillis());
                redisTemplate.opsForValue().set(id, form, 120, TimeUnit.SECONDS);
                String payUrl = PayConstant.ALIPAY_PRINT_PAY_FORM_LINK.replace("{formId}", id);
                orderLogger.info("订单创建支付宝支付链接成功:id-{} 链接-{}", record.getId(), payUrl);
                return new PayWayInfoDTO(OrderRecord
                        .PAY_WAY_ALIPAY, payUrl);
            }
            case OrderRecord
                    .PAY_WAY_WX_GOLDCORN:
                try {
                    goldCornManager.consumeGoldCorn(record, record.getGoldCorn());
                } catch (Exception e) {
                    throw new GoldCornException(1, "影视豆扣除出错");
                }
                paySuccess(new OrderPaySuccessForm(record.getId(), OrderRecord.PAY_WAY_GOLDCORN, null, new Date()));
                orderLogger.info("订单影视豆支付成功:id-{} 类型-{}", record.getId(), record.getOrderType().name());
            case OrderRecord
                    .PAY_WAY_WX: {
                if (record.getMoney() != null && record.getMoney().compareTo(new BigDecimal(0)) == 0) {
                    return new PayWayInfoDTO(0, VipUtil.getPaySuccessUrl(record.getId()));
                }
                //生成微信支付订单
                try {
                    String title = "";
                    if (record.getOrderType() == OrderType.vip) {
                        title = "影视大全VIP-" + record.getType().getName();
                    } else {
                        title = "单片购买";
                    }
                    String payUrl = VipUtil.createWXOrder(record.getId(), record.getIpInfo(), orderNo, record.getMoney(), title);
                    orderLogger.info("订单创建微信支付链接成功:id-{} 链接-{}", record.getId(), payUrl);
                    return new PayWayInfoDTO(OrderRecord.PAY_WAY_WX, payUrl);
                } catch (Exception e) {
                    logger.error("生成微信支付订单出错", e);
                    throw new PayException(2, e.getMessage());
                }
            }
            case OrderRecord.PAY_WAY_GOLDCORN: {
                try {
                    goldCornManager.consumeGoldCorn(record, record.getGoldCorn());
                    orderLogger.info("订单影视豆支付成功:id-{}", record.getId());
                } catch (Exception e) {
                    throw new GoldCornException(1, "影视豆扣除出错");
                }
                paySuccess(new OrderPaySuccessForm(record.getId(), OrderRecord.PAY_WAY_GOLDCORN, null, new Date()));
                return new PayWayInfoDTO(0, VipUtil.getPaySuccessUrl(record.getId()));
            }
            case OrderRecord.PAY_WAY_IAPP:
                return new PayWayInfoDTO(OrderRecord.PAY_WAY_IAPP, null);
        }
        throw new OrderException(1, "支付方式不存在");
    }
    private int getPayState(OrderRecord record) {
        switch (record.getPayWay()) {
            case OrderRecord.PAY_WAY_ALIPAY:
            case OrderRecord.PAY_WAY_WX:
                if (record.getMoneyPay() != null && record.getMoneyPay()) {
                    return OrderRecord.STATE_PAY;
                } else {
                    return OrderRecord.STATE_NOT_PAY;
                }
            case OrderRecord.PAY_WAY_ALIPAY_GOLDCORN:
            case OrderRecord.PAY_WAY_WX_GOLDCORN:
                if (record.getMoneyPay() != null && record.getMoneyPay() && record.getGoldCornPay() != null && record.getGoldCornPay()) {
                    return OrderRecord.STATE_PAY;
                } else {
                    return OrderRecord.STATE_NOT_PAY;
                }
            case OrderRecord.PAY_WAY_GOLDCORN:
                if (record.getGoldCornPay() != null && record.getGoldCornPay()) {
                    return OrderRecord.STATE_PAY;
                } else {
                    return OrderRecord.STATE_NOT_PAY;
                }
            case OrderRecord.PAY_WAY_IAPP:
                if (record.getMoneyPay()) {
                    return OrderRecord.STATE_PAY;
                } else {
                    return OrderRecord.STATE_NOT_PAY;
                }
        }
        return OrderRecord.STATE_NOT_PAY;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OrderRecord paySuccess(OrderPaySuccessForm successForm) throws
            VIPException, OrderException {
        return paySuccess(successForm, (OrderRecord record) -> {
            //TODO 支付成功
        });
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OrderRecord paySuccess(OrderPaySuccessForm successForm, IPaySuccess paySuccess) throws VIPException, OrderException {
        orderLogger.info("订单支付成功目的执行:id-{},支付方式-{},支付金额-{},支付时间-{}", successForm.getId(), successForm.getPayWay(), successForm.getPayMoney(), successForm.getPayTime());
        OrderRecord record = OrderRecordDao.selectByPrimaryKeyForUpdate(successForm.getId());
        //修改记录
        if (record == null) {
            throw new OrderException(10, "订单不存在");
        }
        if (record.getState() != OrderRecord.STATE_NOT_PAY) {
            throw new OrderException(1, "订单未处于待支付状态");
        }
        if (successForm.getPayWay() != OrderRecord.PAY_WAY_GOLDCORN) {
            record.setPayMoney(successForm.getPayMoney());
            record.setMoneyPay(true);
            record.setAppleTransactionId(successForm.getAppleTransactionId());
            record.setAppleOriginalTransactionId(successForm.getAppleOriginalTransactionId());
        } else {
            record.setGoldCornPay(true);
        }
        record.setPayTime(successForm.getPayTime());
        record.setUpdateTime(new Date());
        record.setState(getPayState(record));
        //已经支付成功
        if (record.getState() == OrderRecord.STATE_PAY) {
            OrderRecordDao.insertPaySuccess(successForm.getId());
        }
        if (record.getOrderType() == OrderType.vip) {
            Date[] expireDate = addExpireTime(record.getUid(), successForm.getPayTime(), record.getType());
            record.setVipStartTime(expireDate[0]);
            record.setVipEndTime(expireDate[1]);
            if (expireDate == null) {
                throw new VIPException(2, "添加用户会员时间出错");
            }
            OrderRecordDao.updateByPrimaryKeySelective(record);
            if (record.getState() == OrderRecord.STATE_PAY) {
                orderLogger.info("订单全部支付成功:id-{}", successForm.getId());
                if (paySuccess != null) {
                    paySuccess.onSuccess(record);
                }
                orderLogger.info("购买VIP成功:id-{}", successForm.getId());
            } else {
                orderLogger.info("订单部分支付成功:id-{}", successForm.getId());
            }
        }
        return record;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelOrder(Long id, String reason) throws OrderException, GoldCornException {
        OrderRecord record = OrderRecordDao.selectByPrimaryKeyForUpdate(id);
        if (record == null) {
            throw new OrderException(1, "订单不存在");
        }
        if (record.getState() == OrderRecord.STATE_PAY) {
            throw new OrderException(1, "已支付成功的订单不能取消");
        }
        if (record.getPayWay() != OrderRecord.PAY_WAY_GOLDCORN && record.getMoneyPay() != null && record.getMoneyPay()) {
            throw new OrderException(2, "资金支付成功的订单不能取消");
        }
        //返回豆
        if (record.getGoldCornPay() != null && record.getGoldCornPay() && record.getGoldCorn() != null && record.getGoldCorn() > 0) {
            try {
                goldCornManager.drawbackGoldCorn(record);
            } catch (Exception e) {
                throw new GoldCornException(1, "影视豆退款失败");
            }
        }
        //设置订单状态
        record.setState(OrderRecord.STATE_CANCEL);
        record.setUpdateTime(new Date());
        record.setRemarks(reason);
        OrderRecordDao.updateByPrimaryKeySelective(record);
        orderLogger.info("取消订单成功:id-{}", id);
    }
    @Override
    public List<OrderRecord> getCanCancelOrderList(int page, int pageSize) {
        OrderRecordDao.DaoQuery daoQuery = new OrderRecordDao.DaoQuery();
        daoQuery.state = OrderRecord.STATE_NOT_PAY;
        //30分钟未支付取消订单
        daoQuery.maxCreateTime = new Date(System.currentTimeMillis() - 1000 * 60 * 30);
        daoQuery.minCreateTime = new Date(daoQuery.maxCreateTime.getTime() - 1000 * 60 * 60L * 24);
        return OrderRecordDao.list(daoQuery);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OrderRecord checkOrderPayState(Long id) {
        OrderRecord record = OrderRecordDao.selectByPrimaryKeyForUpdate(id);
        if (record.getState() == OrderRecord.STATE_PAY) {
            return record;
        }
        switch (record.getPayWay()) {
            case OrderRecord.PAY_WAY_ALIPAY_GOLDCORN:
            case OrderRecord.PAY_WAY_ALIPAY: {
                //支付宝
                AlipayTradeQueryResponse res = null;
                try {
                    res = AlipayH5PayUtil.queryOrder(VipUtil.getAlipayApp(), VIPOrderUtil.getOutOrderNo(userInfoService.getSystem(record.getUid()), record.getOrderType(), id), null);
                    //支付成功
                    if (res.isSuccess() && "TRADE_SUCCESS".equalsIgnoreCase(res.getTradeStatus())) {
                        try {
                            return paySuccess(new OrderPaySuccessForm(id, OrderRecord.PAY_WAY_ALIPAY, new BigDecimal(res.getTotalAmount()), new Date()));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                } catch (AlipayApiException e) {
                    e.printStackTrace();
                }
            }
            break;
            case OrderRecord.PAY_WAY_WX_GOLDCORN:
            case OrderRecord.PAY_WAY_WX: {
                //微信
                try {
                    WXPayOrderInfoV3 info = WXPayV3Util.getPayOrderInfo(VIPOrderUtil.getOutOrderNo(userInfoService.getSystem(record.getUid()), record.getOrderType(), id), VipUtil.getWXAPP());
                    if (info != null && info.getTrade_state().equalsIgnoreCase("SUCCESS")) {
                        paySuccess(new OrderPaySuccessForm(id, record.getPayWay(), new BigDecimal(info.getAmount().getPayer_total()).divide(new BigDecimal(100), 2, RoundingMode.FLOOR), new Date()));
                        return record;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            break;
        }
        return record;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OrderRecord checkApplePay(Long orderNo, String receipt) throws Exception {
        OrderRecord orderRecord = OrderRecordDao.selectByPrimaryKeyForUpdate(orderNo);
        if (orderRecord == null) {
            throw new OrderException(1, "订单号不存在");
        }
        SystemEnum system = userInfoService.getSystem(orderRecord.getUid());
        if (!StringUtil.isNullOrEmpty(orderRecord.getAppleTransactionId())) {
            throw new OrderException(2, "订单已支付");
        }
        IOSAPPBuyVerifyResult result = IOSPayVerifyUtil.buyAppVerify(receipt, "28ca52e358b94c4eba3de41dfa7dd023", false);
        List<IOSAPPBuyVerifyResult.OrderInfo> orderInfoList = result.getLatestReceiptInfo();
        IOSAPPBuyVerifyResult.OrderInfo orderInfo = orderInfoList.get(0);
        String productId = orderInfo.getProduct_id();
        VIPPrice vipPrice = vipPriceService.selectByIOSProductId(productId, system);
        if (vipPrice == null) {
            throw new Exception("商品ID不存在");
        }
        if (orderRecord.getType() != vipPrice.getType()) {
            throw new Exception("价格类型不匹配");
        }
//String id, int payWay, BigDecimal payMoney, Date payTime, String appleTransactionId, String appleOriginalTransactionId
        OrderPaySuccessForm successForm = new OrderPaySuccessForm(orderRecord.getId(), OrderRecord.PAY_WAY_IAPP, new BigDecimal(0), new Date(orderInfo.getPurchaseDateMs()), orderInfo.getTransactionId(), orderInfo.getOriginalTransactionId());
        paySuccess(successForm);
        return null;
    }
    @Override
    public List<OrderRecord> listOrderRecord(Long uid, OrderType orderType, Integer state, int page, int pageSize) {
        OrderRecordDao.DaoQuery query = new OrderRecordDao.DaoQuery();
        query.start = (page - 1) * pageSize;
        query.count = pageSize;
        query.uid = uid;
        query.state = state;
        query.orderType = orderType;
        return OrderRecordDao.list(query);
    }
    @Override
    public long countOrderRecord(Long uid, OrderType orderType, Integer state) {
        OrderRecordDao.DaoQuery query = new OrderRecordDao.DaoQuery();
        query.uid = uid;
        query.state = state;
        query.orderType = orderType;
        return OrderRecordDao.count(query);
    }
    @Override
    public OrderRecord getOrderRecord(Long id) {
        return OrderRecordDao.selectByPrimaryKey(id);
    }
    /**
     * 续期
     *
     * @param uid
     * @param payTime
     * @param type
     * @return
     */
    private Date[] addExpireTime(Long uid, Date payTime, VIPPriceType type) {
        if (type == null || uid == null) {
            return null;
        }
        UserVIPInfo userVIPInfo = userVIPInfoDao.selectByPrimaryKeyForUpdate(uid);
        if (userVIPInfo == null) {
            //新增
            UserVIPInfo vip = new UserVIPInfo();
            vip.setUid(uid);
            vip.setCreateTime(new Date());
            Date[] expireDate = getExpireTime(payTime, null, type);
            vip.setExpireDate(expireDate[1]);
            userVIPInfoDao.insertSelective(vip);
            return expireDate;
        } else {
            //修改
            UserVIPInfo update = new UserVIPInfo();
            update.setUid(uid);
            Date[] expireDate = getExpireTime(payTime, userVIPInfo.getExpireDate(), type);
            update.setExpireDate(expireDate[1]);
            update.setUpdateTime(new Date());
            userVIPInfoDao.updateByPrimaryKeySelective(update);
            return expireDate;
        }
    }
    /**
     * 获取到期时间
     *
     * @param payTime
     * @param expireTime
     * @param type
     * @return
     */
    private Date[] getExpireTime(Date payTime, Date expireTime, VIPPriceType type) {
        Calendar calendar = Calendar.getInstance();
        if (expireTime != null) {
            //之前续期时间是否大于付款时间
            if (payTime.getTime() < expireTime.getTime()) {
                calendar.setTimeInMillis(expireTime.getTime());
            } else {
                calendar.setTimeInMillis(payTime.getTime());
            }
        } else {
            calendar.setTimeInMillis(payTime.getTime());
        }
        long startTime = calendar.getTimeInMillis();
        if (type == VIPPriceType.day) {
            calendar.add(Calendar.DAY_OF_WEEK, 1);
        } else if (type == VIPPriceType.week) {
            calendar.add(Calendar.WEEK_OF_YEAR, 1);
        } else if (type == VIPPriceType.month) {
            calendar.add(Calendar.MONTH, 1);
        } else if (type == VIPPriceType.season) {
            calendar.add(Calendar.MONTH, 3);
        } else if (type == VIPPriceType.halfYear) {
            calendar.add(Calendar.MONTH, 6);
        } else if (type == VIPPriceType.year) {
            calendar.add(Calendar.YEAR, 1);
        }
        return new Date[]{new Date(startTime), new Date(calendar.getTimeInMillis())};
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/VIPPriceServiceImpl.java
New file
@@ -0,0 +1,147 @@
package com.ks.app.service.impl.vip;
import java.lang.Exception;
import javax.annotation.Resource;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.vip.VIPPriceType;
import com.ks.app.exception.vip.VIPException;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.dao.vip.VIPPriceDao;
import com.ks.app.entity.vip.VIPPrice;
import com.ks.app.service.inter.vip.VIPPriceService;
import com.ks.app.service.query.vip.VIPPriceQuery;
import com.ks.app.dao.vip.VIPPriceDao.DaoQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
@Service
public class VIPPriceServiceImpl implements VIPPriceService {
    @Resource
    private VIPPriceDao vIPPriceDao;
    @Override
    public List<VIPPrice> list(VIPPriceQuery vIPPriceQuery, int page, int pageSize) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(vIPPriceQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        daoQuery.sortList = Arrays.asList(new Sort.Order[]{Sort.Order.asc("order")});
        return vIPPriceDao.list(daoQuery);
    }
    @Override
    public long count(VIPPriceQuery vIPPriceQuery) {
        DaoQuery daoQuery = new DaoQuery();
        try {
            BeanUtil.copyProperties(vIPPriceQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return vIPPriceDao.count(daoQuery);
    }
    @Override
    public VIPPrice get(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        return vIPPriceDao.findOne(query);
    }
    @Override
    public void add(VIPPrice price) throws Exception {
        if (price == null || price.getSystem() == null || price.getActualPrice() == null || price.getType() == null) {
            throw new VIPException(1, "参数不完整");
        }
        if (price.getCreateTime() == null) {
            price.setCreateTime(new Date());
        }
        if (price.getOrder() == null) {
            price.setOrder(price.getActualPrice().multiply(new BigDecimal(100)).intValue());
        }
        price.setId(price.getSystem().name() + "-" + StringUtil.Md5(price.getType().name()));
        vIPPriceDao.save(price);
    }
    @Override
    public void update(VIPPrice vIPPrice) {
        if (vIPPrice.getUpdateTime() == null) {
            vIPPrice.setUpdateTime(new Date());
        }
        //更新
        vIPPriceDao.updateSelective(vIPPrice);
    }
    @Override
    public void delete(List<String> idList) {
        for (String id : idList) {
            vIPPriceDao.delete(id);
        }
    }
    @Override
    public List<VIPPrice> listValidPrice(SystemEnum system) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.count = Integer.MAX_VALUE;
        daoQuery.system = system;
        daoQuery.show = true;
        daoQuery.sortList = Arrays.asList(new Sort.Order[]{Sort.Order.asc("order")});
        return vIPPriceDao.list(daoQuery);
    }
    @Override
    public VIPPrice selectByPrimaryKey(String id) {
        return vIPPriceDao.get(id);
    }
    @Override
    public VIPPrice selectByType(VIPPriceType type, SystemEnum system) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.type = type;
        daoQuery.system = system;
        daoQuery.count = 1;
        List<VIPPrice> list = vIPPriceDao.list(daoQuery);
        if (list == null || list.size() == 0) {
            return null;
        }
        return list.get(0);
    }
    @Override
    public VIPPrice selectByIOSProductId(String productId, SystemEnum system) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.iosProductId = productId;
        daoQuery.system = system;
        List<VIPPrice> list = vIPPriceDao.list(daoQuery);
        if (list == null || list.size() == 0) {
            return null;
        }
        return list.get(0);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/VIPServiceImpl.java
New file
@@ -0,0 +1,80 @@
package com.ks.app.service.impl.vip;
import com.ks.app.dao.vip.UserVIPInfoDao;
import com.ks.app.entity.vip.UserVIPInfo;
import com.ks.app.service.inter.vip.VIPService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
 * @author hxh
 * @title: VIPServiceImpl
 * @description: TODO
 * @date 2021/11/17 17:13
 */
@Service
public class VIPServiceImpl implements VIPService {
    Logger logger = LoggerFactory.getLogger(VIPServiceImpl.class);
    @Resource
    private UserVIPInfoDao userVIPInfoDao;
    @Override
    public UserVIPInfo getVIPInfo(Long uid) {
        return userVIPInfoDao.selectByPrimaryKey(uid);
    }
    @Override
    public void initUserVipInfo(Long uid) {
        UserVIPInfo userVIPInfo = userVIPInfoDao.selectByPrimaryKey(uid);
        if (userVIPInfo == null) {
            userVIPInfo = new UserVIPInfo();
            userVIPInfo.setUid(uid);
            userVIPInfo.setCreateTime(new Date());
            userVIPInfoDao.insertSelective(userVIPInfo);
        }
    }
    @Override
    public List<UserVIPInfo> listVIPUser(Date minVIPExpireDate, Date maxVIPExpireDate, int page, int pageSize) {
        UserVIPInfoDao.DaoQuery daoQuery = new UserVIPInfoDao.DaoQuery();
        daoQuery.maxExpireDate = maxVIPExpireDate;
        daoQuery.minExpireDate = minVIPExpireDate;
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        daoQuery.sortList = Arrays.asList(new String[]{"create_time desc"});
        return userVIPInfoDao.list(daoQuery);
    }
    @Override
    public long countVIPUser(Date minVIPExpireDate, Date maxVIPExpireDate) {
        UserVIPInfoDao.DaoQuery daoQuery = new UserVIPInfoDao.DaoQuery();
        daoQuery.maxExpireDate = maxVIPExpireDate;
        daoQuery.minExpireDate = minVIPExpireDate;
        return userVIPInfoDao.count(daoQuery);
    }
    @Override
    public boolean isVIP(Long uid) {
        UserVIPInfo userVIPInfo = userVIPInfoDao.selectByPrimaryKey(uid);
        if (userVIPInfo == null) {
            return false;
        }
        if (userVIPInfo.getExpireDate() == null) {
            return false;
        }
        if (userVIPInfo.getExpireDate().getTime() < System.currentTimeMillis()) {
            return false;
        }
        return true;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/AdminUserService.java
@@ -12,5 +12,7 @@
    public AdminUser selectByAccount(String account);
    public void add(AdminUser adminUser) throws Exception;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/config/SystemConfigService.java
New file
@@ -0,0 +1,71 @@
package com.ks.app.service.inter.config;
import java.lang.Exception;
import javax.annotation.Resource;
import java.util.Date;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.config.SystemConfigKey;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.entity.config.SystemConfig;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.query.config.SystemConfigQuery;
public interface SystemConfigService {
    /**
     * @author hxh
     * @description 获取缓存值
     * @date 11:50 2021/11/16
     * @param: system
     * @param: key
     * @return java.lang.String
     **/
    public String getValueCache(SystemEnum system, SystemConfigKey key);
    /**
     * 获取列表
     * @param systemConfigQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<SystemConfig> list(SystemConfigQuery systemConfigQuery, int page, int pageSize) ;
    /**
     *
     */
    public long count(SystemConfigQuery systemConfigQuery) ;
    /**
     *
     */
    public SystemConfig get(String id) ;
    /**
     *
     */
    public void add(SystemConfig systemConfig)  throws Exception;
    public void save(SystemConfig config);
    /**
     *
     */
    public void update(SystemConfig systemConfig) ;
    /**
     *
     */
    public void delete(List<String> idList) ;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/QQUserInfoService.java
New file
@@ -0,0 +1,58 @@
package com.ks.app.service.inter.user;
import java.lang.Exception;
import javax.annotation.Resource;
import java.util.Date;
import com.ks.app.entity.SystemEnum;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.entity.user.QQUserInfo;
import com.ks.app.service.inter.user.QQUserInfoService;
import com.ks.app.service.query.user.QQUserInfoQuery;
public interface QQUserInfoService {
    /**
     * 获取列表
     *
     * @param qQUserInfoQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<QQUserInfo> list(QQUserInfoQuery qQUserInfoQuery, int page, int pageSize);
    /**
     *
     */
    public long count(QQUserInfoQuery qQUserInfoQuery);
    /**
     *
     */
    public QQUserInfo get(Long id);
    /**
     *
     */
    public void add(QQUserInfo qQUserInfo) throws Exception;
    /**
     *
     */
    public void update(QQUserInfo qQUserInfo);
    /**
     *
     */
    public void delete(List<Long> idList);
    public QQUserInfo selectBySystemAndOpenId(SystemEnum system, String openId);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserAccountService.java
New file
@@ -0,0 +1,18 @@
package com.ks.app.service.inter.user;
import com.ks.app.dto.user.LoginInfoDTO;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.exception.user.LoginException;
/**
 * @author hxh
 * @title: UserAccountService
 * @description: 用户账号服务
 * @date 2021/11/15 17:56
 */
public interface UserAccountService {
    public UserInfo login(LoginInfoDTO loginInfo) throws LoginException;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserInfoService.java
New file
@@ -0,0 +1,118 @@
package com.ks.app.service.inter.user;
import java.lang.Exception;
import javax.annotation.Resource;
import java.util.Date;
import com.ks.app.entity.SystemEnum;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.service.inter.user.UserInfoService;
import com.ks.app.service.query.user.UserInfoQuery;
import org.yeshi.utils.statistic.BaseStatisticTimeQuery;
import org.yeshi.utils.statistic.StatisticNumberResult;
public interface UserInfoService {
    /**
     * 获取列表
     *
     * @param userInfoQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<UserInfo> list(UserInfoQuery userInfoQuery, int page, int pageSize);
    /**
     *
     */
    public long count(UserInfoQuery userInfoQuery);
    /**
     *
     */
    public UserInfo get(Long id);
    /**
     *
     */
    public void add(UserInfo userInfo) throws Exception;
    /**
     *
     */
    public void update(UserInfo userInfo);
    /**
     *
     */
    public void delete(List<Long> idList);
    /**
     * @return com.ks.app.entity.user.UserInfo
     * @author hxh
     * @description 获取用户信息详情
     * @date 17:15 2021/11/15
     * @param: uid
     **/
    public UserInfo getDetail(Long uid);
    /**
     * @return java.util.List<com.ks.app.entity.user.UserInfo>
     * @author hxh
     * @description 批量获取用户信息详情
     * @date 17:39 2021/11/15
     * @param: uidList
     **/
    public List<UserInfo> getDetailList(List<Long> uidList);
    /**
     * @return com.ks.app.entity.user.UserInfo
     * @author hxh
     * @description 根据电话和系统查询
     * @date 10:26 2021/11/16
     * @param: phone
     * @param: system
     * @param: status
     **/
    public UserInfo selectByPhoneAndSystemAndStatus(String phone, SystemEnum system, Integer status);
    public UserInfo selectByWXIdAndSystemAndStatus(Long wxId, SystemEnum system, Integer status);
    public UserInfo selectByQQIdAndSystemAndStatus(Long qqId, SystemEnum system, Integer status);
    public UserInfo selectByEmailAndSystemAndStatus(String email, SystemEnum system, Integer status);
    /**
     * @return com.ks.app.entity.SystemEnum
     * @author hxh
     * @description //获取用户系统
     * @date 15:06 2021/11/17
     * @param: uid
     **/
    public SystemEnum getSystem(Long uid);
    public UserInfo getAvaiableUser(Long uid);
    /**
     * @return java.util.List<org.yeshi.utils.statistic.StatisticNumberResult>
     * @author hxh
     * @description 统计数据
     * @date 11:23 2021/11/19
     * @param: system
     * @param: timeQuery
     **/
    public List<StatisticNumberResult> statisticRegisterUser(SystemEnum system, BaseStatisticTimeQuery timeQuery);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserLoginRecordService.java
New file
@@ -0,0 +1,35 @@
package com.ks.app.service.inter.user;
import com.ks.app.entity.user.UserLoginRecord;
import com.ks.app.service.query.user.UserLoginRecordQuery;
import java.util.List;
public interface UserLoginRecordService {
    public void addUserLoginRecord(UserLoginRecord record);
    /**
     * 获取列表
     *
     * @param userLoginRecordQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<UserLoginRecord> list(UserLoginRecordQuery userLoginRecordQuery, int page, int pageSize);
    /**
     *
     */
    public long count(UserLoginRecordQuery userLoginRecordQuery);
    /**
     *
     */
    public UserLoginRecord get(String id);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/WXUserInfoService.java
New file
@@ -0,0 +1,64 @@
package com.ks.app.service.inter.user;
import java.lang.Exception;
import javax.annotation.Resource;
import java.util.Date;
import com.ks.app.entity.SystemEnum;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.entity.user.WXUserInfo;
import com.ks.app.service.inter.user.WXUserInfoService;
import com.ks.app.service.query.user.WXUserInfoQuery;
public interface WXUserInfoService {
    /**
     * 获取列表
     *
     * @param wXUserInfoQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<WXUserInfo> list(WXUserInfoQuery wXUserInfoQuery, int page, int pageSize);
    /**
     *
     */
    public long count(WXUserInfoQuery wXUserInfoQuery);
    /**
     *
     */
    public WXUserInfo get(Long id);
    /**
     *
     */
    public void add(WXUserInfo wXUserInfo) throws Exception;
    /**
     * 保存信息
     */
    public WXUserInfo save(WXUserInfo wXUserInfo) throws Exception;
    /**
     *
     */
    public void update(WXUserInfo wXUserInfo);
    /**
     *
     */
    public void delete(List<Long> idList);
    WXUserInfo selectBySystemAndUnionId(SystemEnum system, String unionId);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/vip/IPaySuccess.java
New file
@@ -0,0 +1,15 @@
package com.ks.app.service.inter.vip;
import com.ks.app.entity.vip.OrderRecord;
/**
 * @author hxh
 * @title: IPaySuccess
 * @description: TODO
 * @date 2021/11/17 16:45
 */
public interface IPaySuccess {
    public void onSuccess(OrderRecord record);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/vip/OrderService.java
New file
@@ -0,0 +1,104 @@
package com.ks.app.service.inter.vip;
import com.ks.app.dto.vip.OrderPaySuccessForm;
import com.ks.app.dto.vip.PayWayInfoDTO;
import com.ks.app.entity.vip.OrderRecord;
import com.ks.app.entity.vip.OrderType;
import com.ks.app.exception.goldcorn.GoldCornException;
import com.ks.app.exception.vip.OrderException;
import com.ks.app.exception.vip.PayException;
import com.ks.app.exception.vip.VIPException;
import java.util.List;
public interface OrderService {
    /**
     * 创建订单
     *
     * @param orderRecord
     * @return
     * @throws OrderException
     */
    public OrderRecord createOrder(OrderRecord orderRecord) throws OrderException;
    /**
     * 获取订单记录
     *
     * @param uid
     * @param state
     * @return
     */
    public List<OrderRecord> listOrderRecord(Long uid, OrderType orderType, Integer state, int page, int pageSize);
    /**
     * @param uid
     * @param state
     * @return
     */
    public long countOrderRecord(Long uid, OrderType orderType, Integer state);
    /**
     * 检测支付状态
     *
     * @param id
     */
    public OrderRecord checkOrderPayState(Long id);
    public OrderRecord checkApplePay(Long orderNo, String receipt) throws Exception;
    public OrderRecord getOrderRecord(Long id);
    /**
     * 支付订单
     *
     * @param record
     */
    public PayWayInfoDTO payOrder(OrderRecord record) throws OrderException, GoldCornException, PayException, VIPException;
    /**
     * 支付成功
     *
     * @return
     * @throws VIPException
     * @throws OrderException
     */
    public OrderRecord paySuccess(OrderPaySuccessForm successForm) throws VIPException, OrderException;
    /**
     * 支付成功
     *
     * @return
     * @throws VIPException
     * @throws OrderException
     */
    public OrderRecord paySuccess(OrderPaySuccessForm successForm,IPaySuccess paySuccess) throws VIPException, OrderException;
    /**
     * 取消订单
     *
     * @param id
     */
    public void cancelOrder(Long id, String reason) throws OrderException, GoldCornException;
    /**
     * 获取可以取消的订单记录
     *
     * @param page
     * @param pageSize
     * @return
     */
    public List<OrderRecord> getCanCancelOrderList(int page, int pageSize);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/vip/VIPPriceService.java
New file
@@ -0,0 +1,85 @@
package com.ks.app.service.inter.vip;
import java.lang.Exception;
import javax.annotation.Resource;
import java.util.Date;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.vip.VIPPriceType;
import com.ks.app.exception.vip.VIPException;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.entity.vip.VIPPrice;
import com.ks.app.service.inter.vip.VIPPriceService;
import com.ks.app.service.query.vip.VIPPriceQuery;
public interface VIPPriceService {
    /**
     * 获取列表
     *
     * @param vIPPriceQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<VIPPrice> list(VIPPriceQuery vIPPriceQuery, int page, int pageSize);
    /**
     *
     */
    public long count(VIPPriceQuery vIPPriceQuery);
    /**
     *
     */
    public VIPPrice get(String id);
    /**
     *
     */
    public void add(VIPPrice vIPPrice) throws Exception;
    /**
     *
     */
    public void update(VIPPrice vIPPrice);
    /**
     *
     */
    public void delete(List<String> idList);
    /**
     * 拉取列表
     *
     * @return
     */
    public List<VIPPrice> listValidPrice(SystemEnum system);
    /**
     * 主键查询
     *
     * @param id
     * @return
     */
    public VIPPrice selectByPrimaryKey(String id);
    /**
     * 根据类型查询
     *
     * @param type
     * @return
     */
    public VIPPrice selectByType(VIPPriceType type, SystemEnum system);
    public VIPPrice selectByIOSProductId(String productId, SystemEnum system);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/vip/VIPService.java
New file
@@ -0,0 +1,43 @@
package com.ks.app.service.inter.vip;
import com.ks.app.entity.vip.UserVIPInfo;
import com.ks.app.entity.vip.VIPPrice;
import com.ks.app.service.query.VIPPriceQuery;
import java.util.Date;
import java.util.List;
public interface VIPService {
    /**
     * 获取会员信息
     *
     * @param uid
     * @return
     */
    public UserVIPInfo getVIPInfo(Long uid);
    public void initUserVipInfo(Long uid);
    /**
     * 获取vip用户列表
     *
     * @param minVIPExpireDate
     * @param page
     * @param pageSize
     * @return
     */
    public List<UserVIPInfo> listVIPUser(Date minVIPExpireDate, Date maxVIPExpireDate, int page, int pageSize);
    /**
     * @param minVIPExpireDate
     * @return
     */
    public long countVIPUser(Date minVIPExpireDate, Date maxVIPExpireDate);
    public boolean isVIP(Long uid);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/manager/GoldCornManager.java
New file
@@ -0,0 +1,200 @@
package com.ks.app.service.manager;
import com.ks.goldcorn.exception.GoldAppException;
import com.ks.goldcorn.exception.GoldTradeException;
import com.ks.goldcorn.exception.GoldUserException;
import com.ks.goldcorn.pojo.DO.GoldCornGetSource;
import com.ks.goldcorn.pojo.DO.GoldCornRecord;
import com.ks.goldcorn.pojo.DO.GoldCornRecordCountMap;
import com.ks.goldcorn.pojo.Query.GoldCornRecordQuery;
import com.ks.goldcorn.service.remote.GoldCornBalanceService;
import com.ks.goldcorn.service.remote.GoldCornGetSourceService;
import com.ks.goldcorn.service.remote.GoldCornRecordService;
import com.ks.goldcorn.service.remote.GoldCornTradeService;
import com.ks.app.entity.vip.OrderRecord;
import com.ks.app.entity.vip.OrderType;
import com.ks.app.exception.goldcorn.GoldCornException;
import com.ks.app.service.inter.config.SystemConfigService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Component;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * @author hxh
 * @title: GoldCornManager
 * @description: TODO
 * @date 2021/11/17 14:54
 */
@Component
public class GoldCornManager {
    @Resource
    private SystemConfigService systemConfigService;
//    @Reference(version = "1.0", check = false)
    private GoldCornTradeService goldCornTradeService;
//    @Reference(version = "1.0", check = false)
    private GoldCornRecordService goldCornRecordService;
//    @Reference(version = "1.0", check = false)
    private GoldCornBalanceService goldCornBalanceService;
//    @Reference(version = "1.0", check = false)
    private GoldCornGetSourceService goldCornGetSourceService;
    public void init(Long uid) throws Exception {
        goldCornBalanceService.init(getAppCode(), getUid(uid));
    }
    /**
     * 获取金币系统的用户ID
     *
     * @param uid
     * @return
     * @throws Exception
     */
    public String getUid(Long uid) throws Exception {
        String prefix = "";//systemConfigService.getValueCache(SystemEnum.location,"thirdUidPrefix");
        if (StringUtil.isNullOrEmpty(prefix)) {
            throw new Exception("用户ID前缀获取出错");
        }
        return prefix + uid;
    }
    public String getAppCode() {
        String appCode = "XXXX";
        //TODO 获取appcode
        return appCode;
    }
    public long getBalance(Long uid) {
        if (uid == null) {
            return 0;
        }
        try {
            Long count = goldCornBalanceService.getBalance(getAppCode(), getUid(uid));
            if (count == null) {
                init(uid);
            }
            return count == null ? 0 : count;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
    /**
     * 金币消耗
     *
     * @param record
     * @param goldCornCount 金币数量
     * @throws GoldCornException
     * @throws Exception
     */
    public void consumeGoldCorn(OrderRecord record, int goldCornCount) throws GoldCornException, Exception {
        String tuid = getUid(record.getUid());
        String appCode = getAppCode();
        String sourceCode = "";
        String title = "";
        String desc = "";
        if (record.getOrderType() == OrderType.vip) {
            sourceCode = "buyVIP";
            title = "购买VIP";
        }
        consumeGoldCorn(appCode, tuid, sourceCode, goldCornCount, title, desc);
    }
    /**
     * 添加金币
     *
     * @param uid
     * @param source
     * @param goldCorn
     * @param title
     * @param desc
     * @throws GoldUserException
     * @throws GoldAppException
     * @throws GoldTradeException
     * @throws Exception
     */
//    public void addGoldCorn(String uid, CodeCornGetSourceType source, Integer goldCorn, String title, String desc) throws GoldUserException, GoldAppException, GoldTradeException, Exception {
//        addGoldCorn(getAppCode(), getUid(uid), source.name(), goldCorn, title, desc);
//    }
//
//    public GoldCornGetSource getGoldCornGetSource(CodeCornGetSourceType source) throws GoldAppException {
//        return goldCornGetSourceService.selectByAppAndCode(getAppCode(), source.name());
//    }
    /**
     * 返回影视豆
     *
     * @param record
     * @throws GoldCornException
     * @throws Exception
     */
    public void drawbackGoldCorn(OrderRecord record) throws GoldCornException, Exception {
        String tuid = getUid(record.getUid());
        String appCode = getAppCode();
        String sourceCode = "";
        String title = "";
        String desc = "";
        if (record.getOrderType() == OrderType.vip) {
            sourceCode = "buyVIP";
            title = "购买VIP退款";
        }
        addGoldCorn(appCode, tuid, sourceCode, record.getGoldCorn(), title, desc);
    }
    public List<GoldCornRecord> getRecordList(GoldCornRecordQuery query, Long uid) throws Exception {
        query.setAppCode(getAppCode());
        query.setUid(getUid(uid));
        return goldCornRecordService.listUserRecord(query);
    }
    public long getRecordCount(GoldCornRecordQuery query, Long uid) throws Exception {
        query.setAppCode(getAppCode());
        query.setUid(getUid(uid));
        return goldCornRecordService.countUserRecord(query);
    }
    private void addGoldCorn(String appCode, String uid, String sourceCode, Integer goldCornCount, String title, String desc) throws GoldUserException, GoldAppException, GoldTradeException {
        goldCornTradeService.addGoldCorn(appCode, uid, sourceCode, goldCornCount, title, desc);
    }
    private void consumeGoldCorn(String appCode, String uid, String sourceCode, Integer goldCornCount, String title, String desc) throws GoldUserException, GoldAppException, GoldTradeException {
        goldCornTradeService.consumeGoldCorn(appCode, uid, sourceCode, goldCornCount, title, desc);
    }
    public List<GoldCornGetSource> listGetCornSource(int page, int pageSize) throws GoldAppException {
        return goldCornGetSourceService.listShow(getAppCode(), page, pageSize);
    }
    public List<GoldCornRecordCountMap> countRecordByGetSource(Long uid, List<String> sourceCodes, Date minCreateTime, Date maxCreateTime) throws Exception {
        if (uid == null) {
            return new ArrayList<>();
        }
        GoldCornRecordQuery query = new GoldCornRecordQuery();
        query.setUid(getUid(uid));
        query.setAppCode(getAppCode());
        query.setSourceCodes(sourceCodes);
        query.setMinCreateTime(minCreateTime);
        query.setMaxCreateTime(maxCreateTime);
        query.setType(GoldCornRecord.TYPE_GET);
        return goldCornRecordService.countUserRecordBySource(query);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/manager/VerifyCodeManager.java
New file
@@ -0,0 +1,79 @@
package com.ks.app.service.manager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.yeshi.utils.NumberUtil;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.sms.TencentSMSUtil;
import org.yeshi.utils.sms.VerifyCodeFactory;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
/**
 * @author hxh
 * @title: VerifyCodeManager
 * @description: 验证码管理
 * @date 2021/11/15 18:38
 */
@Component
public class VerifyCodeManager {
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    /**
     * @return void
     * @author hxh
     * @description 发送电话验证码
     * @date 18:40 2021/11/15
     * @param: phone
     * @param: msg 变量为:{验证码}
     **/
    public void sendSMSSuccess(String phone, String code) {
        redisTemplate.opsForValue().set("v-c-p-" + phone, code, 120, TimeUnit.SECONDS);
    }
    /**
     * @return void
     * @author hxh
     * @description 发送邮箱验证码
     * @date 18:41 2021/11/15
     * @param: email
     * @param: title
     * @param: content
     **/
    public void sendEmailCodeSuccess(String email, String code) {
        redisTemplate.opsForValue().set("v-c-e-" + StringUtil.Md5(email), code, 120, TimeUnit.SECONDS);
    }
    /**
     * @return boolean
     * @author hxh
     * @description 电话验证码是否正确
     * @date 19:05 2021/11/15
     * @param: phone
     * @param: code
     **/
    public boolean isPhoneCodeRight(String phone, String code) {
        String oldCode = redisTemplate.opsForValue().get("v-c-p-" + phone);
        return oldCode != null && oldCode.equalsIgnoreCase(code);
    }
    /**
     * @return boolean
     * @author hxh
     * @description /邮箱验证码是否正确
     * @date 19:05 2021/11/15
     * @param: email
     * @param: code
     **/
    public boolean isEMailCodeRight(String email, String code) {
        String oldCode = redisTemplate.opsForValue().get("v-c-e-" + StringUtil.Md5(email));
        return oldCode != null && oldCode.equalsIgnoreCase(code);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/VIPPriceQuery.java
New file
@@ -0,0 +1,16 @@
package com.ks.app.service.query;
public class VIPPriceQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/config/SystemConfigQuery.java
New file
@@ -0,0 +1,16 @@
package com.ks.app.service.query.config;
public class SystemConfigQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/user/QQUserInfoQuery.java
New file
@@ -0,0 +1,16 @@
package com.ks.app.service.query.user;
public class QQUserInfoQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/user/UserInfoQuery.java
New file
@@ -0,0 +1,16 @@
package com.ks.app.service.query.user;
public class UserInfoQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/user/UserLoginRecordQuery.java
New file
@@ -0,0 +1,16 @@
package com.ks.app.service.query.user;
public class UserLoginRecordQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/user/WXUserInfoQuery.java
New file
@@ -0,0 +1,16 @@
package com.ks.app.service.query.user;
public class WXUserInfoQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/vip/VIPPriceQuery.java
New file
@@ -0,0 +1,16 @@
package com.ks.app.service.query.vip;
public class VIPPriceQuery {
    //搜索关键词
    private String kw;
    private String getKw(){
        return kw;
    }
    private void setKw(String kw){
        this.kw = kw;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/AliyunOneKeyLoginUtil.java
New file
@@ -0,0 +1,51 @@
package com.ks.app.utils;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileRequest;
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import org.yeshi.utils.StringUtil;
/**
 * @author hxh
 * @title: AliyunOneKeyLoginUtil
 * @description: 阿里云一键登录
 * @date 2021/11/15 11:03
 */
public class AliyunOneKeyLoginUtil {
    private final static String ACCESS_KEY = "LTAI4FwmTxVCuzTaoZtDiV8z";
    private final static String ACESS_SCRET = "ixWg90QbYFKP6ae5xpAo2P1qwIyll5";
    public static String getMobile(String accessToken, String outId,String acessKey,String acessSecret) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", acessKey, acessSecret);
        IAcsClient client = new DefaultAcsClient(profile);
        GetMobileRequest request = new GetMobileRequest();
        request.setAccessToken(accessToken);
        if (!StringUtil.isNullOrEmpty(outId))
            request.setOutId(outId);
        try {
            GetMobileResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
            if (response.getGetMobileResultDTO() != null) {
                String mobile = response.getGetMobileResultDTO().getMobile();
                return mobile;
            }
            System.out.println(new Gson().toJson(response));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
        return null;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/ApiCodeConstant.java
New file
@@ -0,0 +1,20 @@
package com.ks.app.utils;
/**
 * @author hxh
 * @title: ApiCodeConstant
 * @description: 接口请求的枚举值
 * @date 2021/11/16 17:53
 */
public class ApiCodeConstant {
    //客户端请求时间错误(误差超过10分钟)
    public final static int CODE_FAIL_OUT_TIME = -2;
    //签名错误
    public final static int CODE_FAIL_SIGN_ERROR = -1;
    //请求正确
    public final static int CODE_OK = 0;
    //用户被封禁
    public final static int CODE_FAIL_USER_FORBIDDEN = 80001;
    //服务器内部错误
    public final static int CODE_ERROR_IN_SERVER = 10001;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/Constant.java
New file
@@ -0,0 +1,14 @@
package com.ks.app.utils;
/**
 * @author hxh
 * @title: Constant
 * @description: TODO
 * @date 2021/11/16 17:41
 */
public class Constant {
    public final static int PAGE_SIZE=20;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/PayConstant.java
New file
@@ -0,0 +1,23 @@
package com.ks.app.utils;
/**
 * @author hxh
 * @title: PayConstant
 * @description:TODO 支付常量(还需要配置resources下的wxpay.properties,alipay.properties与wx/apiclient_key.pem
 * )
 * @date 2021/11/17 16:58
 */
public class PayConstant {
    public final static String ALIPAY_NOTIFY_URL="**/alipay/pay";
    public final static String WX_NOTIFY_URL="**/wx/pay/vip";
    public final static String PAY_SUCCESS_LINK="http://vip.ysdq.yeshitv.com/pay_success.html?id={id}";
    public final static String WX_PAY_FINISH_LINK="http://vip.ysdq.yeshitv.com/pay_finish.html?id={id}";
    public final static String ALIPAY_PRINT_PAY_FORM_LINK="alipay/printPayForm?formId={formId}";
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/SystemInfoUtil.java
New file
@@ -0,0 +1,62 @@
package com.ks.app.utils;
import com.ks.app.entity.APPPlatform;
import com.ks.app.entity.SystemEnum;
import javax.servlet.http.HttpSession;
/**
 * @author hxh
 * @title: SystemInfoUtil
 * @description: TODO
 * @date 2021/11/16 17:57
 */
public class SystemInfoUtil {
    /**
     * @return com.ks.app.entity.SystemEnum
     * @author hxh
     * @description 获取系统
     * @date 18:02 2021/11/16
     * @param: platform
     * @param: packageName
     **/
    public static SystemEnum getSystem(APPPlatform platform, String packageName) {
        for (SystemEnum system : SystemEnum.values()) {
            if (platform == APPPlatform.android) {
                if (system.getPackageName().equalsIgnoreCase(packageName)) {
                    return system;
                }
            } else if (platform == APPPlatform.ios) {
                if (system.getBundleId().equalsIgnoreCase(packageName)) {
                    return system;
                }
            }
        }
        return null;
    }
    /**
     * 获取system
     *
     * @param session
     * @return
     */
    public static SystemEnum getAdminSelectedSystem(HttpSession session) {
        SystemEnum systemInfo = (SystemEnum) session.getAttribute("SELECTED-SYSTEM");
        return systemInfo;
    }
    /**
     * 保存System
     *
     * @param session
     * @param systemInfo
     */
    public static void saveAdminSelectedSystem(HttpSession session, SystemEnum systemInfo) {
        session.setAttribute("SELECTED-SYSTEM", systemInfo);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/vip/VIPOrderUtil.java
New file
@@ -0,0 +1,36 @@
package com.ks.app.utils.vip;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.vip.OrderType;
/**
 * @author hxh
 * @title: VIPOrderUtil
 * @description: TODO
 * @date 2021/11/17 14:59
 */
public class VIPOrderUtil {
    /**
     * 获取第三方订单号
     *
     * @param orderType
     * @param id
     * @return
     */
    public static String getOutOrderNo(SystemEnum system, OrderType orderType, Long id) {
        if (orderType == OrderType.vip) {
            return system.name() + "_vip_" + id;
        }
        return null;
    }
    public static Long getIdFromOutOrderNo(String orderNo) {
        String system = orderNo.split("_")[0];
        return Long.parseLong(orderNo.replace(system + "_vip_", ""));
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/vip/VipUtil.java
New file
@@ -0,0 +1,121 @@
package com.ks.app.utils.vip;
import com.alipay.api.AlipayApiException;
import com.ks.app.entity.vip.OrderType;
import com.ks.app.utils.Constant;
import com.ks.app.utils.PayConstant;
import org.apache.commons.io.IOUtils;
import org.yeshi.utils.alipay.AlipayH5PayUtil;
import org.yeshi.utils.entity.alipay.AlipayAppInfo;
import org.yeshi.utils.entity.wx.WXAPPInfo;
import org.yeshi.utils.entity.wx.WXPlaceOrderParams;
import org.yeshi.utils.wx.WXPayV3Util;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Properties;
public class VipUtil {
    public static AlipayAppInfo getAlipayApp() {
        try {
            Properties properties = new Properties();
            properties.load(VipUtil.class.getClassLoader().getResourceAsStream("alipay.properties"));
            String appId = properties.getProperty("app_id");
            String privateKey = properties.getProperty("private_key");
            String publicKey = properties.getProperty("alipay_public_key");
            AlipayAppInfo appInfo = new AlipayAppInfo(appId, privateKey, publicKey);
            return appInfo;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取微信app
     *
     * @return
     */
    public static WXAPPInfo getWXAPP() {
        String privateKey = "";
        try {
            String content = IOUtils.toString(VipUtil.class.getClassLoader().getResourceAsStream("wx/apiclient_key.pem"));
            privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
        } catch (Exception e) {
        }
        Properties properties = new Properties();
        try {
            properties.load(VipUtil.class.getClassLoader().getResourceAsStream("wxpay.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        String appId = properties.getProperty("app_id");
        String mchId = properties.getProperty("mch_id");
        String mchSerialNo = properties.getProperty("mch_serial_no");
        String apiV3Key = properties.getProperty("api_v3_key");
        WXAPPInfo app = new WXAPPInfo(appId, mchId, mchSerialNo, privateKey, apiV3Key);
        return app;
    }
    /**
     * 获取会员充值支付宝支付表单
     *
     * @param orderNo
     * @param money
     * @return
     */
    public static String getVipChargeAlipayForm(Long id, OrderType orderType, String orderNo, BigDecimal money) {
        try {
            String goodsTitle = "会员购买";
            String returnUrl = getPaySuccessUrl(id);
            String notifyUrl = PayConstant.ALIPAY_NOTIFY_URL;
            AlipayAppInfo appInfo = getAlipayApp();
            String form = AlipayH5PayUtil.createOrderForm(appInfo, orderNo, money, goodsTitle, returnUrl, notifyUrl);
            return form;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static String getPaySuccessUrl(Long id) {
        return PayConstant.PAY_SUCCESS_LINK.replace("{id}", id+"");
    }
    /**
     * 微信下单
     *
     * @param ip
     * @param orderNo
     * @param money
     * @param title
     * @return
     * @throws Exception
     */
    public static String createWXOrder(Long id, String ip, String orderNo, BigDecimal money, String title) throws Exception {
        WXPlaceOrderParams params = new WXPlaceOrderParams();
        params.setIp(ip);
        params.setOrderNo(orderNo);
        params.setNotifyUrl(PayConstant.WX_NOTIFY_URL);
        params.setFee(money);
        params.setBody(title);
        params.setApp(getWXAPP());
        String returnUrl = PayConstant.WX_PAY_FINISH_LINK.replace("{id}", id+"");
        String payUrl = WXPayV3Util.createH5Order(params, returnUrl);
        return payUrl;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/AcceptAdminData.java
New file
@@ -0,0 +1,22 @@
package com.ks.app.vo;
import com.ks.app.entity.APPPlatform;
import com.ks.app.entity.SystemEnum;
/**
 * @author hxh
 * @title: AcceptData
 * @description: 后台接口基础数据
 * @date 2021/11/16 17:40
 */
public class AcceptAdminData {
    private SystemEnum system;
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/AcceptData.java
New file
@@ -0,0 +1,106 @@
package com.ks.app.vo;
import com.ks.app.entity.APPPlatform;
import com.ks.app.entity.SystemEnum;
/**
 * @author hxh
 * @title: AcceptData
 * @description: 接口基础数据
 * @date 2021/11/16 17:40
 */
public class AcceptData {
    //时间戳
    private long timestamp;
    private String sign;
    private SystemEnum system;
    private APPPlatform platform;
    private String packages;
    private int version;
    private String channel;
    private String osVersion;
    private String idfa;
    private String utdid;
    public long getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }
    public String getSign() {
        return sign;
    }
    public void setSign(String sign) {
        this.sign = sign;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public String getPackages() {
        return packages;
    }
    public void setPackages(String packages) {
        this.packages = packages;
    }
    public int getVersion() {
        return version;
    }
    public void setVersion(int version) {
        this.version = version;
    }
    public String getChannel() {
        return channel;
    }
    public void setChannel(String channel) {
        this.channel = channel;
    }
    public String getOsVersion() {
        return osVersion;
    }
    public void setOsVersion(String osVersion) {
        this.osVersion = osVersion;
    }
    public String getIdfa() {
        return idfa;
    }
    public void setIdfa(String idfa) {
        this.idfa = idfa;
    }
    public String getUtdid() {
        return utdid;
    }
    public void setUtdid(String utdid) {
        this.utdid = utdid;
    }
    public APPPlatform getPlatform() {
        return platform;
    }
    public void setPlatform(APPPlatform platform) {
        this.platform = platform;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/SystemVO.java
New file
@@ -0,0 +1,43 @@
package com.ks.app.vo;
/**
 * @author hxh
 * @title: Systemvo
 * @description: TODO
 * @date 2021/11/18 11:48
 */
public class SystemVO {
    private String  name;
    private String key;
    private boolean selected;
    public SystemVO(String name, String key, boolean selected) {
        this.name = name;
        this.key = key;
        this.selected = selected;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public boolean isSelected() {
        return selected;
    }
    public void setSelected(boolean selected) {
        this.selected = selected;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/user/UserInfoVO.java
New file
@@ -0,0 +1,47 @@
package com.ks.app.vo.user;
/**
 * @author hxh
 * @title: UserInfoVO
 * @description: TODO
 * @date 2021/11/17 17:15
 */
public class UserInfoVO {
    private String id;
    private String nickName;
    private String portrait;
    //VIP到期时间
    private Long vipExpireTime;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getNickName() {
        return nickName;
    }
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    public String getPortrait() {
        return portrait;
    }
    public void setPortrait(String portrait) {
        this.portrait = portrait;
    }
    public Long getVipExpireTime() {
        return vipExpireTime;
    }
    public void setVipExpireTime(Long vipExpireTime) {
        this.vipExpireTime = vipExpireTime;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/vip/OrderInfoVO.java
New file
@@ -0,0 +1,149 @@
package com.ks.app.vo.vip;
import com.ks.app.entity.vip.OrderRecord;
import com.ks.app.entity.vip.OrderType;
import org.yeshi.utils.TimeUtil;
/**
 * @author hxh
 * @title: OrderInfoVO
 * @description: TODO
 * @date 2021/11/17 17:19
 */
public class OrderInfoVO {
    private String title;
    private String orderNo;
    private String date;
    private String startTime;
    private String endTime;
    private String payWay;
    private int state;
    private String type;
    private String cid;
    private String vid;
    public String getCid() {
        return cid;
    }
    public void setCid(String cid) {
        this.cid = cid;
    }
    public String getVid() {
        return vid;
    }
    public void setVid(String vid) {
        this.vid = vid;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getOrderNo() {
        return orderNo;
    }
    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }
    public String getDate() {
        return date;
    }
    public void setDate(String date) {
        this.date = date;
    }
    public String getStartTime() {
        return startTime;
    }
    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
    public String getEndTime() {
        return endTime;
    }
    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }
    public String getPayWay() {
        return payWay;
    }
    public void setPayWay(String payWay) {
        this.payWay = payWay;
    }
    public int getState() {
        return state;
    }
    public void setState(int state) {
        this.state = state;
    }
    public static OrderInfoVO create(OrderRecord record) {
        OrderInfoVO vo = new OrderInfoVO();
        if (record.getOrderType() == OrderType.vip) {
            vo.setTitle(record.getType().getName() + "VIP/会员");
        }
        vo.setDate(TimeUtil.getGernalTime(record.getCreateTime().getTime(), "yyyy.MM.dd HH:mm"));
        if (record.getVipStartTime() != null) {
            vo.setStartTime(TimeUtil.getGernalTime(record.getVipStartTime().getTime(), "yyyy.MM.dd HH:mm"));
        }
        if (record.getVipEndTime() != null) {
            vo.setEndTime(TimeUtil.getGernalTime(record.getVipEndTime().getTime(), "yyyy.MM.dd HH:mm"));
        }
        vo.setOrderNo(record.getId() + "");
        vo.setType(record.getOrderType().name());
        String payWay = "";
        switch (record.getPayWay()) {
            case OrderRecord.PAY_WAY_ALIPAY:
                payWay = "支付宝";
                break;
            case OrderRecord.PAY_WAY_GOLDCORN:
                payWay = "金币";
                break;
            case OrderRecord.PAY_WAY_WX:
                payWay = "微信";
                break;
            case OrderRecord.PAY_WAY_ALIPAY_GOLDCORN:
                payWay = "金币+支付宝";
                break;
            case OrderRecord.PAY_WAY_WX_GOLDCORN:
                payWay = "金币+微信";
                break;
        }
        if (record.getState() == OrderRecord.STATE_PAY) {
            vo.setPayWay(payWay);
        }
        vo.setState(record.getState());
        return vo;
    }
}
src/main/resources/code/service/app/src/main/resources/alipay.properties
New file
@@ -0,0 +1,3 @@
app_id=2021002122664142
private_key=MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCobx3dj48eJ8xg9twd0Yo2j/t0UzawGHcCJ5lmA+LR3ZJHKud2/YhsekN5ZXR9BgJ3DZNTlZfRK3/DyW2CxEJmpCU9tNAM8WapkaXobQOaBqVhcfj9YevygcGYfAK0vPYNuGwCOW93Cl0Lm9SWIZQZIv3w8mWQBX9+7csAt9K46hk7QCJG/YyHORgTFWeHLATbj+j8JywyFpd5ZSrGFUj/bC5Z1v2Gx7lXOLF5VnAjY7slPdElYe93MHnLh901NQPI/IoqJupEJhHgV2Qi3Z+7PXXNTa/tWAew3rlYdEtfRojFPhqB5rNF3inIKLryMfxBcbVTG13QGFWo3gJZ9BdbAgMBAAECggEBAJkaiBdBy2Ip4wmw21zvf6chMf0HNwrS8jqvLC0jEyaZNcIjKctronqYmITcyAptUAhP+r9bl2i3FagujLD1HTaXtpJkrUlWlW9FyX2Aumlj6SiupRoNzJ/fes7UytDngvHt1aAf/UZD0VggChl95FUFDbfbXp6PoNkL5h98+LrD9eKrRd2Oeclpnet5E3benQogLLtW+n10PB2PTrBJg+HGk+M5J5t5O4fEZ4mCpEPl2Pq6g5KVR7Hbb5n0x7K5Uo8WXU79OIdMt8zy6a8BHx3VPYjkqr9VjMCEfgKBngMJ1ezFJGQ6rc3xJD9DoSR7/YXuFeHKQao8tX6UmUGjRUECgYEA4amyumywa37lmDtkmHXXgJHcpvejxM+A7F8DBw/uUBekVSCq3rU/kPsnXCr+/pL91ulEcJduCmPIbfkvTmAthD5IqDhQYnnYX+ulhX1C8Aj6zulkGqfa8sevuPjaLelLNZxvXXIYNik4+z5o7CSIgOrCjBhAWCKAgb/45BEwpIMCgYEAvxPb/ib7MMdEbWBmvqtauPPi170GOT9IiIcXQwyhcfj5/+0E83bjoEj0GOUH2X8qT0liSmj1LJqny4K00qnG05zijL+vna/pn3zFTKrRVtCmRDtYSJtzcCju7RdkNQ8WXASTmjaSinuEdg+aTI9G+oOMyIYGEQVZ8o+w2KzaukkCgYEAkPH+Ie5UNwewE2L6z07J2ARYlUp0/6JE7g5tFGkwKnO1ExTDi/8hUE9xzaq0VPI3Z4Y3dpZdkQDcqX6n2xC9y7Zx1tMtFsOqrpnenGqDx0gNST/yE4kDgnOutAHrqheyPkI36e6yDH/X4NEKdbtVjnC7+15MXg/zOOQEywEbnF8CgYAqcSHTYRs4aXqUhO4teehL3rhLTUw9mQXmdYNAPGT76N627xHDdmv3JV06zlyg/fMK63TurEORJcURmjXJ+TYVuOpFcypx7yoIZ/F3JxYan3ve+gORFR5eEmmHtkNm2bQQul+CyI5iPi9c/fg6+zQ73s59l+9vBm5FR49zgWmQKQKBgQCmq14mUPPe5LF3W342qZTKSKtwF82XYmuJ0EtjYxlt+D70fSvaB8Dtj/XanL0FRMVZsJaIM1pjdnMIqRN2AGOXLRt8DV9lTELqBfq2aI7f9vscc28T4ySUTkWVbZYwC6iDlPBha3MUwGGiO/rNbnIY7GB3BUSpgazo02lvzd0vsw==
alipay_public_key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHWEgMOlGb/VbN5pcSXv+DLX2EJ43p93zP9eyao8ghj1LcBSf5Sx4gYpuySKZ0oimILb+ErOAlDzcXwvMxcVTK0W2M6UaUW0Vh71vOorqggOGqMJsSDpV1hvYrUSCYu1Qe5KtV85w+Kw4dImC3fayIaxUMhwySuniQ/uQtezRHn/vwXrGigu3Y2tRgPMUptqA14EYEfhpm3KjLXsqWdJBO6ziiqILHJtow65QzkeoLM2ZHpYH6oYy2rIj/iSIpos18MKWvr4XrqSptJYIQp+G3dwqjlt2kk4bpgAXQSR6wKAtGTkAYvlOSpkQXVqI3tIGZO3ZM9bFQurMBoJFX790wIDAQAB
src/main/resources/code/service/app/src/main/resources/application-dev.yml
@@ -17,7 +17,7 @@
      password: 'Yeshi2016@'
      host: 193.112.35.168
      port: 27016
      database: app
      database: location
      authentication-database: admin
  redis:
    host: 193.112.35.168 #193.112.34.40
@@ -44,7 +44,7 @@
  datasource:
    url: jdbc:mysql://gz-cdb-r13d0yi9.sql.tencentcdb.com:62929/bpush?serverTimezone=GMT%2B8
    url: jdbc:mysql://gz-cdb-r13d0yi9.sql.tencentcdb.com:62929/location?serverTimezone=GMT%2B8
    username: root
    password: Yeshi2016@
    driver-class-name: com.mysql.jdbc.Driver
@@ -99,4 +99,5 @@
#  scan:
#    base-packages: com.ks.app.service.remote
#  provider:
#    timeout: 10000
#    timeout: 10000
src/main/resources/code/service/app/src/main/resources/ehcache.xml
New file
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
    <!--磁盘缓存的地址 -->
    <diskStore path="java.io.tmpdir/ehcache" /><!-- 达到内存上限后缓存文件保存位置 -->
    <!-- <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446,
        timeToLive=32" /> -->
    <!-- timeToLive 0是限制在同一个服务器 1是限制在同一个子网 32是限制在同一个网站 64是限制在同一个region 128是限制在同一个大洲
        255是不限制 -->
    <!-- 默认缓存 -->
    <defaultCache maxElementsInMemory="1000" eternal="false"
        maxElementsOnDisk="10000" timeToIdleSeconds="120" timeToLiveSeconds="120"
        overflowToDisk="false" />
    <!-- 配置文件缓存 -->
    <cache name="configCache" maxElementsInMemory="1000"
           maxElementsOnDisk="10000" eternal="false" timeToIdleSeconds="120"
           timeToLiveSeconds="120" overflowToDisk="true"
           memoryStoreEvictionPolicy="LRU" />
</ehcache>
src/main/resources/code/service/app/src/main/resources/mapper/BaseMapper.xml
New file
@@ -0,0 +1,18 @@
<?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="com.ks.app.mapper.basemapper">
    <resultMap id="Statistic_Number_BaseResultMap"
               type="org.yeshi.utils.statistic.StatisticNumberResult">
        <result column="time" property="time" jdbcType="VARCHAR"/>
        <result column="number" property="number" jdbcType="BIGINT"/>
    </resultMap>
    <resultMap id="Statistic_Value_BaseResultMap"
               type="org.yeshi.utils.statistic.StatisticValueResult">
        <result column="time" property="time" jdbcType="VARCHAR"/>
        <result column="value" property="value" jdbcType="DECIMAL"/>
    </resultMap>
</mapper>
src/main/resources/code/service/app/src/main/resources/mapper/OrderRecordMapper.xml
New file
@@ -0,0 +1,268 @@
<?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="com.ks.app.dao.vip.OrderRecordDao">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.vip.OrderRecord">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="order_type" property="orderType" jdbcType="VARCHAR"/>
        <result column="uid" property="uid" jdbcType="BIGINT"/>
        <result column="state" property="state" jdbcType="INTEGER"/>
        <result column="money_pay" property="moneyPay" jdbcType="BOOLEAN"/>
        <result column="gold_corn_pay" property="goldCornPay" jdbcType="BOOLEAN"/>
        <result column="gold_corn" property="goldCorn" jdbcType="INTEGER"/>
        <result column="type" property="type" jdbcType="VARCHAR"/>
        <result column="money" property="money" jdbcType="DECIMAL"/>
        <result column="pay_way" property="payWay" jdbcType="INTEGER"/>
        <result column="pay_money" property="payMoney" jdbcType="DECIMAL"/>
        <result column="ip_info" property="ipInfo" jdbcType="VARCHAR"/>
        <result column="pay_time" property="payTime" jdbcType="TIMESTAMP"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
        <result column="vip_start_time" property="vipStartTime" jdbcType="TIMESTAMP"/>
        <result column="vip_end_time" property="vipEndTime" jdbcType="TIMESTAMP"/>
        <result column="remarks" property="remarks" jdbcType="VARCHAR"/>
        <result column="apple_transaction_id" property="appleTransactionId" jdbcType="VARCHAR"/>
        <result column="apple_original_transaction_id" property="appleOriginalTransactionId" jdbcType="VARCHAR"/>
    </resultMap>
    <sql id="Base_Column_List">
        <trim suffixOverrides=",">
            id,order_type,uid,state,money_pay,gold_corn_pay,gold_corn,type,money,pay_way,pay_money,ip_info,pay_time,create_time,update_time,vip_start_time,vip_end_time,remarks,apple_transaction_id,apple_original_transaction_id,
        </trim>
    </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_vip_order_record where id = #{id, jdbcType=BIGINT}
    </select>
    <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_vip_order_record where id = #{id,jdbcType=BIGINT} for update
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
        delete from
        lt_vip_order_record where id = #{id,jdbcType=BIGINT}
    </delete>
    <insert id="insert"
            parameterType="com.ks.app.entity.vip.OrderRecord"
            useGeneratedKeys="true" keyProperty="id">
        insert into
        lt_vip_order_record
        <trim prefix="(" suffix=")" suffixOverrides=",">
            order_type,
            uid,
            state,
            money_pay,
            gold_corn_pay,
            gold_corn,
            type,
            money,
            pay_way,
            pay_money,
            ip_info,
            pay_time,
            create_time,
            update_time,
            vip_start_time,
            vip_end_time,
            remarks,
            apple_transaction_id,
            apple_original_transaction_id,
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{orderType},jdbcType=VARCHAR},
            #{uid},jdbcType=BIGINT},
            #{state},jdbcType=INTEGER},
            #{moneyPay},jdbcType=BOOLEAN},
            #{goldCornPay},jdbcType=BOOLEAN},
            #{goldCorn},jdbcType=INTEGER},
            #{type},jdbcType=VARCHAR},
            #{money},jdbcType=DECIMAL},
            #{payWay},jdbcType=INTEGER},
            #{payMoney},jdbcType=DECIMAL},
            #{ipInfo},jdbcType=VARCHAR},
            #{payTime},jdbcType=TIMESTAMP},
            #{createTime},jdbcType=TIMESTAMP},
            #{updateTime},jdbcType=TIMESTAMP},
            #{vipStartTime},jdbcType=TIMESTAMP},
            #{vipEndTime},jdbcType=TIMESTAMP},
            #{remarks},jdbcType=VARCHAR},
            #{appleTransactionId},jdbcType=VARCHAR},
            #{appleOriginalTransactionId},jdbcType=VARCHAR},
        </trim>
    </insert>
    <insert id="insertSelective"
            parameterType="com.ks.app.entity.vip.OrderRecord"
            useGeneratedKeys="true" keyProperty="id">
        insert into lt_vip_order_record
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="orderType != null">order_type,</if>
            <if test="uid != null">uid,</if>
            <if test="state != null">state,</if>
            <if test="moneyPay != null">money_pay,</if>
            <if test="goldCornPay != null">gold_corn_pay,</if>
            <if test="goldCorn != null">gold_corn,</if>
            <if test="type != null">type,</if>
            <if test="money != null">money,</if>
            <if test="payWay != null">pay_way,</if>
            <if test="payMoney != null">pay_money,</if>
            <if test="ipInfo != null">ip_info,</if>
            <if test="payTime != null">pay_time,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="vipStartTime != null">vip_start_time,</if>
            <if test="vipEndTime != null">vip_end_time,</if>
            <if test="remarks != null">remarks,</if>
            <if test="appleTransactionId != null">apple_transaction_id,</if>
            <if test="appleOriginalTransactionId != null">apple_original_transaction_id,</if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id,jdbcType=BIGINT},</if>
            <if test="orderType != null">#{orderType,jdbcType=VARCHAR},</if>
            <if test="uid != null">#{uid,jdbcType=BIGINT},</if>
            <if test="state != null">#{state,jdbcType=INTEGER},</if>
            <if test="moneyPay != null">#{moneyPay,jdbcType=BOOLEAN},</if>
            <if test="goldCornPay != null">#{goldCornPay,jdbcType=BOOLEAN},</if>
            <if test="goldCorn != null">#{goldCorn,jdbcType=INTEGER},</if>
            <if test="type != null">#{type,jdbcType=VARCHAR},</if>
            <if test="money != null">#{money,jdbcType=DECIMAL},</if>
            <if test="payWay != null">#{payWay,jdbcType=INTEGER},</if>
            <if test="payMoney != null">#{payMoney,jdbcType=DECIMAL},</if>
            <if test="ipInfo != null">#{ipInfo,jdbcType=VARCHAR},</if>
            <if test="payTime != null">#{payTime,jdbcType=TIMESTAMP},</if>
            <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
            <if test="vipStartTime != null">#{vipStartTime,jdbcType=TIMESTAMP},</if>
            <if test="vipEndTime != null">#{vipEndTime,jdbcType=TIMESTAMP},</if>
            <if test="remarks != null">#{remarks,jdbcType=VARCHAR},</if>
            <if test="appleTransactionId != null">#{appleTransactionId,jdbcType=VARCHAR},</if>
            <if test="appleOriginalTransactionId != null">#{appleOriginalTransactionId,jdbcType=VARCHAR},</if>
        </trim>
    </insert>
    <update id="updateByPrimaryKey"
            parameterType="com.ks.app.entity.vip.OrderRecord">
        update lt_vip_order_record
        <set>
            <if test="id != null">id = #{id,jdbcType=BIGINT},</if>
            <if test="orderType != null">order_type = #{orderType,jdbcType=VARCHAR},</if>
            <if test="uid != null">uid = #{uid,jdbcType=BIGINT},</if>
            <if test="state != null">state = #{state,jdbcType=INTEGER},</if>
            <if test="moneyPay != null">money_pay = #{moneyPay,jdbcType=BOOLEAN},</if>
            <if test="goldCornPay != null">gold_corn_pay = #{goldCornPay,jdbcType=BOOLEAN},</if>
            <if test="goldCorn != null">gold_corn = #{goldCorn,jdbcType=INTEGER},</if>
            <if test="type != null">type = #{type,jdbcType=VARCHAR},</if>
            <if test="money != null">money = #{money,jdbcType=DECIMAL},</if>
            <if test="payWay != null">pay_way = #{payWay,jdbcType=INTEGER},</if>
            <if test="payMoney != null">pay_money = #{payMoney,jdbcType=DECIMAL},</if>
            <if test="ipInfo != null">ip_info = #{ipInfo,jdbcType=VARCHAR},</if>
            <if test="payTime != null">pay_time = #{payTime,jdbcType=TIMESTAMP},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
            <if test="vipStartTime != null">vip_start_time = #{vipStartTime,jdbcType=TIMESTAMP},</if>
            <if test="vipEndTime != null">vip_end_time = #{vipEndTime,jdbcType=TIMESTAMP},</if>
            <if test="remarks != null">remarks = #{remarks,jdbcType=VARCHAR},</if>
            <if test="appleTransactionId != null">apple_transaction_id = #{appleTransactionId,jdbcType=VARCHAR},</if>
            <if test="appleOriginalTransactionId != null">apple_original_transaction_id =
                #{appleOriginalTransactionId,jdbcType=VARCHAR},
            </if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <update id="updateByPrimaryKeySelective"
            parameterType="com.ks.app.entity.vip.OrderRecord">
        update lt_vip_order_record
        <set>
            <if test="orderType != null">order_type = #{orderType,jdbcType=VARCHAR},</if>
            <if test="uid != null">uid = #{uid,jdbcType=BIGINT},</if>
            <if test="state != null">state = #{state,jdbcType=INTEGER},</if>
            <if test="moneyPay != null">money_pay = #{moneyPay,jdbcType=BOOLEAN},</if>
            <if test="goldCornPay != null">gold_corn_pay = #{goldCornPay,jdbcType=BOOLEAN},</if>
            <if test="goldCorn != null">gold_corn = #{goldCorn,jdbcType=INTEGER},</if>
            <if test="type != null">type = #{type,jdbcType=VARCHAR},</if>
            <if test="money != null">money = #{money,jdbcType=DECIMAL},</if>
            <if test="payWay != null">pay_way = #{payWay,jdbcType=INTEGER},</if>
            <if test="payMoney != null">pay_money = #{payMoney,jdbcType=DECIMAL},</if>
            <if test="ipInfo != null">ip_info = #{ipInfo,jdbcType=VARCHAR},</if>
            <if test="payTime != null">pay_time = #{payTime,jdbcType=TIMESTAMP},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
            <if test="vipStartTime != null">vip_start_time = #{vipStartTime,jdbcType=TIMESTAMP},</if>
            <if test="vipEndTime != null">vip_end_time = #{vipEndTime,jdbcType=TIMESTAMP},</if>
            <if test="remarks != null">remarks = #{remarks,jdbcType=VARCHAR},</if>
            <if test="appleTransactionId != null">apple_transaction_id = #{appleTransactionId,jdbcType=VARCHAR},</if>
            <if test="appleOriginalTransactionId != null">apple_original_transaction_id =
                #{appleOriginalTransactionId,jdbcType=VARCHAR},
            </if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <sql id="listWhere">
        <if test="query.state!=null">
            state=#{query.state}
        </if>
        <if test="query.orderType!=null">
            order_type=#{query.orderType}
        </if>
        <if test="query.uid!=null">
            uid=#{query.uid}
        </if>
        <if test="query.minCreateTime!=null">
            create_time>= #{query.minCreateTime}
        </if>
        <if test="query.maxCreateTime!=null">
            #{query.maxCreateTime}>create_time
        </if>
    </sql>
    <select id="list"
            resultMap="BaseResultMap">
        SELECT * FROM lt_vip_order_record
        <where>
            <include refid="listWhere">
            </include>
        </where>
        <if test="query.sortList!=null">
            <foreach collection="query.sortList" open=" order by " separator="," item="item">
                #{item}
            </foreach>
        </if>
        limit #{query.start},#{query.count}
    </select>
    <select id="count"
            resultType="java.lang.Long">
        SELECT count(*) FROM lt_vip_order_record
        <where>
            <include refid="listWhere">
            </include>
        </where>
    </select>
    <insert id="insertPaySuccess">
        insert into wk_vip_order_pay_success(id,create_time) value(#{id},now())
    </insert>
</mapper>
src/main/resources/code/service/app/src/main/resources/mapper/QQUserInfoMapper.xml
New file
@@ -0,0 +1,156 @@
<?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="com.ks.app.dao.user.QQUserInfoDao">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.user.QQUserInfo">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="system" property="system" jdbcType="VARCHAR"/>
        <result column="nick_name" property="nickName" jdbcType="VARCHAR"/>
        <result column="portrait" property="portrait" jdbcType="VARCHAR"/>
        <result column="open_id" property="openId" jdbcType="VARCHAR"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
    </resultMap>
    <sql id="Base_Column_List">
        <trim suffixOverrides=",">
            id, system,nick_name,portrait,open_id,create_time,update_time,
        </trim>
    </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user_qq where id = #{id, jdbcType=BIGINT}
    </select>
    <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user_qq where id = #{id,jdbcType=BIGINT} for update
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
        delete from
        lt_user_qq where id = #{id,jdbcType=BIGINT}
    </delete>
    <insert id="insert"
            parameterType="com.ks.app.entity.user.QQUserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into
        lt_user_qq
        <trim prefix="(" suffix=")" suffixOverrides=",">
            system,
            nick_name,
            portrait,
            open_id,
            create_time,
            update_time,
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{system},jdbcType=VARCHAR},
            #{nickName},jdbcType=VARCHAR},
            #{portrait},jdbcType=VARCHAR},
            #{openId},jdbcType=VARCHAR},
            #{createTime},jdbcType=TIMESTAMP},
            #{updateTime},jdbcType=TIMESTAMP},
        </trim>
    </insert>
    <insert id="insertSelective"
            parameterType="com.ks.app.entity.user.QQUserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into lt_user_qq
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="system != null">system,</if>
            <if test="nickName != null">nick_name,</if>
            <if test="portrait != null">portrait,</if>
            <if test="openId != null">open_id,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateTime != null">update_time,</if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id,jdbcType=BIGINT},</if>
            <if test="system != null">#{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">#{nickName,jdbcType=VARCHAR},</if>
            <if test="portrait != null">#{portrait,jdbcType=VARCHAR},</if>
            <if test="openId != null">#{openId,jdbcType=VARCHAR},</if>
            <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
        </trim>
    </insert>
    <update id="updateByPrimaryKey"
            parameterType="com.ks.app.entity.user.QQUserInfo">
        update lt_user_qq
        <set>
            <if test="id != null">id = #{id,jdbcType=BIGINT},</if>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">nick_name = #{nickName,jdbcType=VARCHAR},</if>
            <if test="portrait != null">portrait = #{portrait,jdbcType=VARCHAR},</if>
            <if test="openId != null">open_id = #{openId,jdbcType=VARCHAR},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <update id="updateByPrimaryKeySelective"
            parameterType="com.ks.app.entity.user.QQUserInfo">
        update lt_user_qq
        <set>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">nick_name = #{nickName,jdbcType=VARCHAR},</if>
            <if test="portrait != null">portrait = #{portrait,jdbcType=VARCHAR},</if>
            <if test="openId != null">open_id = #{openId,jdbcType=VARCHAR},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <sql id="listWhere">
        <if test="query.system!=null">
            system= #{query.system}
        </if>
        <if test="query.openId!=null">
            open_id= #{query.openId}
        </if>
    </sql>
    <select id="list"
            resultMap="BaseResultMap">
        SELECT * FROM lt_user_qq
        <where>
            <include refid="listWhere">
            </include>
        </where>
        <if test="query.sortList!=null">
            <foreach collection="query.sortList" open=" order by " separator="," item="item">
                #{item}
            </foreach>
        </if>
        limit #{query.start},#{query.count}
    </select>
    <select id="count"
            resultType="java.lang.Long">
        SELECT count(*) FROM lt_user_qq
        <where>
            <include refid="listWhere">
            </include>
        </where>
    </select>
</mapper>
src/main/resources/code/service/app/src/main/resources/mapper/UserInfoMapper.xml
New file
@@ -0,0 +1,236 @@
<?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="com.ks.app.dao.user.UserInfoDao">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.user.UserInfo">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="system" property="system" jdbcType="VARCHAR"/>
        <result column="nick_name" property="nickName" jdbcType="VARCHAR"/>
        <result column="portrait" property="portrait" jdbcType="VARCHAR"/>
        <result column="phone" property="phone" jdbcType="VARCHAR"/>
        <result column="email" property="email" jdbcType="VARCHAR"/>
        <result column="pwd" property="pwd" jdbcType="VARCHAR"/>
        <result column="status" property="status" jdbcType="INTEGER"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
        <association property="wxUser" column="wx_id" javaType="com.ks.app.entity.user.WXUserInfo">
            <id column="wx_id" property="id"></id>
        </association>
        <association property="qqUser" column="qq_id" javaType="com.ks.app.entity.user.QQUserInfo">
            <id column="qq_id" property="id"></id>
        </association>
    </resultMap>
    <sql id="Base_Column_List">
        <trim suffixOverrides=",">
            id,system,nick_name,portrait,phone,email,pwd,wx_id,qq_id,status,create_time,update_time,
        </trim>
    </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user where id = #{id, jdbcType=BIGINT}
    </select>
    <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user where id = #{id,jdbcType=BIGINT} for update
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
        delete from
        lt_user where id = #{id,jdbcType=BIGINT}
    </delete>
    <insert id="insert"
            parameterType="com.ks.app.entity.user.UserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into
        lt_user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            system,
            nick_name,
            portrait,
            phone,
            email,
            pwd,
            wx_id,
            qq_id,
            status,
            create_time,
            update_time,
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{system},jdbcType=VARCHAR},
            #{nickName},jdbcType=VARCHAR},
            #{portrait},jdbcType=VARCHAR},
            #{phone},jdbcType=VARCHAR},
            #{email},jdbcType=VARCHAR},
            #{pwd},jdbcType=VARCHAR},
            #{wxUser.id},jdbcType=BIGINT},
            #{qqUser.id},jdbcType=BIGINT},
            #{status},jdbcType=INTEGER},
            #{createTime},jdbcType=TIMESTAMP},
            #{updateTime},jdbcType=TIMESTAMP},
        </trim>
    </insert>
    <insert id="insertSelective"
            parameterType="com.ks.app.entity.user.UserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into lt_user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="system != null">system,</if>
            <if test="nickName != null">nick_name,</if>
            <if test="portrait != null">portrait,</if>
            <if test="phone != null">phone,</if>
            <if test="email != null">email,</if>
            <if test="pwd != null">pwd,</if>
            <if test="wxUser != null">wx_id,</if>
            <if test="qqUser != null">qq_id,</if>
            <if test="status != null">status,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateTime != null">update_time,</if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id,jdbcType=BIGINT},</if>
            <if test="system != null">#{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">#{nickName,jdbcType=VARCHAR},</if>
            <if test="portrait != null">#{portrait,jdbcType=VARCHAR},</if>
            <if test="phone != null">#{phone,jdbcType=VARCHAR},</if>
            <if test="email != null">#{email,jdbcType=VARCHAR},</if>
            <if test="pwd != null">#{pwd,jdbcType=VARCHAR},</if>
            <if test="wxUser != null">#{wxUser.id,jdbcType=BIGINT},</if>
            <if test="qqUser != null">#{qqUser.id,jdbcType=BIGINT},</if>
            <if test="status != null">#{status,jdbcType=INTEGER},</if>
            <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
        </trim>
    </insert>
    <update id="updateByPrimaryKey"
            parameterType="com.ks.app.entity.user.UserInfo">
        update lt_user
        <set>
            <if test="id != null">id = #{id,jdbcType=BIGINT},</if>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">nick_name = #{nickName,jdbcType=VARCHAR},</if>
            <if test="portrait != null">portrait = #{portrait,jdbcType=VARCHAR},</if>
            <if test="phone != null">phone = #{phone,jdbcType=VARCHAR},</if>
            <if test="email != null">email = #{email,jdbcType=VARCHAR},</if>
            <if test="pwd != null">pwd = #{pwd,jdbcType=VARCHAR},</if>
            <if test="wxUser != null">wx_id = #{wxUser.id,jdbcType=BIGINT},</if>
            <if test="qqUser != null">qq_id = #{qqUser.id,jdbcType=BIGINT},</if>
            <if test="status != null">status = #{status,jdbcType=INTEGER},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <update id="updateByPrimaryKeySelective"
            parameterType="com.ks.app.entity.user.UserInfo">
        update lt_user
        <set>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">nick_name = #{nickName,jdbcType=VARCHAR},</if>
            <if test="portrait != null">portrait = #{portrait,jdbcType=VARCHAR},</if>
            <if test="phone != null">phone = #{phone,jdbcType=VARCHAR},</if>
            <if test="email != null">email = #{email,jdbcType=VARCHAR},</if>
            <if test="pwd != null">pwd = #{pwd,jdbcType=VARCHAR},</if>
            <if test="wxUser != null">wx_id = #{wxUser.id,jdbcType=BIGINT},</if>
            <if test="qqUser != null">qq_id = #{qqUser.id,jdbcType=BIGINT},</if>
            <if test="status != null">status = #{status,jdbcType=INTEGER},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <sql id="listWhere">
        public SystemEnum system;
        public Long wxId;
        public Long qqId;
        <if test="query.system!=null">
            and system = #{query.system}
        </if>
        <if test="query.wxId!=null">
            and wx_id = #{query.wxId}
        </if>
        <if test="query.qqId!=null">
            and qq_id = #{query.qqId}
        </if>
        <if test="query.nickName!=null">
            and nick_name = '%#{query.nickName}%'
        </if>
        <if test="query.phone!=null">
            and phone = #{query.phone}
        </if>
        <if test="query.email!=null">
            and email = #{query.email}
        </if>
        <if test="query.maxCreateTime!=null">
            and create_time <![CDATA[<]]> #{query.maxCreateTime}
        </if>
        <if test="query.minCreateTime!=null">
            and create_time >= #{query.minCreateTime}
        </if>
        <if test="query.status!=null">
            and status >= #{query.status}
        </if>
    </sql>
    <select id="list"
            resultMap="BaseResultMap">
        SELECT * FROM lt_user
        <where>
            <include refid="listWhere">
            </include>
        </where>
        <if test="query.sortList!=null">
            <foreach collection="query.sortList" open=" order by " separator="," item="item">
                #{item}
            </foreach>
        </if>
        limit #{query.start},#{query.count}
    </select>
    <select id="count"
            resultType="java.lang.Long">
        SELECT count(*) FROM lt_user
        <where>
            <include refid="listWhere">
            </include>
        </where>
    </select>
    <select id="statisticByCreateTime"
            resultMap="com.ks.app.mapper.basemapper.Statistic_Number_BaseResultMap">
        SELECT DATE_FORMAT(l.`create_time`,'${timeQuery.timeFormat}') AS time,COUNT(*) AS number FROM lt_user l WHERE
        l.`create_time`>#{timeQuery.startTime} AND #{timeQuery.endTime}>l.`create_time`
        <if test="system!=null">
            and system=#{system}
        </if>
        GROUP BY DATE_FORMAT( l.`create_time`,'${timeQuery.timeFormat}')
    </select>
</mapper>
src/main/resources/code/service/app/src/main/resources/mapper/UserVIPInfoMapper.xml
New file
@@ -0,0 +1,134 @@
<?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="com.ks.app.dao.vip.UserVIPInfoDao">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.vip.UserVIPInfo">
        <id column="uid" property="uid" jdbcType="BIGINT"/>
        <result column="expire_date" property="expireDate" jdbcType="TIMESTAMP"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
    </resultMap>
    <sql id="Base_Column_List">
        <trim suffixOverrides=",">
            uid,expire_date,create_time,update_time,
        </trim>
    </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user_vip_info where uid = #{id, jdbcType=BIGINT}
    </select>
    <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user_vip_info where uid = #{id,jdbcType=BIGINT} for update
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
        delete from
        lt_user_vip_info where uid = #{id,jdbcType=BIGINT}
    </delete>
    <insert id="insert"
            parameterType="com.ks.app.entity.vip.UserVIPInfo"
            useGeneratedKeys="true" keyProperty="uid">
        insert into
        lt_user_vip_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            expire_date,
            create_time,
            update_time,
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{expireDate},jdbcType=TIMESTAMP},
            #{createTime},jdbcType=TIMESTAMP},
            #{updateTime},jdbcType=TIMESTAMP},
        </trim>
    </insert>
    <insert id="insertSelective"
            parameterType="com.ks.app.entity.vip.UserVIPInfo"
            useGeneratedKeys="true" keyProperty="uid">
        insert into lt_user_vip_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="uid != null">uid,</if>
            <if test="expireDate != null">expire_date,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateTime != null">update_time,</if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="uid != null">#{uid,jdbcType=BIGINT},</if>
            <if test="expireDate != null">#{expireDate,jdbcType=TIMESTAMP},</if>
            <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
        </trim>
    </insert>
    <update id="updateByPrimaryKey"
            parameterType="com.ks.app.entity.vip.UserVIPInfo">
        update lt_user_vip_info
        <set>
            <if test="uid != null">uid = #{uid,jdbcType=BIGINT},</if>
            <if test="expireDate != null">expire_date = #{expireDate,jdbcType=TIMESTAMP},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
        </set>
        where uid = #{uid,jdbcType=BIGINT}
    </update>
    <update id="updateByPrimaryKeySelective"
            parameterType="com.ks.app.entity.vip.UserVIPInfo">
        update lt_user_vip_info
        <set>
            <if test="expireDate != null">expire_date = #{expireDate,jdbcType=TIMESTAMP},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
        </set>
        where uid = #{uid,jdbcType=BIGINT}
    </update>
    <sql id="listWhere">
        <if test="query.minExpireDate!=null">
            expire_date>=#{query.minExpireDate}
        </if>
        <if test="query.maxExpireDate!=null">
            #{query.maxExpireDate}>expire_date
        </if>
    </sql>
    <select id="list"
            resultMap="BaseResultMap">
        SELECT * FROM lt_user_vip_info
        <where>
            <include refid="listWhere">
            </include>
        </where>
        <if test="query.sortList!=null">
            <foreach collection="query.sortList" open=" order by " separator="," item="item">
                #{item}
            </foreach>
        </if>
        limit #{query.start},#{query.count}
    </select>
    <select id="count"
            resultType="java.lang.Long">
        SELECT count(*) FROM lt_user_vip_info
        <where>
            <include refid="listWhere">
            </include>
        </where>
    </select>
</mapper>
src/main/resources/code/service/app/src/main/resources/mapper/WXUserInfoMapper.xml
New file
@@ -0,0 +1,191 @@
<?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="com.yeshi.location.app.mapper.user.WXUserInfoMapper">
    <resultMap id="BaseResultMap"
               type="com.yeshi.location.app.entity.user.WXUserInfo">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="system" property="system" jdbcType="VARCHAR"/>
        <result column="nick_name" property="nickName" jdbcType="VARCHAR"/>
        <result column="sex" property="sex" jdbcType="INTEGER"/>
        <result column="province" property="province" jdbcType="VARCHAR"/>
        <result column="city" property="city" jdbcType="VARCHAR"/>
        <result column="country" property="country" jdbcType="VARCHAR"/>
        <result column="head_img_url" property="headImgUrl" jdbcType="VARCHAR"/>
        <result column="open_id" property="openId" jdbcType="VARCHAR"/>
        <result column="union_id" property="unionId" jdbcType="VARCHAR"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
    </resultMap>
    <sql id="Base_Column_List">
        <trim suffixOverrides=",">
            id, system,nick_name,sex,province,city,country,head_img_url,open_id,union_id,create_time,update_time,
        </trim>
    </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user_wx where id = #{id, jdbcType=BIGINT}
    </select>
    <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user_wx where id = #{id,jdbcType=BIGINT} for update
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
        delete from
        lt_user_wx where id = #{id,jdbcType=BIGINT}
    </delete>
    <insert id="insert"
            parameterType="com.yeshi.location.app.entity.user.WXUserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into
        lt_user_wx
        <trim prefix="(" suffix=")" suffixOverrides=",">
            system,
            nick_name,
            sex,
            province,
            city,
            country,
            head_img_url,
            open_id,
            union_id,
            create_time,
            update_time,
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{system},jdbcType=VARCHAR},
            #{nickName},jdbcType=VARCHAR},
            #{sex},jdbcType=INTEGER},
            #{province},jdbcType=VARCHAR},
            #{city},jdbcType=VARCHAR},
            #{country},jdbcType=VARCHAR},
            #{headImgUrl},jdbcType=VARCHAR},
            #{openId},jdbcType=VARCHAR},
            #{unionId},jdbcType=VARCHAR},
            #{createTime},jdbcType=TIMESTAMP},
            #{updateTime},jdbcType=TIMESTAMP},
        </trim>
    </insert>
    <insert id="insertSelective"
            parameterType="com.yeshi.location.app.entity.user.WXUserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into lt_user_wx
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="system != null">system,</if>
            <if test="nickName != null">nick_name,</if>
            <if test="sex != null">sex,</if>
            <if test="province != null">province,</if>
            <if test="city != null">city,</if>
            <if test="country != null">country,</if>
            <if test="headImgUrl != null">head_img_url,</if>
            <if test="openId != null">open_id,</if>
            <if test="unionId != null">union_id,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateTime != null">update_time,</if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id,jdbcType=BIGINT},</if>
            <if test="system != null">#{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">#{nickName,jdbcType=VARCHAR},</if>
            <if test="sex != null">#{sex,jdbcType=INTEGER},</if>
            <if test="province != null">#{province,jdbcType=VARCHAR},</if>
            <if test="city != null">#{city,jdbcType=VARCHAR},</if>
            <if test="country != null">#{country,jdbcType=VARCHAR},</if>
            <if test="headImgUrl != null">#{headImgUrl,jdbcType=VARCHAR},</if>
            <if test="openId != null">#{openId,jdbcType=VARCHAR},</if>
            <if test="unionId != null">#{unionId,jdbcType=VARCHAR},</if>
            <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
        </trim>
    </insert>
    <update id="updateByPrimaryKey"
            parameterType="com.yeshi.location.app.entity.user.WXUserInfo">
        update lt_user_wx
        <set>
            <if test="id != null">id = #{id,jdbcType=BIGINT},</if>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">nick_name = #{nickName,jdbcType=VARCHAR},</if>
            <if test="sex != null">sex = #{sex,jdbcType=INTEGER},</if>
            <if test="province != null">province = #{province,jdbcType=VARCHAR},</if>
            <if test="city != null">city = #{city,jdbcType=VARCHAR},</if>
            <if test="country != null">country = #{country,jdbcType=VARCHAR},</if>
            <if test="headImgUrl != null">head_img_url = #{headImgUrl,jdbcType=VARCHAR},</if>
            <if test="openId != null">open_id = #{openId,jdbcType=VARCHAR},</if>
            <if test="unionId != null">union_id = #{unionId,jdbcType=VARCHAR},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <update id="updateByPrimaryKeySelective"
            parameterType="com.yeshi.location.app.entity.user.WXUserInfo">
        update lt_user_wx
        <set>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">nick_name = #{nickName,jdbcType=VARCHAR},</if>
            <if test="sex != null">sex = #{sex,jdbcType=INTEGER},</if>
            <if test="province != null">province = #{province,jdbcType=VARCHAR},</if>
            <if test="city != null">city = #{city,jdbcType=VARCHAR},</if>
            <if test="country != null">country = #{country,jdbcType=VARCHAR},</if>
            <if test="headImgUrl != null">head_img_url = #{headImgUrl,jdbcType=VARCHAR},</if>
            <if test="openId != null">open_id = #{openId,jdbcType=VARCHAR},</if>
            <if test="unionId != null">union_id = #{unionId,jdbcType=VARCHAR},</if>
            <if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
            <if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if>
        </set>
        where id = #{id,jdbcType=BIGINT}
    </update>
    <sql id="listWhere">
        <if test="query.system!=null">
            system=#{query.system}
        </if>
        <if test="query.unionId!=null">
            union_id=#{query.unionId}
        </if>
    </sql>
    <select id="list"
            resultMap="BaseResultMap">
        SELECT * FROM lt_user_wx
        <where>
            <include refid="listWhere">
            </include>
        </where>
        <if test="query.sortList!=null">
            <foreach collection="query.sortList" open=" order by " separator="," item="item">
                #{item}
            </foreach>
        </if>
        limit #{query.start},#{query.count}
    </select>
    <select id="count"
            resultType="java.lang.Long">
        SELECT count(*) FROM lt_user_wx
        <where>
            <include refid="listWhere">
            </include>
        </where>
    </select>
</mapper>
src/main/resources/code/service/app/src/main/resources/static/css/login.css
@@ -10,18 +10,38 @@
    background-size: cover;
    overflow: hidden;
}
.login{
    margin: 120px auto 0 auto;
    min-height: 420px;
    max-width: 420px;
    padding: 40px;
    background-color: #ffffff;
    margin-left: auto;
    margin-right: auto;
    border-radius: 4px;
    /* overflow-x: hidden; */
    box-sizing: border-box;
@media screen and (min-width: 700px){
    .login{
        margin: 120px auto 0 auto;
        min-height: 420px;
        max-width: 420px;
        padding: 40px;
        background-color: #ffffff;
        margin-left: auto;
        margin-right: auto;
        border-radius: 4px;
        /* overflow-x: hidden; */
        box-sizing: border-box;
    }
}
@media screen and (max-width: 700px){
    .login{
        margin: 20px auto 0 auto;
        min-height: 420px;
        max-width: 420px;
        padding: 40px;
        background-color: #ffffff;
        margin-left: auto;
        margin-right: auto;
        border-radius: 4px;
        /* overflow-x: hidden; */
        box-sizing: border-box;
    }
}
.login a.logo{
    display: block;
    height: 58px;
src/main/resources/code/service/app/src/main/resources/static/index.html
@@ -2,7 +2,7 @@
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>推送管理系统</title>
    <title>定位管理系统</title>
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
@@ -25,39 +25,36 @@
        // 是否开启刷新记忆tab功能
        // var is_remember = false;
    </script>
    <style>
        body {
            font-size: 0;
        }
        .container .layui-nav-more {
            top: 0 !important;
        }
    </style>
</head>
<body class="index">
<!-- 顶部开始 -->
<div class="container">
    <div class="logo">
        <a href="index.html">推送系统</a></div>
        <a href="index.html">定位追踪系统</a></div>
    <div class="left_open">
        <a><i title="展开左侧栏" class="iconfont">&#xe699;</i></a>
    </div>
    <ul class="layui-nav left fast-add" lay-filter="">
        <li class="layui-nav-item">
            <a href="javascript:;">+新增</a>
            <dl class="layui-nav-child">
                <!-- 二级菜单 -->
                <dd>
                    <a onclick="xadmin.open('最大化','http://www.baidu.com','','',true)">
                        <i class="iconfont">&#xe6a2;</i>弹出最大化</a></dd>
                <dd>
                    <a onclick="xadmin.open('弹出自动宽高','http://www.baidu.com')">
                        <i class="iconfont">&#xe6a8;</i>弹出自动宽高</a></dd>
                <dd>
                    <a onclick="xadmin.open('弹出指定宽高','http://www.baidu.com',500,300)">
                        <i class="iconfont">&#xe6a8;</i>弹出指定宽高</a></dd>
                <dd>
                    <a onclick="xadmin.add_tab('在tab打开','member-list.html')">
                        <i class="iconfont">&#xe6b8;</i>在tab打开</a></dd>
                <dd>
                    <a onclick="xadmin.add_tab('在tab打开刷新','member-del.html',true)">
                        <i class="iconfont">&#xe6b8;</i>在tab打开刷新</a></dd>
            </dl>
        </li>
    </ul>
    <ul class="layui-nav right" lay-filter="">
        <li class="layui-nav-item" id="system">
            <a href="javascript:;"> 当前系统:<b></b></a>
            <dl class="layui-nav-child">
            </dl>
        </li>
        <li class="layui-nav-item">
            <a href="javascript:;">admin</a>
            <dl class="layui-nav-child">
@@ -78,47 +75,39 @@
        <ul id="nav">
            <li>
                <a href="javascript:;">
                    <i class="iconfont left-nav-li" lay-tips="应用管理">&#xe6b8;</i>
                    <cite>应用管理</cite>
                    <i class="layui-icon layui-icon-user" lay-tips="用户管理"></i>
                    <cite>用户管理</cite>
                    <i class="iconfont nav_right">&#xe697;</i></a>
                <ul class="sub-menu">
                    <li>
                        <a onclick="xadmin.add_tab('统计页面','welcome.html')">
                        <a onclick="xadmin.add_tab('用户列表','user/user_info_list.html')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>统计页面</cite></a>
                            <cite>用户列表</cite></a>
                    </li>
                    <li>
                        <a onclick="xadmin.add_tab('应用列表','app-list.html',true)">
                        <a onclick="xadmin.add_tab('登录记录','user/user_login_record_list.html',true)">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>应用列表</cite></a>
                            <cite>登录记录</cite></a>
                    </li>
                    <li>
                        <a onclick="xadmin.add_tab('三方平台','pushplatform-appinfo-list.html',true)">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>三方推送平台应用信息</cite></a>
                        <a href="javascript:;">
                            <i class="left-nav-li" lay-tips="会员"></i>
                            <cite>会员</cite>
                            <i class="iconfont nav_right">&#xe697;</i></a>
                        <ul class="sub-menu">
                            <li>
                                <a onclick="xadmin.add_tab('会员套餐','vip/vipprice_list.html')">
                                    <i class="iconfont">&#xe6a7;</i>
                                    <cite>会员套餐</cite></a>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>
                <a href="javascript:;">
                    <i class="iconfont left-nav-li" lay-tips="推送">&#xe6b8;</i>
                    <cite>推送任务</cite>
                    <i class="iconfont nav_right">&#xe697;</i></a>
                <ul class="sub-menu">
                    <li>
                        <a onclick="xadmin.add_tab('推送任务列表','pushtask-list.html')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>推送任务列表</cite></a>
                    </li>
                    <li>
                        <a onclick="xadmin.add_tab('添加推送任务','pushplatform-appinfo-list.html')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>添加推送任务</cite></a>
                    </li>
                </ul>
            </li>
        </ul>
    </div>
</div>
@@ -173,6 +162,40 @@
                }
            });
        });
        function getSystemList() {
            ksapp.post("/admin/api/system/systemList", {}, function (res) {
                if (res.code == 0) {
                    $("#system").find("dl").eq(0).empty();
                    var list = res.data.list;
                    for (var i = 0; i < list.length; i++) {
                        $("#system").find("dl").append("<dd key='" + list[i].key + "'><a href='javascript:void();' >" + list[i].name + "</a></dd>");
                        if (list[i].selected) {
                            $("#system").find("b").eq(0).html(list[i].name);
                        }
                    }
                    $("#system").find("dd").bind("click", function () {
                        ksapp.post("/admin/api/system/selectSystem", {key: $(this).attr("key")}, function (res) {
                            if (res.code == 0) {
                                layer.msg("更改成功");
                                getSystemList();
                            } else {
                                layer.msg(res.msg);
                            }
                        }, function (res) {
                        })
                    })
                }
            }, function (res) {
            })
        }
        getSystemList();
    });
src/main/resources/code/service/app/src/main/resources/static/js/http.js
@@ -6,10 +6,10 @@
            dataType: 'json',
            success: function (data) {
                success(data);
            },
            fail: function (result) {
                fail(result);
            }
        }).fail(function (e) {
            ksapp.processError(e);
            fail(e);
        });
    },
    postJSON: function (url, params, success, fail) {
@@ -20,10 +20,10 @@
            contentType: "application/json",
            success: function (data) {
                success(data);
            },
            fail: function (result) {
                fail(result);
            }
        }).fail(function (e) {
            ksapp.processError(e);
            fail(e);
        });
    },
    get: function (params) {
@@ -32,10 +32,10 @@
            data: params.params,
            success: function (data) {
                params.success(data);
            },
            fail: function (result) {
                params.fail(result);
            }
        }).fail(function (e) {
            ksapp.processError(e);
            fail(e);
        });
    },
    getQueryParam: function (key) {
@@ -43,6 +43,18 @@
        var r = window.location.search.substr(1).match(reg);
        if (r != null) return decodeURIComponent(r[2]);
        return null;
    },
    //表格数据出错
    tableError: function (e) {
        ksapp.processError(e);
    },
    processError: function (e) {
        //未登录
        if (e.status == 401) {
            //打开登录窗口
            xadmin.open('登录', '/login.html?from=page', 500, 530)
        }
    }
src/main/resources/code/service/app/src/main/resources/static/js/xadmin.js
@@ -91,7 +91,7 @@
            area: [w+'px', h +'px'],
            fix: false, //不固定
            maxmin: true,
            shadeClose: true,
            shadeClose: false,
            shade:0.4,
            title: title,
            content: url
src/main/resources/code/service/app/src/main/resources/static/login.html
@@ -15,6 +15,7 @@
    <script src="lib/layui/layui.js" charset="utf-8"></script>
    <script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/http.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="js/xadmin.js"></script>
    <script type="text/javascript">
    </script>
    <!--[if lt IE 9]>
@@ -25,7 +26,7 @@
<body class="login-bg">
<div class="login layui-anim" id="allwai">
    <div class="message">积分管理系统</div>
    <div class="message">管理系统</div>
    <div id="darkbannerwrap"></div>
    <form class="layui-form" lay-filter="login">
@@ -99,8 +100,18 @@
                        }, function (data) {
                            layer.close(index);
                            if (data.code == 0) {
                                window.location.replace("index.html");
                            }else{
                                var from = ksapp.getQueryParam("from");
                                var refresh = ksapp.getQueryParam("refresh")
                                if (from) {
                                    //关闭当前frame
                                    xadmin.close();
                                    // 可以对父窗口进行刷新
                                    if (refresh)
                                        xadmin.father_reload();
                                } else {
                                    window.location.replace("index.html");
                                }
                            } else {
                                layer.msg(data.msg);
                            }
src/main/resources/code/service/app/src/main/resources/static/user/user_info_list.html
New file
@@ -0,0 +1,259 @@
<!DOCTYPE html>
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>用户信息列表</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
    <link rel="stylesheet" href="../css/font.css">
    <link rel="stylesheet" href="../css/xadmin.css">
    <script src="../lib/layui/layui.js" charset="utf-8"></script>
    <link rel="stylesheet" href="../css/theme3049.min.css">
    <script src="../js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="../js/xadmin.js"></script>
    <script src="../js/http.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="../js/utils.js"></script>
</head>
<body>
<div class="x-nav">
            <span class="layui-breadcrumb">
                <a href="">###</a>
                <a>
                    <cite>###</cite></a>
            </span>
    <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right"
       onclick="location.reload()" title="刷新">
        <i class="layui-icon layui-icon-refresh" style="line-height:30px"></i>
    </a>
</div>
<div class="layui-fluid" id="app">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body">
                    <form class="layui-form layui-col-space5">
                        <div class="layui-inline layui-show-xs-block">
                            <input type="date" name="startDate" lay-verify="" placeholder="" autocomplete="off"
                                   class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                            <input type="date" name="endDate" lay-verify="" placeholder="" autocomplete="off"
                                   class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                            <input type="text" name="key" lay-verify="" placeholder="请输入用户ID" autocomplete="off"
                                   class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                            <button id="search" class="layui-btn" lay-submit="" lay-filter="search">
                                <i class="layui-icon">&#xe615;</i></button>
                        </div>
                    </form>
                </div>
                <div class="layui-card-body ">
                    <table class="layui-table" id="table_list" lay-filter="app">
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script type="text/html" id="deleteContainer">
    <div class="layui-btn-container">
        <!-- <a title='恢复' onclick='member_resume(this,{{d.LAY_INDEX }}, {{d.id}})' href='javascript:;'> -->
        <!--<i class="layui-icon">&#xe669;</i>-->
        <!--</a>-->
        <a title="删除" onclick="member_del(this,{{d.LAY_INDEX }},'{{d.id}}')" href="javascript:;">
            <i class="layui-icon">&#xe640;</i>
        </a>
    </div>
</script>
<script type="text/html" id="statusContainer">
    <div class="layui-btn-container">
        {{# if(d.status==0){ }}
        <span class="layui-btn layui-btn-mini">
            正常
        </span>
        {{# }else{ }}
        <span class="layui-btn layui-btn-danger layui-btn-mini">
             已删除
        </span>
        {{# } }}
    </div>
</script>
<script type="text/html" id="switchTpl">
    <!-- 这里的checked的状态只是演示 -->
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script type="text/html" id="imgshow">
    <!-- 这里的checked的状态只是演示 -->
    <img src="{{d.}}"/>
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script>
    function member_del(obj, index, id) {
        layer.confirm('确认要删除吗?', function (index) {
            //发异步删除数据
            app.delete(obj, index, id);
        });
    }
</script>
<script>
    var tableIns = null;
    $(function () {
        var app = new Vue({
            el: "#app",
            data: {
                key: '',
                start: '',
                end: '',
                appList: []
            },
            watch: {},
            created: function () {
            },
            methods: {
                init: function () {
                    //初始化
                    layui.use(['laydate', 'form', 'table'], function () {
                        var laydate = layui.laydate,
                            form = layui.form,
                            table = layui.table;
                        //渲染日期输入框
                        laydate.render({
                            elem: "intput[name=startDate]" //指定元素
                        });
                        laydate.render({
                            elem: "intput[name=endDate]" //指定元素
                        });
                        //搜索条件
                        form.on('submit(search)', function (data) {
                            app.search(data.field);
                            return false;
                        });
                        tableIns = table.render({
                            elem: '#table_list',
                            url: "/admin/api/user/list",
                            toolbar: "#toolbar",
                            totalRow: true,
                            cols: [[{type: 'checkbox', title: "ID"},
                                {field: 'id', width: 120, sort: false, title: "用户ID"},
                                {field: 'nickName', width: 120, sort: false, title: "昵称"},
                                {
                                    field: 'portrait',
                                    template: "<img src='{{d.portrait}}'>",
                                    width: 120,
                                    sort: false,
                                    title: "头像"
                                },
                                {field: 'phone', width: 120, sort: false, title: "电话"},
                                {field: 'email', width: 120, sort: false, title: "邮箱"},
                                {field: 'wxUser', width: 120, sort: false, title: "微信用户信息"},
                                {field: 'qqUser', width: 120, sort: false, title: "QQ用户信息"},
                                {field: 'createTime', width: 120, sort: false, title: "创建时间"},
                                {field: 'updateTime', width: 120, sort: false, title: "修改时间"},
                                {fixed: 'right', width: 80, title: "操作", toolbar: '#deleteContainer'}]],
                            page: true,
                            parseData: function (res) { //res 即为原始返回的数据
                                if (res.code != 0)
                                    return;
                                if (res.data.list == null)
                                    return;
                                console.log(res.data.list)
                                return {
                                    "code": res.code, //解析接口状态
                                    "msg": res.msg, //解析提示文本
                                    "count": res.data.count, //解析数据长度
                                    "data": res.data.list //解析数据列表
                                };
                            },
                            error: function (e, msg) {
                                ksapp.tableError(e)
                            }
                            //,…… //其他参数
                        });
                        //头工具栏事件
                        table.on('toolbar(app)',
                            function (obj) {
                                var checkStatus = table.checkStatus(obj.config.id);
                                switch (obj.event) {
                                    case 'delete':
                                        var data = checkStatus.data;
                                        if (data == null || data.length == 0) {
                                            layer.msg("未选择选项");
                                            return;
                                        }
                                        var ids = new Array();
                                        for (var i = 0; i < data.length; i++)
                                            ids.push(data[i].id);
                                        layer.confirm('确认要删除吗?', function (index) {
                                            //发异步删除数据
                                            app.deleteList(ids, function () {
                                                layer.msg("删除成功");
                                                $("form").submit();
                                            });
                                        });
                                        break;
                                }
                                ;
                            });
                        //请求搜索表单中需要的数据
                        $('#search').trigger("click");
                    });
                },
                delete: function (obj, index, id) {
                    var ids = new Array();
                    ids.push(id);
                    app.deleteList(ids, function () {
                        $(obj).parents("tr").remove();
                        layer.msg('已删除!', {icon: 1, time: 1000});
                    });
                },
                search: function (params) {
                    //数据重载
                    tableIns.reload({
                        where: params,
                        page: {
                            curr: 1 //重新从第 1 页开始
                        }
                    });
                },
            }
        });
        app.init();
    });
</script>
<script>
</script>
</html>
src/main/resources/code/service/app/src/main/resources/static/user/user_login_record_list.html
New file
@@ -0,0 +1,248 @@
<!DOCTYPE html>
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>用户登录记录列表</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
    <link rel="stylesheet" href="../css/font.css">
    <link rel="stylesheet" href="../css/xadmin.css">
    <script src="../lib/layui/layui.js" charset="utf-8"></script>
    <link rel="stylesheet" href="../css/theme3049.min.css">
    <script src="../js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="../js/xadmin.js"></script>
    <script src="../js/http.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="../js/utils.js"></script>
</head>
<body>
<div class="x-nav">
            <span class="layui-breadcrumb">
                <a href="">###</a>
                <a>
                    <cite>###</cite></a>
            </span>
    <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right"
       onclick="location.reload()" title="刷新">
        <i class="layui-icon layui-icon-refresh" style="line-height:30px"></i>
    </a>
</div>
<div class="layui-fluid" id="app">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body">
                    <form class="layui-form layui-col-space5">
                        <div class="layui-inline layui-show-xs-block">
                          <input type="date" name="startDate"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                          <input type="date" name="endDate"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                          <input type="text" name="key"  lay-verify=""  placeholder="请输入用户ID" autocomplete="off"
                               class="layui-input">
                        </div>
                        <div class="layui-inline layui-show-xs-block">
                            <button id="search" class="layui-btn" lay-submit="" lay-filter="search">
                                <i class="layui-icon">&#xe615;</i></button>
                        </div>
                    </form>
                </div>
                <div class="layui-card-body ">
                    <table class="layui-table" id="table_list" lay-filter="app">
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script type="text/html" id="deleteContainer">
    <div class="layui-btn-container">
        <!-- <a title='恢复' onclick='member_resume(this,{{d.LAY_INDEX }}, {{d.id}})' href='javascript:;'> -->
        <!--<i class="layui-icon">&#xe669;</i>-->
        <!--</a>-->
        <a title="删除" onclick="member_del(this,{{d.LAY_INDEX }},'{{d.id}}')" href="javascript:;">
            <i class="layui-icon">&#xe640;</i>
        </a>
    </div>
</script>
<script type="text/html" id="statusContainer">
    <div class="layui-btn-container">
        {{# if(d.status==0){ }}
        <span class="layui-btn layui-btn-mini">
            正常
        </span>
        {{# }else{ }}
        <span class="layui-btn layui-btn-danger layui-btn-mini">
             已删除
        </span>
        {{# } }}
    </div>
</script>
<script type="text/html" id="switchTpl">
    <!-- 这里的checked的状态只是演示 -->
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script type="text/html" id="imgshow">
    <!-- 这里的checked的状态只是演示 -->
    <img  src="{{d.}}"/>
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script>
    function member_del(obj, index, id) {
        layer.confirm('确认要删除吗?', function (index) {
            //发异步删除数据
            app.delete(obj, index, id);
        });
    }
</script>
<script>
    var tableIns = null;
    $(function () {
        var app = new Vue({
            el: "#app",
            data: {
                key: '',
                start: '',
                end: '',
                appList: []
            },
            watch: {},
            created: function () {
            },
            methods: {
                init: function () {
                    //初始化
                    layui.use(['laydate', 'form', 'table'], function () {
                        var laydate = layui.laydate,
                                form = layui.form,
                                table = layui.table;
                        //渲染日期输入框
                                laydate.render({
                                    elem: "intput[name=startDate]" //指定元素
                                });
                                laydate.render({
                                    elem: "intput[name=endDate]" //指定元素
                                });
                        //搜索条件
                        form.on('submit(search)', function (data) {
                            app.search(data.field);
                            return false;
                        });
                        tableIns = table.render({
                            elem: '#table_list',
                            url: "/admin/api/user/loginrecord/list",
                            toolbar: "#toolbar",
                            totalRow: true,
                            cols: [[
                                    {field: 'id', width: 120, sort: false, title: "ID"},
                                    {field: 'uid', width: 120, sort: false, title: "用户ID"},
                                    {field: 'loginIPInfo', width: 120, sort: false, title: "登录IP信息"},
                                    {field: 'loginType', width: 120, sort: false, title: "登录类型"},
                                    {field: 'createTime', width: 150, sort: false, title: "登录时间"}]],
                            page: true,
                            parseData: function (res) { //res 即为原始返回的数据
                                if (res.code != 0)
                                    return;
                                if (res.data.list == null)
                                    return;
                                console.log(res.data.list)
                                return {
                                    "code": res.code, //解析接口状态
                                    "msg": res.msg, //解析提示文本
                                    "count": res.data.count, //解析数据长度
                                    "data": res.data.list //解析数据列表
                                };
                            },
                            error: function (e, msg) {
                                ksapp.tableError(e)
                            }
                            //,…… //其他参数
                        });
                        //头工具栏事件
                        tableIns.on('toolbar(app)',
                                function (obj) {
                                    var checkStatus = table.checkStatus(obj.config.id);
                                    switch (obj.event) {
                                        case 'delete':
                                            var data = checkStatus.data;
                                            if (data == null || data.length == 0) {
                                                layer.msg("未选择选项");
                                                return;
                                            }
                                            var ids = new Array();
                                            for (var i = 0; i < data.length; i++)
                                                ids.push(data[i].id);
                                            layer.confirm('确认要删除吗?', function (index) {
                                                //发异步删除数据
                                                app.deleteList(ids, function () {
                                                    layer.msg("删除成功");
                                                    $("form").submit();
                                                });
                                            });
                                            break;
                                    };
                                });
                        //请求搜索表单中需要的数据
                          $('#search').trigger("click");
                    });
                },
                delete: function (obj, index, id) {
                    var ids = new Array();
                    ids.push(id);
                    app.deleteList(ids, function () {
                        $(obj).parents("tr").remove();
                        layer.msg('已删除!', {icon: 1, time: 1000});
                    });
                },
                search: function (params) {
                    //数据重载
                    tableIns.reload({
                        where: params,
                        page: {
                            curr: 1 //重新从第 1 页开始
                        }
                    });
                },
            }
    });
    app.init();
    });
</script>
<script>
</script>
</html>
src/main/resources/code/service/app/src/main/resources/static/vip/vipprice_add.html
New file
@@ -0,0 +1,186 @@
<!DOCTYPE html>
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>新增会员套餐</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
    <link rel="stylesheet" href="../css/font.css">
    <link rel="stylesheet" href="../css/xadmin.css">
    <script type="text/javascript" src="../lib/layui/layui.js" charset="utf-8"></script>
    <script type="text/javascript" src="../js/xadmin.js"></script>
    <script src="../js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../js/http.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <!-- 让IE8/9支持媒体查询,从而兼容栅格 -->
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<div class="layui-fluid">
    <div class="layui-row">
        <form class="layui-form" lay-filter="add">
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    套餐类型</label>
                <div class="layui-input-block">
                    <select name="type" lay-verify="required">
                        <option value="day">包天</option>
                        <option value="week">包周</option>
                        <option value="month">包月</option>
                        <option value="season">包季</option>
                        <option value="halfYear">包半年</option>
                        <option value="year">包年</option>
                    </select></div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    价格</label>
                <div class="layui-input-block">
                    <input type="text" name="price" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    原价</label>
                <div class="layui-input-block">
                    <input type="text" name="actualPrice" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    APPStore内购ID</label>
                <div class="layui-input-block">
                    <input type="text" name="iosProductId" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    是否显示</label>
                <div class="layui-input-block">
                    <input type="checkbox" name="show" lay-skin="switch"></div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    排序值</label>
                <div class="layui-input-block">
                    <input type="text" name="order" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_remarks" class="layui-form-label"></label>
                <button class="layui-btn" lay-filter="add" lay-submit="">确定</button>
            </div>
        </form>
    </div>
</div>
<script>
    //初始化上传控件
    var uploadTool = {
        callback: null,
        chooseImage: {},
        uploadArray: new Array(),
        init: function (upload) {
            this.uploadArray = new Array();
        },
        upload: function (result) {
            if (this.uploadArray.length > 0) {
                this.callback = result;
                //同时上传
                for (var i = 0; i < this.uploadArray.length; i++) {
                    this.uploadArray[i].upload();
                }
            } else {
                result();
            }
        }
    };
</script>
<script>
    layui.use(['form', 'layer', 'jquery', 'upload'], function () {
        $ = layui.jquery;
        var form = layui.form,
            layer = layui.layer,
            upload = layui.upload;
        var verify = {};
        //自定义验证规则
        form.verify(verify);
        //渲染上传控件
        uploadTool.init(upload);
        //监听提交
        form.on('submit(add)',
            function (data) {
                console.log(data.field);
                var checkBoxList = $("input[type=checkbox]");
                if (checkBoxList) {
                    for (var i = 0; i < checkBoxList.length; i++) {
                        data.field[checkBoxList.eq(i).attr("name")] = checkBoxList.eq(i).is(':checked');
                    }
                }
                //转换json对象
                for (key in data.field) {
                    if (key.indexOf(".") > -1) {
                        var value = data.field[key];
                        delete data.field[key];
                        var onkeys = key.split(".");
                        //创建对象
                        if (data.field[onkeys[0]] == undefined) {
                            data.field[onkeys[0]] = {};
                        }
                        data.field[onkeys[0]][onkeys[1]] = value;
                    }
                }
                uploadTool.upload(function () {
                    //发异步,把数据提交给php
                    ksapp.post('/admin/api/vip/vipprice/add', data.field, function (res) {
                        if (res.code == 0) {
                            layer.alert("增加成功", {
                                    icon: 6
                                },
                                function () {
                                    //关闭当前frame
                                    xadmin.close();
                                    // 可以对父窗口进行刷新
                                    xadmin.father_reload();
                                });
                        } else {
                            layer.msg(res.msg);
                        }
                    }, function (res) {
                    });
                });
                return false;
            });
        //请求select的数据API
    })
    ;
</script>
</body>
</html>
src/main/resources/code/service/app/src/main/resources/static/vip/vipprice_list.html
New file
@@ -0,0 +1,273 @@
<!DOCTYPE html>
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>会员套餐列表</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
    <link rel="stylesheet" href="../css/font.css">
    <link rel="stylesheet" href="../css/xadmin.css">
    <script src="../lib/layui/layui.js" charset="utf-8"></script>
    <link rel="stylesheet" href="../css/theme3049.min.css">
    <script src="../js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="../js/xadmin.js"></script>
    <script src="../js/http.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="../js/utils.js"></script>
</head>
<body>
<div class="x-nav">
            <span class="layui-breadcrumb">
                <a href="">###</a>
                <a>
                    <cite>###</cite></a>
            </span>
    <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right"
       onclick="location.reload()" title="刷新">
        <i class="layui-icon layui-icon-refresh" style="line-height:30px"></i>
    </a>
</div>
<div class="layui-fluid" id="app">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body">
                    <form class="layui-form layui-col-space5">
                        <div class="layui-inline layui-show-xs-block">
                            <button id="search" class="layui-btn" lay-submit="" lay-filter="search">
                                <i class="layui-icon">&#xe615;</i></button>
                        </div>
                    </form>
                </div>
                <div class="layui-card-body ">
                    <table class="layui-table" id="table_list" lay-filter="app">
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn" onclick="xadmin.open('添加会员套餐','vipprice_add.html',500,580)"><i
                class="layui-icon"></i>添加
        </button>
        <button class="layui-btn layui-btn-danger" lay-event="delete">
            <i class="layui-icon">&#xe640;</i>
            删除
        </button>
    </div>
</script>
<script type="text/html" id="optContainer">
    <div class="layui-btn-container">
        <!-- <a title='恢复' onclick='member_resume(this,{{d.LAY_INDEX }}, {{d.id}})' href='javascript:;'> -->
        <!--<i class="layui-icon">&#xe669;</i>-->
        <!--</a>-->
        <a title="修改" onclick="xadmin.open('修改会员套餐','vipprice_update.html?id={{d.id}}',500,580)" href="javascript:;">
            <i class="layui-icon">&#xe642;</i>
        </a>
        <a title="删除" onclick="member_del(this,{{d.LAY_INDEX }},'{{d.id}}')" href="javascript:;">
            <i class="layui-icon">&#xe640;</i>
        </a>
    </div>
</script>
<script type="text/html" id="statusContainer">
    <div class="layui-btn-container">
        {{# if(d.status==0){ }}
        <span class="layui-btn layui-btn-mini">
            正常
        </span>
        {{# }else{ }}
        <span class="layui-btn layui-btn-danger layui-btn-mini">
             已删除
        </span>
        {{# } }}
    </div>
</script>
<script type="text/html" id="switchTpl">
    <!-- 这里的checked的状态只是演示 -->
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" readonly lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script type="text/html" id="imgshow">
    <!-- 这里的checked的状态只是演示 -->
    <img src="{{d.}}"/>
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
<script>
    function member_del(obj, index, id) {
        layer.confirm('确认要删除吗?', function (index) {
            //发异步删除数据
            app.delete(obj, index, id);
        });
    }
</script>
<script>
    var tableIns = null;
    var app = null;
    $(function () {
        app = new Vue({
            el: "#app",
            data: {
                key: '',
                start: '',
                end: '',
                appList: []
            },
            watch: {},
            created: function () {
            },
            methods: {
                init: function () {
                    //初始化
                    layui.use(['laydate', 'form', 'table'], function () {
                        var laydate = layui.laydate,
                            form = layui.form,
                            table = layui.table;
                        //渲染日期输入框
                        //搜索条件
                        form.on('submit(search)', function (data) {
                            app.search(data.field);
                            return false;
                        });
                        tableIns = table.render({
                            elem: '#table_list',
                            url: "/admin/api/vip/vipprice/list",
                            toolbar: "#toolbar",
                            totalRow: true,
                            cols: [[{type: 'checkbox', title: "ID"},
                                {field: 'type', width: 120, sort: false, title: "套餐类型"},
                                {field: 'price', width: 120, sort: false, title: "价格"},
                                {field: 'actualPrice', width: 120, sort: false, title: "原价"},
                                {field: 'iosProductId', width: 120, sort: false, title: "APPStore内购ID"},
                                {
                                    field: 'show', width: 80, sort: false, title: "是否显示", templet: function (res) {
                                        if (res.show) {
                                            return " <input type=\"checkbox\" checked='true'  disabled  lay-skin=\"switch\"";
                                        } else {
                                            return " <input type=\"checkbox\"  disabled  lay-skin=\"switch\"";
                                        }
                                    }
                                },
                                {field: 'order', width: 80, sort: false, title: "排序值"},
                                {field: 'createTime', width: 150, sort: false, title: "创建时间"},
                                {field: 'updateTime', width: 150, sort: false, title: "更新时间"},
                                {fixed: 'right', width: 80, title: "操作", toolbar: '#optContainer'}]],
                            page: true,
                            parseData: function (res) { //res 即为原始返回的数据
                                console.log("返回数据:" + res);
                                if (res.code != 0)
                                    return;
                                if (res.data.list == null)
                                    return;
                                console.log(res.data.list)
                                return {
                                    "code": res.code, //解析接口状态
                                    "msg": res.msg, //解析提示文本
                                    "count": res.data.count, //解析数据长度
                                    "data": res.data.list //解析数据列表
                                };
                            },
                            error: function (e, msg) {
                                    ksapp.tableError(e)
                            }
                            //,…… //其他参数
                        });
                        //头工具栏事件
                        table.on('toolbar(app)',
                            function (obj) {
                                var checkStatus = table.checkStatus(obj.config.id);
                                switch (obj.event) {
                                    case 'delete':
                                        var data = checkStatus.data;
                                        if (data == null || data.length == 0) {
                                            layer.msg("未选择选项");
                                            return;
                                        }
                                        var ids = new Array();
                                        for (var i = 0; i < data.length; i++)
                                            ids.push(data[i].id);
                                        layer.confirm('确认要删除吗?', function (index) {
                                            //发异步删除数据
                                            app.deleteList(ids, function () {
                                                layer.msg("删除成功");
                                                $("form").submit();
                                            });
                                        });
                                        break;
                                }
                                ;
                            });
                        //请求搜索表单中需要的数据
                        $('#search').trigger("click");
                    });
                },
                delete: function (obj, index, id) {
                    var ids = new Array();
                    ids.push(id);
                    app.deleteList(ids, function () {
                        $(obj).parents("tr").remove();
                        layer.msg('已删除!', {icon: 1, time: 1000});
                    });
                },
                deleteList: function (ids, callback) {
                    ksapp.post("/admin/api/vip/vipprice/delete", {ids: JSON.stringify(ids)}, function (res) {
                        if (res.code == 0) {
                            callback();
                        } else {
                            layer.msg(res.msg);
                        }
                    }, function () {
                    });
                },
                search: function (params) {
                    //数据重载
                    tableIns.reload({
                        where: params,
                        page: {
                            curr: 1 //重新从第 1 页开始
                        }
                    });
                },
            }
        });
        app.init();
    });
</script>
<script>
</script>
</html>
src/main/resources/code/service/app/src/main/resources/static/vip/vipprice_update.html
New file
@@ -0,0 +1,216 @@
<!DOCTYPE html>
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>修改会员套餐</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
    <link rel="stylesheet" href="../css/font.css">
    <link rel="stylesheet" href="../css/xadmin.css">
    <script type="text/javascript" src="../lib/layui/layui.js" charset="utf-8"></script>
    <script type="text/javascript" src="../js/xadmin.js"></script>
    <script src="../js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../js/http.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <!-- 让IE8/9支持媒体查询,从而兼容栅格 -->
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<div class="layui-fluid">
    <div class="layui-row">
        <form class="layui-form" lay-filter="update">
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    套餐类型</label>
                <div class="layui-input-block">
                    <select name="type" lay-verify="required" disabled>
                        <option value="day">包天</option>
                        <option value="week">包周</option>
                        <option value="month">包月</option>
                        <option value="season">包季</option>
                        <option value="halfYear">包半年</option>
                        <option value="year">包年</option>
                    </select></div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    价格</label>
                <div class="layui-input-block">
                    <input type="text" name="price" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    原价</label>
                <div class="layui-input-block">
                    <input type="text" name="actualPrice" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    APPStore内购ID</label>
                <div class="layui-input-block">
                    <input type="text" name="iosProductId" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    是否显示</label>
                <div class="layui-input-block">
                    <input type="checkbox" name="show" lay-skin="switch"></div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    排序值</label>
                <div class="layui-input-block">
                    <input type="text" name="order" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_remarks" class="layui-form-label"></label>
                <button class="layui-btn" lay-filter="update" lay-submit="">确定修改</button>
            </div>
        </form>
    </div>
</div>
<script>
    //初始化上传控件
    var uploadTool = {
        callback: null,
        chooseImage: {},
        uploadArray: new Array(),
        init: function (upload) {
            this.uploadArray = new Array();
        },
        upload: function (result) {
            if (this.uploadArray.length > 0) {
                this.callback = result;
                //同时上传
                for (var i = 0; i < this.uploadArray.length; i++) {
                    this.uploadArray[i].upload();
                }
            } else {
                result();
            }
        }
    };
</script>
<script>
    //填充数据
    function fillData(form) {
        var id = ksapp.getQueryParam("id");
        if (id) {
        } else {
            layer.msg("id为空");
            return;
        }
        ksapp.post('/admin/api/vip/vipprice/get', {id: id}, function (res) {
            if (res.code == 0) {
                form.val("update", res.data);
            } else {
                layer.msg(res.msg);
            }
        }, function (res) {
            layer.msg("详情获取失败");
        });
    }
</script>
<script>
    layui.use(['form', 'layer', 'jquery', 'upload'], function () {
        $ = layui.jquery;
        var form = layui.form,
            layer = layui.layer,
            upload = layui.upload;
        var verify = {};
        //自定义验证规则
        form.verify(verify);
        //渲染上传控件
        uploadTool.init(upload);
        //填充表单数据
        //请求数据
        //form.data();
        //监听提交
        form.on('submit(update)',
            function (data) {
                console.log(data.field);
                var checkBoxList = $("input[type=checkbox]");
                if (checkBoxList) {
                    for (var i = 0; i < checkBoxList.length; i++) {
                        data.field[checkBoxList.eq(i).attr("name")] = checkBoxList.eq(i).is(':checked');
                    }
                }
                //转换json对象
                for (key in data.field) {
                    if (key.indexOf(".") > -1) {
                        var value = data.field[key];
                        delete data.field[key];
                        var onkeys = key.split(".");
                        //创建对象
                        if (data.field[onkeys[0]] == undefined) {
                            data.field[onkeys[0]] = {};
                        }
                        data.field[onkeys[0]][onkeys[1]] = value;
                    }
                }
                uploadTool.upload(function () {
                    //发异步,把数据提交给php
                    var params = data.field;
                    params.id = ksapp.getQueryParam("id");
                    ksapp.post('/admin/api/vip/vipprice/update', data.field, function (res) {
                        if (res.code == 0) {
                            layer.alert("修改成功", {
                                    icon: 6
                                },
                                function () {
                                    //关闭当前frame
                                    xadmin.close();
                                    // 可以对父窗口进行刷新
                                    xadmin.father_reload();
                                });
                        } else {
                            layer.msg(res.msg);
                        }
                    }, function (res) {
                    });
                });
                return false;
            });
        //请求select的数据API
        fillData(form)
    })
    ;
</script>
</body>
</html>
src/main/resources/code/service/app/src/main/resources/static/welcome.html
New file
@@ -0,0 +1,240 @@
<!doctype html>
<html class="x-admin-sm">
<head>
    <meta charset="UTF-8">
    <title>板栗快省</title>
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi"/>
    <meta http-equiv="Cache-Control" content="no-siteapp"/>
    <link rel="stylesheet" href="css/font.css">
    <link rel="stylesheet" href="css/xadmin.css">
    <link rel="stylesheet" href="css/theme3049.min.css">
    <!-- <link rel="stylesheet" href="./css/theme5.css"> -->
    <script type="text/javascript" src="js/xadmin.js"></script>
    <script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/http.js" type="text/javascript" charset="utf-8"></script>
    <script src="lib/layui/layui.js" charset="utf-8"></script>
    <!-- 让IE8/9支持媒体查询,从而兼容栅格 -->
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script>
        // 是否开启刷新记忆tab功能
        // var is_remember = false;
    </script>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.min.js"></script>
    <style>
        .layui-elem-quote {
            color: #666;
            font-size: 16px;
            font-weight: bold;
            border-left: none;
        }
        .time-psan {
            height: 25px;
            display: flex;
            margin: 20px 0;
        }
        .time-psan div {
            width: 50px;
            height: 100%;
            text-align: center;
            line-height:25px;
            font-size: 12px;
            background: #F5F5F5;
            color: #666;
            cursor: pointer;
        }
        .time-psan .active {
            background: #DDDDDD;
        }
        .time-psan :first-child {
            border-top-left-radius: 8px;
            border-bottom-left-radius: 8px;
        }
        .time-psan :last-child {
            border-top-right-radius: 8px;
            border-bottom-right-radius: 8px;
        }
    </style>
</head>
<body>
<div class="layui-card">
    <div class="layui-card-body">
        <blockquote class="layui-elem-quote">
            新增用户统计
        </blockquote>
        <form class="layui-form layui-col-space5">
            <div class="layui-inline layui-show-xs-block">
                <input type="text" name="date" lay-verify="" placeholder="" autocomplete="off"
                       class="layui-input">
            </div>
            <div class="layui-inline layui-show-xs-block">
                <button id="search" class="layui-btn" lay-submit="" lay-filter="search">
                    <i class="layui-icon">&#xe615;</i></button>
            </div>
        </form>
        <div class="time-psan">
            <div key="hour">小时</div>
            <div key="day" class="active">天</div>
            <div key="month">月</div>
        </div>
        <canvas id="myChart" width="100%" height="25"></canvas>
    </div>
</div>
</body>
<script>
    $(function () {
        //时间间隔点击事件
        $(".time-psan div").click(function () {
            if (!$(this).hasClass("active")) {
                $(".time-psan div").removeClass("active");
                $(this).addClass("active");
                $("#search").click();
            }
        });
        layui.use(['laydate', 'form'], function () {
            var laydate = layui.laydate,
                form = layui.form;
            //渲染日期输入框
            var d = new Date();
            var nowDay = d.format('yyyy-MM-dd');
            laydate.render({
                elem: 'input[name=date]' //指定元素
                , type: 'date'
                , trigger: 'click'
                //,lang: 'en'
                //,theme: 'grid'
                , range: true //开启日期范围,默认使用“-”分割
                // ,min: '2020-01-01'
                //,max: '2021-5-9'
                //,value: '2021-05-09 12:06:09'
                , value: nowDay + " - " + nowDay
                , done: function (value, date, endDate) {
                    console.log(value, date, endDate);
                    requestData(value);
                }
                , change: function (value, date, endDate) {
                }
            });
            //搜索条件
            form.on('submit(search)', function (data) {
                requestData(data.field.date);
                return false;
            });
            $("#search").click();
        });
        function requestData(value) {
            var date = value.split(" - ");
            ksapp.post("/admin/api/user/statisticRegisterUser", {
                startTime: new Date(date[0]).getTime()-1000*60*60*8,
                endTime: new Date(date[1]).getTime()-1000*60*60*8+1000*60*60*24-1,
                span: $(".time-psan .active").attr("key")
            }, function (res) {
                if (res.code == 0) {
                    var labels = new Array();
                    var values = new Array();
                    for (var i = 0; i < res.data.list.length; i++) {
                        labels.push(res.data.list[i].time);
                        values.push(res.data.list[i].number);
                    }
                    draw(labels, values);
                } else {
                    layer.msg(res.msg);
                }
            }, function (res) {
            });
        }
    });
</script>
<script>
    var ctx = document.getElementById("myChart").getContext('2d');
    var myChar = null;
    function draw(labels, data) {
        if (myChar == null) {
            myChar = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: labels,
                    datasets: [{
                        label: '新增用户数',
                        data: data,
                        backgroundColor: 'rgba(255, 99, 132, 0.2)',
                        borderColor: 'rgba(54, 162, 235, 1)',
                        borderWidth: 3
                    }]
                },
                options: {
                    scales: {
                        yAxes: [{
                            ticks: {
                                beginAtZero: true
                            }
                        }]
                    }
                }
            });
        } else {
            myChar.data.labels = labels;
            myChar.data.datasets[0].data = data;
            myChar.update();
        }
    }
</script>
<script>
    Date.prototype.format = function (format) {
        var o = {
            "M+": this.getMonth() + 1, //month
            "d+": this.getDate(), //day
            "h+": this.getHours(), //hour
            "m+": this.getMinutes(), //minute
            "s+": this.getSeconds(), //second
            "q+": Math.floor((this.getMonth() + 3) / 3), //quarter
            "S": this.getMilliseconds() //millisecond
        }
        if (/(y+)/.test(format)) format = format.replace(RegExp.$1,
            (this.getFullYear() + "").substr(4 - RegExp.$1.length));
        for (var k in o) if (new RegExp("(" + k + ")").test(format))
            format = format.replace(RegExp.$1,
                RegExp.$1.length == 1 ? o[k] :
                    ("00" + o[k]).substr(("" + o[k]).length));
        return format;
    }
</script>
</html>
src/main/resources/code/service/app/src/main/resources/wx/apiclient_key.pem
New file
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDMD+LQJ3LJJZAR
+ix+XEO6GjClzau5unLZQNNF6KwqISV/x2oyIFwV7rNvmVNByfA3OcxZKTsW4iXT
1DI5v7cUr4dwRgOLxya7IBaziJEQ70IHqmPVjf2aR381HvF4t4ILS1PDhlHEqNXY
onCDhqDbjCGcboV21wd7+borEWst6Kx8qud59Duv8bwcmwshSQFX7k/nyqmn8DWQ
JXB8GwZUQy7i9xtnAvhjgzsaUcSj5GH8NRmuW8bb2uPOlYZ5BwuEd25zq7cy1Y94
Ji3ZX3QCl3KXk1QluxRM/hMJAnBgRok+BdTR62xmsDDpdfXgjYMzxDarB2keCnZa
A9AM7wvZAgMBAAECggEARd4+k3SeSZ6x2GXm7BDdI5AqDesAnCPphNc8P1ht8jLN
KxX1F1qbDOtgxpohtonU1KPWgsSqNaiSuReTZtBseAmtftSKDEbQzQssmqXsvXae
Dg/aBNmL9lH6jQ6eMO3r+b/92xlXT9Va+sSLb40d8G3naC8zRUBUkK8tfeeF4f6G
jcdZOvDLEb3CzULxT+l9gVhJ4fUvolPZqGFHsW0j+j73YMviatKUN21s0vnJt/xp
z3kcyIAKa7f7fy+WsDUudbkq1aVTU4Aq11Wv5AcMRx1PT5rF7XXafW27hbf09Mal
oMd3E9YS5dOo/7dIcEjZqi1nPA/iUzGLrFU1rFvPcQKBgQD0HTcf7BVdolp45RaZ
BRv2Bg/m+KPT5pzHIrfme/0ccrel2td9lNHXrjMiUWngBMWN+gB6hUeeyXcnB7Tv
c+NmnPGPC/cIO/zRF0sj/6Sv1T6I7pqF6OqeBlL1DWPxdKJCdBx4x/b0G+Mi42pB
n+rX1MMFKny8/+Re/O9Q/LOUxQKBgQDV/3AMe3fS5pM0zrJzVRuPsmlgdGeVhK7f
UGHMdaPNNN/5tPN2XJdK1EHj3dtNI6pQN22VHSLFoPuBR03dLK7s6tAaT3Xg+2Si
ItT0fyUmJzyo8H38G/uHy+5WeUH8fN4gHqeFgY/nuOCTurji9Ai4jEA12tzykM7L
GQdI9PLUBQKBgDB7fO9CHBw0mnNYTFynvx3lplLhHuh+7LRAGPYVufdkcUTnadTv
MZ38Yvt13+k2CWZhOKccwVSv/pIp3a2Q/qDqmq8mWTGxeEyuq6XCqBqj53+ao+Xk
lHQ+HUu+FRNnbrJ0DROP42QoBbxwHjJaaHHlN7ZW8d83k0uqQH19Ms1hAoGBAJpk
n7+xuMKlbmF0G1WQesES9GoNscozH0Oop9aurU5ZLprnDZxAszrepucy4ozmBXO4
ecxSaArz2WDtQ+Ul3tK5mwjQeXinh3Re8wuvS+sZ9e7hC9Q/kBrqa/thotT6dfvw
geaVknCZdxW+arP7Yuta7NyuGii7hycK2LGvYB7NAoGAYTdxBkLw0jIseDPYbMsA
TRo7HVfleduhUZdNfrjQokJbsbEeLbHb1DFM/BH99xAQ/Kv6L/tXXoExLHbU4xQq
nwT6DLzn9pTbAhbSqVQE8H0oelJQLxjyk/d8fNutIiSmhXaHpc++LycHgfBDgOpf
00bxvSPu1/7qJ1dN0jwxPxA=
-----END PRIVATE KEY-----
src/main/resources/code/service/app/src/main/resources/wxpay.properties
New file
@@ -0,0 +1,4 @@
app_id=wxa99686bb65a9f466
mch_id=1520950211
mch_serial_no=68E815B30C95747A572B2DCDBC838FC784A78F55
api_v3_key=XYJkJ2018FAfaodCCx899mLl138rfGVd
src/main/resources/code/service/app/src/test/java/test/GeneratorTest.java
@@ -18,10 +18,10 @@
    @Test
    public void generater() throws Exception {
        GeneraterManager.getInstance().init("D:\\workspace\\server\\utils\\src\\test\\java", TestEntity.class);
        AdminGeneraterParams adminGeneraterParams = new AdminGeneraterParams("com.generater.temp.controller", "D:\\workspace\\server\\utils\\src\\test");
        AdminGeneraterParams adminGeneraterParams = new AdminGeneraterParams().setControllerPackage("com.generater.temp.controller").setHtmlDir("D:\\workspace\\server\\utils\\src\\test");
        //创建整个功能模块
        GeneraterManager.getInstance().createWholeFunction(new DaoGeneraterParams("com.generater.temp.dao", "D:\\workspace\\server\\utils\\src\\test"), new ServiceGeneraterParams("com.generater.temp.query", "com.generater.temp.service", "com.generater.temp.service.impl"), adminGeneraterParams);
        GeneraterManager.getInstance().createWholeFunction(new DaoGeneraterParams().setDaoPackage("com.generater.temp.dao").setMapperXMLDir("D:\\workspace\\server\\utils\\src\\test"), new ServiceGeneraterParams().setQueryPackage("com.generater.temp.query").setServiceInterPackage("com.generater.temp.service").setServiceImplPackage("com.generater.temp.service.impl"), adminGeneraterParams);
    }
src/main/resources/code/service/pom.xml
@@ -34,6 +34,7 @@
            <url>http://193.112.35.168:8889/nexus/content/groups/public/</url>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
@@ -141,11 +142,14 @@
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>${mongo.driver.version}</version>
        </dependency>
        <!--<dependency>-->
        <!--<groupId>org.mongodb</groupId>-->
        <!--<artifactId>mongo-java-driver</artifactId>-->
        <!--<version>${mongo.driver.version}</version>-->
        <!--</dependency>-->
        <!-- Redis -->
        <dependency>
@@ -153,6 +157,24 @@
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yeshi</groupId>
            <artifactId>utils</artifactId>
            <version>0.2.7</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.data</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>