mrr.sj.front/pages/settings/password.vue

330 lines
8.5 KiB
Vue
Raw Permalink Normal View History

2026-03-24 11:45:13 +08:00
<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">
2026-06-02 11:39:23 +08:00
<text>登录密码用于美融融商家登录密码<text style="color: #FF4767;">至少6个字符不能全是字母或者数字</text></text>
2026-03-24 11:45:13 +08:00
</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需替换为实际的设置密码接口
2026-03-25 13:29:04 +08:00
request.post('/sj/passwordSet', { // 建议替换为实际接口名
2026-03-24 11:45:13 +08:00
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;
2026-06-02 11:39:23 +08:00
color: #FF4767;
2026-03-24 11:45:13 +08:00
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 {
2026-06-02 11:39:23 +08:00
background: #FF4767;
2026-03-24 11:45:13 +08:00
&:active {
opacity: 0.9; // 点击反馈
}
}
}
}
</style>