Files
AIGC/demo/frontend/src/views/SetPassword.vue

368 lines
7.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="login-page">
<!-- Logo -->
<div class="logo">
<img src="/images/backgrounds/logo.svg?v=2" alt="Logo" />
</div>
<!-- 设置密码卡片 -->
<div class="login-card">
<!-- 标题 -->
<div class="page-title">设置密码</div>
<!-- 表单 -->
<div class="password-form">
<!-- 新密码 -->
<div class="input-group">
<el-input
v-model="form.newPassword"
placeholder="输入密码至少8位包含字母和数字"
class="password-input"
show-password
@keyup.enter="handleSubmit"
/>
<div class="input-error" v-if="errors.newPassword">{{ errors.newPassword }}</div>
</div>
<!-- 确认密码 -->
<div class="input-group">
<el-input
v-model="form.confirmPassword"
placeholder="确认密码"
class="password-input"
show-password
@keyup.enter="handleSubmit"
/>
<div class="input-error" v-if="errors.confirmPassword">{{ errors.confirmPassword }}</div>
</div>
<!-- 确定按钮 -->
<el-button
type="primary"
class="submit-button"
:loading="loading"
@click="handleSubmit"
>
{{ loading ? '提交中...' : '确定' }}
</el-button>
<!-- 跳过按钮 -->
<div class="skip-button-wrapper">
<el-button
class="skip-button"
@click="handleSkip"
>
跳过稍后设置
</el-button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useUserStore } from '@/stores/user'
import { ElMessage } from 'element-plus'
import request from '@/api/request'
const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
const loading = ref(false)
const form = reactive({
newPassword: '',
confirmPassword: ''
})
const errors = reactive({
newPassword: '',
confirmPassword: ''
})
// 验证表单
const validateForm = () => {
let valid = true
errors.newPassword = ''
errors.confirmPassword = ''
// 密码必填且必须包含英文字母和数字不少于8位
if (!form.newPassword) {
errors.newPassword = '请输入密码'
valid = false
} else if (form.newPassword.length < 8) {
errors.newPassword = '密码长度至少8位'
valid = false
} else if (!/[a-zA-Z]/.test(form.newPassword)) {
errors.newPassword = '密码必须包含英文字母'
valid = false
} else if (!/[0-9]/.test(form.newPassword)) {
errors.newPassword = '密码必须包含数字'
valid = false
}
// 确认密码必填且必须与密码一致
if (!form.confirmPassword) {
errors.confirmPassword = '请确认密码'
valid = false
} else if (form.newPassword !== form.confirmPassword) {
errors.confirmPassword = '两次输入的密码不一致'
valid = false
}
return valid
}
// 提交设置
const handleSubmit = async () => {
if (!validateForm()) return
loading.value = true
try {
const response = await request({
url: '/auth/change-password',
method: 'post',
data: {
oldPassword: null,
newPassword: form.newPassword,
isFirstTimeSetup: true
}
})
console.log('设置密码响应:', response)
const result = response.data
if (result && result.success) {
ElMessage.success('密码设置成功')
// 清除首次设置标记
localStorage.removeItem('needSetPassword')
// 跳转到首页或之前的页面
const redirect = route.query.redirect || '/'
router.replace(redirect)
} else {
ElMessage.error(result?.message || '设置失败')
}
} catch (error) {
console.error('设置密码失败:', error)
const errorMsg = error.response?.data?.message || error.message || '设置失败,请重试'
ElMessage.error(errorMsg)
} finally {
loading.value = false
}
}
// 跳过
const handleSkip = () => {
// 清除首次设置标记
localStorage.removeItem('needSetPassword')
// 跳转到首页
const redirect = route.query.redirect || '/'
router.replace(redirect)
}
onMounted(() => {
// 检查用户是否已登录
if (!userStore.isAuthenticated) {
router.replace('/login')
}
})
</script>
<style scoped>
.login-page {
min-height: 100vh;
width: 100vw;
height: 100vh;
background: #0a0e1a url('/images/backgrounds/login_bg.png') center/cover no-repeat;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 0;
z-index: 1;
}
/* 左上角Logo */
.logo {
position: absolute;
top: 30px;
left: 30px;
z-index: 10;
}
.logo img {
height: 40px;
width: auto;
}
/* 卡片 */
.login-card {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 550px;
max-width: 90vw;
background: rgba(121, 121, 121, 0.1);
backdrop-filter: blur(50px);
-webkit-backdrop-filter: blur(50px);
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.1);
padding: 60px 80px;
z-index: 10;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
/* 页面标题 */
.page-title {
text-align: center;
font-size: 32px;
font-weight: 500;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 50px;
}
/* 表单 */
.password-form {
display: flex;
flex-direction: column;
gap: 20px;
}
/* 输入组 */
.input-group {
margin-bottom: 5px;
}
.password-input {
width: 100%;
}
.password-input :deep(.el-input__wrapper) {
background: rgba(217, 217, 217, 0.2);
border: none;
border-radius: 10px;
box-shadow: none;
height: 60px;
transition: all 0.3s ease;
}
.password-input :deep(.el-input__wrapper:hover) {
background: rgba(217, 217, 217, 0.25);
}
.password-input :deep(.el-input__wrapper.is-focus) {
background: rgba(217, 217, 217, 0.3);
box-shadow: none;
}
.password-input :deep(.el-input__inner) {
color: rgba(255, 255, 255, 0.9);
background: transparent;
font-size: 16px;
}
.password-input :deep(.el-input__inner::placeholder) {
color: rgba(255, 255, 255, 0.5);
}
.input-error {
color: #ff7875;
font-size: 12px;
margin-top: 6px;
text-align: left;
}
.input-hint {
color: rgba(255, 255, 255, 0.5);
font-size: 12px;
margin-top: 6px;
text-align: left;
}
/* 确定按钮 */
.submit-button {
width: 100%;
height: 60px;
background: #0DC0FF;
border: none;
border-radius: 10px;
color: white;
font-size: 18px;
font-weight: 500;
margin-top: 20px;
transition: all 0.3s ease;
}
.submit-button:hover {
background: #4DD4FF;
transform: translateY(-1px);
}
.submit-button:active {
transform: translateY(0);
}
/* 跳过按钮 */
.skip-button {
width: 100%;
height: 60px;
background: rgba(217, 217, 217, 0.2);
border: none;
border-radius: 10px;
color: rgba(255, 255, 255, 0.9);
font-size: 18px;
font-weight: 500;
transition: all 0.3s ease;
}
.skip-button:hover {
background: rgba(217, 217, 217, 0.3);
}
.skip-button-wrapper {
width: 100%;
}
.skip-button-wrapper .skip-button {
width: 100%;
}
/* 响应式设计 */
@media (max-width: 768px) {
.login-card {
width: 90%;
padding: 40px 30px;
}
.page-title {
font-size: 28px;
}
}
@media (max-width: 480px) {
.login-card {
padding: 30px 20px;
}
.page-title {
font-size: 24px;
}
}
</style>