本文檔詳細說(shuō)明了如何修改項目中的登錄頁(yè)面,包括樣式、功能、文本內容等各個(gè)方面的自定義配置。
src/pages/login/
├── index.vue # 登錄頁(yè)面主文件
├── index.less # 登錄頁(yè)面樣式文件
└── components/
├── Header.vue # 登錄頁(yè)面頭部組件
├── Login.vue # 登錄表單組件
└── Register.vue # 注冊表單組件
這是登錄頁(yè)面的主要入口文件,控制整體布局和頁(yè)面切換邏輯。
<template>
<div class="login-wrapper">
<login-header />
<div class="login-container">
<div class="title-container">
<!-- 修改登錄頁(yè)面標題 -->
<h1 class="title margin-no">{{ t('pages.login.loginTitle') }}</h1>
<h1 class="title">您的項目名稱(chēng)</h1>
<div class="sub-title">
<p class="tip">{{ type === 'register' ? t('pages.login.existAccount') : t('pages.login.noAccount') }}</p>
<p class="tip" @click="switchType(type === 'register' ? 'login' : 'register')">
{{ type === 'register' ? t('pages.login.signIn') : t('pages.login.createAccount') }}
</p>
</div>
</div>
<!-- 登錄表單 -->
<login v-if="type === 'login'" />
<!-- 注冊表單 -->
<register v-else @register-success="switchType('login')" />
<tdesign-setting />
</div>
</div>
</template>
這是核心的登錄表單組件,包含多種登錄方式。
A. 賬號密碼登錄
<template v-if="type === 'password'">
<t-form-item name="account">
<t-input
v-model="formData.account"
size="large"
:placeholder="`${t('pages.login.input.account')}:admin`"
>
<template #prefix-icon>
<t-icon name="user" />
</template>
</t-input>
</t-form-item>
<t-form-item name="password">
<t-input
v-model="formData.password"
size="large"
type="password"
clearable
:placeholder="`${t('pages.login.input.password')}:admin`"
>
<template #prefix-icon>
<t-icon name="lock-on" />
</template>
</t-input>
</t-form-item>
</template>
B. 手機號登錄
<template v-else-if="type === 'phone'">
<t-form-item name="phone">
<t-input
v-model="formData.phone"
size="large"
:placeholder="t('pages.login.input.phone')"
>
<template #prefix-icon>
<t-icon name="mobile" />
</template>
</t-input>
</t-form-item>
<t-form-item class="verification-code" name="verifyCode">
<t-input
v-model="formData.verifyCode"
size="large"
:placeholder="t('pages.login.input.verification')"
/>
<t-button
size="large"
variant="outline"
:disabled="countDown > 0"
@click="sendCode"
>
{{ countDown === 0 ? t('pages.login.sendVerification') : `${countDown}秒后可重發(fā)` }}
</t-button>
</t-form-item>
</template>
C. 二維碼登錄
<template v-else-if="type === 'qrcode'">
<div class="qrcode-container">
<!-- 這里可以放置二維碼圖片 -->
<div class="qrcode-placeholder">
<t-icon name="qrcode" size="120px" />
</div>
</div>
<div class="tip-container">
<span class="tip">{{ t('pages.login.wechatLogin') }}</span>
<span class="refresh">{{ t('pages.login.refresh') }} <t-icon name="refresh" /></span>
</div>
</template>
<template>
<header class="login-header">
<!-- 修改Logo -->
<logo-full-icon class="logo" />
<!-- 或者使用自定義Logo -->
<!-- <img src="@/assets/your-logo.png" alt="Logo" class="logo" /> -->
</header>
</template>
包含用戶(hù)注冊功能的表單組件。
export default {
loginTitle: '登錄到',
signIn: '登錄',
createAccount: '注冊賬號',
noAccount: '沒(méi)有賬號嗎?',
existAccount: '已有賬號?',
remember: '記住賬號',
forget: '忘記密碼?',
refresh: '刷新',
wechatLogin: '使用微信掃一掃登錄',
accountLogin: '使用賬號登錄',
phoneLogin: '使用手機號登錄',
sendVerification: '發(fā)送驗證碼',
input: {
account: '請輸入賬號',
password: '請輸入密碼',
phone: '請輸入手機號',
verification: '請輸入驗證碼',
},
required: {
account: '賬號必填',
password: '密碼必填',
phone: '手機號必填',
verification: '驗證碼必填',
},
}
export default {
loginTitle: 'Login in',
signIn: 'Sign In',
createAccount: 'Create Account',
noAccount: 'No Account?',
existAccount: 'Have Account?',
remember: 'Remember Account',
forget: 'Forgot Password?',
refresh: 'refresh',
wechatLogin: 'Login with WeChat',
accountLogin: 'Login with Account',
phoneLogin: 'Login with Mobile Phone',
sendVerification: 'Send Code',
input: {
account: 'Please enter account',
password: 'Please enter password',
phone: 'Please enter phone number',
verification: 'Please enter verification code',
},
required: {
account: 'Account is required',
password: 'Password is required',
phone: 'Phone number is required',
verification: 'Verification code is required',
},
}
.login-wrapper {
height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
// 或者使用圖片背景
// background-image: url('@/assets/login-bg.jpg');
// background-size: cover;
// background-position: center;
.login-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: calc(100vh - 80px);
.title-container {
text-align: center;
margin-bottom: 40px;
.title {
color: #fff;
font-size: 32px;
font-weight: bold;
margin-bottom: 8px;
&.margin-no {
margin-bottom: 0;
}
}
.sub-title {
.tip {
color: rgba(255, 255, 255, 0.8);
font-size: 14px;
cursor: pointer;
&:hover {
color: #fff;
}
}
}
}
}
}
.login-form {
width: 400px;
background: rgba(255, 255, 255, 0.95);
border-radius: 8px;
padding: 40px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
.btn-container {
margin-top: 24px;
.t-button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
&:hover {
background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%);
}
}
}
.switch-container {
display: flex;
justify-content: space-between;
margin-top: 16px;
.tip {
color: #666;
font-size: 14px;
cursor: pointer;
&:hover {
color: #667eea;
}
}
}
}
export const useUserStore = defineStore('user', {
state: () => ({
token: '',
userInfo: {} as UserInfo,
}),
actions: {
async login(userInfo: Record<string, unknown>) {
try {
// 這里可以修改登錄API調用
const res = await loginApi(userInfo);
if (res.code === 200) {
this.token = res.data.token;
this.userInfo = res.data.userInfo;
// 存儲到本地
localStorage.setItem('token', this.token);
localStorage.setItem('userInfo', JSON.stringify(this.userInfo));
return Promise.resolve(res);
} else {
return Promise.reject(res);
}
} catch (error) {
return Promise.reject(error);
}
},
},
});
const routes = [
{
path: '/login',
name: 'login',
component: () => import('@/pages/login/index.vue'),
meta: {
title: '登錄',
requiresAuth: false,
},
},
// 其他路由...
];
<!-- src/pages/login/index.vue -->
<template>
<div class="title-container">
<h1 class="title margin-no">歡迎登錄</h1>
<h1 class="title">您的系統名稱(chēng)</h1>
</div>
</template>
<!-- src/pages/login/components/Header.vue -->
<template>
<header class="login-header">
<img src="@/assets/your-logo.png" alt="Logo" class="logo" />
</header>
</template>
<!-- src/pages/login/components/Login.vue -->
<template>
<div class="switch-container">
<!-- 注釋掉不需要的登錄方式 -->
<!-- <span v-if="type !== 'qrcode'" class="tip" @click="switchType('qrcode')">
{{ t('pages.login.wechatLogin') }}
</span> -->
<span v-if="type !== 'phone'" class="tip" @click="switchType('phone')">
{{ t('pages.login.phoneLogin') }}
</span>
</div>
</template>
<!-- src/pages/login/components/Login.vue -->
<script setup lang="ts">
// 修改默認登錄類(lèi)型
const type = ref('password'); // 'password' | 'phone' | 'qrcode'
</script>
// src/pages/login/components/Login.vue
const FORM_RULES: Record<string, FormRule[]> = {
account: [
{ required: true, message: '賬號必填', type: 'error' },
{ min: 3, message: '賬號長(cháng)度不能少于3位', type: 'error' },
],
password: [
{ required: true, message: '密碼必填', type: 'error' },
{ min: 6, message: '密碼長(cháng)度不能少于6位', type: 'error' },
],
phone: [
{ required: true, message: '手機號必填', type: 'error' },
{ pattern: /^1[3-9]\d{9}$/, message: '手機號格式不正確', type: 'error' },
],
};
<!-- src/pages/login/components/Login.vue -->
<template>
<div class="third-party-login">
<div class="divider">
<span>或</span>
</div>
<div class="third-party-buttons">
<t-button variant="outline" @click="loginWithGithub">
<t-icon name="logo-github" />
GitHub登錄
</t-button>
<t-button variant="outline" @click="loginWithGoogle">
<t-icon name="logo-google" />
Google登錄
</t-button>
</div>
</div>
</template>
<script setup lang="ts">
const loginWithGithub = () => {
// GitHub登錄邏輯
};
const loginWithGoogle = () => {
// Google登錄邏輯
};
</script>
# 啟動(dòng)開(kāi)發(fā)服務(wù)器
npm run dev
# 訪(fǎng)問(wèn)登錄頁(yè)面
http://localhost:3000/login
最后更新: 2025/10/2