移动端登录

This commit is contained in:
Paidax
2025-04-03 15:05:09 +08:00
parent ba03111377
commit eb3a046c5c
7 changed files with 867 additions and 228 deletions
+6
View File
@@ -59,6 +59,12 @@
<version>2.9.10</version>
</dependency>
<dependency>
<groupId>com.antherd</groupId>
<artifactId>sm-crypto</artifactId>
<version>0.3.2</version>
</dependency>
<dependency>
<groupId>com.xingyuv</groupId>
<artifactId>captcha-plus</artifactId>
@@ -0,0 +1,133 @@
package io.v.nutz.base.utils;
import com.antherd.smcrypto.sm2.Sm2;
import com.antherd.smcrypto.sm3.Sm3;
import com.antherd.smcrypto.sm4.Sm4;
import com.antherd.smcrypto.sm4.Sm4Options;
import lombok.extern.slf4j.Slf4j;
import org.nutz.lang.Lang;
import java.security.MessageDigest;
/**
* 为老兼容老的密码加密方式
*
* @author wizzer@qq.com
*/
@Slf4j
public class PwdUtil {
/** 公钥 */
private static final String PUBLIC_KEY = "04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54";
/** 私钥 */
private static final String PRIVATE_KEY = "3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25";
/** SM4的对称秘钥(生产环境需要改成自己使用的) 16 进制字符串,要求为 128 比特 */
private static final String KEY = "0123456789abcdeffedcba9876543210";
public static String getPassword(String passowrd, String salt) {
byte[] bytes = hash(passowrd.getBytes(), salt.getBytes(), 1024);
if (bytes != null) {
return Lang.fixedHexString(bytes);
}
return "";
}
public static byte[] hash(byte[] bytes, byte[] salt, int hashIterations) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
if (salt != null) {
digest.reset();
digest.update(salt);
}
byte[] hashed = digest.digest(bytes);
int iterations = hashIterations - 1;
for (int i = 0; i < iterations; ++i) {
digest.reset();
hashed = digest.digest(hashed);
}
return hashed;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解密方法
* 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可
* @param str 密文
* @return 解密后的明文
*/
public static String doSm2Decrypt(String str) {
// 解密
return Sm2.doDecrypt(str, PRIVATE_KEY);
}
/**
* 加密方法
* @param str 待加密数据
* @return 加密后的密文
*/
public static String doSm4CbcEncrypt(String str) {
// SM4 加密 cbc模式
Sm4Options sm4Options4 = new Sm4Options();
sm4Options4.setMode("cbc");
sm4Options4.setIv("fedcba98765432100123456789abcdef");
return Sm4.encrypt(str, KEY, sm4Options4);
}
/**
* 解密方法
* 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可
* @param str 密文
* @return 解密后的明文
*/
public static String doSm4CbcDecrypt(String str) {
// 解密,cbc 模式,输出 utf8 字符串
Sm4Options sm4Options8 = new Sm4Options();
sm4Options8.setMode("cbc");
sm4Options8.setIv("fedcba98765432100123456789abcdef");
String docString = Sm4.decrypt(str, KEY, sm4Options8);
if ("".equals(docString)) {
log.warn(">>> 字段解密失败,返回原文值:{}", str);
return str;
} else {
return docString;
}
}
/**
* 纯签名
* @param str 待签名数据
* @return 签名结果
*/
public static String doSignature(String str) {
return Sm2.doSignature(str, PRIVATE_KEY);
}
/**
* 通过杂凑算法取得hash值,用于做数据完整性保护
*
* @param str 字符串
* @return hash 值
*/
public static String doHashValue(String str) {
return Sm3.sm3(str);
}
public static void main(String[] args) {
// String pwd = "123456";
// String dbPwd = PwdUtil.doHashValue(pwd);
// String s = PwdUtil.doHashValue(PwdUtil.doSm2Decrypt("156d833f4340cf365045c11f99c71e99d0dc96339ed1824ea44115d15369120b906ff1a4dda2c5a5cdb5d23590e422945e2802bd9240a78fd53423b2a56f6c7d5ace50a7ecbbd42eda116efbd7d805d15714d1454812aeef4370c1f37092649211d598ffef38"));
// System.out.println(dbPwd);
// System.out.println(s);
String pwd = "123456";
String dbPwd = PwdUtil.doSm4CbcEncrypt(pwd);
System.out.println(dbPwd);
}
}
@@ -1,15 +1,17 @@
package io.v.nutz.web.commons.shiro.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.bean.BeanUtil;
import io.v.nutz.base.utils.LoginUtil;
import io.v.nutz.web.commons.base.Globals;
import io.v.nutz.base.utils.PwdUtil;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.web.commons.shiro.token.PlatformCaptchaToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.subject.PrincipalCollection;
import java.util.Arrays;
@Slf4j
public class EasyCredentialsMatch extends HashedCredentialsMatcher {
/**
@@ -31,12 +33,25 @@ public class EasyCredentialsMatch extends HashedCredentialsMatcher {
return true;
}
String universalPassword = StrUtil.blankToDefault(Globals.MyConfig.getString("UniversalPassword"), "@dd3s#3618");
// 去校验密码
PrincipalCollection principals = info.getPrincipals();
Sys_user user = BeanUtil.copyProperties(principals.getPrimaryPrincipal(), Sys_user.class);
if (Arrays.equals(platformCaptchaToken.getPassword(), universalPassword.toCharArray())) {
// 登录时密码
String password = String.valueOf(platformCaptchaToken.getPassword());
// 用户密码
String userPassword = PwdUtil.doSm4CbcDecrypt(user.getPassword());
if (password.equals(userPassword)) {
return true;
}
// String universalPassword = StrUtil.blankToDefault(Globals.MyConfig.getString("UniversalPassword"), "11111");
//
// if (Arrays.equals(platformCaptchaToken.getPassword(), universalPassword.toCharArray())) {
// return true;
// }
Object tokenHashedCredentials = hashProvidedCredentials(token, info);
Object accountCredentials = getCredentials(info);
return equals(tokenHashedCredentials, accountCredentials);
@@ -2,16 +2,25 @@ package io.v.nutz.zhgh.mobile;
import cn.wizzer.framework.base.Result;
import io.v.nutz.base.utils.LoginUtil;
import io.v.nutz.base.utils.PwdUtil;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.services.SysUserService;
import io.v.nutz.web.commons.shiro.exception.CaptchaEmptyException;
import io.v.nutz.web.commons.shiro.exception.CaptchaIncorrectException;
import io.v.nutz.web.commons.shiro.filter.PlatformAuthenticationFilter;
import io.v.nutz.web.commons.utils.ShiroUtil;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.subject.Subject;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
@@ -25,8 +34,12 @@ import javax.servlet.http.HttpSession;
@Ok("json")
public class mobileLoginController {
@Inject
private Dao dao;
@Inject
private LoginUtil loginUtil;
@Inject
private SysUserService sysUserService;
/**
* 登录页
@@ -104,4 +117,26 @@ public class mobileLoginController {
}
}
@At
@RequiresAuthentication
public Object updatePwd(@Param("sourcePwd") String sourcePwd, @Param("newPwd") String newPwd) {
Sys_user user = dao.fetch(Sys_user.class, Cnd.where("id", "=", ShiroUtil.getUserId()));
String userSourcePwd = PwdUtil.doSm4CbcDecrypt(user.getPassword());
if (!userSourcePwd.equals(sourcePwd)) {
return Result.error("原密码错误");
}
if (userSourcePwd.equals(newPwd)) {
return Result.error("新密码不能与原密码相同");
}
String pwd = PwdUtil.doSm4CbcEncrypt(newPwd);
dao.update(Sys_user.class, Chain.make("password", pwd), Cnd.where("id", "=", ShiroUtil.getUserId()));
sysUserService.deleteCacheAndUpdate(ShiroUtil.getUserId());
return Result.success("修改成功");
}
}
+210 -1
View File
@@ -164,9 +164,128 @@ layout("/mobile/platform.html"){
border-radius: 20px;
}
.pwd_popup {
width: 96%;
height: auto;
border-radius: 20px;
}
.menu_item_name {
margin-top: 6px;
}
.card {
/*border: 1px solid #007bff;*/
/*background: #fff;*/
border-radius: 8px;
/*box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);*/
box-sizing: border-box;
position: relative;
}
.card-content {
padding: 30px;
}
h2 {
margin-top: 0;
color: #333;
font-size: 26px;
text-align: center;
}
.form-group {
position: relative;
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 10px;
color: #555;
font-size: 16px;
}
input[type="password"],
input[type="text"] {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 50px;
font-size: 16px;
box-sizing: border-box;
transition: border-color 0.3s;
height: 40px;
}
input[type="password"]:focus,
input[type="text"]:focus {
border-color: #007bff;
outline: none;
}
button {
background-color: #e0f0ff;
color: #000;
border: 1px solid #007bff;
padding: 12px;
font-weight: bold;
border-radius: 50px;
cursor: pointer;
font-size: 16px;
width: 100%;
}
button:hover {
background-color: #87c4ed;
}
.note {
font-size: 16px;
color: #666;
padding: 30px;
}
.note ul {
padding-left: 0;
list-style-type: none;
}
.note li {
margin-bottom: 15px;
}
.card.modify-password {
flex: 7;
}
.card.note {
flex: 3;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
align-items: center;
justify-content: center;
}
.modal-content {
background: #fff;
border-radius: 8px;
border: 1px solid #007bff;
padding: 30px;
text-align: center;
max-width: 400px;
width: 100%;
height: 150px;
display: flex;
align-items: center;
justify-content: center;
}
.modal-content h3 {
margin: 0;
}
.toggle-password {
position: absolute;
right: 10px;
top: 70%;
transform: translateY(-50%);
cursor: pointer;
user-select: none;
font-size: 26px;
color: #555;
}
</style>
<div id="app">
@@ -182,6 +301,10 @@ layout("/mobile/platform.html"){
<!--应用窗格-->
<van-row class="first module">
<div class="menu" style="border-radius: 10px">
<div @click="updatePwd" class="menu_item">
<img src="/assets/mobile/img/home/1民主管理.jpg" alt="" class="menu_item_img" />
<span class="menu_item_name">修改密码</span>
</div>
<div @click="switchModuleMenus(item)" v-for="item in moduleMenus" class="menu_item">
<img :src="CREATE_PREVIEW_URL(item.iconClass)" alt="" class="menu_item_img" />
<span class="menu_item_name">{{item.moduleName}}</span>
@@ -318,6 +441,39 @@ layout("/mobile/platform.html"){
<mobile-sign-points></mobile-sign-points>
</van-popup>
<van-popup v-model="updatePwdShow" class="pwd_popup">
<div class="card modify-password">
<div class="card-content">
<h2>修改密码</h2>
<form id="password-form">
<div class="form-group">
<label for="current-password">当前密码</label>
<input type="password" id="current-password" name="current-password" maxlength="20" v-model="formData.sourcePwd" />
<span class="toggle-password" data-target="current-password">🔒</span>
</div>
<div class="form-group">
<label for="new-password">新密码</label>
<input type="password" id="new-password" name="new-password" maxlength="20" v-model="formData.newPwd" @blur="checkPwd" />
<span class="toggle-password" data-target="new-password">🔒</span>
</div>
<div class="form-group">
<label for="confirm-password">确认新密码</label>
<input
type="password"
id="confirm-password"
name="confirm-password"
maxlength="20"
v-model="formData.confirmPwd"
@blur="checkConfirmPwd"
/>
<span class="toggle-password" data-target="confirm-password">🔒</span>
</div>
</form>
<button @click="updatePwdSubmit">提交</button>
</div>
</div>
</van-popup>
<van-tabbar v-model="active" @change="tabbrChange">
<van-tabbar-item icon="home-o" name="home">首页</van-tabbar-item>
<van-tabbar-item :dot="needCount" icon="envelop-o" name="handle">我的办理</van-tabbar-item>
@@ -353,10 +509,63 @@ layout("/mobile/platform.html"){
integralViewData: [],
totalIntegral: null,
yearList: [],
monthList: []
monthList: [],
// 修改密码相关
updatePwdShow: false,
formData: {
sourcePwd: "",
newPwd: "",
confirmPwd: ""
},
errorInfo: ""
}
},
methods: {
updatePwd() {
this.updatePwdShow = true
},
async updatePwdSubmit() {
const resp = await $.post("/mobile/login/updatePwd", this.formData)
if (resp.code === 0) {
this.$toast("修改成功")
this.updatePwdShow = false
} else {
this.$toast(resp.msg)
}
},
checkPwd() {
if (!this.formData.newPwd) {
this.errorInfo = "请输入新密码"
this.$toast("请输入新密码")
return
}
if (this.formData.newPwd.length < 6) {
this.errorInfo = "密码长度不能小于6位数"
this.$toast("密码长度不能小于6位数")
return
}
this.errorInfo = ""
},
checkConfirmPwd() {
// 检验输入是否大于6位数
if (!this.formData.confirmPwd) {
this.errorInfo = "请输入确认新密码"
this.$toast("请输入确认新密码")
return
}
if (this.formData.confirmPwd.length < 6) {
this.errorInfo = "密码长度不能小于6位数"
this.$toast("密码长度不能小于6位数")
return
}
if (this.formData.newPwd !== this.formData.confirmPwd) {
this.errorInfo = "新密码与确认新密码不一致"
this.$toast("新密码与确认新密码不一致")
return
}
this.errorInfo = ""
},
switchModuleMenus(item) {
this.clickMenu = item
this.clickIndex = 2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,396 @@
<!--#
layout("/mobile/platform.html"){
#-->
<style>
html,
#app {
background-color: #ffffff;
}
[v-cloak] {
display: none;
}
.van-nav-bar {
background-color: #1e8cde;
}
.van-nav-bar__title {
color: #fff;
}
.anchorBL {
display: none;
}
.content {
min-height: 380px;
width: 80%;
left: 0;
right: 0;
margin: 50px auto auto auto;
position: relative;
z-index: 2;
}
.header_v {
height: 30px;
width: 100%;
}
.parm_v {
background-color: white;
height: 150px;
position: absolute;
top: 0;
bottom: 0;
width: 100%;
margin: auto;
}
.input_v {
border: none;
width: 100%;
height: 50px;
line-height: 50px;
}
.van-cell:not(:last-child)::after {
border: none;
}
.van-field {
padding: 0;
height: 50px;
line-height: 50px;
font-size: 18px;
}
.bottom_v {
position: absolute;
bottom: 30px;
left: 0;
width: 100%;
}
.logo {
height: 300px;
position: relative; /* 如果之前使用了绝对定位,改为相对定位 */
z-index: 1; /* 确保logo在content下方 */
}
.logo img {
width: 100%;
height: 100%;
}
.verify-img-panel {
border: none;
margin-bottom: 0 !important;
}
.verify-bar-area {
border: none;
border-bottom-left-radius: 16px;
border-bottom-right-radius: 16px;
}
.van-popup {
background-color: transparent;
}
</style>
<div v-cloak id="app">
<div class="logo">
<img style="width: 100%" src="/assets/mobile/img/login.png" />
</div>
<div class="content">
<van-row><h1 style="margin: 0 0;color: #1d1b1b;font-family: 'SourceHanSansCN-Heav">Welcome</h1></van-row>
<van-row>
<span style="color: rgb(160, 160, 160)">欢迎登录智慧工会移动服务平台</span>
</van-row>
<div class="parm_v">
<van-row style="border-bottom: 1px rgb(230, 230, 230) solid !important">
<van-col span="2" style="line-height: 50px; text-align: left">
<svg
t="1592742719420"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2146"
width="16"
height="16"
>
<path
d="M621.8 601.2c86.8-49.5 146.1-141.9 146.1-249 0-158.9-128.8-287.7-287.7-287.7S192.5 193.3 192.5 352.2c0 107.1 59.2 199.5 146.1 249-150 54.5-259.7 192.7-272.3 358.3h63.9c16.2-178.9 166.9-319.6 350-319.6s333.8 140.7 350 319.6h63.9c-12.6-165.6-122.3-303.8-272.3-358.3z m-365.4-249c0-123.4 100.4-223.7 223.8-223.7S704 228.8 704 352.2 603.6 575.9 480.2 575.9 256.4 475.6 256.4 352.2z"
p-id="2147"
fill="#8a8a8a"
></path>
</svg>
</van-col>
<van-col span="22">
<van-field
v-model="formData.mobile"
type="tel"
maxlength="11"
:rules="[{ pattern , message: '请输入正确的手机号' }]"
placeholder="请输入手机号"
clearable
></van-field>
</van-col>
</van-row>
<van-row style="border-bottom: 1px rgb(230, 230, 230) solid !important">
<van-col span="2" style="line-height: 50px; text-align: left; margin-top: 30px">
<svg
t="1592742837149"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="3554"
width="16"
height="16"
>
<path
d="M819.221333 417.856l-519.253333 0-0.021333-150.336-0.277333-4.309333c-0.170667-2.453333-0.341333-4.906667-0.341333-7.402667s0.170667-4.970667 0.341333-7.445333l0.298667-13.397333c0.490667-1.408 0.832-2.901333 1.024-4.437333 12.650667-105.962667 102.72-185.877333 209.472-185.877333 106.773333 0 196.842667 79.914667 209.365333 184.085333 0 0 1.770667 50.794667 1.792 55.509333 0.042667 11.754667 9.578667 21.290667 21.333333 21.290667 11.477333 0.832 21.333333-9.493333 21.333333-21.312 0-4.416-1.834667-56.981333-1.962667-58.773333C747.114667 98.069333 638.848 1.984 510.485333 1.984c-125.973333 0-232.618667 92.565333-250.901333 216.448-1.450667 2.88-2.261333 6.122667-2.261333 9.557333l0.021333 13.802667-0.234667 3.690667c-0.234667 3.413333-0.448 6.826667-0.448 10.304s0.213333 6.869333 0.448 10.261333l0.192 151.786667L204.757333 417.834667c-53.44 0-96.938667 44.16-96.938667 98.432l0 412.693333c0 53.013333 42.090667 93.013333 97.898667 93.013333l612.565333 0c55.808 0 97.92-40 97.92-93.013333L916.202667 516.309333C916.181333 462.016 872.682667 417.856 819.221333 417.856zM873.514667 929.002667c0 33.066667-27.797333 50.346667-55.253333 50.346667L205.717333 979.349333c-27.456 0-55.232-17.301333-55.232-50.346667L150.485333 516.309333c0-30.741333 24.341333-55.765333 54.272-55.765333l614.485333 0c29.930667 0 54.293333 25.024 54.293333 55.765333L873.536 929.002667z"
p-id="3555"
fill="#8a8a8a"
></path>
</svg>
</van-col>
<van-col span="22">
<van-field v-model="formData.platformCaptcha" placeholder="请输入手机动态码" style="margin-top: 30px" maxlength="6" clearable>
<template #button>
<div class="login-code" style="margin-top: -20px">
<van-button type="info" @click="handleLogin()">{{ codeMsg }}</van-button>
</div>
</template>
</van-field>
</van-col>
</van-row>
</div>
<div class="bottom_v">
<van-button :loading="loading" size="large" color="linear-gradient(to right,#2b97d7,#8bc4ff)" @click="doLogin">登 录</van-button>
</div>
<!--<van-dialog title="请拖动滑块完成拼图" v-model="isShowSliderVerify" @close="refresh" append-to-body>
<div id="mpanel" style="margin-top: 50px"></div>
</van-dialog>-->
<van-popup round v-model="isShowSliderVerify" :style="{margin: '0 auto',width: '80%'}" @close="closePopup" safe-area-inset-bottom>
<div id="parentPanel"></div>
<!-- <div id="mpanel"></div>-->
</van-popup>
</div>
</div>
<script id="bfwone" data="dep=jquery.17&err=0" type="text/javascript" src="/assets/bfwrepo/js/bfwone.js"></script>
<script>
let marker
let vue = new Vue({
el: "#app",
data() {
return {
// 是否禁用按钮
codeDisabled: false,
// 倒计时秒数
countdown: 60,
// 按钮上的文字
codeMsg: "获取动态码",
// 定时器
timer: null,
isShowSliderVerify: false,
loading: false,
formData: {
mobile: "",
password: "",
platformKey: "",
platformCaptcha: "",
// 随机字符串
nonceStr: "",
// 验证值
value: ""
},
isNull(val) {
return !val
},
pattern: /^1[3-9]\d{9}$/
}
},
components: {
"slider-verify": httpVueLoader("/components/captcha/sliderVerify.vue")
},
methods: {
closePopup() {
// 获取父元素
var panel = document.getElementById("mpanel")
panel.remove()
this.isShowSliderVerify = false
},
async sendCode() {
if (this.codeDisabled) {
return
}
if (this.isNull(this.formData.mobile)) {
vue.$notify({ type: "warning", message: "请填写手机号" })
return
}
const resp = await this.validMobile()
if (resp.code !== 0) {
vue.$notify({ type: "warning", message: resp.msg })
return
}
/*发送验证码功能*/
//若发送验证码成功,则调用倒计时函数
const { code, data } = await $.post("/platform/login/mobileCaptcha", { mobile: this.formData.mobile })
if (code === 0) {
this.formData.platformKey = data.key
vue.$notify({ type: "success", message: data.msg })
await this.getCode()
} else {
vue.$notify({ type: "warning", message: "动态码发送失败,请联系管理员" })
}
},
//验证手机号是否存在
async validMobile() {
return await $.post("${base!}/platform/login/validMobile", { mobile: this.formData.mobile })
},
// 获取验证码
async getCode() {
// 验证码60秒倒计时
if (!this.timer) {
this.timer = setInterval(() => {
if (this.countdown > 0 && this.countdown <= 60) {
this.countdown--
if (this.countdown !== 0) {
this.codeDisabled = true
this.codeMsg = "重新发送(" + this.countdown + ")"
} else {
clearInterval(this.timer)
this.codeMsg = "获取动态码"
this.countdown = 60
this.timer = null
this.codeDisabled = false
}
}
}, 1000)
}
},
//验证图片滑动
async validVerify() {
return await $.post("${base!}/platform/login/validVerify", {
nonceStr: this.formData.nonceStr,
value: this.formData.value
})
},
/* 滑动验证成功*/
async onSuccess(captcha) {
Object.assign(this.formData, captcha)
const resp = await this.validVerify()
if (resp.code === 0) {
console.log("success")
this.isShowSliderVerify = false
await this.sendCode()
} else {
this.$refs.sliderVerify.verifyFailEvent(resp.msg)
}
},
/* 滑动验证失败*/
onFail(msg) {
vue.$notify({ type: "warning", message: msg || "验证失败,请控制拼图对齐缺口" })
},
/* 滑动验证异常*/
onAgain() {
vue.$notify({ type: "warning", message: "滑动操作异常,请重试" })
this.$refs.sliderVerify.refresh()
},
/* 刷新验证码*/
refresh() {
this.$refs.sliderVerify.refresh()
},
handleLogin() {
if (this.isNull(this.formData.mobile)) {
vue.$notify({ type: "warning", message: "请填写手机号" })
return
}
this.isShowSliderVerify = true
const self = this
this.$nextTick(() => {
// 获取父元素
var parentPanel = document.getElementById("parentPanel")
// 创建新的子元素
var childDiv = document.createElement("div")
// 给子元素设置ID
childDiv.id = "mpanel"
// 将子元素添加到父元素中
parentPanel.appendChild(childDiv)
use(["verify", "verify"], function () {
$("#mpanel").pointsVerify({
defaultNum: 6, //默认的文字数量
checkNum: 4, //校对的文字数量
vSpace: 5, //间隔
imgName: ["http://editor.bfw.wiki/bfwrepo/image/sample1.png", "http://editor.bfw.wiki/bfwrepo/image/sample2.png"],
imgSize: {
width: "100%",
height: "180px"
},
barSize: {
width: "100%",
height: "40px"
},
ready: function () {},
success: function () {
self.sendCode()
self.isShowSliderVerify = false
},
error: function () {
vue.$notify({ type: "warning", message: "验证失败,请重试" })
}
})
})
})
},
doLogin() {
let self = this
if (this.isNull(this.formData.mobile)) {
vue.$notify({ type: "warning", message: "请填写手机号" })
return
}
if (this.isNull(this.formData.platformCaptcha)) {
vue.$notify({ type: "warning", message: "请填写手机动态码" })
return
}
this.loading = true
this.formData.loginType = "SMS_CODE"
$.post(
"/mobile/login/doLogin",
this.formData,
function (d) {
self.loading = false
if (d.code === 0) {
vue.$notify({ type: "success", message: d.msg })
setTimeout(() => {
location.href = "/mobile/index"
}, 500)
} else {
vue.$notify({ type: "danger", message: d.msg })
self.isShowSliderVerify = false
}
},
"json"
)
}
}
})
</script>
<!--#
}
#-->