修改登陆api
This commit is contained in:
parent
4f5e971cb6
commit
60667511b4
@ -5,7 +5,6 @@
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
<script src="https://v-cn.vaptcha.com/v3.js"></script>
|
||||
<title>红色警戒3数据分析中心</title>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -50,39 +50,45 @@ import { loginSuccess } from '../utils/jwt';
|
||||
// }
|
||||
// )
|
||||
|
||||
export const userLogin = async (username, password, server, token) => {
|
||||
// 获取验证码
|
||||
export const getCaptcha = async () => {
|
||||
try {
|
||||
const response = await axiosInstance.get('/captcha');
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 用户登录
|
||||
export const userLogin = async (username, password, token, captcha) => {
|
||||
try {
|
||||
// console.log('登录请求参数:', { username, password, server, token }); // 保留此调试日志以备将来使用,或按需移除
|
||||
const response = await axiosInstance.post('/user/login', {
|
||||
username,
|
||||
password,
|
||||
server,
|
||||
token
|
||||
token,
|
||||
captcha
|
||||
});
|
||||
|
||||
if (response.data.access_token) {
|
||||
loginSuccess(response.data.access_token, username); // 使用 username 作为 userId
|
||||
loginSuccess(response.data.access_token);
|
||||
}
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
// 错误将由响应拦截器统一处理和记录,这里可以直接抛出
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const userRegister = async (qq_code, password, server, token) => {
|
||||
// 用户注册
|
||||
export const userRegister = async (qq_code, password, token, captcha) => {
|
||||
try {
|
||||
const requestData = {
|
||||
const response = await axiosInstance.post('/user/register', {
|
||||
qq_code,
|
||||
password,
|
||||
server,
|
||||
token
|
||||
};
|
||||
// console.log('注册请求参数:', requestData); // 保留此调试日志以备将来使用,或按需移除
|
||||
|
||||
const response = await axiosInstance.post('/user/register', requestData);
|
||||
// console.log('注册响应数据:', response.data); // 保留此调试日志以备将来使用,或按需移除
|
||||
token,
|
||||
captcha
|
||||
});
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="login-form">
|
||||
<div>登陆</div>
|
||||
<form class="login-form-container" @submit.prevent = "handleLogin">
|
||||
<form class="login-form-container" @submit.prevent="handleLogin">
|
||||
<div class="input-container">
|
||||
<label for="username">QQ号</label>
|
||||
<input
|
||||
@ -26,43 +26,29 @@
|
||||
/>
|
||||
<span class="error-message" v-if="passwordError">{{ passwordError }}</span>
|
||||
</div>
|
||||
<div class="input-container">
|
||||
<!-- 人机验证 -->
|
||||
<div id="VAPTCHAContainer" style="width: 100%; height: 36px;">
|
||||
<div class="VAPTCHA-init-main">
|
||||
<div class="VAPTCHA-init-loading">
|
||||
<a href="/" target="_blank">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48px"
|
||||
height="60px" viewBox="0 0 24 30"
|
||||
style="enable-background: new 0 0 50 50; width: 14px; height: 14px; vertical-align: middle"
|
||||
xml:space="preserve">
|
||||
<rect x="0" y="9.22656" width="4" height="12.5469" fill="#CCCCCC">
|
||||
<animate attributeName="height" attributeType="XML" values="5;21;5" begin="0s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
<animate attributeName="y" attributeType="XML" values="13; 5; 13" begin="0s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
<rect x="10" y="5.22656" width="4" height="20.5469" fill="#CCCCCC">
|
||||
<animate attributeName="height" attributeType="XML" values="5;21;5" begin="0.15s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
<animate attributeName="y" attributeType="XML" values="13; 5; 13" begin="0.15s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
<rect x="20" y="8.77344" width="4" height="13.4531" fill="#CCCCCC">
|
||||
<animate attributeName="height" attributeType="XML" values="5;21;5" begin="0.3s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
<animate attributeName="y" attributeType="XML" values="13; 5; 13" begin="0.3s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</svg>
|
||||
</a>
|
||||
<span class="VAPTCHA-text">Vaptcha Initializing...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-container captcha-container">
|
||||
<label for="captcha">验证码</label>
|
||||
<div class="captcha-wrapper">
|
||||
<input
|
||||
type="text"
|
||||
id="captcha"
|
||||
v-model="captcha"
|
||||
placeholder="请输入验证码"
|
||||
@blur="validateCaptcha"
|
||||
:class="{ 'error': captchaError }"
|
||||
/>
|
||||
<img
|
||||
v-if="captchaImage"
|
||||
:src="captchaImage"
|
||||
alt="验证码"
|
||||
class="captcha-image"
|
||||
@click="refreshCaptcha"
|
||||
/>
|
||||
</div>
|
||||
<span class="error-message" v-if="captchaError">{{ captchaError }}</span>
|
||||
</div>
|
||||
<div class="login-button">
|
||||
<button type="submit" :disabled="!isFormValid" >登录</button>
|
||||
<button type="submit" :disabled="!isFormValid">登录</button>
|
||||
</div>
|
||||
<div class="register-link">
|
||||
<a @click.prevent="$emit('register')">注册账号</a>
|
||||
@ -72,20 +58,21 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref, onMounted, computed} from 'vue'
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { userLogin } from '../api/login'
|
||||
import { userLogin, getCaptcha } from '../api/login'
|
||||
|
||||
const router = useRouter()
|
||||
const VAPTCHAObj = ref(null)
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const captcha = ref('')
|
||||
const captchaImage = ref('')
|
||||
const captchaToken = ref('')
|
||||
|
||||
// 错误信息
|
||||
const usernameError = ref('')
|
||||
const passwordError = ref('')
|
||||
|
||||
const isVaptchaVerified = ref(false)
|
||||
const captchaError = ref('')
|
||||
|
||||
const validateUsername = () => {
|
||||
if (!username.value) {
|
||||
@ -121,40 +108,43 @@ const validatePassword = () => {
|
||||
return true
|
||||
}
|
||||
|
||||
const validateCaptcha = () => {
|
||||
if (!captcha.value) {
|
||||
captchaError.value = '请输入验证码'
|
||||
return false
|
||||
}
|
||||
if (captcha.value.length !== 4) {
|
||||
captchaError.value = '验证码长度不正确'
|
||||
return false
|
||||
}
|
||||
captchaError.value = ''
|
||||
return true
|
||||
}
|
||||
|
||||
const isFormValid = computed(() => {
|
||||
return !usernameError.value &&
|
||||
!passwordError.value &&
|
||||
!captchaError.value &&
|
||||
username.value &&
|
||||
password.value &&
|
||||
VAPTCHAObj.value && // 确保人机验证已初始化
|
||||
isVaptchaVerified.value // 确保人机验证已通过
|
||||
captcha.value
|
||||
})
|
||||
|
||||
const refreshCaptcha = async () => {
|
||||
try {
|
||||
const response = await getCaptcha()
|
||||
// 直接使用API返回的img(base64格式的验证码图片)
|
||||
captchaImage.value = `data:image/png;base64,${response.img}`
|
||||
captchaToken.value = response.token
|
||||
captcha.value = '' // 清空验证码输入
|
||||
} catch (error) {
|
||||
console.error('获取验证码失败:', error)
|
||||
alert('获取验证码失败,请刷新页面重试')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.vaptcha({
|
||||
vid: '6828264bdc0ff12924d9bfe3',
|
||||
mode: 'click',
|
||||
scene: 1,
|
||||
container: '#VAPTCHAContainer',
|
||||
area: 'auto'
|
||||
}).then(function (obj) {
|
||||
VAPTCHAObj.value = obj
|
||||
obj.render()
|
||||
// 监听验证成功事件
|
||||
obj.listen('pass', function () {
|
||||
isVaptchaVerified.value = true
|
||||
})
|
||||
|
||||
// 监听验证失败事件
|
||||
obj.listen('fail', function () {
|
||||
isVaptchaVerified.value = false
|
||||
})
|
||||
|
||||
// 监听关闭事件
|
||||
obj.listen('close', function () {
|
||||
isVaptchaVerified.value = false
|
||||
})
|
||||
})
|
||||
refreshCaptcha()
|
||||
})
|
||||
|
||||
const handleLogin = async () => {
|
||||
@ -163,58 +153,37 @@ const handleLogin = async () => {
|
||||
if (!validateForm()) {
|
||||
return
|
||||
}
|
||||
// 验证人机验证
|
||||
if (!VAPTCHAObj.value) {
|
||||
alert('请完成人机验证')
|
||||
return
|
||||
}
|
||||
const serverToken = await VAPTCHAObj.value.getServerToken()
|
||||
console.log('获取到的 serverToken:', serverToken)
|
||||
|
||||
if (!serverToken || !serverToken.token || !serverToken.server) {
|
||||
alert('获取验证token失败,请重新验证')
|
||||
return
|
||||
}
|
||||
const registerData = {
|
||||
username: username.value,
|
||||
password: password.value,
|
||||
server: serverToken.server,
|
||||
token: serverToken.token
|
||||
}
|
||||
// 调用登录 API
|
||||
const response = await userLogin(
|
||||
registerData.username,
|
||||
registerData.password,
|
||||
registerData.server,
|
||||
registerData.token
|
||||
username.value,
|
||||
password.value,
|
||||
captchaToken.value,
|
||||
captcha.value
|
||||
)
|
||||
|
||||
// 登录成功,跳转到首页
|
||||
if (response.access_token) {
|
||||
// 存储 token 和用户ID (QQ号)
|
||||
localStorage.setItem('access_token', response.access_token)
|
||||
localStorage.setItem('user_id', username.value) // username.value 是用户输入的QQ号
|
||||
localStorage.setItem('user_id', username.value)
|
||||
router.push('/')
|
||||
|
||||
} else {
|
||||
throw new Error('登录失败:未获取到访问令牌')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error)
|
||||
if (error.response && error.response.status === 401) {
|
||||
alert('错误的用户名或密码,或未注册')
|
||||
alert('错误的用户名或密码')
|
||||
} else {
|
||||
alert(error.response?.data?.message || error.message || '登录失败,请稍后重试')
|
||||
}
|
||||
// 登录失败时刷新验证码
|
||||
refreshCaptcha()
|
||||
}
|
||||
}
|
||||
|
||||
const validateForm = () => {
|
||||
if (!username.value || !password.value) {
|
||||
alert('请输入用户名和密码')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return validateUsername() && validatePassword() && validateCaptcha()
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -351,5 +320,98 @@ const validateForm = () => {
|
||||
.input-container input.error {
|
||||
border-color: #f56c6c;
|
||||
}
|
||||
|
||||
.captcha-container {
|
||||
margin-bottom: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.captcha-wrapper {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.captcha-wrapper input {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
border: 1px solid #d0d7de;
|
||||
border-radius: 6px;
|
||||
padding: 0 12px;
|
||||
font-size: 15px;
|
||||
background: #f7fbfd;
|
||||
transition: border 0.2s;
|
||||
width: calc(100% - 120px); /* 减去验证码图片的宽度和间距 */
|
||||
}
|
||||
|
||||
.captcha-wrapper input:focus {
|
||||
border: 1.5px solid #409eff;
|
||||
outline: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.captcha-image {
|
||||
width: 110px;
|
||||
height: 40px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
object-fit: cover;
|
||||
border: 1px solid #d0d7de;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.captcha-image:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 移动端适配 */
|
||||
@media screen and (max-width: 480px) {
|
||||
.login-form {
|
||||
width: 90%;
|
||||
max-width: 340px;
|
||||
padding: 24px 20px 20px 20px;
|
||||
}
|
||||
|
||||
.captcha-wrapper {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.captcha-wrapper input {
|
||||
width: calc(100% - 100px);
|
||||
}
|
||||
|
||||
.captcha-image {
|
||||
width: 90px;
|
||||
}
|
||||
|
||||
.input-container input,
|
||||
.captcha-wrapper input {
|
||||
height: 38px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.login-button button {
|
||||
height: 40px;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 超小屏幕适配 */
|
||||
@media screen and (max-width: 320px) {
|
||||
.login-form {
|
||||
padding: 20px 16px 16px 16px;
|
||||
}
|
||||
|
||||
.captcha-wrapper input {
|
||||
width: calc(100% - 90px);
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.captcha-image {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -20,40 +20,26 @@
|
||||
@blur="validateConfirmPassword" :class="{ 'error': confirmPasswordError }" />
|
||||
<span class="error-message" v-if="confirmPasswordError">{{ confirmPasswordError }}</span>
|
||||
</div>
|
||||
<div class="input-container">
|
||||
<!-- 人机验证 -->
|
||||
<div id="VAPTCHAContainer" style="width: 100%; height: 36px;">
|
||||
<div class="VAPTCHA-init-main">
|
||||
<div class="VAPTCHA-init-loading">
|
||||
<a href="/" target="_blank">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48px"
|
||||
height="60px" viewBox="0 0 24 30"
|
||||
style="enable-background: new 0 0 50 50; width: 14px; height: 14px; vertical-align: middle"
|
||||
xml:space="preserve">
|
||||
<rect x="0" y="9.22656" width="4" height="12.5469" fill="#CCCCCC">
|
||||
<animate attributeName="height" attributeType="XML" values="5;21;5" begin="0s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
<animate attributeName="y" attributeType="XML" values="13; 5; 13" begin="0s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
<rect x="10" y="5.22656" width="4" height="20.5469" fill="#CCCCCC">
|
||||
<animate attributeName="height" attributeType="XML" values="5;21;5" begin="0.15s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
<animate attributeName="y" attributeType="XML" values="13; 5; 13" begin="0.15s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
<rect x="20" y="8.77344" width="4" height="13.4531" fill="#CCCCCC">
|
||||
<animate attributeName="height" attributeType="XML" values="5;21;5" begin="0.3s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
<animate attributeName="y" attributeType="XML" values="13; 5; 13" begin="0.3s" dur="0.6s"
|
||||
repeatCount="indefinite"></animate>
|
||||
</rect>
|
||||
</svg>
|
||||
</a>
|
||||
<span class="VAPTCHA-text">Vaptcha Initializing...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-container captcha-container">
|
||||
<label for="captcha">验证码</label>
|
||||
<div class="captcha-wrapper">
|
||||
<input
|
||||
type="text"
|
||||
id="captcha"
|
||||
v-model="captcha"
|
||||
placeholder="请输入验证码"
|
||||
@blur="validateCaptcha"
|
||||
:class="{ 'error': captchaError }"
|
||||
/>
|
||||
<img
|
||||
v-if="captchaImage"
|
||||
:src="captchaImage"
|
||||
alt="验证码"
|
||||
class="captcha-image"
|
||||
@click="refreshCaptcha"
|
||||
/>
|
||||
</div>
|
||||
<span class="error-message" v-if="captchaError">{{ captchaError }}</span>
|
||||
</div>
|
||||
<div class="login-button">
|
||||
<button type="submit" :disabled="!isFormValid">注册</button>
|
||||
@ -68,13 +54,15 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { userRegister } from "@/api/login.js";
|
||||
import { userRegister, getCaptcha } from "@/api/login.js";
|
||||
|
||||
const router = useRouter()
|
||||
const VAPTCHAObj = ref(null)
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const confirmPassword = ref('')
|
||||
const captcha = ref('')
|
||||
const captchaImage = ref('')
|
||||
const captchaToken = ref('')
|
||||
|
||||
// 定义 emit
|
||||
const emit = defineEmits(['login'])
|
||||
@ -83,8 +71,7 @@ const emit = defineEmits(['login'])
|
||||
const usernameError = ref('')
|
||||
const passwordError = ref('')
|
||||
const confirmPasswordError = ref('')
|
||||
|
||||
|
||||
const captchaError = ref('')
|
||||
|
||||
// 表单验证规则
|
||||
const validateUsername = () => {
|
||||
@ -126,92 +113,76 @@ const validateConfirmPassword = () => {
|
||||
confirmPasswordError.value = ''
|
||||
return true
|
||||
}
|
||||
const isVaptchaVerified = ref(false)
|
||||
|
||||
const validateCaptcha = () => {
|
||||
if (!captcha.value) {
|
||||
captchaError.value = '请输入验证码'
|
||||
return false
|
||||
}
|
||||
if (captcha.value.length !== 4) {
|
||||
captchaError.value = '验证码长度不正确'
|
||||
return false
|
||||
}
|
||||
captchaError.value = ''
|
||||
return true
|
||||
}
|
||||
|
||||
// 计算表单是否有效
|
||||
const isFormValid = computed(() => {
|
||||
return !usernameError.value &&
|
||||
!passwordError.value &&
|
||||
!confirmPasswordError.value &&
|
||||
!captchaError.value &&
|
||||
username.value &&
|
||||
password.value &&
|
||||
confirmPassword.value &&
|
||||
VAPTCHAObj.value && // 确保人机验证已初始化
|
||||
isVaptchaVerified.value // 确保人机验证已通过
|
||||
captcha.value
|
||||
})
|
||||
|
||||
const refreshCaptcha = async () => {
|
||||
try {
|
||||
const response = await getCaptcha()
|
||||
captchaImage.value = `data:image/png;base64,${response.img}`
|
||||
captchaToken.value = response.token
|
||||
captcha.value = '' // 清空验证码输入
|
||||
} catch (error) {
|
||||
console.error('获取验证码失败:', error)
|
||||
alert('获取验证码失败,请刷新页面重试')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 添加人机验证状态
|
||||
onMounted(() => {
|
||||
window.vaptcha({
|
||||
vid: '6828264bdc0ff12924d9bfe3',
|
||||
mode: 'click',
|
||||
scene: 2,
|
||||
container: '#VAPTCHAContainer',
|
||||
area: 'auto'
|
||||
}).then(function (obj) {
|
||||
VAPTCHAObj.value = obj
|
||||
obj.render()
|
||||
|
||||
// 监听验证成功事件
|
||||
obj.listen('pass', function () {
|
||||
isVaptchaVerified.value = true
|
||||
console.log('验证通过')
|
||||
})
|
||||
|
||||
// 监听验证失败事件
|
||||
obj.listen('fail', function () {
|
||||
isVaptchaVerified.value = false
|
||||
console.log('验证失败')
|
||||
})
|
||||
|
||||
// 监听关闭事件
|
||||
obj.listen('close', function () {
|
||||
isVaptchaVerified.value = false
|
||||
console.log('验证关闭')
|
||||
})
|
||||
})
|
||||
refreshCaptcha()
|
||||
})
|
||||
|
||||
const handleRegister = async () => {
|
||||
// 验证表单
|
||||
if (!validateUsername() || !validatePassword() || !validateConfirmPassword()) {
|
||||
return
|
||||
}
|
||||
// 验证人机验证
|
||||
if (!isVaptchaVerified.value || !VAPTCHAObj.value) {
|
||||
alert('请完成人机验证')
|
||||
return
|
||||
}
|
||||
try {
|
||||
// 验证表单
|
||||
if (!validateUsername() || !validatePassword() || !validateConfirmPassword() || !validateCaptcha()) {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取验证token
|
||||
const serverToken = await VAPTCHAObj.value.getServerToken()
|
||||
console.log('获取到的 serverToken:', serverToken)
|
||||
// 发送注册请求
|
||||
await userRegister(
|
||||
username.value,
|
||||
password.value,
|
||||
captchaToken.value,
|
||||
captcha.value
|
||||
)
|
||||
|
||||
if (!serverToken || !serverToken.token || !serverToken.server) {
|
||||
alert('获取验证token失败,请重新验证')
|
||||
return
|
||||
alert('注册成功')
|
||||
// 切换到登录模块
|
||||
emit('login')
|
||||
} catch (error) {
|
||||
console.error('注册失败:', error)
|
||||
if (error.response && error.response.status === 400) {
|
||||
alert('该QQ号已被注册')
|
||||
} else {
|
||||
alert(error.response?.data?.message || error.message || '注册失败,请稍后重试')
|
||||
}
|
||||
// 注册失败时刷新验证码
|
||||
refreshCaptcha()
|
||||
}
|
||||
|
||||
// 构造注册请求参数
|
||||
const registerData = {
|
||||
qq_code: username.value,
|
||||
password: password.value,
|
||||
server: serverToken.server,
|
||||
token: serverToken.token
|
||||
}
|
||||
console.log('注册请求参数:', registerData)
|
||||
|
||||
// 发送注册请求
|
||||
await userRegister(
|
||||
registerData.qq_code,
|
||||
registerData.password,
|
||||
registerData.server,
|
||||
registerData.token
|
||||
)
|
||||
alert('注册成功')
|
||||
// 切换到登录模块
|
||||
emit('login')
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -355,4 +326,97 @@ const handleRegister = async () => {
|
||||
color: #666;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.captcha-container {
|
||||
margin-bottom: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.captcha-wrapper {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.captcha-wrapper input {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
border: 1px solid #d0d7de;
|
||||
border-radius: 6px;
|
||||
padding: 0 12px;
|
||||
font-size: 15px;
|
||||
background: #f7fbfd;
|
||||
transition: border 0.2s;
|
||||
width: calc(100% - 120px); /* 减去验证码图片的宽度和间距 */
|
||||
}
|
||||
|
||||
.captcha-wrapper input:focus {
|
||||
border: 1.5px solid #409eff;
|
||||
outline: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.captcha-image {
|
||||
width: 110px;
|
||||
height: 40px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
object-fit: cover;
|
||||
border: 1px solid #d0d7de;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.captcha-image:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 移动端适配 */
|
||||
@media screen and (max-width: 480px) {
|
||||
.login-form {
|
||||
width: 90%;
|
||||
max-width: 340px;
|
||||
padding: 24px 20px 20px 20px;
|
||||
}
|
||||
|
||||
.captcha-wrapper {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.captcha-wrapper input {
|
||||
width: calc(100% - 100px);
|
||||
}
|
||||
|
||||
.captcha-image {
|
||||
width: 90px;
|
||||
}
|
||||
|
||||
.input-container input,
|
||||
.captcha-wrapper input {
|
||||
height: 38px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.login-button button {
|
||||
height: 40px;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 超小屏幕适配 */
|
||||
@media screen and (max-width: 320px) {
|
||||
.login-form {
|
||||
padding: 20px 16px 16px 16px;
|
||||
}
|
||||
|
||||
.captcha-wrapper input {
|
||||
width: calc(100% - 90px);
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.captcha-image {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user