1:个人如何使用阿里云短信服务?
2022如何使用个人阿里云短信服务?_linxiMY的博客-CSDN博客添加完成之后,等待审核!一般2个小时就会出来审核结果了,这里我因为注册申请时填写规则有误,足足审核了7次才通过!点击进来以后,按照要求填写:因为一个账号只能选购一种,所以我这里就没法仔细演示了。然后点击添加即可,一把2-3个小时就可以申请出结果了。ConstantPropertiesUtils 工具类。点击登录阿里云短信服务控制台--->点击。3:创建一个SpringBoot 启动类。将下面的服务地址改为自己对应的地址。AccessKey 保存下来!4:添加一个配置工具类类。开启启动类调接口测试。https://blog.csdn.net/XikYu/article/details/127617049?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168232320316800192242795%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=168232320316800192242795&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-127617049-null-null.blog_rank_default&utm_term=%E9%98%BF%E9%87%8C%E4%BA%91&spm=1018.2226.3001.4450
2:直接上代码
2.1:建表SQL
CREATE TABLE `sys_user`
(
`id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'id',
`username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
`password` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密码',
`nickname` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '昵称',
`email` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '邮箱',
`phone` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '电话',
`address` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '地址',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`avatarUrl` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '头像',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
2.2:后端代码
引入pom.xml 依 赖:
<dependencies>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
</dependencies>
yml 文件:
server:
port: 9999
spring:
application:
name: demo-end
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/数据库?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
redis:
host: ip地址
port: 6379
lettuce:
pool:
max-active: 8 # ????
max-idle: 8 # ??????
min-idle: 0 # ??????
max-wait: 100ms # ??????
mybatis:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.xi.demoend.entity
application.properties:
aliyun.sms.regionId=default
aliyun.sms.accessKeyId=LTAI5tBP98NtTK3gC5mgRQBz
aliyun.sms.secret=gH1w8F0jEWVXSiClmAAnowRw93YTFg
common公共包下的类:
全局统一返回结果:
package com.xialj.demoend.common;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @Author
* @Date Created in 2023/2/23 17:25
* @DESCRIPTION: 全局统一返回结果
* @Version V1.0
*/
@Data
@ApiModel(value = "全局统一返回结果")
@SuppressWarnings("all")
public class Result<T> {
@ApiModelProperty(value = "返回码")
private Integer code;
@ApiModelProperty(value = "返回消息")
private String message;
@ApiModelProperty(value = "返回数据")
private T data;
private Long total;
public Result(){}
protected static <T> Result<T> build(T data) {
Result<T> result = new Result<T>();
if (data != null)
result.setData(data);
return result;
}
public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
Result<T> result = build(body);
result.setCode(resultCodeEnum.getCode());
result.setMessage(resultCodeEnum.getMessage());
return result;
}
public static <T> Result<T> build(Integer code, String message) {
Result<T> result = build(null);
result.setCode(code);
result.setMessage(message);
return result;
}
public static<T> Result<T> ok(){
return Result.ok(null);
}
/**
* 操作成功
* @param data
* @param <T>
* @return
*/
public static<T> Result<T> ok(T data){
Result<T> result = build(data);
return build(data, ResultCodeEnum.SUCCESS);
}
public static<T> Result<T> fail(){
return Result.fail(null);
}
/**
* 操作失败
* @param data
* @param <T>
* @return
*/
public static<T> Result<T> fail(T data){
Result<T> result = build(data);
return build(data, ResultCodeEnum.FAIL);
}
public Result<T> message(String msg){
this.setMessage(msg);
return this;
}
public Result<T> code(Integer code){
this.setCode(code);
return this;
}
public boolean isOk() {
if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
return true;
}
return false;
}
}
统一返回结果状态信息类:
package com.xialj.demoend.common;
import lombok.Getter;
/**
* @Author
* @Date Created in 2023/2/23 17:25
* @DESCRIPTION: 统一返回结果状态信息类
* @Version V1.0
*/
@Getter
@SuppressWarnings("all")
public enum ResultCodeEnum {
SUCCESS(200,"成功"),
FAIL(201, "失败"),
PARAM_ERROR( 202, "参数不正确"),
SERVICE_ERROR(203, "服务异常"),
DATA_ERROR(204, "数据异常"),
DATA_UPDATE_ERROR(205, "数据版本异常"),
LOGIN_AUTH(208, "未登陆"),
PERMISSION(209, "没有权限"),
CODE_ERROR(210, "验证码错误"),
// LOGIN_MOBLE_ERROR(211, "账号不正确"),
LOGIN_DISABLED_ERROR(212, "改用户已被禁用"),
REGISTER_MOBLE_ERROR(213, "手机号码格式不正确"),
REGISTER_MOBLE_ERROR_NULL(214, "手机号码为空"),
LOGIN_AURH(214, "需要登录"),
LOGIN_ACL(215, "没有权限"),
URL_ENCODE_ERROR( 216, "URL编码失败"),
ILLEGAL_CALLBACK_REQUEST_ERROR( 217, "非法回调请求"),
FETCH_ACCESSTOKEN_FAILD( 218, "获取accessToken失败"),
FETCH_USERINFO_ERROR( 219, "获取用户信息失败"),
//LOGIN_ERROR( 23005, "登录失败"),
PAY_RUN(220, "支付中"),
CANCEL_ORDER_FAIL(225, "取消订单失败"),
CANCEL_ORDER_NO(225, "不能取消预约"),
HOSCODE_EXIST(230, "医院编号已经存在"),
NUMBER_NO(240, "可预约号不足"),
TIME_NO(250, "当前时间不可以预约"),
SIGN_ERROR(300, "签名错误"),
HOSPITAL_OPEN(310, "医院未开通,暂时不能访问"),
HOSPITAL_LOCK(320, "医院被锁定,暂时不能访问"),
HOSPITAL_LOCKKEY(330,"医院对应key不一致")
;
private Integer code;
private String message;
private ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}
untils包下的工具类:
ConstantPropertiesUtils 用来读取 application.properties文件中的配置
package com.xialj.demoend.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Author
* @Date Created in 2023/2/23 17:25
* @DESCRIPTION:
* @Version V1.0
*/
@Component
public class ConstantPropertiesUtils implements InitializingBean {
//InitializingBean 初始化bean 让spring 容器一初始化就加载
@Value("${aliyun.sms.regionId}")
private String regionId;
@Value("${aliyun.sms.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.sms.secret}")
private String secret;
public static String REGION_Id;
public static String ACCESS_KEY_ID;
public static String SECRECT;
@Override
public void afterPropertiesSet() throws Exception {
REGION_Id=regionId;
ACCESS_KEY_ID=accessKeyId;
SECRECT=secret;
}
}
RandomUtil 工具类用来生成6位验证码:
package com.xialj.demoend.utils;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
/**
* @Author
* @Date Created in 2023/2/23 17:25
* @DESCRIPTION:
* @Version V1.0
*/
@SuppressWarnings("ALL")
public class RandomUtil {
private static final Random random = new Random();
private static final DecimalFormat fourdf = new DecimalFormat("0000");
private static final DecimalFormat sixdf = new DecimalFormat("000000");
public static String getFourBitRandom() {
return fourdf.format(random.nextInt(10000));
}
public static String getSixBitRandom() {
return sixdf.format(random.nextInt(1000000));
}
/**
* 给定数组,抽取n个数据
* @param list
* @param n
* @return
*/
public static ArrayList getRandom(List list, int n) {
Random random = new Random();
HashMap<Object, Object> hashMap = new HashMap<Object, Object>();
// 生成随机数字并存入HashMap
for (int i = 0; i < list.size(); i++) {
int number = random.nextInt(100) + 1;
hashMap.put(number, i);
}
// 从HashMap导入数组
Object[] robjs = hashMap.values().toArray();
ArrayList r = new ArrayList();
// 遍历数组并打印数据
for (int i = 0; i < n; i++) {
r.add(list.get((int) robjs[i]));
System.out.print(list.get((int) robjs[i]) + "\t");
}
System.out.print("\n");
return r;
}
}
User实体类:(实现了简单的手机验证码登录+email邮箱登录)
package com.xialj.demoend.entity;
import com.alibaba.druid.sql.visitor.functions.Insert;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author
* @Date Created in 2023/2/24 13:07
* @DESCRIPTION: User 实体类
* @Version V1.0
*/
@Data
public class User extends PageQuery implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
private String id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 昵称
*/
private String nickname;
/**
* 邮箱
*/
@ApiModelProperty(value = "联系人邮箱")
@NotBlank(message = "邮箱不能为空", groups = {Insert.class})
@NotNull(message = "邮箱不能为空", groups = {Insert.class})
@Pattern(regexp = ".+@.+\\.com$", message = "Email格式不正确")
private String email;
/**
* 电话
*/
@ApiModelProperty(value = "联系人电话")
@NotBlank(message = "手机号码不能为空", groups = {Insert.class})
@NotNull(message = "手机号不能为空", groups = {Insert.class})
@Length(min = 11, max = 11, message = "手机号只能为11位")
@Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
private String phone;
/**
* 地址
*/
private String address;
/**
* 验证码
*/
private Integer code;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date createTime;
/**
* 头像
*/
private String avatarUrl;
}
MsmApiController:用来实现发送验证码的接口
package com.xialj.demoend.controller;
import cn.hutool.extra.mail.MailUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xialj.demoend.common.Result;
import com.xialj.demoend.common.ResultCodeEnum;
import com.xialj.demoend.common.paramCommon;
import com.xialj.demoend.entity.User;
import com.xialj.demoend.service.MsmService;
import com.xialj.demoend.utils.JsonSerializer;
import com.xialj.demoend.utils.RandomUtil;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.mail.MessagingException;
import javax.validation.constraints.Email;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @Author xlj
* @Date Created in 2023/2/23 17:25
* @DESCRIPTION: 主要是为了实现邮箱发送验证码,以及手机发送验证码登录
* @Version V1.0
*/
@RestController
@RequestMapping("/api/msm")
@SuppressWarnings("ALL")
@Slf4j
@CrossOrigin
public class MsmApiController {
@Autowired
private MsmService msmService;
@Autowired
private RedisTemplate<String,String> redisTemplate;
//将手机验证码存放到redis 中,并设置过期时间
@ApiOperation(value = "发送手机验证码")
@PostMapping("sendPhoneCode")
public Result sendCode(@RequestBody(required = true) @Validated User user){
String phoneNum = user.getPhone();
// phone 作为redis 中的key, code 作为redis 中的value值
String code = redisTemplate.opsForValue().get(phoneNum);
if (!StringUtils.isEmpty(code)) {
//这里为什么从redis 拿取 验证码 我理解的是 ,因为redis 验证码我们给他设置了时间限制,所以在规定时间内,验证码
//可以多次使用,一旦时间到期之后,我们就需要从新生成6位数的验证码了。
return Result.ok(code);
}
//生成六位验证码
code = RandomUtil.getSixBitRandom();
//调用service 方法,整合阿里云短信服务进行发送
Boolean isSend = msmService.send(phoneNum,code);
//返回的Boolean 值进行判断 ,如果发送信息成功,即存入到redis 中,如果没有则提示验证码发送失败
if (isSend) {
//放到redis中规定时间内有效
redisTemplate.opsForValue().set(phoneNum,code,1, TimeUnit.MINUTES);
redisTemplate.setDefaultSerializer(new JsonSerializer<>());
// redisTemplate.opsForValue().set(phoneNum,code);
String codeMessage = redisTemplate.opsForValue().get(phoneNum);
Set<String> allKeys = redisTemplate.keys("*");
for (String key : allKeys) {
System.out.println(key);
System.out.println(key.getClass().getName());
}
log.info("当前存储的验证码为:{}",codeMessage);
return Result.ok(code);
} else {
return Result.fail().message(paramCommon.FAIL_MESSAGE);
}
}
}
MsmServiceImpl实现类:
package com.hospital.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.hospital.service.MsmService;
import com.hospital.utils.ConstantPropertiesUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
@Service
public class MsmServiceImpl implements MsmService {
//根据手机号,存入验证码
@Override
public Boolean send(String phone, String code) {
//判断手机号是否为空
if (StringUtils.isEmpty(phone)) {
return false;
}
//整合阿里云的短信服务
DefaultProfile profile = DefaultProfile.
getProfile(ConstantPropertiesUtils.REGION_Id,
ConstantPropertiesUtils.ACCESS_KEY_ID,
ConstantPropertiesUtils.SECRECT);
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
//request.setProtocol(ProtocolType.HTTPS);
request.setMethod(MethodType.POST);
request.setDomain("dysmsapi.aliyuncs.com");
request.setVersion("2017-05-25");
request.setAction("SendSms");
// request.setSysAction();
//手机号
request.putQueryParameter("PhoneNumbers", phone);
//签名名称
request.putQueryParameter("SignName", "自己申请的短信签名");
//模板code
request.putQueryParameter("TemplateCode", "短信模板CODE");
//验证码 使用json格式 {"code":"123456"}
Map<String,Object> param = new HashMap();
param.put("code",code);
request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param));
//调用方法进行短信发送
try {
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
return response.getHttpResponse().isSuccess();
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
return false;
}
}
LoginController登录接口:(通过@Validated 对手机号,邮箱等参数进行校验)
package com.xialj.demoend.controller;
import cn.hutool.core.util.StrUtil;
import com.xialj.demoend.common.Result;
import com.xialj.demoend.entity.User;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.Optional;
import java.util.function.Supplier;
/**
* @Author
* @Date Created in 2023/3/18 14:30
* @DESCRIPTION:
* @Version V1.0
*/
@RestController
@RequestMapping("/user/login")
@Slf4j
@CrossOrigin
public class LoginController {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@ApiOperation("手机验证码登录接口")
@PostMapping("/phoneCode")
@SuppressWarnings("all")
public Result phoneCodeLogin(@RequestBody @Validated User user) throws Throwable {
Optional.ofNullable(user.getPhone()).orElseThrow((Supplier<Throwable>) () -> new RuntimeException("手机号码为null"));
String phone = user.getPhone();
log.info("当前获取的手机号为:{}",phone);
//从redis中获取手机验证码
String userPhoneKey = redisTemplate.opsForValue().get(phone);
if (StringUtils.isEmpty(userPhoneKey)) {
return Result.fail("手机验证码有误");
}
if (!userPhoneKey.equals(String.valueOf(user.getCode()))) {
return Result.fail("手机验证码有误");
}
return Result.ok("登录成功");
}
}
前端vue代码:
<template>
<div class="cont1" id="mainContainer" v-title data-title="若梦管理系统">
<p class="tip">Click on button in image container</p>
<div class="cont" style="border-radius: 15px">
<div class="form sign-in" style="line-height: 50px;">
<h2 style="margin-top: 1px">后台管理系统</h2>
<el-form ref="elForm" :model="formData" :rules="rules" size="medium" label-width="100px">
<el-form-item label="手机号" prop="phone" style="width: 50%;margin-left: 110px;margin-top: 80px">
<el-input v-model.number="formData.phone" placeholder="请输入手机号" :maxlength="11" show-word-limit
clearable
prefix-icon='el-icon-mobile-phone' :style="{width: '200px'}"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="yzm" style="width: 50%;margin-left: 110px;margin-top: 50px">
<el-input v-model.number="formData.yzm" :maxlength="6" :minlength="6"
clearable show-word-limit
prefix-icon='el-icon-chat-round'
oninput="value=value.replace(/[^0-9.]/g,'')"
:style="{width: '200px'}">
<template #append >
<el-button class="test" style="width: 5px;
margin-right: 10px;
text-align: center;
background-color: inherit;"
type="danger"
:disabled="remainingTime > 0"
@click="startTimer">
{{ remainingTime > 0 ? '('+remainingTime+'s)' : '获取' }}
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="submitForm('/manage/home')"
class="submit">登录
</el-button>
</el-form-item>
</el-form>
</div>
<div class="sub-cont">
<div class="img">
<div class="img__text m--up">
<h2>第一次来?</h2>
<p>注册并发现大量的新机会!</p>
</div>
<div class="img__text m--in">
<h2>加入我们 ?</h2>
<p>如果你已经有一个账户,只需登录即可 </p>
<span>We've missed you!</span>
</div>
<div class="img__btn">
<span class="m--up">邮箱登录</span>
<span class="m--in">手机登录</span>
</div>
</div>
<div class="form sign-up" style="line-height: 50px">
<h2>Time to feel like home</h2>
<el-form ref="elForm2" :model="formData" :rules="rules2" size="medium" label-width="100px">
<el-form-item label="电子邮箱" prop="email" style="width: 50%;margin-left: 110px;margin-top: 80px">
<el-input v-model="formData.email" placeholder="请输入邮箱" show-word-limit clearable
prefix-icon='el-icon-message' :style="{width: '200px'}"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="yzm2" style="width: 50%;margin-left: 110px;margin-top: 50px">
<el-input v-model.number="formData.yzm2" :maxlength="6" :minlength="6"
clearable show-word-limit
prefix-icon='el-icon-chat-round'
oninput="value=value.replace(/[^0-9.]/g,'')"
:style="{width: '200px'}">
<template #append >
<el-button class="test" style="width: 5px;
margin-right: 10px;
text-align: center;
background-color: inherit;"
type="danger"
:disabled="remainingTime > 0"
@click="startTimer2">
{{ remainingTime > 0 ? '('+remainingTime+'s)' : '获取' }}
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading2" @click="submitForm2('/manage/home')"
class="submit">登录
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</div>
</template>
<script>
import {sendPhoneCode, sendEmailCode,phoneLogin,emailLogin} from "@/api/login.js";
export default {
name: 'login',
props: {
msg: String
},
data() {
return {
remainingTime: 0,
loading: false,
loading2:false,
timer: null,
formData: {
pwd: '',
phone: '',
email: '',
yzm: '',
yzm2: ''
},
rules: {
phone: [{
required: true,
message: '请输入手机号',
trigger: 'change'
}, {
pattern: /^1(3|4|5|7|8|9)\d{9}$/,
message: '手机号格式错误',
trigger: 'blur'
}],
yzm: [
{required: true, message: '验证码不能为空', trigger: 'change'},
// {type: 'number', message: '验证码必须为数字', trigger: ['blur', 'change']}
],
},
rules2: {
email: [
{required: true, message: '请输入邮箱地址', trigger: 'change'},
{type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change']}
],
yzm2: [
{required: true, message: '验证码不能为空', trigger: 'change'},
// {type: 'number', message: '验证码必须为数字', trigger: ['blur', 'change']}
]
},
}
},
methods: {
//手机号登录
submitForm(path) {
this.$refs['elForm'].validate(valid => {
if (!valid) return
// 显示loading 加载效果
this.loading = true;
const user = {
phone:this.formData.phone,
code: this.formData.yzm
}
this.timer = setTimeout(() => {
phoneLogin(user).then( res=>{
if (res.code == 200){
this.$message({
type: 'success',
message: '登录成功!'
})
// 处理业务逻辑 以及发送请求
this.$router.push(path)
}else {
this.$message({
type: 'error',
message: '登录失败!'
});
}
}).finally((
this.loading = false
));
}, 1000);
})
},
//邮箱登录
submitForm2(path) {
this.$refs['elForm2'].validate(valid => {
if (!valid) return
// TODO 提交表单
// 显示loading 加载效果
this.loading2 = true;
const user = {
email:this.formData.email,
code: this.formData.yzm2
}
this.timer = setTimeout(() => {
// 处理业务逻辑 以及发送请求
emailLogin(user).then(res=>{
console.log(res)
if (res.code == 200){
this.$message({
type: 'success',
message: '登录成功!'
})
// 处理业务逻辑 以及发送请求
this.$router.push(path)
}else {
this.$message({
type:'error',
message: '登录失败!'
})
}
}).finally((
this.loading2 = false
));
}, 1000);
})
},
//发送手机验证码
sendCode() {
// TODO 提交表单
let user ={phone:this.formData.phone}
console.log(user)
sendPhoneCode(user).then(res => {
if (res.code == 200) {
this.$message({
type: 'success',
message: '验证码发送成功!'
})
} else {
this.$message({
type: 'warning',
message: '验证码发送失败!'
});
}
})
},
startTimer() {
this.$refs['elForm'].validateField('phone', valid => {
if (valid) return
// TODO 提交表单
this.remainingTime = 60;
this.sendCode()
const timer = setInterval(() => {
this.remainingTime--;
if (this.remainingTime === 0) {
clearInterval(timer);
}
}, 1000);
})
},
startTimer2() {
this.$refs['elForm2'].validateField('email', valid => {
if (valid) return
// TODO 提交表单
this.remainingTime = 60;
this.sendCodeTwo()
const timer = setInterval(() => {
this.remainingTime--;
if (this.remainingTime === 0) {
clearInterval(timer);
}
}, 1000);
})
},
//发送邮箱验证码
sendCodeTwo() {
// TODO 提交表单
let user ={email:this.formData.email}
console.log(user)
sendEmailCode(user).then(res => {
if (res.code == 200) {
this.$message({
type: 'success',
message: '验证码发送成功!'
})
} else {
this.$message({
type: 'warning',
message: '验证码发送失败!'
});
}
})
},
},
mounted() {
document.querySelector('.img__btn').addEventListener('click', function () {
const contEl = document.querySelector('.cont');
contEl.classList.toggle('s--signup');
contEl.addEventListener('transitionend', function () {
if (contEl.classList.contains('s--signup')) {
contEl.querySelectorAll('input').forEach(inputEl => inputEl.value = '');
}
}, {once: true});
});
},
beforeDestroy() {
// eslint-disable-next-line no-irregular-whitespace
clearInterval(this.timer); // 清除定时器
this.timer = null;
},
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
*, *:before, *:after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
input, button {
border: none;
outline: none;
background: none;
font-family: "Open Sans", Helvetica, Arial, sans-serif;
}
.tip {
font-size: 20px;
margin: 40px auto 50px;
text-align: center;
}
.cont1::before {
content: '';
position: fixed;
background-color: #ededed;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-image: linear-gradient(to bottom right ,#d3dae9,#14c2c2)
}
.cont {
overflow: hidden;
position: relative;
width: 900px;
height: 550px;
margin: 0 auto 100px;
background: #fff;
}
.form {
position: relative;
width: 640px;
height: 100%;
transition: transform 1.2s ease-in-out;
padding: 50px 30px 0;
}
.sub-cont {
overflow: hidden;
position: absolute;
left: 640px;
top: 0;
width: 900px;
height: 100%;
padding-left: 260px;
background: #fff;
transition: transform 1.2s ease-in-out;
}
.cont.s--signup .sub-cont {
transform: translate3d(-640px, 0, 0);
}
button {
display: block;
margin: 0 auto;
width: 260px;
height: 36px;
border-radius: 30px;
color: #fff;
font-size: 15px;
cursor: pointer;
}
.img {
overflow: hidden;
z-index: 2;
position: absolute;
left: 0;
top: 0;
width: 260px;
height: 100%;
padding-top: 360px;
}
.img:before {
content: "";
position: absolute;
right: 0;
top: 0;
width: 900px;
height: 100%;
background-image: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/142996/sections-3.jpg");
background-size: cover;
transition: transform 1.2s ease-in-out;
}
.img:after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
}
.cont.s--signup .img:before {
transform: translate3d(640px, 0, 0);
}
.img__text {
z-index: 2;
position: absolute;
left: 0;
top: 50px;
width: 100%;
padding: 0 20px;
text-align: center;
color: #fff;
transition: transform 1.2s ease-in-out;
}
.img__text h2 {
margin-bottom: 10px;
font-weight: normal;
}
.img__text p {
font-size: 14px;
line-height: 1.5;
}
.cont.s--signup .img__text.m--up {
transform: translateX(520px);
}
.img__text.m--in {
transform: translateX(-520px);
}
.cont.s--signup .img__text.m--in {
transform: translateX(0);
}
.img__btn {
overflow: hidden;
z-index: 2;
position: relative;
width: 100px;
height: 36px;
margin: 0 auto;
background: transparent;
color: #fff;
text-transform: uppercase;
font-size: 15px;
cursor: pointer;
}
.img__btn:after {
content: "";
z-index: 2;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border: 2px solid #fff;
border-radius: 30px;
}
.img__btn span {
position: absolute;
left: 0;
top: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
transition: transform 1.2s;
}
.img__btn span.m--in {
transform: translateY(-72px);
}
.cont.s--signup .img__btn span.m--in {
transform: translateY(0);
}
.cont.s--signup .img__btn span.m--up {
transform: translateY(72px);
}
h2 {
width: 100%;
font-size: 26px;
text-align: center;
}
label {
display: block;
width: 260px;
margin: 25px auto 0;
text-align: center;
}
label span {
font-size: 12px;
color: #cfcfcf;
text-transform: uppercase;
}
input {
display: block;
width: 100%;
margin-top: 5px;
padding-bottom: 5px;
font-size: 16px;
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
text-align: center;
}
.forgot-pass {
margin-top: 15px;
text-align: center;
font-size: 12px;
color: #cfcfcf;
}
.submit {
margin-top: 30px;
margin-left: 50px;
margin-bottom: 10px;
background: #d4af7a;
/*text-transform: uppercase;*/
}
.style2 {
margin-top: 10px;
margin-right: 100px;
margin-bottom: 10px;
background: darkgrey;
text-transform: uppercase;
}
.fb-btn {
border: 2px solid #d3dae9;
color: #8fa1c7;
}
.fb-btn span {
font-weight: bold;
color: #455a81;
}
.sign-in {
transition-timing-function: ease-out;
}
.cont.s--signup .sign-in {
transition-timing-function: ease-in-out;
transition-duration: 1.2s;
transform: translate3d(640px, 0, 0);
}
.sign-up {
transform: translate3d(-900px, 0, 0);
}
.cont.s--signup .sign-up {
transform: translate3d(0, 0, 0);
}
.icon-link {
position: absolute;
left: 5px;
bottom: 5px;
width: 32px;
}
.icon-link img {
width: 100%;
vertical-align: top;
}
.icon-link--twitter {
left: auto;
right: 5px;
}
.test[disabled]:not(.is-loading) {
opacity: 0.5;
cursor: not-allowed;
width: 5px;
margin-right: 10px;
text-align: center;
}
</style>
页面效果图:
手机登录
邮箱登录
短信: