修改目录
This commit is contained in:
347
src/components/login_module.vue
Normal file
347
src/components/login_module.vue
Normal file
@@ -0,0 +1,347 @@
|
||||
<template>
|
||||
<div class="login-form">
|
||||
<div>登陆</div>
|
||||
<form class="login-form-container" @submit.prevent = "handleLogin">
|
||||
<div class="input-container">
|
||||
<label for="username">QQ号</label>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
v-model="username"
|
||||
placeholder="请输入QQ号"
|
||||
@blur="validateUsername"
|
||||
:class="{ 'error': usernameError }"
|
||||
/>
|
||||
<span class="error-message" v-if="usernameError">{{ usernameError }}</span>
|
||||
</div>
|
||||
<div class="input-container">
|
||||
<label for="password">密码</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
v-model="password"
|
||||
placeholder="请输入密码"
|
||||
@blur="validatePassword"
|
||||
:class="{ 'error': passwordError }"
|
||||
/>
|
||||
<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>
|
||||
</div>
|
||||
<div class="login-button">
|
||||
<button type="submit" :disabled="!isFormValid" >登录</button>
|
||||
</div>
|
||||
<div class="register-link">
|
||||
<a @click.prevent="$emit('register')">注册账号</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref, onMounted, computed} from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { userLogin } from '../api/login'
|
||||
|
||||
const router = useRouter()
|
||||
const VAPTCHAObj = ref(null)
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
|
||||
// 错误信息
|
||||
const usernameError = ref('')
|
||||
const passwordError = ref('')
|
||||
|
||||
const isVaptchaVerified = ref(false)
|
||||
|
||||
const validateUsername = () => {
|
||||
if (!username.value) {
|
||||
usernameError.value = '请输入QQ号码'
|
||||
return false
|
||||
}
|
||||
if (!/^[/\d/g]+$/.test(username.value)) {
|
||||
usernameError.value = 'QQ号码只能包含数字'
|
||||
return false
|
||||
}
|
||||
if (username.value.length < 4) {
|
||||
usernameError.value = 'QQ号码长度不能小于4个字符'
|
||||
return false
|
||||
}
|
||||
usernameError.value = ''
|
||||
return true
|
||||
}
|
||||
|
||||
const validatePassword = () => {
|
||||
if (!password.value) {
|
||||
passwordError.value = '请输入密码'
|
||||
return false
|
||||
}
|
||||
if (password.value.length < 4) {
|
||||
passwordError.value = '密码长度不能小于4个字符'
|
||||
return false
|
||||
}
|
||||
if (password.value.length > 20) {
|
||||
passwordError.value = '密码长度不能超过20个字符'
|
||||
return false
|
||||
}
|
||||
passwordError.value = ''
|
||||
return true
|
||||
}
|
||||
|
||||
const isFormValid = computed(() => {
|
||||
return !usernameError.value &&
|
||||
!passwordError.value &&
|
||||
username.value &&
|
||||
password.value &&
|
||||
VAPTCHAObj.value && // 确保人机验证已初始化
|
||||
isVaptchaVerified.value // 确保人机验证已通过
|
||||
})
|
||||
|
||||
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
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const handleLogin = async () => {
|
||||
try {
|
||||
// 验证表单
|
||||
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
|
||||
)
|
||||
|
||||
// 登录成功,跳转到首页
|
||||
if (response.access_token) {
|
||||
router.push('/dashboard')
|
||||
} else {
|
||||
throw new Error('登录失败:未获取到访问令牌')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error)
|
||||
alert(error.response?.data?.message || error.message || '登录失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
|
||||
const validateForm = () => {
|
||||
if (!username.value || !password.value) {
|
||||
alert('请输入用户名和密码')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-form {
|
||||
width: 340px;
|
||||
margin: 0 auto;
|
||||
background: rgba(255,255,255,0.95);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 32px rgba(0,0,0,0.10);
|
||||
padding: 36px 32px 28px 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.login-form > div:first-child {
|
||||
font-size: 26px;
|
||||
font-weight: bold;
|
||||
color: #222;
|
||||
margin-bottom: 28px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.login-form-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.input-container label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.input-container input {
|
||||
height: 40px;
|
||||
border: 1px solid #d0d7de;
|
||||
border-radius: 6px;
|
||||
padding: 0 12px;
|
||||
font-size: 15px;
|
||||
background: #f7fbfd;
|
||||
transition: border 0.2s;
|
||||
}
|
||||
|
||||
.input-container input:focus {
|
||||
border: 1.5px solid #409eff;
|
||||
outline: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.login-button {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.login-button button {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
background: linear-gradient(90deg, #409eff 0%, #6dd5fa 100%);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 8px rgba(64,158,255,0.10);
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.login-button button:hover {
|
||||
background: linear-gradient(90deg, #66b1ff 0%, #6dd5fa 100%);
|
||||
}
|
||||
|
||||
.register-link {
|
||||
margin-top: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.register-link a {
|
||||
color: #409eff;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.register-link a:hover {
|
||||
color: #1a73e8;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* VAPTCHA 相关样式 */
|
||||
.VAPTCHA-init-main {
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f7fbfd;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #d0d7de;
|
||||
}
|
||||
|
||||
.VAPTCHA-init-loading {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.VAPTCHA-init-loading>a {
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.VAPTCHA-init-loading .VAPTCHA-text {
|
||||
font-family: sans-serif;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.error-message {
|
||||
color: #f56c6c;
|
||||
font-size: 12px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.input-container input.error {
|
||||
border-color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
383
src/components/register_module.vue
Normal file
383
src/components/register_module.vue
Normal file
@@ -0,0 +1,383 @@
|
||||
<template>
|
||||
<div class="login-form">
|
||||
<div>注册</div>
|
||||
<form class="login-form-container" @submit.prevent="handleRegister">
|
||||
<div class="input-container">
|
||||
<label for="username">QQ号</label>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
v-model="username"
|
||||
placeholder="请输入QQ号"
|
||||
@blur="validateUsername"
|
||||
:class="{ 'error': usernameError }"
|
||||
/>
|
||||
<span class="error-message" v-if="usernameError">{{ usernameError }}</span>
|
||||
</div>
|
||||
<div class="input-container">
|
||||
<label for="password">密码</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
v-model="password"
|
||||
placeholder="请输入密码"
|
||||
@blur="validatePassword"
|
||||
:class="{ 'error': passwordError }"
|
||||
/>
|
||||
<span class="error-message" v-if="passwordError">{{ passwordError }}</span>
|
||||
</div>
|
||||
<div class="input-container">
|
||||
<label for="confirmPassword">再次输入密码</label>
|
||||
<input
|
||||
type="password"
|
||||
id="confirmPassword"
|
||||
v-model="confirmPassword"
|
||||
placeholder="请输入密码"
|
||||
@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>
|
||||
</div>
|
||||
<div class="login-button">
|
||||
<button type="submit" :disabled="!isFormValid">注册</button>
|
||||
</div>
|
||||
<div class="register-link">
|
||||
<a @click.prevent="$emit('login')">返回登陆</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { userRegister } from "@/api/login.js";
|
||||
|
||||
const router = useRouter()
|
||||
const VAPTCHAObj = ref(null)
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const confirmPassword = ref('')
|
||||
|
||||
// 错误信息
|
||||
const usernameError = ref('')
|
||||
const passwordError = ref('')
|
||||
const confirmPasswordError = ref('')
|
||||
|
||||
|
||||
|
||||
// 表单验证规则
|
||||
const validateUsername = () => {
|
||||
if (!username.value) {
|
||||
usernameError.value = '请输入QQ号码'
|
||||
return false
|
||||
}
|
||||
// 只允许纯数字
|
||||
if (!/^\d+$/.test(username.value)) {
|
||||
usernameError.value = 'QQ号只能包含数字'
|
||||
return false
|
||||
}
|
||||
usernameError.value = ''
|
||||
return true
|
||||
}
|
||||
|
||||
const validatePassword = () => {
|
||||
if (!password.value) {
|
||||
passwordError.value = '请输入密码'
|
||||
return false
|
||||
}
|
||||
if (password.value.length < 6) {
|
||||
passwordError.value = '密码长度不能小于6个字符'
|
||||
return false
|
||||
}
|
||||
passwordError.value = ''
|
||||
return true
|
||||
}
|
||||
|
||||
const validateConfirmPassword = () => {
|
||||
if (!confirmPassword.value) {
|
||||
confirmPasswordError.value = '请再次输入密码'
|
||||
return false
|
||||
}
|
||||
if (confirmPassword.value !== password.value) {
|
||||
confirmPasswordError.value = '两次输入的密码不一致'
|
||||
return false
|
||||
}
|
||||
confirmPasswordError.value = ''
|
||||
return true
|
||||
}
|
||||
const isVaptchaVerified = ref(false)
|
||||
// 计算表单是否有效
|
||||
const isFormValid = computed(() => {
|
||||
return !usernameError.value &&
|
||||
!passwordError.value &&
|
||||
!confirmPasswordError.value &&
|
||||
username.value &&
|
||||
password.value &&
|
||||
confirmPassword.value &&
|
||||
VAPTCHAObj.value && // 确保人机验证已初始化
|
||||
isVaptchaVerified.value // 确保人机验证已通过
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 添加人机验证状态
|
||||
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('验证关闭')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const handleRegister = async () => {
|
||||
try {
|
||||
// 验证表单
|
||||
if (!validateUsername() || !validatePassword() || !validateConfirmPassword()) {
|
||||
return
|
||||
}
|
||||
// 验证人机验证
|
||||
if (!isVaptchaVerified.value || !VAPTCHAObj.value) {
|
||||
alert('请完成人机验证')
|
||||
return
|
||||
}
|
||||
|
||||
// 获取验证token
|
||||
try {
|
||||
const serverToken = await VAPTCHAObj.value.getServerToken()
|
||||
console.log('获取到的 serverToken:', serverToken)
|
||||
|
||||
if (!serverToken || !serverToken.token || !serverToken.server) {
|
||||
alert('获取验证token失败,请重新验证')
|
||||
return
|
||||
}
|
||||
|
||||
// 构造注册请求参数
|
||||
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')
|
||||
} catch (tokenError) {
|
||||
console.error('获取验证token失败:', tokenError)
|
||||
alert('获取验证token失败,请重新验证')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('注册失败:', error)
|
||||
alert(error.message || '注册失败')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-form {
|
||||
width: 340px;
|
||||
margin: 0 auto;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 32px rgba(0, 0, 0, 0.10);
|
||||
padding: 36px 32px 28px 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.login-form>div:first-child {
|
||||
font-size: 26px;
|
||||
font-weight: bold;
|
||||
color: #222;
|
||||
margin-bottom: 28px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.login-form-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.input-container label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.input-container input {
|
||||
height: 40px;
|
||||
border: 1px solid #d0d7de;
|
||||
border-radius: 6px;
|
||||
padding: 0 12px;
|
||||
font-size: 15px;
|
||||
background: #f7fbfd;
|
||||
transition: border 0.2s;
|
||||
}
|
||||
|
||||
.input-container input:focus {
|
||||
border: 1.5px solid #409eff;
|
||||
outline: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.input-container input.error {
|
||||
border-color: #f56c6c;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: #f56c6c;
|
||||
font-size: 12px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.login-button {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.login-button button {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
background: linear-gradient(90deg, #409eff 0%, #6dd5fa 100%);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.10);
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.login-button button:hover:not(:disabled) {
|
||||
background: linear-gradient(90deg, #66b1ff 0%, #6dd5fa 100%);
|
||||
}
|
||||
|
||||
.login-button button:disabled {
|
||||
background: #a0cfff;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.register-link {
|
||||
margin-top: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.register-link a {
|
||||
color: #409eff;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.register-link a:hover {
|
||||
color: #1a73e8;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* VAPTCHA 相关样式 */
|
||||
.VAPTCHA-init-main {
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f7fbfd;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #d0d7de;
|
||||
}
|
||||
|
||||
.VAPTCHA-init-loading {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.VAPTCHA-init-loading>a {
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.VAPTCHA-init-loading .VAPTCHA-text {
|
||||
font-family: sans-serif;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user