From 67f39351a5571b822f93c09e8c6e7986fe91e758 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期三, 06 九月 2023 16:46:29 +0800
Subject: [PATCH] #短信登录

---
 src/main/java/com/zy/crm/manager/entity/SmsCode.java                  |  127 ++++++++++
 src/main/java/com/zy/crm/manager/controller/SmsCodeController.java    |  164 +++++++++++++
 src/main/java/com/zy/crm/manager/service/impl/SmsCodeServiceImpl.java |   67 +++++
 src/main/java/com/zy/crm/manager/service/SmsCodeService.java          |   14 +
 src/main/java/com/zy/crm/common/CodeRes.java                          |    1 
 src/main/java/com/zy/crm/common/web/AuthController.java               |   39 +++
 pom.xml                                                               |    6 
 src/main/java/com/zy/crm/manager/utils/SmsUtils.java                  |  119 +++++++++
 src/main/resources/mapper/SmsCodeMapper.xml                           |   23 +
 src/main/webapp/views/login.html                                      |  142 ++++++++++-
 src/main/java/com/zy/crm/manager/mapper/SmsCodeMapper.java            |   14 +
 11 files changed, 702 insertions(+), 14 deletions(-)

diff --git a/pom.xml b/pom.xml
index 15db921..32b5017 100644
--- a/pom.xml
+++ b/pom.xml
@@ -134,6 +134,12 @@
             <artifactId>poi-scratchpad</artifactId>
             <version>4.1.2</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>alibabacloud-dysmsapi20170525</artifactId>
+            <version>2.0.24</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/src/main/java/com/zy/crm/common/CodeRes.java b/src/main/java/com/zy/crm/common/CodeRes.java
index 1f5a766..65d5517 100644
--- a/src/main/java/com/zy/crm/common/CodeRes.java
+++ b/src/main/java/com/zy/crm/common/CodeRes.java
@@ -9,6 +9,7 @@
     String USER_10002 = "10002-璐﹀彿宸茶绂佺敤";
     String USER_10003 = "10003-瀵嗙爜閿欒";
     String USER_10004 = "10004-瀵嗙爜鏈垵濮嬪寲";
+    String USER_10005 = "10005-鐭俊鐧诲綍楠岃瘉澶辫触";
 
     // stock
     String NONE_STOCK = "20002-搴撳瓨涓嶈冻";
diff --git a/src/main/java/com/zy/crm/common/web/AuthController.java b/src/main/java/com/zy/crm/common/web/AuthController.java
index 6711669..4b8fe69 100644
--- a/src/main/java/com/zy/crm/common/web/AuthController.java
+++ b/src/main/java/com/zy/crm/common/web/AuthController.java
@@ -8,6 +8,8 @@
 import com.core.common.Cools;
 import com.core.common.R;
 import com.core.exception.CoolException;
+import com.zy.crm.manager.service.SmsCodeService;
+import com.zy.crm.manager.utils.SmsUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.transaction.annotation.Transactional;
@@ -53,9 +55,11 @@
     private RolePermissionService rolePermissionService;
     @Autowired
     private HostService hostService;
+    @Autowired
+    private SmsCodeService smsCodeService;
 
     @RequestMapping("/login.action")
-    @ManagerAuth(value = ManagerAuth.Auth.NONE, memo = "鐧诲綍")
+    @ManagerAuth(value = ManagerAuth.Auth.NONE, memo = "瀵嗙爜鐧诲綍")
     public R loginAction(String username, String password){
         if (username.equals("super") && password.equals(Cools.md5(superPwd))) {
             Map<String, Object> res = new HashMap<>();
@@ -95,6 +99,39 @@
         return R.ok(res);
     }
 
+    @RequestMapping("/smsLogin.action")
+    @ManagerAuth(value = ManagerAuth.Auth.NONE, memo = "鐭俊鐧诲綍")
+    public R smsLoginAction(String phone, String code){
+        EntityWrapper<User> userWrapper = new EntityWrapper<>();
+        userWrapper.eq("mobile", phone);
+        User user = userService.selectOne(userWrapper);
+        if (Cools.isEmpty(user)){
+            return R.parse(CodeRes.USER_10001);
+        }
+        if (user.getStatus()!=1){
+            return R.parse(CodeRes.USER_10002);
+        }
+        boolean verify = smsCodeService.verifySmsCode(phone, code);
+        if (!verify) {
+            return R.parse(CodeRes.USER_10005);
+        }
+        String token = Cools.enToken(System.currentTimeMillis() + phone, code);
+        userLoginService.delete(new EntityWrapper<UserLogin>().eq("user_id", user.getId()));
+        UserLogin userLogin = new UserLogin();
+        userLogin.setUserId(user.getId());
+        userLogin.setToken(token);
+        userLogin.setCreateTime(new Date());
+        if (user.getRoleId() == 1) {
+            userLogin.setHostId(hostService.getTop1().getId());
+        }
+        userLoginService.insert(userLogin);
+        Map<String, Object> res = new HashMap<>();
+        res.put("username", user.getUsername());
+        res.put("nickname", user.getNickname());
+        res.put("token", token);
+        return R.ok(res);
+    }
+
     @RequestMapping("/show/host.action")
     @ManagerAuth
     public R showHosts() {
diff --git a/src/main/java/com/zy/crm/manager/controller/SmsCodeController.java b/src/main/java/com/zy/crm/manager/controller/SmsCodeController.java
new file mode 100644
index 0000000..a71a463
--- /dev/null
+++ b/src/main/java/com/zy/crm/manager/controller/SmsCodeController.java
@@ -0,0 +1,164 @@
+package com.zy.crm.manager.controller;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.core.common.DateUtils;
+import com.zy.crm.manager.entity.SmsCode;
+import com.zy.crm.manager.service.SmsCodeService;
+import com.core.annotations.ManagerAuth;
+import com.core.common.BaseRes;
+import com.core.common.Cools;
+import com.core.common.R;
+import com.core.domain.KeyValueVo;
+import com.zy.crm.common.web.BaseController;
+import com.zy.crm.manager.utils.SmsUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+@RestController
+public class SmsCodeController extends BaseController {
+
+    @Autowired
+    private SmsCodeService smsCodeService;
+
+    @RequestMapping(value = "/smsCode/{id}/auth")
+    @ManagerAuth
+    public R get(@PathVariable("id") String id) {
+        return R.ok(smsCodeService.selectById(String.valueOf(id)));
+    }
+
+    @RequestMapping(value = "/smsCode/list/auth")
+    @ManagerAuth
+    public R list(@RequestParam(defaultValue = "1") Integer curr,
+                  @RequestParam(defaultValue = "10") Integer limit,
+                  @RequestParam(required = false) String orderByField,
+                  @RequestParam(required = false) String orderByType,
+                  @RequestParam(required = false) String condition,
+                  @RequestParam Map<String, Object> param) {
+        EntityWrapper<SmsCode> wrapper = new EntityWrapper<>();
+        excludeTrash(param);
+        convert(param, wrapper);
+        allLike(SmsCode.class, param.keySet(), wrapper, condition);
+        if (!Cools.isEmpty(orderByField)) {
+            wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType));
+        }
+        return R.ok(smsCodeService.selectPage(new Page<>(curr, limit), wrapper));
+    }
+
+    private <T> void convert(Map<String, Object> map, EntityWrapper<T> wrapper) {
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+            String val = String.valueOf(entry.getValue());
+            if (val.contains(RANGE_TIME_LINK)) {
+                String[] dates = val.split(RANGE_TIME_LINK);
+                wrapper.ge(entry.getKey(), DateUtils.convert(dates[0]));
+                wrapper.le(entry.getKey(), DateUtils.convert(dates[1]));
+            } else {
+                wrapper.like(entry.getKey(), val);
+            }
+        }
+    }
+
+    @RequestMapping(value = "/smsCode/add/auth")
+    @ManagerAuth
+    public R add(SmsCode smsCode) {
+        smsCodeService.insert(smsCode);
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/smsCode/update/auth")
+    @ManagerAuth
+    public R update(SmsCode smsCode) {
+        if (Cools.isEmpty(smsCode) || null == smsCode.getId()) {
+            return R.error();
+        }
+        smsCodeService.updateById(smsCode);
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/smsCode/delete/auth")
+    @ManagerAuth
+    public R delete(@RequestParam(value = "ids[]") Long[] ids) {
+        for (Long id : ids) {
+            smsCodeService.deleteById(id);
+        }
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/smsCode/export/auth")
+    @ManagerAuth
+    public R export(@RequestBody JSONObject param) {
+        EntityWrapper<SmsCode> wrapper = new EntityWrapper<>();
+        List<String> fields = JSONObject.parseArray(param.getJSONArray("fields").toJSONString(), String.class);
+        Map<String, Object> map = excludeTrash(param.getJSONObject("smsCode"));
+        convert(map, wrapper);
+        List<SmsCode> list = smsCodeService.selectList(wrapper);
+        return R.ok(exportSupport(list, fields));
+    }
+
+    @RequestMapping(value = "/smsCodeQuery/auth")
+    @ManagerAuth
+    public R query(String condition) {
+        EntityWrapper<SmsCode> wrapper = new EntityWrapper<>();
+        wrapper.like("id", condition);
+        Page<SmsCode> page = smsCodeService.selectPage(new Page<>(0, 10), wrapper);
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (SmsCode smsCode : page.getRecords()) {
+            Map<String, Object> map = new HashMap<>();
+            map.put("id", smsCode.getId());
+            map.put("value", smsCode.getId());
+            result.add(map);
+        }
+        return R.ok(result);
+    }
+
+    @RequestMapping(value = "/smsCode/check/column/auth")
+    @ManagerAuth
+    public R query(@RequestBody JSONObject param) {
+        Wrapper<SmsCode> wrapper = new EntityWrapper<SmsCode>().eq(humpToLine(String.valueOf(param.get("key"))), param.get("val"));
+        if (null != smsCodeService.selectOne(wrapper)) {
+            return R.parse(BaseRes.REPEAT).add(getComment(SmsCode.class, String.valueOf(param.get("key"))));
+        }
+        return R.ok();
+    }
+
+    @RequestMapping("/smsCode/all/get/kv")
+    @ManagerAuth
+    public R getDataKV(@RequestParam(required = false) String condition) {
+        List<KeyValueVo> vos = new ArrayList<>();
+        Wrapper<SmsCode> wrapper = new EntityWrapper<SmsCode>().andNew().like("id", condition).orderBy("create_time", false);
+        smsCodeService.selectPage(new Page<>(1, 30), wrapper).getRecords().forEach(item -> vos.add(new KeyValueVo(String.valueOf(item.getId()), item.getId())));
+        return R.ok().add(vos);
+    }
+
+    /**
+     * 鍙戦�佺煭淇¢獙璇佺爜
+     */
+    @PostMapping("/smsCode/sendCode")
+    public R sendSmsCode(@RequestParam("phone") String phone) {
+        if (!SmsUtils.verifyPhone(phone)) {
+            return R.error("鎵嬫満鍙锋牸寮忎笉姝g‘");
+        }
+
+        SmsCode smsCode1 = smsCodeService.selectByPhone(phone);
+        if (smsCode1 != null) {
+            long createTime = smsCode1.getCreateTime().getTime();
+            long nowTime = new Date().getTime();
+            long diff = nowTime - createTime;
+            if (diff < 60000) {
+                return R.error("鍙戦�侀棿闅斾笉鑳藉皬浜�1鍒嗛挓");
+            }
+        }
+
+        boolean sendSmsCode = smsCodeService.sendSmsCode(phone);
+        if (!sendSmsCode) {
+            return R.error();
+        }
+        return R.ok();
+    }
+
+}
diff --git a/src/main/java/com/zy/crm/manager/entity/SmsCode.java b/src/main/java/com/zy/crm/manager/entity/SmsCode.java
new file mode 100644
index 0000000..9c26ea7
--- /dev/null
+++ b/src/main/java/com/zy/crm/manager/entity/SmsCode.java
@@ -0,0 +1,127 @@
+package com.zy.crm.manager.entity;
+
+import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.enums.IdType;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotations.TableField;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import com.baomidou.mybatisplus.annotations.TableName;
+import java.io.Serializable;
+
+@Data
+@TableName("sys_sms_code")
+public class SmsCode implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value= "")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鎵嬫満鍙�
+     */
+    @ApiModelProperty(value= "鎵嬫満鍙�")
+    private String phone;
+
+    /**
+     * 楠岃瘉鐮�
+     */
+    @ApiModelProperty(value= "楠岃瘉鐮�")
+    private String code;
+
+    /**
+     * 鐘舵�� 0: 鏈彂閫�  1: 宸插彂閫�  2: 宸蹭娇鐢�  
+     */
+    @ApiModelProperty(value= "鐘舵�� 0: 鏈彂閫�  1: 宸插彂閫�  2: 宸蹭娇鐢�  ")
+    private Integer status;
+
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    @ApiModelProperty(value= "鍒涘缓鏃堕棿")
+    @TableField("create_time")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 鍙戦�佹椂闂�
+     */
+    @ApiModelProperty(value= "鍙戦�佹椂闂�")
+    @TableField("send_time")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date sendTime;
+
+    /**
+     * 浣跨敤鏃堕棿
+     */
+    @ApiModelProperty(value= "浣跨敤鏃堕棿")
+    @TableField("use_time")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date useTime;
+
+    public SmsCode() {}
+
+    public SmsCode(String phone,String code,Integer status,Date createTime,Date sendTime,Date useTime) {
+        this.phone = phone;
+        this.code = code;
+        this.status = status;
+        this.createTime = createTime;
+        this.sendTime = sendTime;
+        this.useTime = useTime;
+    }
+
+//    SmsCode smsCode = new SmsCode(
+//            null,    // 鎵嬫満鍙�
+//            null,    // 楠岃瘉鐮�
+//            null,    // 鐘舵��
+//            null,    // 鍒涘缓鏃堕棿
+//            null,    // 鍙戦�佹椂闂�
+//            null    // 浣跨敤鏃堕棿
+//    );
+
+    public String getStatus$(){
+        if (null == this.status){ return null; }
+        switch (this.status){
+            case 0:
+                return "鏈彂閫�";
+            case 1:
+                return "宸插彂閫�";
+            case 2:
+                return "宸蹭娇鐢�";
+            default:
+                return String.valueOf(this.status);
+        }
+    }
+
+    public String getCreateTime$(){
+        if (Cools.isEmpty(this.createTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
+    }
+
+    public String getSendTime$(){
+        if (Cools.isEmpty(this.sendTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.sendTime);
+    }
+
+    public String getUseTime$(){
+        if (Cools.isEmpty(this.useTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.useTime);
+    }
+
+
+}
diff --git a/src/main/java/com/zy/crm/manager/mapper/SmsCodeMapper.java b/src/main/java/com/zy/crm/manager/mapper/SmsCodeMapper.java
new file mode 100644
index 0000000..5051d42
--- /dev/null
+++ b/src/main/java/com/zy/crm/manager/mapper/SmsCodeMapper.java
@@ -0,0 +1,14 @@
+package com.zy.crm.manager.mapper;
+
+import com.zy.crm.manager.entity.SmsCode;
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface SmsCodeMapper extends BaseMapper<SmsCode> {
+
+    SmsCode selectByPhone(String phone);
+
+}
diff --git a/src/main/java/com/zy/crm/manager/service/SmsCodeService.java b/src/main/java/com/zy/crm/manager/service/SmsCodeService.java
new file mode 100644
index 0000000..7afbde2
--- /dev/null
+++ b/src/main/java/com/zy/crm/manager/service/SmsCodeService.java
@@ -0,0 +1,14 @@
+package com.zy.crm.manager.service;
+
+import com.zy.crm.manager.entity.SmsCode;
+import com.baomidou.mybatisplus.service.IService;
+
+public interface SmsCodeService extends IService<SmsCode> {
+
+    SmsCode selectByPhone(String phone);
+
+    boolean sendSmsCode(String phone);
+
+    boolean verifySmsCode(String phone, String code);
+
+}
diff --git a/src/main/java/com/zy/crm/manager/service/impl/SmsCodeServiceImpl.java b/src/main/java/com/zy/crm/manager/service/impl/SmsCodeServiceImpl.java
new file mode 100644
index 0000000..571e3c7
--- /dev/null
+++ b/src/main/java/com/zy/crm/manager/service/impl/SmsCodeServiceImpl.java
@@ -0,0 +1,67 @@
+package com.zy.crm.manager.service.impl;
+
+import com.core.common.R;
+import com.zy.crm.manager.mapper.SmsCodeMapper;
+import com.zy.crm.manager.entity.SmsCode;
+import com.zy.crm.manager.service.SmsCodeService;
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.zy.crm.manager.utils.SmsUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+@Service("smsCodeService")
+public class SmsCodeServiceImpl extends ServiceImpl<SmsCodeMapper, SmsCode> implements SmsCodeService {
+
+    @Override
+    public SmsCode selectByPhone(String phone) {
+        return this.baseMapper.selectByPhone(phone);
+    }
+
+    @Override
+    public boolean sendSmsCode(String phone) {
+        String randomNum = SmsUtils.getRandomNum(6);//鑾峰彇鍏綅闅忔満鏁�
+        SmsCode smsCode = new SmsCode();
+        smsCode.setPhone(phone);
+        smsCode.setCode(randomNum);
+        smsCode.setStatus(0);
+        smsCode.setCreateTime(new Date());
+        if (this.baseMapper.insert(smsCode) <= 0) {
+            return false;
+        }
+
+        boolean sendSmsCode = SmsUtils.sendSmsCode(phone, smsCode.getCode());
+        if (!sendSmsCode) {
+            return false;
+        }
+
+        smsCode.setSendTime(new Date());
+        smsCode.setStatus(1);
+        this.baseMapper.updateById(smsCode);
+        return true;
+    }
+
+    @Override
+    public boolean verifySmsCode(String phone, String code) {
+        SmsCode smsCode1 = this.baseMapper.selectByPhone(phone);
+        if (smsCode1 == null) {
+            return false;
+        }
+
+        long createTime = smsCode1.getCreateTime().getTime();
+        long nowTime = new Date().getTime();
+        long diff = nowTime - createTime;
+        if (diff > (60000 * 5)) {//鐭俊鏃堕棿瓒呰繃浜斿垎閽燂紝宸插け鏁�
+            return false;
+        }
+
+        if (smsCode1.getStatus() == 2) {
+            return false;//鐭俊宸茶浣跨敤
+        }
+
+        smsCode1.setStatus(2);
+        smsCode1.setUseTime(new Date());
+        this.baseMapper.updateById(smsCode1);
+        return true;
+    }
+}
diff --git a/src/main/java/com/zy/crm/manager/utils/SmsUtils.java b/src/main/java/com/zy/crm/manager/utils/SmsUtils.java
new file mode 100644
index 0000000..390d67f
--- /dev/null
+++ b/src/main/java/com/zy/crm/manager/utils/SmsUtils.java
@@ -0,0 +1,119 @@
+package com.zy.crm.manager.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.aliyun.auth.credentials.Credential;
+import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
+import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
+import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
+import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
+import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponseBody;
+import darabonba.core.client.ClientOverrideConfiguration;
+
+import java.util.HashMap;
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 鐭俊鍙戦�佸伐鍏�
+ */
+public class SmsUtils {
+
+    public static AsyncClient getClient() {
+        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
+                .accessKeyId("LTAI4GBCtqGZAn5XDEREh1Pp")
+                .accessKeySecret("SQQkh2kps3wxfbNXUg5nLZgWS2CMjm")
+                .build());
+
+        // Configure the Client
+        AsyncClient client = AsyncClient.builder()
+                //.httpClient(httpClient) // Use the configured HttpClient, otherwise use the default HttpClient (Apache HttpClient)
+                .credentialsProvider(provider)
+                //.serviceConfiguration(Configuration.create()) // Service-level configuration
+                // Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.
+                .overrideConfiguration(
+                        ClientOverrideConfiguration.create()
+                                // Endpoint 璇峰弬鑰� https://api.aliyun.com/product/Dysmsapi
+                                .setEndpointOverride("dysmsapi.aliyuncs.com")
+                        //.setConnectTimeout(Duration.ofSeconds(30))
+                )
+                .build();
+
+        return client;
+    }
+
+    /**
+     * 鍙戦�佺煭淇¢獙璇佺爜
+     */
+    public static boolean sendSmsCode(String phone, String code) {
+        AsyncClient client = getClient();
+        try {
+            HashMap<String, Object> templateParam = new HashMap<>();
+            templateParam.put("code", code);
+
+            // Parameter settings for API request
+            SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
+                    .phoneNumbers(phone)
+                    .signName("鏌愭煇鍟嗗満")
+                    .templateCode("SMS_195220399")
+                    .templateParam(JSON.toJSONString(templateParam))
+                    // Request-level configuration rewrite, can set Http request parameters, etc.
+                    // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
+                    .build();
+
+            // Asynchronously get the return value of the API request
+            CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
+            // Synchronously get the return value of the API request
+            SendSmsResponse resp = response.get();
+            SendSmsResponseBody body = resp.getBody();
+//            System.out.println(body.getCode());
+//            System.out.println(body.getMessage());
+            if (body.getCode().equals("OK")) {
+                return true;
+            }
+            return false;
+        } catch (Exception e) {
+            return false;
+        } finally {
+            // Finally, close the client
+            client.close();
+        }
+    }
+
+    /**
+     * 鑾峰彇闅忔満鏁�
+     * @param length 闅忔満鏁伴暱搴�
+     */
+    public static String getRandomNum(Integer length) {
+        Random random = new Random();
+        StringBuffer buffer = new StringBuffer();
+        for (int i = 0; i < length; i++) {
+            buffer.append(random.nextInt(10));
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * 姝e垯楠岃瘉鎵嬫満鍙�
+     */
+    public static boolean verifyPhone(String phone) {
+        // 瀹氫箟鎵嬫満鍙风爜鐨勬鍒欒〃杈惧紡
+        String regex = "^1[3456789]\\d{9}$";
+        // 缂栬瘧姝e垯琛ㄨ揪寮�
+        Pattern pattern = Pattern.compile(regex);
+        // 鍒涘缓 Matcher 瀵硅薄
+        Matcher matcher = pattern.matcher(phone);
+        // 杩涜鍖归厤
+        if (!matcher.matches()) {
+            return false;
+        }
+        return true;
+    }
+
+    public static void main(String[] args) throws Exception {
+        sendSmsCode("17788886666","666666");
+    }
+
+}
diff --git a/src/main/resources/mapper/SmsCodeMapper.xml b/src/main/resources/mapper/SmsCodeMapper.xml
new file mode 100644
index 0000000..4410811
--- /dev/null
+++ b/src/main/resources/mapper/SmsCodeMapper.xml
@@ -0,0 +1,23 @@
+<?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.zy.crm.manager.mapper.SmsCodeMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.zy.crm.manager.entity.SmsCode">
+        <id column="id" property="id" />
+        <result column="phone" property="phone" />
+        <result column="code" property="code" />
+        <result column="status" property="status" />
+        <result column="create_time" property="createTime" />
+        <result column="send_time" property="sendTime" />
+        <result column="use_time" property="useTime" />
+
+    </resultMap>
+
+    <select id="selectByPhone" resultMap="BaseResultMap">
+        select top 1 * from sys_sms_code
+        where phone = #{phone}
+        order by create_time desc
+    </select>
+
+</mapper>
diff --git a/src/main/webapp/views/login.html b/src/main/webapp/views/login.html
index 81ab8b8..e0fb01f 100644
--- a/src/main/webapp/views/login.html
+++ b/src/main/webapp/views/login.html
@@ -76,22 +76,55 @@
           <img src="../static/image/logo.png" alt="" style="width: 80%">
           <span class="login100-form-title p-t-20 p-b-45">涓壃绔嬪簱</span>
           <span class="login100-form-title p-t-20 p-b-45" style="margin: 15px 0;color: #868686;font-size: 24px">CRM</span>
-          <div class="wrap-input100 validate-input m-b-10" data-validate="璇疯緭鍏ョ敤鎴峰悕">
-            <input id="username" class="input100" type="text" name="username" placeholder="username" autocomplete="off">
-            <span class="focus-input100"></span>
-            <span class="symbol-input100">
+          <div id="passwdContent" style="display: none;">
+            <div class="wrap-input100 validate-input m-b-10" data-validate="璇疯緭鍏ョ敤鎴峰悕">
+              <input id="username" class="input100" type="text" name="username" placeholder="username" autocomplete="off">
+              <span class="focus-input100"></span>
+              <span class="symbol-input100">
               <i class="fa fa-user"></i>
             </span>
-          </div>
-          <div class="wrap-input100 validate-input m-b-10" data-validate="璇疯緭鍏ュ瘑鐮�">
-            <input id="password" class="input100" type="password" name="pass" placeholder="password">
-            <span class="focus-input100"></span>
-            <span class="symbol-input100">
+            </div>
+            <div class="wrap-input100 validate-input m-b-10" data-validate="璇疯緭鍏ュ瘑鐮�">
+              <input id="password" class="input100" type="password" name="pass" placeholder="password">
+              <span class="focus-input100"></span>
+              <span class="symbol-input100">
               <i class="fa fa-lock"></i>
             </span>
+            </div>
+            <div style="text-align: right;">
+              <button onclick="switchLogin('sms')">鐭俊鐧诲綍</button>
+            </div>
+            <div class="container-login100-form-btn p-t-10">
+              <button id="passLogin" class="login100-form-btn login-btn">Login</button>
+            </div>
           </div>
-          <div class="container-login100-form-btn p-t-10">
-            <button class="login100-form-btn login-btn">Login</button>
+          <div id="smsContent">
+            <div class="wrap-input100 validate-input m-b-10" data-validate="璇疯緭鍏ユ墜鏈哄彿">
+              <input id="phone" class="input100" type="text" name="phone" placeholder="鎵嬫満鍙�" autocomplete="off">
+              <span class="focus-input100"></span>
+              <span class="symbol-input100">
+              <i class="fa fa-user"></i>
+            </span>
+            </div>
+            <div style="display: flex;justify-content: center;align-items: center;">
+              <div class="wrap-input100 validate-input m-b-10" style="width: 60%" data-validate="璇疯緭鍏ラ獙璇佺爜">
+                <input id="code" class="input100" type="text" name="code" placeholder="楠岃瘉鐮�">
+                <span class="focus-input100"></span>
+                <span class="symbol-input100">
+                <i class="fa fa-lock"></i>
+              </span>
+              </div>
+              <div style="width: 20%;">
+                <div id="getCodeBox"><button onclick="getCode()">鑾峰彇楠岃瘉鐮�</button></div>
+                <div id="getCodeTime"></div>
+              </div>
+            </div>
+            <div style="text-align: right;">
+              <button onclick="switchLogin('password')">瀵嗙爜鐧诲綍</button>
+            </div>
+            <div class="container-login100-form-btn p-t-10">
+              <button id="smsLogin" class="login100-form-btn login-btn">Login</button>
+            </div>
           </div>
         </div>
       </div>
@@ -106,7 +139,7 @@
       console.log('%c CRM %c 1.0.0','background-color:rgb(53,73,94);color: #fff;border-radius:2px 0 0 2px;padding:2px 4px;','background-color:rgb(25,190,107);color: #fff;border-radius:0 2px 2px 0;padding:2px 4px;font: 9pt "Apercu Regular", Georgia, "Times New Roman", Times, serif;');
       window.onload = function(){document.getElementById("username").focus();}
 
-      $(document).on('click','.login-btn', function () {
+      $(document).on('click','#passLogin', function () {
         let username = $("#username").val();
         if (username === "") {
           layer.tips('璇疯緭鍏ョ櫥褰曡处鍙�', '#username', {tips: [4, '#ff0000']});
@@ -136,7 +169,41 @@
             } else if (res.code === 10003) {
               layer.tips(res.msg, '#password', {tips: [4, '#ff0000']});
             } else {
-              layer.tips(res.msg, '.login-btn', {tips: [3, '#ff0000']});
+              layer.tips(res.msg, '#passLogin', {tips: [3, '#ff0000']});
+            }
+          }
+        });
+      });
+
+      $(document).on('click','#smsLogin', function () {
+        let phone = $("#phone").val();
+        if (phone === "") {
+          layer.tips('璇疯緭鍏ユ墜鏈哄彿', '#phone', {tips: [4, '#ff0000']});
+          return;
+        }
+        let code = $("#code").val();
+        if (code === "") {
+          layer.tips('璇疯緭鍏ラ獙璇佺爜', '#code', {tips: [4, '#ff0000']});
+          return;
+        }
+        $.ajax({
+          url: baseUrl+"/smsLogin.action",
+          data: {
+            phone: phone,
+            code: code
+          },
+          method: 'POST',
+          success: function (res) {
+            if (res.code === 200){
+              localStorage.setItem("token", res.data.token);
+              localStorage.setItem("nickname", res.data.nickname);
+              window.location.href = "index.html";
+            } else if (res.code === 10001) {
+              layer.tips(res.msg, '#phone', {tips: [4, '#ff0000']});
+            } else if (res.code === 10002) {
+              layer.tips(res.msg, '#phone', {tips: [4, '#ff0000']});
+            } else {
+              layer.tips(res.msg, '#smsLogin', {tips: [3, '#ff0000']});
             }
           }
         });
@@ -147,6 +214,55 @@
           $(".login-btn").click();
         }
       });
+
+      function switchLogin(type) {
+        if(type === 'sms'){
+          //鐭俊鐧诲綍
+          $("#passwdContent").hide()
+          $("#smsContent").show()
+        }else {
+          //瀵嗙爜鐧诲綍
+          $("#passwdContent").show()
+          $("#smsContent").hide()
+        }
+      }
+
+      function getCode() {
+        //鑾峰彇楠岃瘉鐮�
+        let phone = $("#phone").val();
+        if (phone === "") {
+          layer.tips('璇疯緭鍏ユ墜鏈哄彿', '#phone', {tips: [4, '#ff0000']});
+          return;
+        }
+
+        $.ajax({
+          url: baseUrl+"/smsCode/sendCode",
+          data: {
+            phone: phone
+          },
+          method: 'POST',
+          success: function (res) {
+            if (res.code === 200){
+              $("#getCodeBox").hide()
+              $("#getCodeTime").show()
+              let tmp = null;
+              let time = 60
+              tmp = setInterval(() => {
+                if (time <= 0) {
+                  $("#getCodeTime").hide()
+                  $("#getCodeBox").show()
+                  clearInterval(tmp)
+                }else {
+                  $("#getCodeTime").text(time + "绉�")
+                  time--;
+                }
+              },1000)
+            } else {
+              layer.tips(res.msg, '#getCodeBox', {tips: [3, '#ff0000']});
+            }
+          }
+        });
+      }
     </script>
   </body>
 </html>

--
Gitblit v1.9.1