330 lines
8.5 KiB
Vue
330 lines
8.5 KiB
Vue
<template>
|
||
<view class="editPassword">
|
||
<!-- 顶部导航栏 -->
|
||
<custom-navbar title="设置密码" :showBack="true" borderBottom="none" backgroundColor="transparent"></custom-navbar>
|
||
|
||
<view class="password-title">
|
||
<text>设置新密码</text>
|
||
</view>
|
||
|
||
<view class="password-tip">
|
||
<text>登录密码用于美融融商家登录,密码<text style="color: #FF4767;">至少6个字符,不能全是字母或者数字</text></text>
|
||
</view>
|
||
|
||
<!-- 新密码输入区域 -->
|
||
<view class="newPassword">
|
||
<view class="password-text">新密码</view>
|
||
<view class="input-item">
|
||
<input type="text" v-model="newPassword" placeholder="请输入密码" :password="!showNewPassword" maxlength="20"
|
||
class="input-text" @input="checkPwdError" />
|
||
<image src="/static/images/icons/noLook.png" mode="widthFix" class="look-icon" v-if="!showNewPassword"
|
||
@click.stop="showNewPassword = true"></image>
|
||
<image src="/static/images//icons/look.png" mode="widthFix" class="look-icon"
|
||
@click.stop="showNewPassword = false" v-else></image>
|
||
</view>
|
||
<!-- 密码错误提示 -->
|
||
<text class="pwd-error" v-if="pwdErrorMsg">{{pwdErrorMsg}}</text>
|
||
</view>
|
||
|
||
<!-- 确认密码输入区域 -->
|
||
<view class="surePassword">
|
||
<view class="password-text">确认密码</view>
|
||
<view class="input-item">
|
||
<input type="text" v-model="surePassword" placeholder="请输入密码" maxlength="20"
|
||
:password="!showSurePassword" class="input-text" @input="checkPwdError" />
|
||
<image src="/static/images/icons/noLook.png" mode="widthFix" class="look-icon" v-if="!showSurePassword"
|
||
@click.stop="showSurePassword = true"></image>
|
||
<image src="/static/images//icons/look.png" mode="widthFix" class="look-icon"
|
||
@click.stop="showSurePassword = false" v-else></image>
|
||
</view>
|
||
<!-- 两次密码不一致提示 -->
|
||
<text class="pwd-error"
|
||
v-if="!pwdErrorMsg && newPassword && surePassword && newPassword !== surePassword">两次输入的密码不一致</text>
|
||
</view>
|
||
|
||
<!-- 确认按钮 -->
|
||
<view class="select-serve-footer">
|
||
<view class="select-serve-footer__btn" :class="{active: canSubmit}" @click="submit">确认</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import request from '../../utils/request';
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
showNewPassword: false,
|
||
newPassword: "",
|
||
showSurePassword: false,
|
||
surePassword: "",
|
||
pwdErrorMsg: "", // 密码错误提示信息
|
||
phone: uni.getStorageSync('loginAccount') // 登录账号/手机号(从全局缓存或路由参数获取)
|
||
}
|
||
},
|
||
computed: {
|
||
// 判断是否可提交:密码合法 + 两次密码一致 + 均有值
|
||
canSubmit() {
|
||
return !this.pwdErrorMsg && this.newPassword && this.surePassword && this.newPassword === this
|
||
.surePassword;
|
||
}
|
||
},
|
||
onLoad() {
|
||
// 获取登录账号/手机号(从缓存中获取,需与登录页的存储逻辑一致)
|
||
this.phone = uni.getStorageSync('loginAccount') || '';
|
||
// 若从路由参数传递,可使用:this.phone = this.$route.query.phone || '';
|
||
},
|
||
methods: {
|
||
/**
|
||
* 密码校验总函数
|
||
* @param {String} pwd - 待校验的密码
|
||
* @returns {Object} { valid: 布尔值, msg: 错误提示 }
|
||
*/
|
||
validatePassword(pwd) {
|
||
// 1. 长度校验:6-20位
|
||
if (pwd.length < 6 || pwd.length > 20) {
|
||
return {
|
||
valid: false,
|
||
msg: '密码长度需在6-20位之间'
|
||
};
|
||
}
|
||
|
||
// 修复后的禁用字符正则:
|
||
// 去掉易兼容出错的\p{Emoji},改用具体的Emoji Unicode范围
|
||
// 匹配:空格(\s)、中文(\u4e00-\u9fa5)、全角字符(\uFF00-\uFFEF)、常见Emoji(\u{1F600}-\u{1F64F}等)
|
||
const forbiddenReg =
|
||
/[\s\u4e00-\u9fa5\uFF00-\uFFEF\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}]/gu;
|
||
if (forbiddenReg.test(pwd)) {
|
||
return {
|
||
valid: false,
|
||
msg: '密码不可包含空格、中文或特殊表情'
|
||
};
|
||
}
|
||
|
||
|
||
// 3. // 正则说明:
|
||
// (?=.*[A-Za-z]):必须包含至少一个字母
|
||
// (?=.*\d):必须包含至少一个数字
|
||
// [\w\W]{6,20}:匹配任意字符(字母、数字、符号、中文等),长度6-20位
|
||
// 若想限制仅允许常见符号(排除中文),可改用:/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d!@#$%^&*()_+\-=\[\]{}|;':",./<>?]{6,20}$/
|
||
const reg = /^(?=.*[A-Za-z])(?=.*\d)[\w\W]{6,20}$/;
|
||
if (!reg.test(pwd)) {
|
||
return {
|
||
valid: false,
|
||
msg: '密码需包含数字+字母/符号组合'
|
||
};
|
||
}
|
||
|
||
// 4. 禁止包含手机号/账号
|
||
if (this.phone && pwd.includes(this.phone)) {
|
||
return {
|
||
valid: false,
|
||
msg: '密码不可包含账号/手机号,存在安全风险'
|
||
};
|
||
}
|
||
|
||
// 所有校验通过
|
||
return {
|
||
valid: true,
|
||
msg: ''
|
||
};
|
||
},
|
||
|
||
/**
|
||
* 实时检查密码错误
|
||
*/
|
||
checkPwdError() {
|
||
if (!this.newPassword) {
|
||
this.pwdErrorMsg = '';
|
||
return;
|
||
}
|
||
const {
|
||
valid,
|
||
msg
|
||
} = this.validatePassword(this.newPassword);
|
||
this.pwdErrorMsg = valid ? '' : msg;
|
||
},
|
||
|
||
|
||
|
||
/**
|
||
* 提交设置密码
|
||
*/
|
||
submit() {
|
||
let that = this;
|
||
|
||
// 1. 再次校验密码(防止实时校验被绕过)
|
||
const {
|
||
valid,
|
||
msg
|
||
} = this.validatePassword(this.newPassword);
|
||
if (!valid) {
|
||
uni.showToast({
|
||
title: msg,
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 2. 校验两次密码是否一致
|
||
if (this.newPassword !== this.surePassword) {
|
||
uni.showToast({
|
||
title: '两次输入的密码不一致',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 3. 调用设置密码接口(注意:原接口是sendcode,需替换为实际的设置密码接口)
|
||
request.post('/sj/passwordSet', { // 建议替换为实际接口名
|
||
account: that.phone,
|
||
password: that.surePassword
|
||
}).then(result => {
|
||
if (result.code == 200) {
|
||
uni.showToast({
|
||
title: '密码设置成功',
|
||
icon: 'success'
|
||
});
|
||
// 密码设置成功后返回上一页
|
||
setTimeout(() => {
|
||
uni.navigateBack();
|
||
}, 1500);
|
||
} else {
|
||
uni.showToast({
|
||
title: result.msg,
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}).catch(err => {
|
||
uni.showToast({
|
||
title: err.msg,
|
||
icon: 'none'
|
||
});
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.editPassword {
|
||
background-image: url("/static/images/background/editPassword.png");
|
||
background-position: top;
|
||
background-repeat: no-repeat;
|
||
background-size: 100%;
|
||
background-color: #fff;
|
||
min-height: 100vh;
|
||
padding: 0 60rpx;
|
||
position: relative; // 为底部固定按钮做兼容
|
||
|
||
.password-title {
|
||
margin-top: 82rpx;
|
||
font-weight: 500;
|
||
font-size: 46rpx;
|
||
color: #333333;
|
||
line-height: 65rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
|
||
.password-tip {
|
||
margin-top: 20rpx;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
line-height: 40rpx;
|
||
}
|
||
|
||
.newPassword,
|
||
.surePassword {
|
||
margin-top: 100rpx;
|
||
}
|
||
|
||
.surePassword {
|
||
margin-top: 40rpx;
|
||
}
|
||
|
||
.password-text {
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
color: #333333;
|
||
line-height: 45rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
|
||
.input-item {
|
||
display: flex;
|
||
align-items: center;
|
||
box-sizing: border-box;
|
||
width: 630rpx;
|
||
height: 98rpx;
|
||
background: #F5F5F5;
|
||
border-radius: 49rpx;
|
||
padding: 28rpx 24rpx 28rpx 30rpx;
|
||
margin-bottom: 10rpx; // 减少底部间距,给错误提示留空间
|
||
position: relative;
|
||
margin-top: 19rpx;
|
||
|
||
.look-icon {
|
||
width: 37rpx;
|
||
position: absolute;
|
||
top: 50%;
|
||
right: 30rpx;
|
||
transform: translateY(-50%);
|
||
}
|
||
|
||
.input-text {
|
||
flex: 1;
|
||
font-size: 30rpx;
|
||
height: 40rpx;
|
||
color: #333;
|
||
}
|
||
}
|
||
|
||
// 密码错误提示样式
|
||
.pwd-error {
|
||
display: block;
|
||
font-size: 24rpx;
|
||
color: #FF4767;
|
||
margin-left: 30rpx;
|
||
margin-top: 10rpx;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.select-serve-footer {
|
||
background-color: #fff;
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
padding: 40rpx 60rpx;
|
||
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); // 增加阴影提升质感
|
||
|
||
&__btn {
|
||
width: 630rpx;
|
||
height: 98rpx;
|
||
background: rgba(232, 16, 30, 0.4);
|
||
border-radius: 798rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-weight: 500;
|
||
font-size: 30rpx;
|
||
color: #ffffff;
|
||
line-height: 39rpx;
|
||
text-align: center;
|
||
font-style: normal;
|
||
transition: background-color 0.2s ease; // 增加过渡动画
|
||
}
|
||
|
||
.active {
|
||
background: #FF4767;
|
||
|
||
&:active {
|
||
opacity: 0.9; // 点击反馈
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |