优化
This commit is contained in:
@@ -1,62 +1,102 @@
|
||||
<template>
|
||||
<ThemeProvider :color="{
|
||||
middle: { 'bg-base': '#f8fafc' }, // 浅灰底色
|
||||
primary: { DEFAULT: '#60a5fa' } // 柔和蓝色作为主色调
|
||||
}">
|
||||
<!-- 清新风格登录框 -->
|
||||
<div class="login-box rounded-xl bg-white shadow-md p-8 max-w-2xl mx-auto my-10 border border-gray-100 transition-all duration-300 hover:shadow-lg">
|
||||
<a-form :model="form" :wrapperCol="{ span: 24 }" @finish="login" class="login-form w-full p-lg text-gray-700">
|
||||
<div class="third-platform">
|
||||
<div class="third-title mb-6 text-xl text-center font-semibold text-gray-800">抖音同步小帮手</div>
|
||||
<div class="login-page min-h-screen flex items-center justify-center p-4 md:p-8">
|
||||
<ThemeProvider :color="{
|
||||
middle: { 'bg-base': '#f8fafc' },
|
||||
primary: { DEFAULT: '#4f46e5', hover: '#4338ca' }
|
||||
}">
|
||||
<!-- 登录卡片 -->
|
||||
<div class="login-box rounded-2xl shadow-lg p-8 md:p-10 max-w-md w-full border border-gray-200 transition-all duration-500 hover:shadow-xl transform hover:-translate-y-1">
|
||||
<!-- 顶部Logo区域 -->
|
||||
<div class="flex flex-col items-center mb-8">
|
||||
<div class="w-16 h-16 bg-primary/10 rounded-full flex items-center justify-center mb-4">
|
||||
<img src="/public/logo.png">
|
||||
</div>
|
||||
<h2 class="third-title text-2xl font-bold text-gray-800 tracking-tight">抖音同步小帮手</h2>
|
||||
</div>
|
||||
<a-divider class="my-6 bg-gray-200"></a-divider>
|
||||
|
||||
<!-- 清新风格输入框 -->
|
||||
<a-form-item :required="true" name="username" class="mb-5">
|
||||
<a-input v-model:value="form.username" autocomplete="new-username" placeholder="请输入用户名" class="login-input h-[45px] rounded-md bg-gray-50 border-gray-200 text-gray-800 placeholder:text-gray-400 focus:border-primary text-base transition-all focus:ring-1 focus:ring-primary" />
|
||||
</a-form-item>
|
||||
<a-form :model="form" :wrapperCol="{ span: 24 }" @finish="login" class="login-form w-full text-gray-700">
|
||||
<!-- 用户名输入框 -->
|
||||
<a-form-item :required="true" name="username" class="mb-5" :validate-status="usernameStatus">
|
||||
<a-input v-model:value="form.username" autocomplete="new-username" placeholder="请输入用户名" class="login-input h-[50px] rounded-lg bg-gray-50 border-gray-200 text-gray-800 placeholder:text-gray-400 focus:border-primary focus:bg-white text-base transition-all duration-300 focus:ring-2 focus:ring-primary/20">
|
||||
<template #prefix>
|
||||
<svg class="w-5 h-5 text-gray-400 mr-2" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :required="true" name="password" class="mb-2">
|
||||
<a-input v-model:value="form.password" autocomplete="new-password" placeholder="请输入密码" class="login-input h-[45px] rounded-md bg-gray-50 border-gray-200 text-gray-800 placeholder:text-gray-400 focus:border-primary text-base transition-all focus:ring-1 focus:ring-primary" :type="showPassword ? 'text' : 'password'">
|
||||
<!-- 密码显示/隐藏图标 -->
|
||||
<template #suffix>
|
||||
<EyeOutlined v-if="showPassword" @click="showPassword = !showPassword" class="text-gray-400 hover:text-primary cursor-pointer transition-colors" aria-label="隐藏密码" />
|
||||
<EyeInvisibleOutlined v-else @click="showPassword = !showPassword" class="text-gray-400 hover:text-primary cursor-pointer transition-colors" aria-label="显示密码" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<!-- 密码输入框 -->
|
||||
<a-form-item :required="true" name="password" class="mb-2" :validate-status="passwordStatus">
|
||||
<a-input v-model:value="form.password" autocomplete="new-password" placeholder="请输入密码" class="login-input h-[50px] rounded-lg bg-gray-50 border-gray-200 text-gray-800 placeholder:text-gray-400 focus:border-primary focus:bg-white text-base transition-all duration-300 focus:ring-2 focus:ring-primary/20" :type="showPassword ? 'text' : 'password'">
|
||||
<template #prefix>
|
||||
<svg class="w-5 h-5 text-gray-400 mr-2" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||||
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
||||
</svg>
|
||||
</template>
|
||||
<!-- 密码显示/隐藏图标 -->
|
||||
<template #suffix>
|
||||
<EyeOutlined v-if="showPassword" @click="showPassword = !showPassword" class="text-gray-400 hover:text-primary cursor-pointer transition-colors duration-300 text-lg" aria-label="隐藏密码" />
|
||||
<EyeInvisibleOutlined v-else @click="showPassword = !showPassword" class="text-gray-400 hover:text-primary cursor-pointer transition-colors duration-300 text-lg" aria-label="显示密码" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 记住密码选项 -->
|
||||
<a-form-item class="mb-6 pl-2">
|
||||
<a-checkbox v-model:checked="rememberPassword" class="text-gray-600 hover:text-primary transition-colors">
|
||||
记住密码
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<!-- 记住密码与忘记密码 -->
|
||||
<div class="flex items-center justify-between mb-6 px-1">
|
||||
<a-form-item class="mb-0">
|
||||
<a-checkbox v-model:checked="rememberPassword" class="text-gray-600 hover:text-primary transition-colors duration-300 cursor-pointer">
|
||||
<span class="text-sm">记住密码</span>
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<!-- <a href="#" class="text-primary hover:text-primary/80 text-sm font-medium transition-colors duration-300" @click.prevent="handleForgotPassword">
|
||||
忘记密码?
|
||||
</a> -->
|
||||
</div>
|
||||
|
||||
<a-button htmlType="submit" class="h-[48px] w-full rounded-md transition-colors hover:bg-primary/90 bg-primary border-primary text-white text-base shadow-sm hover:shadow" type="primary" :loading="loading">
|
||||
登录
|
||||
</a-button>
|
||||
</a-form>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
<!-- 登录按钮 -->
|
||||
<a-button htmlType="submit" class="h-[52px] w-full rounded-lg transition-all duration-300 hover:bg-primary/90 bg-primary border-primary text-white text-base font-medium shadow-md hover:shadow-lg transform hover:-translate-y-0.5 active:translate-y-0" type="primary" :loading="loading">
|
||||
<span v-if="!loading">登录</span>
|
||||
<span v-else>登录中...</span>
|
||||
</a-button>
|
||||
|
||||
<!-- 注册入口 -->
|
||||
<!-- <div class="text-center mt-6 text-gray-500 text-sm">
|
||||
还没有账号?
|
||||
<a href="#" class="text-primary hover:text-primary/80 font-medium transition-colors duration-300 ml-1" @click.prevent="handleRegister">
|
||||
立即注册
|
||||
</a>
|
||||
</div> -->
|
||||
</a-form>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { reactive, ref, onMounted, computed } from 'vue';
|
||||
import { useAccountStore } from '@/store';
|
||||
import { ThemeProvider } from 'stepin';
|
||||
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
// 控制密码显示/隐藏的状态
|
||||
const showPassword = ref(false);
|
||||
// 记住密码状态
|
||||
const rememberPassword = ref(false);
|
||||
// 加载状态
|
||||
const loading = ref(false);
|
||||
|
||||
// 表单状态(用于输入框验证反馈)
|
||||
const usernameStatus = computed(() => (form.username ? 'success' : ''));
|
||||
const passwordStatus = computed(() => (form.password ? 'success' : ''));
|
||||
|
||||
export interface LoginFormProps {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
const loading = ref(false);
|
||||
|
||||
const form = reactive<LoginFormProps>({
|
||||
username: '',
|
||||
@@ -66,6 +106,8 @@ const form = reactive<LoginFormProps>({
|
||||
const emit = defineEmits<{
|
||||
(e: 'success', fields: LoginFormProps): void;
|
||||
(e: 'failure', reason: string, fields: LoginFormProps): void;
|
||||
(e: 'register'): void;
|
||||
(e: 'forgot-password'): void;
|
||||
}>();
|
||||
|
||||
const accountStore = useAccountStore();
|
||||
@@ -86,7 +128,18 @@ onMounted(() => {
|
||||
}
|
||||
});
|
||||
|
||||
function login(params: LoginFormProps) {
|
||||
// 登录处理
|
||||
async function login(params: LoginFormProps) {
|
||||
// 简单表单验证
|
||||
if (!params.username) {
|
||||
message.warning('请输入用户名');
|
||||
return;
|
||||
}
|
||||
if (!params.password) {
|
||||
message.warning('请输入密码');
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
|
||||
// 根据记住密码状态保存/清除用户信息
|
||||
@@ -102,14 +155,95 @@ function login(params: LoginFormProps) {
|
||||
localStorage.removeItem('rememberedUser');
|
||||
}
|
||||
|
||||
accountStore
|
||||
.login(params.username, params.password)
|
||||
.then((res) => {
|
||||
emit('success', params);
|
||||
})
|
||||
.catch((e) => {
|
||||
emit('failure', e.message, e.data);
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
try {
|
||||
const res = await accountStore.login(params.username, params.password);
|
||||
emit('success', params);
|
||||
message.success('登录成功!');
|
||||
} catch (e: any) {
|
||||
// emit('failure', e.message, e.data);
|
||||
message.error(e.data.erro || '登录失败,请重试');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
// 忘记密码处理
|
||||
function handleForgotPassword() {
|
||||
emit('forgot-password');
|
||||
message.info('忘记密码功能即将上线');
|
||||
}
|
||||
|
||||
// 注册处理
|
||||
function handleRegister() {
|
||||
emit('register');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 页面基础样式 */
|
||||
.login-page {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
|
||||
/* 输入框聚焦动画优化 */
|
||||
::v-deep(.ant-input:focus) {
|
||||
box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2) !important;
|
||||
border-color: #4f46e5 !important;
|
||||
}
|
||||
|
||||
/* 复选框样式优化 */
|
||||
::v-deep(.ant-checkbox-checked .ant-checkbox-inner) {
|
||||
background-color: #4f46e5 !important;
|
||||
border-color: #4f46e5 !important;
|
||||
}
|
||||
|
||||
::v-deep(.ant-checkbox:hover .ant-checkbox-inner) {
|
||||
border-color: #4f46e5 !important;
|
||||
}
|
||||
|
||||
/* 按钮样式优化 */
|
||||
::v-deep(.ant-btn-primary) {
|
||||
background-color: #4f46e5 !important;
|
||||
border-color: #4f46e5 !important;
|
||||
}
|
||||
|
||||
::v-deep(.ant-btn-primary:hover) {
|
||||
background-color: #4338ca !important;
|
||||
border-color: #4338ca !important;
|
||||
}
|
||||
|
||||
::v-deep(.ant-btn-primary:focus) {
|
||||
box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.3) !important;
|
||||
}
|
||||
|
||||
/* 分割线样式优化 */
|
||||
::v-deep(.ant-divider) {
|
||||
background-color: #e5e7eb !important;
|
||||
}
|
||||
|
||||
/* 加载状态动画优化 */
|
||||
::v-deep(.ant-btn-loading .ant-btn-loading-icon) {
|
||||
margin-right: 8px !important;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 375px) {
|
||||
.login-box {
|
||||
padding: 60px 20px !important;
|
||||
}
|
||||
|
||||
.third-title {
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 平滑滚动 */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* 防止点击闪烁 */
|
||||
* {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
</style>
|
||||
@@ -116,15 +116,15 @@ const beforeUpload = (file: UploadProps['fileList'][number]) => {
|
||||
// const userInfo = ref<string>();
|
||||
|
||||
const loadUserInfo = () => {
|
||||
useApiStore()
|
||||
.apiUserInfo()
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
if (res.data.avatar != null && res.data.avatar !== '') imageUrl.value = `/upload/${res.data.avatar}`;
|
||||
passwordFormData.UserId = res.data.id;
|
||||
uploadAction.value = `/api/auth/UpdateUserAvatar?Uid=${res.data.id}`;
|
||||
}
|
||||
});
|
||||
// useApiStore()
|
||||
// .apiUserInfo()
|
||||
// .then((res) => {
|
||||
// if (res.code === 0) {
|
||||
// if (res.data.avatar != null && res.data.avatar !== '') imageUrl.value = `/upload/${res.data.avatar}`;
|
||||
// passwordFormData.UserId = res.data.id;
|
||||
// uploadAction.value = `/api/auth/UpdateUserAvatar?Uid=${res.data.id}`;
|
||||
// }
|
||||
// });
|
||||
};
|
||||
|
||||
interface PassFormState {
|
||||
|
||||
Reference in New Issue
Block a user