orgManager/src/views/set-password.vue

231 lines
5.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="change-password-container">
<div class="header">修改密码</div>
<el-form
:model="form"
:rules="rules"
label-width="120px"
ref="passwordForm"
label-position="top"
status-icon
>
<!-- 新密码输入 -->
<el-form-item label="新密码" prop="newPassword">
<el-input
v-model="form.newPassword"
type="password"
show-password
clearable
placeholder="请输入8-20位包含字母和数字的组合"
>
</el-input>
<!-- 强度指示条 -->
<div class="strength-indicator" :data-strength="strengthLevel">
<div class="indicator-bar" :style="barStyle"></div>
</div>
</el-form-item>
<!-- 警告提示 -->
<el-alert
title="注意:您是首次登录或被重置密码,为了账号安全,请务必修改密码"
type="warning"
:closable="false"
show-icon
class="custom-alert"
/>
<!-- 确认密码输入 -->
<el-form-item label="确认新密码" prop="confirmPassword">
<el-input
v-model="form.confirmPassword"
type="password"
show-password
clearable
placeholder="请再次输入新密码"
></el-input>
</el-form-item>
<!-- 提交按钮 -->
<el-form-item class="submit-btn">
<el-button
type="primary"
@click="submitForm"
style="width: 100%;"
:loading="loading"
>
{{ loading ? '提交中...' : '确认' }}
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { updateUserPassword } from "@/api/system/user";
const router = useRouter();
// 表单数据
const form = ref({
newPassword: '',
confirmPassword: ''
});
// 表单引用
const passwordForm = ref(null);
// 加载状态
const loading = ref(false);
// 密码复杂度验证函数
const validatePassword = (rule, value, callback) => {
if (!value) {
return callback(new Error('密码不能为空'));
}
if (value.length < 6 || value.length > 20) {
return callback(new Error('密码长度需在8-20位之间'));
}
if (!/[A-Za-z]/.test(value) || !/[0-9]/.test(value)) {
return callback(new Error('需包含字母和数字组合'));
}
callback();
};
// 确认密码验证
const validateConfirm = (rule, value, callback) => {
if (value !== form.value.newPassword) {
callback(new Error('两次输入密码不一致'));
} else {
callback();
}
};
// 表单验证规则
const rules = {
newPassword: [
{ required: true, message: '请输入新密码', trigger: 'change' },
{ validator: validatePassword, trigger: 'change' }
],
confirmPassword: [
{ required: true, message: '请输入确认密码', trigger: 'change' },
{ validator: validateConfirm, trigger: 'change' }
]
};
// 提交处理
const submitForm = async () => {
try {
loading.value = true;
await passwordForm.value.validate();
let objForm = {
password:form.value.newPassword
}
// 这里添加实际的API调用
updateUserPassword(objForm).then(response => {
ElMessage.success('密码修改成功3秒后自动跳转');
// 模拟跳转(根据实际需求修改)
setTimeout(() => {
router.replace({ path: "/index", query: '' });
}, 3000);
});
} catch (error) {
ElMessage.error(error.message || '提交失败,请检查表单');
} finally {
loading.value = false;
}
};
// 密码强度计算模型 :ml-citation{ref="2,4" data="citationList"}
const strengthLevel = computed(() => {
const value = form.value.newPassword;
if (!value) return 0;
let score = 0;
// 长度检测
if (value.length >= 6) score++;
if (value.length >= 12) score++;
// 字符类型检测
if (/[A-Za-z]/.test(value)) score++;
if (/\d/.test(value)) score++;
if (/[^\w]/.test(value)) score++;
return Math.min(Math.floor(score/2), 3);
});
// 进度条动态样式
const barStyle = computed(() => ({
width: `${(strengthLevel.value / 3) * 100}%`,
backgroundColor: ['#ff4d4f', '#faad14', '#52c41a'][strengthLevel.value - 1]
}));
</script>
<style scoped lang="scss">
.change-password-container {
width: 100%;
max-width: 500px;
margin: 300px auto;
padding: 30px;
background: rgba(255, 255, 255, 0.9);
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.header {
font-size: 26px;
font-weight: 600;
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
letter-spacing: 2px;
}
/* */
.strength-indicator {
width: 100%;
height: 4px;
background: #f0f0f0;
border-radius: 2px;
overflow: hidden;
margin-top: 8px;
.indicator-bar {
height: 100%;
transition: all 0.3s ease;
}
}
.custom-alert {
margin: 20px 0;
}
.submit-btn {
margin-top: 30px;
display: flex;
justify-content: flex-end;
}
/* */
@media (max-width: 768px) {
.change-password-container {
margin: 20px;
padding: 20px;
}
.header {
font-size: 22px;
}
}
/* */
:deep(.el-input__inner) {
transition: all 0.3s ease;
}
:deep(.el-input__inner:focus) {
border-color: #409eff;
box-shadow: 0 0 8px rgba(64, 158, 255, 0.3);
}
</style>