验证码
This commit is contained in:
@@ -122,6 +122,49 @@ namespace Ewide.Core
|
|||||||
[ErrorCodeItemMetadata("账号已冻结")]
|
[ErrorCodeItemMetadata("账号已冻结")]
|
||||||
D1017,
|
D1017,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送验证流程错误
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("发送验证流程错误")]
|
||||||
|
D1018,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 没有可验证方式
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("没有可验证方式")]
|
||||||
|
D1019,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证错误
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("验证错误")]
|
||||||
|
D1020,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 绑定失败
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("绑定失败")]
|
||||||
|
D1021,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证码失效
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("验证码失效")]
|
||||||
|
D1022,
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请不要频繁发送验证码
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("请不要频繁发送验证码")]
|
||||||
|
D1023,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请不要频繁发送验证码
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("验证码发送失败")]
|
||||||
|
D1024,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 父机构不存在
|
/// 父机构不存在
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
31
Api/Ewide.Core/Service/User/Dto/Userphone.cs
Normal file
31
Api/Ewide.Core/Service/User/Dto/Userphone.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ewide.Core.Service
|
||||||
|
{
|
||||||
|
public class Usermailphone
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 绑定的值
|
||||||
|
/// </summary>
|
||||||
|
public string Target { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送验证码类型,1为发送给原邮箱,2为发送给原手机号
|
||||||
|
/// </summary>
|
||||||
|
public int? Type { get; set; }
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// 第一次验证码
|
||||||
|
/// </summary>
|
||||||
|
public int? Orgcode { get; set; }
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// 第二次验证码
|
||||||
|
/// </summary>
|
||||||
|
public int? Code { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,5 +26,8 @@ namespace Ewide.Core.Service
|
|||||||
Task UpdateUser(UpdateUserInput input);
|
Task UpdateUser(UpdateUserInput input);
|
||||||
Task UpdateUserInfo(UserInput input);
|
Task UpdateUserInfo(UserInput input);
|
||||||
Task UpdateUserPwd(ChangePasswordUserInput input);
|
Task UpdateUserPwd(ChangePasswordUserInput input);
|
||||||
|
|
||||||
|
Task<dynamic> SendCode(Usermailphone input);
|
||||||
|
Task<dynamic> CheckBindcode(Usermailphone input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Ewide.Core.Service.Role;
|
using Ewide.Core.Service.Role;
|
||||||
|
using Ewide.Core.Util;
|
||||||
using Furion.DatabaseAccessor;
|
using Furion.DatabaseAccessor;
|
||||||
using Furion.DatabaseAccessor.Extensions;
|
using Furion.DatabaseAccessor.Extensions;
|
||||||
using Furion.DataEncryption;
|
using Furion.DataEncryption;
|
||||||
@@ -8,9 +9,11 @@ using Furion.FriendlyException;
|
|||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ewide.Core.Service
|
namespace Ewide.Core.Service
|
||||||
@@ -23,15 +26,16 @@ namespace Ewide.Core.Service
|
|||||||
{
|
{
|
||||||
private readonly IRepository<SysUser> _sysUserRep; // 用户表仓储
|
private readonly IRepository<SysUser> _sysUserRep; // 用户表仓储
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
|
|
||||||
private readonly ISysCacheService _sysCacheService;
|
private readonly ISysCacheService _sysCacheService;
|
||||||
private readonly ISysEmpService _sysEmpService;
|
private readonly ISysEmpService _sysEmpService;
|
||||||
|
private readonly IMemoryCache _iMemoryCache;
|
||||||
private readonly ISysUserDataScopeService _sysUserDataScopeService;
|
private readonly ISysUserDataScopeService _sysUserDataScopeService;
|
||||||
private readonly ISysUserRoleService _sysUserRoleService;
|
private readonly ISysUserRoleService _sysUserRoleService;
|
||||||
private readonly ISysUserAreaService _sysUserAreaService;
|
private readonly ISysUserAreaService _sysUserAreaService;
|
||||||
|
|
||||||
public SysUserService(IRepository<SysUser> sysUserRep,
|
public SysUserService(IRepository<SysUser> sysUserRep,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
|
IMemoryCache memoryCache,
|
||||||
ISysCacheService sysCacheService,
|
ISysCacheService sysCacheService,
|
||||||
ISysEmpService sysEmpService,
|
ISysEmpService sysEmpService,
|
||||||
ISysUserDataScopeService sysUserDataScopeService,
|
ISysUserDataScopeService sysUserDataScopeService,
|
||||||
@@ -40,6 +44,7 @@ namespace Ewide.Core.Service
|
|||||||
{
|
{
|
||||||
_sysUserRep = sysUserRep;
|
_sysUserRep = sysUserRep;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
_iMemoryCache = memoryCache;
|
||||||
_sysCacheService = sysCacheService;
|
_sysCacheService = sysCacheService;
|
||||||
_sysEmpService = sysEmpService;
|
_sysEmpService = sysEmpService;
|
||||||
_sysUserDataScopeService = sysUserDataScopeService;
|
_sysUserDataScopeService = sysUserDataScopeService;
|
||||||
@@ -448,5 +453,204 @@ namespace Ewide.Core.Service
|
|||||||
throw Oops.Oh(ErrorCode.D1013);
|
throw Oops.Oh(ErrorCode.D1013);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///发送验证码
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("/sysUser/SendCode")]
|
||||||
|
public async Task<dynamic> SendCode(Usermailphone input)
|
||||||
|
{
|
||||||
|
var Orgcode_Key = "ewide_Orgcode";
|
||||||
|
var Smscode_Key = "ewide_smscode";
|
||||||
|
var Mailcode_Key = "ewide_mailcode";
|
||||||
|
var Regex_phone = @"^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$";
|
||||||
|
var Regex_Email = @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$";
|
||||||
|
CodeHelper ch = new CodeHelper(_iMemoryCache);
|
||||||
|
//Type为1时,给原手机号发送验证码
|
||||||
|
if(input.Type == 1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ch.SendSmscode(_userManager.User.Phone, Orgcode_Key);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw Oops.Oh(ErrorCode.D1018);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//Type为2时,给原邮箱发送验证码
|
||||||
|
else if(input.Type == 2)
|
||||||
|
{
|
||||||
|
if(new Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$").IsMatch(_userManager.User.Email))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ch.SendMail(_userManager.User.Email, Orgcode_Key);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw Oops.Oh(ErrorCode.D1018);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Oops.Oh("原邮箱错误");
|
||||||
|
}
|
||||||
|
//Type为null时,则发验证码
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//通过正则判断绑定类型
|
||||||
|
if(new Regex(Regex_phone).IsMatch(input.Target))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
ch.SendSmscode(input.Target, Smscode_Key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
throw Oops.Oh(ErrorCode.D1018);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(new Regex(Regex_Email).IsMatch(input.Target))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ch.SendMail(input.Target, Mailcode_Key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw Oops.Oh(ErrorCode.D1018);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Oops.Oh("格式错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///检验验证码并且绑定
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("/sysUser/CheckBindcode")]
|
||||||
|
public async Task<dynamic> CheckBindcode(Usermailphone input)
|
||||||
|
{
|
||||||
|
var Orgcode_Key = "ewide_Orgcode";
|
||||||
|
var Smscode_Key = "ewide_smscode";
|
||||||
|
var Mailcode_Key = "ewide_mailcode";
|
||||||
|
var Regex_phone = @"^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$";
|
||||||
|
var Regex_Email = @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$";
|
||||||
|
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == _userManager.UserId);
|
||||||
|
CodeHelper ch = new CodeHelper(_iMemoryCache);
|
||||||
|
if(input.Type == 1)
|
||||||
|
{
|
||||||
|
if (ch.Checkcode(_userManager.User.Phone, input.Orgcode, Orgcode_Key))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
throw Oops.Oh("验证错误");
|
||||||
|
}
|
||||||
|
else if(input.Type == 2)
|
||||||
|
{
|
||||||
|
if(ch.Checkcode(_userManager.User.Email, input.Orgcode, Orgcode_Key))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
throw Oops.Oh("验证错误");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//为第一次绑定
|
||||||
|
if(string.IsNullOrEmpty(_userManager.User.Phone) && string.IsNullOrEmpty(_userManager.User.Email))
|
||||||
|
{
|
||||||
|
if(new Regex(Regex_phone).IsMatch(input.Target))
|
||||||
|
{
|
||||||
|
if (ch.Checkcode(input.Target,input.Code, Smscode_Key))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
user.Phone = input.Target;
|
||||||
|
await user.UpdateIncludeNowAsync(new string[] {
|
||||||
|
nameof(SysUser.Phone)
|
||||||
|
}, true);
|
||||||
|
return "手机绑定成功";
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw Oops.Oh("手机绑定错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Oops.Oh("验证码失效");
|
||||||
|
}
|
||||||
|
if(new Regex(Regex_Email).IsMatch(input.Target))
|
||||||
|
{
|
||||||
|
if (ch.Checkcode(input.Target, input.Code, Mailcode_Key))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
user.Email = input.Target;
|
||||||
|
await user.UpdateIncludeNowAsync(new string[] {
|
||||||
|
nameof(SysUser.Email)
|
||||||
|
}, true);
|
||||||
|
return "邮箱绑定成功";
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw Oops.Oh("邮箱绑定错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Oops.Oh("验证码失效");
|
||||||
|
}
|
||||||
|
throw Oops.Oh("号码格式不对");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool CheckOrgPhone = ch.Checkcode(_userManager.User.Phone, input.Orgcode, Orgcode_Key);
|
||||||
|
bool CheckOrgEmail = ch.Checkcode(_userManager.User.Email, input.Orgcode, Orgcode_Key);
|
||||||
|
if (CheckOrgPhone || CheckOrgEmail)
|
||||||
|
{
|
||||||
|
if (new Regex(Regex_phone).IsMatch(input.Target))
|
||||||
|
{
|
||||||
|
if (ch.Checkcode(input.Target, input.Code, Smscode_Key))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
user.Phone = input.Target;
|
||||||
|
await user.UpdateIncludeNowAsync(new string[] {
|
||||||
|
nameof(SysUser.Phone)
|
||||||
|
}, true);
|
||||||
|
return "手机改绑成功";
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw Oops.Oh("手机绑定错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Oops.Oh("验证码失效");
|
||||||
|
}
|
||||||
|
if (new Regex(Regex_Email).IsMatch(input.Target))
|
||||||
|
{
|
||||||
|
if (ch.Checkcode(input.Target, input.Code, Mailcode_Key))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
user.Email = input.Target;
|
||||||
|
await user.UpdateIncludeNowAsync(new string[] {
|
||||||
|
nameof(SysUser.Email)
|
||||||
|
}, true);
|
||||||
|
return "邮箱改绑成功";
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw Oops.Oh("邮箱绑定错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Oops.Oh("验证码失效");
|
||||||
|
}
|
||||||
|
throw Oops.Oh("号码格式不对");
|
||||||
|
}
|
||||||
|
throw Oops.Oh("验证码失效");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
252
Api/Ewide.Core/Util/CodeHelper.cs
Normal file
252
Api/Ewide.Core/Util/CodeHelper.cs
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
using Aliyun.Acs.Core;
|
||||||
|
using Aliyun.Acs.Core.Exceptions;
|
||||||
|
using Aliyun.Acs.Core.Profile;
|
||||||
|
using Furion;
|
||||||
|
using Furion.FriendlyException;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Mail;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ewide.Core.Util
|
||||||
|
{
|
||||||
|
public class CodeHelper
|
||||||
|
{
|
||||||
|
private readonly IMemoryCache _IMemoryCache;
|
||||||
|
public CodeHelper(IMemoryCache IMemoryCache)
|
||||||
|
{
|
||||||
|
_IMemoryCache = IMemoryCache;
|
||||||
|
}
|
||||||
|
public static string Aliyun_AccessKey = App.Configuration["SmsHelper:Aliyun_AccessKey"];
|
||||||
|
public static string Aliyun_AccessSecret = App.Configuration["SmsHelper:Aliyun_AccessSecret"];
|
||||||
|
public static string Aliyun_Smscode_SignName = App.Configuration["SmsHelper:Aliyun_Smscode_SignName"];
|
||||||
|
public static string Aliyun_Smscode_TemplateCode = App.Configuration["SmsHelper:Aliyun_Smscode_TemplateCode"];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送验证码间隔时间(秒)
|
||||||
|
/// </summary>
|
||||||
|
protected static int code_Countdown = 60;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证code
|
||||||
|
/// </summary>
|
||||||
|
protected static string Orgcode_Key = "ewide_Orgcode";
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///邮箱Code
|
||||||
|
/// </summary>
|
||||||
|
protected static string mailcode_Key = "ewide_mailcode";
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///手机Code
|
||||||
|
/// </summary>
|
||||||
|
protected static string smscode_Key = "ewide_smscode";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将code存入缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="way">验证方式</param>
|
||||||
|
/// <param name="code">验证码</param>
|
||||||
|
/// <param name="type">code的类型</param>
|
||||||
|
public void Updatecode(string num, int code, string way)
|
||||||
|
{
|
||||||
|
|
||||||
|
var ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||||
|
_IMemoryCache.Set(
|
||||||
|
way + "_" + num, // code的类型_手机或者邮箱号码
|
||||||
|
code + "_" + (int)ts.TotalSeconds, // 1234567_TimeStamp
|
||||||
|
DateTime.UtcNow.AddMinutes(5)// 5分钟过期
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否含有code
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="way"></param>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool Checkcode(string Target, int? code,string Key)
|
||||||
|
{
|
||||||
|
var cache = (string)_IMemoryCache.Get(Key + "_" + Target);// 获取匹配类型的code值
|
||||||
|
if (string.IsNullOrEmpty(cache))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return code == cache.Split('_').Select(p => int.Parse(p)).First();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否含有code
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="way"></param>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool Checkhavecode(string num, string way)
|
||||||
|
{
|
||||||
|
var cache = (string)_IMemoryCache.Get(way + "_" + num);// 获取匹配类型的code值
|
||||||
|
if (string.IsNullOrEmpty(cache))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除相应缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="way"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
public void removecode(string way, string num){
|
||||||
|
_IMemoryCache.Remove(way + "_" + num);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// code60秒才可再次发送
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="way">验证类型</param>
|
||||||
|
/// <param name="num">值</param>
|
||||||
|
/// <param name="coundown"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IscodeCountdown(string way, string num, int coundown = 60)
|
||||||
|
{
|
||||||
|
return GetSmscodeCountdown(way, num) < coundown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送验证码倒计时
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int GetSmscodeCountdown(string way,string num)
|
||||||
|
{
|
||||||
|
var cache = (string)_IMemoryCache.Get(way + "_" + num);
|
||||||
|
if (String.IsNullOrEmpty(cache))
|
||||||
|
{
|
||||||
|
return code_Countdown;
|
||||||
|
}
|
||||||
|
var ts = cache.Split('_').Select(p => int.Parse(p)).Last();
|
||||||
|
var nowTs = (int)(DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds;
|
||||||
|
return nowTs - ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// 发送手机验证码
|
||||||
|
///</summary>
|
||||||
|
public bool SendSmscode(string mobile, string way ,int length = 6)
|
||||||
|
{
|
||||||
|
if (!new Regex(@"^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$").IsMatch(mobile))
|
||||||
|
{
|
||||||
|
throw Oops.Oh(ErrorCode.D1011);
|
||||||
|
}
|
||||||
|
//if (IscodeCountdown(way, mobile, code_Countdown))
|
||||||
|
//{
|
||||||
|
// throw Oops.Oh(ErrorCode.D1023);
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
IClientProfile profile = DefaultProfile.GetProfile("cn-hangzhou", Aliyun_AccessKey, Aliyun_AccessSecret);
|
||||||
|
DefaultAcsClient client = new DefaultAcsClient(profile);
|
||||||
|
CommonRequest request = new CommonRequest
|
||||||
|
{
|
||||||
|
Method = Aliyun.Acs.Core.Http.MethodType.POST,
|
||||||
|
Domain = "dysmsapi.aliyuncs.com",
|
||||||
|
Version = "2017-05-25",
|
||||||
|
Action = "SendSms"
|
||||||
|
};
|
||||||
|
request.AddQueryParameters("PhoneNumbers", mobile);
|
||||||
|
request.AddQueryParameters("SignName", Aliyun_Smscode_SignName);
|
||||||
|
request.AddQueryParameters("TemplateCode", Aliyun_Smscode_TemplateCode);
|
||||||
|
|
||||||
|
var minValue = Convert.ToInt32("1".PadRight(length, '0'));
|
||||||
|
var maxValue = Convert.ToInt32("1".PadRight(length + 1, '0'));
|
||||||
|
var code = new Random().Next(minValue, maxValue);
|
||||||
|
var param = new { code };
|
||||||
|
request.AddQueryParameters("TemplateParam", JsonConvert.SerializeObject(param));
|
||||||
|
Updatecode(mobile, code,way);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CommonResponse response = client.GetCommonResponse(request);
|
||||||
|
var msg = System.Text.Encoding.UTF8.GetString(response.HttpResponse.Content);
|
||||||
|
var result = JsonConvert.DeserializeObject(msg);
|
||||||
|
var j = (JObject)result;
|
||||||
|
if(!"OK".Equals(j["Code"].ToString(), StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
throw Oops.Oh("请不要频繁发送");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ServerException e)
|
||||||
|
{
|
||||||
|
throw Oops.Oh(ErrorCode.D1024);
|
||||||
|
}catch(Exception e)
|
||||||
|
{
|
||||||
|
throw Oops.Oh("访问异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送邮箱
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mail"></param>
|
||||||
|
/// <param name="length"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool SendMail(string mail, string way,int length = 6)
|
||||||
|
{
|
||||||
|
if (!new Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$").IsMatch(mail))
|
||||||
|
{
|
||||||
|
throw Oops.Oh("格式不对");
|
||||||
|
}
|
||||||
|
if (IscodeCountdown(mail, way, code_Countdown))
|
||||||
|
{
|
||||||
|
throw Oops.Oh("60秒后才能再次发送");
|
||||||
|
|
||||||
|
}
|
||||||
|
string account = App.Configuration["Mail:Account"];
|
||||||
|
string passWord = App.Configuration["Mail:PassWord"];
|
||||||
|
//var options = Options.Create(options: new MemoryCacheOptions());
|
||||||
|
//IMemoryCache cache = new MemoryCache(options);
|
||||||
|
SmtpClient smtpClient = new SmtpClient();
|
||||||
|
smtpClient.EnableSsl = true;
|
||||||
|
smtpClient.UseDefaultCredentials = false;
|
||||||
|
smtpClient.Host = App.Configuration["Mail:Host"];
|
||||||
|
smtpClient.Credentials = new System.Net.NetworkCredential(account, passWord);
|
||||||
|
smtpClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
|
||||||
|
|
||||||
|
MailMessage mailMessage = new MailMessage();
|
||||||
|
MailAddress fromAddr = new MailAddress(account);
|
||||||
|
mailMessage.From = fromAddr;
|
||||||
|
mailMessage.To.Add(mail);
|
||||||
|
mailMessage.Subject = App.Configuration["Mail:Subject"];
|
||||||
|
mailMessage.BodyEncoding = Encoding.UTF8;
|
||||||
|
mailMessage.IsBodyHtml = true;
|
||||||
|
mailMessage.Priority = MailPriority.Low;
|
||||||
|
var minValue = Convert.ToInt32("1".PadRight(length, '0'));
|
||||||
|
var maxValue = Convert.ToInt32("1".PadRight(length + 1, '0'));
|
||||||
|
var code = new Random().Next(minValue, maxValue);
|
||||||
|
var param = new { code };
|
||||||
|
Updatecode(mail, code, way);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var Message = "邮箱验证码为:" + code.ToString();
|
||||||
|
mailMessage.Body = Message;
|
||||||
|
smtpClient.Send(mailMessage);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw Oops.Oh(ErrorCode.xg1100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,4 +73,16 @@ export default {
|
|||||||
* 更新基本信息
|
* 更新基本信息
|
||||||
*/
|
*/
|
||||||
sysUserUpdateInfo: ['/sysUser/updateInfo', 'post'],
|
sysUserUpdateInfo: ['/sysUser/updateInfo', 'post'],
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送验证码
|
||||||
|
*/
|
||||||
|
SendCode: ['/sysUser/SendCode', 'post'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定/验证
|
||||||
|
*/
|
||||||
|
CheckBindcode: ['/sysUser/CheckBindcode', 'post'],
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
const SESSION_KEY = '__SESSION'
|
const SESSION_KEY = '__SESSION'
|
||||||
const SETTING_KEY = '__SETTINGS'
|
const SETTING_KEY = '__SETTINGS'
|
||||||
const GLOBAL_INFO_KEY = '__GLOBAL_INFO'
|
const GLOBAL_INFO_KEY = '__GLOBAL_INFO'
|
||||||
|
const COUNT_DWON_KEY = '__COUNT_DWON'
|
||||||
export {
|
export {
|
||||||
SESSION_KEY,
|
SESSION_KEY,
|
||||||
SETTING_KEY,
|
SETTING_KEY,
|
||||||
GLOBAL_INFO_KEY,
|
GLOBAL_INFO_KEY,
|
||||||
|
COUNT_DWON_KEY
|
||||||
}
|
}
|
||||||
@@ -46,6 +46,9 @@
|
|||||||
>
|
>
|
||||||
<password />
|
<password />
|
||||||
</yo-modal-form>
|
</yo-modal-form>
|
||||||
|
|
||||||
|
<phone @ok="showSafety" ref="phone" />
|
||||||
|
<mail @ok="showSafety" ref="mail" />
|
||||||
</container>
|
</container>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@@ -57,16 +60,19 @@
|
|||||||
background-color: @white;
|
background-color: @white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
import { doLogout } from '@/common/login';
|
import { doLogout } from '@/common/login';
|
||||||
|
|
||||||
import Password from './password';
|
import Password from './password';
|
||||||
|
import phone from './phone';
|
||||||
|
import mail from './mail';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Password,
|
Password,
|
||||||
|
phone,
|
||||||
|
mail,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
@@ -102,70 +108,77 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
const info = this.$root.global.info;
|
this.showSafety();
|
||||||
|
|
||||||
// 登录密码
|
|
||||||
this.data.push({
|
|
||||||
title: '登录密码',
|
|
||||||
description:
|
|
||||||
'安全性高的密码可以使帐号更安全。建议您定期更换密码,设置一个包含字母,符号或数字中至少两项且长度超过6位的密码。',
|
|
||||||
extra: (
|
|
||||||
<div>
|
|
||||||
当前密码强度:
|
|
||||||
{
|
|
||||||
[
|
|
||||||
<span class="text-error">弱</span>,
|
|
||||||
<span class="text-warning">中</span>,
|
|
||||||
<span class="text-success">强</span>,
|
|
||||||
][info.securityLevel - 1]
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
done: true,
|
|
||||||
action: () => {
|
|
||||||
this.$refs['password-form'].onOpen({});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 手机绑定
|
|
||||||
this.data.push({
|
|
||||||
title: '手机绑定(发送验证码到手机,未实现)',
|
|
||||||
description: (
|
|
||||||
<div>
|
|
||||||
手机号可以直接用于登录、找回密码等。
|
|
||||||
{info.phone && (
|
|
||||||
<span>
|
|
||||||
您已绑定了手机<b>{info.phone}</b>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
done: !!info.phone,
|
|
||||||
action: () => {},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 邮箱绑定
|
|
||||||
this.data.push({
|
|
||||||
title: '安全邮箱(发送验证码到邮箱,未实现)',
|
|
||||||
description: (
|
|
||||||
<div>
|
|
||||||
安全邮箱可以直接用于登录、找回密码等。
|
|
||||||
{info.email && (
|
|
||||||
<span>
|
|
||||||
您已绑定了邮箱<b>{info.email}</b>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
done: !!info.email,
|
|
||||||
action: () => {},
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onSetPasswordSuccess() {
|
onSetPasswordSuccess() {
|
||||||
doLogout();
|
doLogout();
|
||||||
},
|
},
|
||||||
|
showSafety() {
|
||||||
|
const info = this.$root.global.info;
|
||||||
|
this.data = [];
|
||||||
|
// 登录密码
|
||||||
|
this.data.push({
|
||||||
|
title: '登录密码',
|
||||||
|
description:
|
||||||
|
'安全性高的密码可以使帐号更安全。建议您定期更换密码,设置一个包含字母,符号或数字中至少两项且长度超过6位的密码。',
|
||||||
|
extra: (
|
||||||
|
<div>
|
||||||
|
当前密码强度:
|
||||||
|
{
|
||||||
|
[
|
||||||
|
<span class="text-error">弱</span>,
|
||||||
|
<span class="text-warning">中</span>,
|
||||||
|
<span class="text-success">强</span>,
|
||||||
|
][info.securityLevel - 1]
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
done: true,
|
||||||
|
action: () => {
|
||||||
|
this.$refs['password-form'].onOpen({});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 手机绑定
|
||||||
|
this.data.push({
|
||||||
|
title: '手机绑定(发送验证码到手机,未实现)',
|
||||||
|
description: (
|
||||||
|
<div>
|
||||||
|
手机号可以直接用于登录、找回密码等。
|
||||||
|
{info.phone && (
|
||||||
|
<span>
|
||||||
|
您已绑定了手机<b>{info.phone}</b>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
done: !!info.phone,
|
||||||
|
action: () => {
|
||||||
|
this.$refs.phone.OnOpen();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 邮箱绑定
|
||||||
|
this.data.push({
|
||||||
|
title: '安全邮箱(发送验证码到邮箱,未实现)',
|
||||||
|
description: (
|
||||||
|
<div>
|
||||||
|
安全邮箱可以直接用于登录、找回密码等。
|
||||||
|
{info.email && (
|
||||||
|
<span>
|
||||||
|
您已绑定了邮箱<b>{info.email}</b>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
done: !!info.email,
|
||||||
|
action: () => {
|
||||||
|
this.$refs.mail.OnOpen();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
360
Web/src/pages/system/account/setting/safety/mail.vue
Normal file
360
Web/src/pages/system/account/setting/safety/mail.vue
Normal file
@@ -0,0 +1,360 @@
|
|||||||
|
<template>
|
||||||
|
<!--
|
||||||
|
普通编辑窗体
|
||||||
|
v 1.2
|
||||||
|
2021-04-30
|
||||||
|
Lufthafen
|
||||||
|
-->
|
||||||
|
<a-modal
|
||||||
|
:footer="false"
|
||||||
|
:visible="visible"
|
||||||
|
@cancel="onResetFields"
|
||||||
|
class="yo-modal-form"
|
||||||
|
title="绑定邮箱"
|
||||||
|
>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-icon slot="indicator" spin type="loading" />
|
||||||
|
<div class="yo-form">
|
||||||
|
<div class="yo-form-group" v-if="this.type.length!==0">
|
||||||
|
<!-- 表单控件 -->
|
||||||
|
<!-- ... -->
|
||||||
|
<div style="padding: 20px 100px">
|
||||||
|
<a-steps :current="current">
|
||||||
|
<a-step :key="item.title" :title="item.title" v-for="item in steps" />
|
||||||
|
</a-steps>
|
||||||
|
</div>
|
||||||
|
<a-form-model :model="form" ref="form">
|
||||||
|
<!-- 发送给原邮箱号码验证码 -->
|
||||||
|
<div v-if="current===0">
|
||||||
|
<a-form-model-item label="选择验证方式">
|
||||||
|
<a-select style="width:300px" v-model="form.type">
|
||||||
|
<a-select-option
|
||||||
|
:key="item.Title"
|
||||||
|
:value="item.Value"
|
||||||
|
v-for="item in type"
|
||||||
|
>{{item.Title}}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="验证码">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入六位验证码"
|
||||||
|
style="width: 185px; margin-right: 15px"
|
||||||
|
v-model="form.orgcode"
|
||||||
|
></a-input>
|
||||||
|
<a-button :loading="codeLoading" @click="sendcode()" v-if="sendOrNo">发送验证码</a-button>
|
||||||
|
<a-button disabled v-else>{{ countdown }}秒后重送</a-button>
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
<!-- 发送给绑定新邮箱号码-->
|
||||||
|
<div v-if="current===1">
|
||||||
|
<a-form-model-item label="新邮箱号码">
|
||||||
|
<a-input placeholder="请输入邮箱账号" style="width:300px" v-model="form.target"></a-input>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="验证码">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入六位验证码"
|
||||||
|
style="width: 185px; margin-right: 15px"
|
||||||
|
v-model="form.code"
|
||||||
|
></a-input>
|
||||||
|
<a-button :loading="codeLoading" @click="sendcode()" v-if="sendOrNo">发送验证码</a-button>
|
||||||
|
<a-button disabled v-else>{{ countdown }}秒后重送</a-button>
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
</a-form-model>
|
||||||
|
<br />
|
||||||
|
<div class="steps-action" style="text-align:center">
|
||||||
|
<a-button :disabled="checkfirst" @click="next" type="primary" v-if="current == 0">下一步</a-button>
|
||||||
|
<a-button
|
||||||
|
:disabled="checkform"
|
||||||
|
:loading="completeLoading"
|
||||||
|
@click="complete"
|
||||||
|
type="primary"
|
||||||
|
v-if="current == 1"
|
||||||
|
>完成</a-button>
|
||||||
|
<a-button @click="prev" style="margin-left: 8px" v-if="current > 0">前一步</a-button>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
<div class="yo-form-group" v-else>
|
||||||
|
<!-- 表单控件 -->
|
||||||
|
<!-- ... -->
|
||||||
|
<a-form-model :model="form" ref="form">
|
||||||
|
<a-form-model-item label="请输入邮箱">
|
||||||
|
<a-input placeholder="请输入邮箱号码" style="width:250px;" v-model="form.target"></a-input>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="验证码">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入验证码"
|
||||||
|
style="width:140px;margin-right:15px"
|
||||||
|
v-model="form.code"
|
||||||
|
></a-input>
|
||||||
|
<a-button @click="sendcode()" v-if="sendOrNo">发送验证码</a-button>
|
||||||
|
<a-button disabled v-else>{{ countdown }}秒后重送</a-button>
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
<br />
|
||||||
|
<div style="text-align:center">
|
||||||
|
<a-button :disabled="checkform" @click="complete" type="primary">绑定</a-button>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
/* 表单内容默认值 */
|
||||||
|
const defaultForm = {
|
||||||
|
target: '',
|
||||||
|
code: '',
|
||||||
|
type: null,
|
||||||
|
orgcode: '',
|
||||||
|
/* ... */
|
||||||
|
};
|
||||||
|
import app from '@/main';
|
||||||
|
import { COUNT_DWON_KEY } from '@/common/storage';
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
/** 表单数据 */
|
||||||
|
form: {},
|
||||||
|
/** 验证格式 */
|
||||||
|
rules: {
|
||||||
|
/* ... */
|
||||||
|
},
|
||||||
|
current: 0,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
title: '验证',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '绑定',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/** 加载异步数据状态 */
|
||||||
|
loading: false,
|
||||||
|
countdown: 0,
|
||||||
|
type: [],
|
||||||
|
sendOrNo: true,
|
||||||
|
codeLoading: false,
|
||||||
|
completeLoading: false,
|
||||||
|
visible: false,
|
||||||
|
checkform: true,
|
||||||
|
checkfirst: true,
|
||||||
|
/** 其他成员属性 */
|
||||||
|
/* ... */
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 必要的方法
|
||||||
|
* 在打开编辑页时允许填充数据
|
||||||
|
*/
|
||||||
|
onFillData(params) {
|
||||||
|
/** 将默认数据覆盖到form */
|
||||||
|
this.form = this.$_.cloneDeep({
|
||||||
|
...defaultForm,
|
||||||
|
//...params.record,
|
||||||
|
/** 在此处添加其他默认数据转换 */
|
||||||
|
/* ... */
|
||||||
|
});
|
||||||
|
if (this.type.length != 0) {
|
||||||
|
this.form.type = this.type[0].Value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要方法
|
||||||
|
* 验证表单并获取表单数据
|
||||||
|
*/
|
||||||
|
// onGetData() {
|
||||||
|
// return new Promise((reslove, reject) => {
|
||||||
|
// this.$refs.form.validate((valid) => {
|
||||||
|
// if (valid) {
|
||||||
|
// const record = this.$_.cloneDeep(this.form);
|
||||||
|
// /** 验证通过后可以对数据进行转换得到想要提交的格式 */
|
||||||
|
// /* ... */
|
||||||
|
// reslove(record);
|
||||||
|
// } else {
|
||||||
|
// reject();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要的方法
|
||||||
|
* 在外部窗口进行保存时调用表单验证
|
||||||
|
*/
|
||||||
|
// onValidate(callback) {
|
||||||
|
// this.$refs.form.validate(callback);
|
||||||
|
// },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要的方法
|
||||||
|
* 在外部窗口关闭或重置时对表单验证进行初始化
|
||||||
|
*/
|
||||||
|
onResetFields() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.form.resetFields();
|
||||||
|
this.current = 0;
|
||||||
|
this.visible = false;
|
||||||
|
window.localStorage.removeItem(COUNT_DWON_KEY);
|
||||||
|
/** 在这里可以初始化当前组件中其他属性 */
|
||||||
|
/* ... */
|
||||||
|
}, 300);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要方法
|
||||||
|
* 加载当前表单中所需要的异步数据
|
||||||
|
*/
|
||||||
|
async onInit(params) {
|
||||||
|
this.loading = true;
|
||||||
|
this.type = [];
|
||||||
|
/** 可以在这里await获取一些异步数据 */
|
||||||
|
const info = this.$root.global.info;
|
||||||
|
info.phone &&
|
||||||
|
this.type.push({
|
||||||
|
Title: '使用手机号' + info.phone + '进行验证',
|
||||||
|
Value: 1,
|
||||||
|
});
|
||||||
|
info.email &&
|
||||||
|
this.type.push({
|
||||||
|
Title: '使用邮箱' + info.email + '进行验证',
|
||||||
|
Value: 2,
|
||||||
|
});
|
||||||
|
this.onFillData();
|
||||||
|
this.showcountdown();
|
||||||
|
/* ... */
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 当前组件的其他方法 */
|
||||||
|
/* ... */
|
||||||
|
SendOrgSms() {
|
||||||
|
this.$api.SendOrgSms().then((res) => {
|
||||||
|
if (res) {
|
||||||
|
this.addTime();
|
||||||
|
this.showcountdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 将倒计时添加入到本地
|
||||||
|
*/
|
||||||
|
addTime() {
|
||||||
|
const now = Date.now();
|
||||||
|
var date = now + 60 * 1000 + 500;
|
||||||
|
window.localStorage.setItem(COUNT_DWON_KEY, date);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 下一步
|
||||||
|
*/
|
||||||
|
next() {
|
||||||
|
this.loading = true;
|
||||||
|
this.$api
|
||||||
|
.CheckBindcode(this.form)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data) {
|
||||||
|
window.localStorage.removeItem(COUNT_DWON_KEY);
|
||||||
|
this.form.type = null;
|
||||||
|
this.current++;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 完成
|
||||||
|
*/
|
||||||
|
complete() {
|
||||||
|
this.completeLoading = true;
|
||||||
|
this.$api
|
||||||
|
.CheckBindcode(this.form)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data) {
|
||||||
|
window.localStorage.removeItem(COUNT_DWON_KEY);
|
||||||
|
var num = this.form.target;
|
||||||
|
num = num.replace(/(\w?)(\w+)(\w)(@\w+\.[a-z]+(\.[a-z]+)?)/, '$1****$4');
|
||||||
|
app.$set(app.global.info, 'email', num);
|
||||||
|
this.$message.success('改绑完成');
|
||||||
|
this.onResetFields();
|
||||||
|
this.$emit('ok', 100, 100);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.completeLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 发送验证码
|
||||||
|
*/
|
||||||
|
sendcode() {
|
||||||
|
this.codeLoading = true;
|
||||||
|
var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
|
||||||
|
if (!reg.test(this.form.target) && this.form.type != '1' && this.form.type != '2') {
|
||||||
|
this.$message.warning('请输入正确的邮箱');
|
||||||
|
this.codeLoading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$api
|
||||||
|
.SendCode(this.form)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
this.addTime();
|
||||||
|
this.showcountdown();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.codeLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//打开弹窗
|
||||||
|
OnOpen() {
|
||||||
|
this.onInit();
|
||||||
|
this.visible = true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 向前异步
|
||||||
|
*/
|
||||||
|
prev() {
|
||||||
|
window.localStorage.removeItem(COUNT_DWON_KEY);
|
||||||
|
this.form = {
|
||||||
|
target: '',
|
||||||
|
code: '',
|
||||||
|
type: this.type[0].Value,
|
||||||
|
orgcode: '',
|
||||||
|
};
|
||||||
|
this.current--;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 显示倒计时
|
||||||
|
*/
|
||||||
|
showcountdown() {
|
||||||
|
let _this = this;
|
||||||
|
var Furdate = window.localStorage.getItem(COUNT_DWON_KEY);
|
||||||
|
var nowdate = new Date().getTime();
|
||||||
|
if (Furdate >= nowdate) {
|
||||||
|
this.sendOrNo = false;
|
||||||
|
this.countdown = parseInt((Furdate - nowdate) / 1000);
|
||||||
|
setTimeout(() => {
|
||||||
|
_this.showcountdown();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
this.sendOrNo = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
form: {
|
||||||
|
deep: true,
|
||||||
|
handler: function (newVal, oldVal) {
|
||||||
|
this.checkform = !(newVal.target != '' && newVal.code != '');
|
||||||
|
this.checkfirst = !(newVal.orgcode != '');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
360
Web/src/pages/system/account/setting/safety/phone.vue
Normal file
360
Web/src/pages/system/account/setting/safety/phone.vue
Normal file
@@ -0,0 +1,360 @@
|
|||||||
|
<template>
|
||||||
|
<!--
|
||||||
|
普通编辑窗体
|
||||||
|
v 1.2
|
||||||
|
2021-04-30
|
||||||
|
Lufthafen
|
||||||
|
-->
|
||||||
|
<a-modal
|
||||||
|
:footer="false"
|
||||||
|
:visible="visible"
|
||||||
|
@cancel="onResetFields"
|
||||||
|
class="yo-modal-form"
|
||||||
|
title="绑定邮箱"
|
||||||
|
>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-icon slot="indicator" spin type="loading" />
|
||||||
|
<div class="yo-form">
|
||||||
|
<div class="yo-form-group" v-if="this.type.length!==0">
|
||||||
|
<!-- 表单控件 -->
|
||||||
|
<!-- ... -->
|
||||||
|
<div style="padding: 20px 100px">
|
||||||
|
<a-steps :current="current">
|
||||||
|
<a-step :key="item.title" :title="item.title" v-for="item in steps" />
|
||||||
|
</a-steps>
|
||||||
|
</div>
|
||||||
|
<a-form-model :model="form" ref="form">
|
||||||
|
<!-- 发送给原邮箱号码验证码 -->
|
||||||
|
<div v-if="current===0">
|
||||||
|
<a-form-model-item label="选择验证方式">
|
||||||
|
<a-select style="width:300px" v-model="form.type">
|
||||||
|
<a-select-option
|
||||||
|
:key="item.Title"
|
||||||
|
:value="item.Value"
|
||||||
|
v-for="item in type"
|
||||||
|
>{{item.Title}}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="验证码">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入六位验证码"
|
||||||
|
style="width: 185px; margin-right: 15px"
|
||||||
|
v-model="form.orgcode"
|
||||||
|
></a-input>
|
||||||
|
<a-button :loading="codeLoading" @click="sendcode()" v-if="sendOrNo">发送验证码</a-button>
|
||||||
|
<a-button disabled v-else>{{ countdown }}秒后重送</a-button>
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
<!-- 发送给绑定新邮箱号码-->
|
||||||
|
<div v-if="current===1">
|
||||||
|
<a-form-model-item label="新手机号码">
|
||||||
|
<a-input placeholder="请输入手机号码" style="width:300px" v-model="form.target"></a-input>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="验证码">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入六位验证码"
|
||||||
|
style="width: 185px; margin-right: 15px"
|
||||||
|
v-model="form.code"
|
||||||
|
></a-input>
|
||||||
|
<a-button :loading="codeLoading" @click="sendcode()" v-if="sendOrNo">发送验证码</a-button>
|
||||||
|
<a-button disabled v-else>{{ countdown }}秒后重送</a-button>
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
</a-form-model>
|
||||||
|
<br />
|
||||||
|
<div class="steps-action" style="text-align:center">
|
||||||
|
<a-button :disabled="checkfirst" @click="next" type="primary" v-if="current == 0">下一步</a-button>
|
||||||
|
<a-button
|
||||||
|
:disabled="checkform"
|
||||||
|
:loading="completeLoading"
|
||||||
|
@click="complete"
|
||||||
|
type="primary"
|
||||||
|
v-if="current == 1"
|
||||||
|
>完成</a-button>
|
||||||
|
<a-button @click="prev" style="margin-left: 8px" v-if="current > 0">前一步</a-button>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
<div class="yo-form-group" v-else>
|
||||||
|
<!-- 表单控件 -->
|
||||||
|
<!-- ... -->
|
||||||
|
<a-form-model :model="form" ref="form">
|
||||||
|
<a-form-model-item label="请输入手机号码">
|
||||||
|
<a-input placeholder="请输入手机号码" style="width:250px;" v-model="form.target"></a-input>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="验证码">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入验证码"
|
||||||
|
style="width:140px;margin-right:15px"
|
||||||
|
v-model="form.code"
|
||||||
|
></a-input>
|
||||||
|
<a-button @click="sendcode()" v-if="sendOrNo">发送验证码</a-button>
|
||||||
|
<a-button disabled v-else>{{ countdown }}秒后重送</a-button>
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
<br />
|
||||||
|
<div style="text-align:center">
|
||||||
|
<a-button :disabled="checkform" @click="complete" type="primary">绑定</a-button>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
/* 表单内容默认值 */
|
||||||
|
const defaultForm = {
|
||||||
|
target: '',
|
||||||
|
code: '',
|
||||||
|
type: null,
|
||||||
|
orgcode: '',
|
||||||
|
/* ... */
|
||||||
|
};
|
||||||
|
import app from '@/main';
|
||||||
|
import { COUNT_DWON_KEY } from '@/common/storage';
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
/** 表单数据 */
|
||||||
|
form: {},
|
||||||
|
/** 验证格式 */
|
||||||
|
rules: {
|
||||||
|
/* ... */
|
||||||
|
},
|
||||||
|
current: 0,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
title: '验证',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '绑定',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/** 加载异步数据状态 */
|
||||||
|
loading: false,
|
||||||
|
countdown: 0,
|
||||||
|
type: [],
|
||||||
|
sendOrNo: true,
|
||||||
|
codeLoading: false,
|
||||||
|
completeLoading: false,
|
||||||
|
visible: false,
|
||||||
|
checkform: true,
|
||||||
|
checkfirst: true,
|
||||||
|
/** 其他成员属性 */
|
||||||
|
/* ... */
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 必要的方法
|
||||||
|
* 在打开编辑页时允许填充数据
|
||||||
|
*/
|
||||||
|
onFillData(params) {
|
||||||
|
/** 将默认数据覆盖到form */
|
||||||
|
this.form = this.$_.cloneDeep({
|
||||||
|
...defaultForm,
|
||||||
|
//...params.record,
|
||||||
|
/** 在此处添加其他默认数据转换 */
|
||||||
|
/* ... */
|
||||||
|
});
|
||||||
|
if (this.type.length != 0) {
|
||||||
|
this.form.type = this.type[0].Value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要方法
|
||||||
|
* 验证表单并获取表单数据
|
||||||
|
*/
|
||||||
|
// onGetData() {
|
||||||
|
// return new Promise((reslove, reject) => {
|
||||||
|
// this.$refs.form.validate((valid) => {
|
||||||
|
// if (valid) {
|
||||||
|
// const record = this.$_.cloneDeep(this.form);
|
||||||
|
// /** 验证通过后可以对数据进行转换得到想要提交的格式 */
|
||||||
|
// /* ... */
|
||||||
|
// reslove(record);
|
||||||
|
// } else {
|
||||||
|
// reject();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要的方法
|
||||||
|
* 在外部窗口进行保存时调用表单验证
|
||||||
|
*/
|
||||||
|
// onValidate(callback) {
|
||||||
|
// this.$refs.form.validate(callback);
|
||||||
|
// },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要的方法
|
||||||
|
* 在外部窗口关闭或重置时对表单验证进行初始化
|
||||||
|
*/
|
||||||
|
onResetFields() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.form.resetFields();
|
||||||
|
this.current = 0;
|
||||||
|
this.visible = false;
|
||||||
|
window.localStorage.removeItem(COUNT_DWON_KEY);
|
||||||
|
/** 在这里可以初始化当前组件中其他属性 */
|
||||||
|
/* ... */
|
||||||
|
}, 300);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必要方法
|
||||||
|
* 加载当前表单中所需要的异步数据
|
||||||
|
*/
|
||||||
|
async onInit(params) {
|
||||||
|
this.loading = true;
|
||||||
|
this.type = [];
|
||||||
|
/** 可以在这里await获取一些异步数据 */
|
||||||
|
const info = this.$root.global.info;
|
||||||
|
info.phone &&
|
||||||
|
this.type.push({
|
||||||
|
Title: '使用手机号' + info.phone + '进行验证',
|
||||||
|
Value: 1,
|
||||||
|
});
|
||||||
|
info.email &&
|
||||||
|
this.type.push({
|
||||||
|
Title: '使用邮箱' + info.email + '进行验证',
|
||||||
|
Value: 2,
|
||||||
|
});
|
||||||
|
this.onFillData();
|
||||||
|
this.showcountdown();
|
||||||
|
/* ... */
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 当前组件的其他方法 */
|
||||||
|
/* ... */
|
||||||
|
SendOrgSms() {
|
||||||
|
this.$api.SendOrgSms().then((res) => {
|
||||||
|
if (res) {
|
||||||
|
this.addTime();
|
||||||
|
this.showcountdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 将倒计时添加入到本地
|
||||||
|
*/
|
||||||
|
addTime() {
|
||||||
|
const now = Date.now();
|
||||||
|
var date = now + 60 * 1000 + 500;
|
||||||
|
window.localStorage.setItem(COUNT_DWON_KEY, date);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 下一步
|
||||||
|
*/
|
||||||
|
next() {
|
||||||
|
this.loading = true;
|
||||||
|
this.$api
|
||||||
|
.CheckBindcode(this.form)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data) {
|
||||||
|
window.localStorage.removeItem(COUNT_DWON_KEY);
|
||||||
|
this.form.type = null;
|
||||||
|
this.current++;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 完成
|
||||||
|
*/
|
||||||
|
complete() {
|
||||||
|
this.completeLoading = true;
|
||||||
|
this.$api
|
||||||
|
.CheckBindcode(this.form)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data) {
|
||||||
|
window.localStorage.removeItem(COUNT_DWON_KEY);
|
||||||
|
var num = this.form.target;
|
||||||
|
num = num.replace(/^(\d{3})\d{3}(\d+)/, '$1****$2');
|
||||||
|
app.$set(app.global.info, 'phone', num);
|
||||||
|
this.$message.success('改绑完成');
|
||||||
|
this.onResetFields();
|
||||||
|
this.$emit('ok', 100, 100);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.completeLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 发送验证码
|
||||||
|
*/
|
||||||
|
sendcode() {
|
||||||
|
this.codeLoading = true;
|
||||||
|
var reg = /^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$/;
|
||||||
|
if (!reg.test(this.form.target) && this.form.type != '1' && this.form.type != '2') {
|
||||||
|
this.$message.warning('请输入正确的手机号');
|
||||||
|
this.codeLoading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$api
|
||||||
|
.SendCode(this.form)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
this.addTime();
|
||||||
|
this.showcountdown();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.codeLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//打开弹窗
|
||||||
|
OnOpen() {
|
||||||
|
this.onInit();
|
||||||
|
this.visible = true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 向前异步
|
||||||
|
*/
|
||||||
|
prev() {
|
||||||
|
window.localStorage.removeItem(COUNT_DWON_KEY);
|
||||||
|
this.form = {
|
||||||
|
target: '',
|
||||||
|
code: '',
|
||||||
|
type: this.type[0].Value,
|
||||||
|
orgcode: '',
|
||||||
|
};
|
||||||
|
this.current--;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 显示倒计时
|
||||||
|
*/
|
||||||
|
showcountdown() {
|
||||||
|
let _this = this;
|
||||||
|
var Furdate = window.localStorage.getItem(COUNT_DWON_KEY);
|
||||||
|
var nowdate = new Date().getTime();
|
||||||
|
if (Furdate >= nowdate) {
|
||||||
|
this.sendOrNo = false;
|
||||||
|
this.countdown = parseInt((Furdate - nowdate) / 1000);
|
||||||
|
setTimeout(() => {
|
||||||
|
_this.showcountdown();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
this.sendOrNo = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
form: {
|
||||||
|
deep: true,
|
||||||
|
handler: function (newVal, oldVal) {
|
||||||
|
this.checkform = !(newVal.target != '' && newVal.code != '');
|
||||||
|
this.checkfirst = !(newVal.orgcode != '');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user