orgManager/src/views/set-password.vue

231 lines
5.8 KiB
Vue
Raw Normal View History

2025-08-14 10:38:42 +08:00
<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>