1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-07-27 04:20:43 +08:00
Files
uni-halo/src/pages/auth/login.vue
T
小莫唐尼 a510875d38 style: 调整多处页面UI细节与默认状态
1. 将动态页面默认视图从时间线模式改为非时间线模式
2. 修复分享按钮的默认样式问题,移除多余边框和背景
3. 调整登录页分隔线上下间距与微信登录按钮高度
4. 隐藏文章卡片的分类信息展示
2026-06-16 01:44:17 +08:00

404 lines
12 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.
<script lang="ts" setup>
import { systemInfo } from '@/utils/systemInfo'
import { useTokenStore } from '@/store/token'
import { useGuestStore } from '@/store/guest'
import GuestInfoPanel from '@/components/post-detail/uh-guest-info-panel.vue'
defineOptions({ name: 'Login' })
definePage({
style: {
navigationBarTitleText: '登录',
navigationStyle: 'custom',
navigationBarBackgroundColor: '#ffffff',
},
})
const tokenStore = useTokenStore()
const guestStore = useGuestStore()
// ---- Tab 切换 ----
type AuthMode = 'login' | 'register'
const activeMode = ref<AuthMode>('login')
function switchMode(mode: AuthMode) {
activeMode.value = mode
// 切换时清空错误提示
clearErrors()
}
// ---- 登录表单 ----
const loginForm = reactive({
username: '',
password: '',
})
const loginErrors = reactive({
username: '',
password: '',
})
function validateLogin(): boolean {
let valid = true
loginErrors.username = ''
loginErrors.password = ''
if (!loginForm.username.trim()) {
loginErrors.username = '请输入用户名'
valid = false
}
if (!loginForm.password.trim()) {
loginErrors.password = '请输入密码'
valid = false
}
return valid
}
async function handleLogin() {
if (!validateLogin())
return
try {
await tokenStore.login({
username: loginForm.username.trim(),
password: loginForm.password.trim(),
})
handleLoginSuccess()
}
catch (error) {
console.error('登录失败:', error)
}
}
// ---- 注册表单 ----
const registerForm = reactive({
username: '',
password: '',
confirmPassword: '',
})
const registerErrors = reactive({
username: '',
password: '',
confirmPassword: '',
})
function validateRegister(): boolean {
let valid = true
registerErrors.username = ''
registerErrors.password = ''
registerErrors.confirmPassword = ''
if (!registerForm.username.trim()) {
registerErrors.username = '请输入用户名'
valid = false
}
if (!registerForm.password.trim()) {
registerErrors.password = '请输入密码'
valid = false
}
else if (registerForm.password.length < 6) {
registerErrors.password = '密码至少6位'
valid = false
}
if (!registerForm.confirmPassword.trim()) {
registerErrors.confirmPassword = '请确认密码'
valid = false
}
else if (registerForm.password !== registerForm.confirmPassword) {
registerErrors.confirmPassword = '两次密码不一致'
valid = false
}
return valid
}
async function handleRegister() {
if (!validateRegister())
return
try {
// TODO: 调用注册 API
// await register({
// username: registerForm.username.trim(),
// password: registerForm.password.trim(),
// })
uni.showToast({ title: '注册成功', icon: 'success' })
// 注册成功后切换到登录
switchMode('login')
loginForm.username = registerForm.username
loginForm.password = ''
}
catch (error) {
console.error('注册失败:', error)
}
}
function clearErrors() {
loginErrors.username = ''
loginErrors.password = ''
registerErrors.username = ''
registerErrors.password = ''
registerErrors.confirmPassword = ''
}
// ---- 密码可见性 ----
const showLoginPwd = ref(false)
const showRegisterPwd = ref(false)
const showConfirmPwd = ref(false)
// ---- 微信一键登录 ----
// #ifdef MP-WEIXIN
async function handleWxLogin() {
try {
await tokenStore.wxLogin()
handleLoginSuccess()
}
catch (error) {
console.error('微信登录失败:', error)
}
}
// #endif
// ---- 游客身份访问 ----
const showGuestPanel = ref(false)
function handleGuestAccess() {
showGuestPanel.value = true
}
function handleGuestSaved() {
showGuestPanel.value = false
uni.navigateBack()
}
// ---- 登录成功处理 ----
function handleLoginSuccess() {
// 检查是否有重定向地址(从路由拦截器传入)
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1] as any
const redirect = currentPage?.$page?.options?.redirect || currentPage?.options?.redirect
if (redirect) {
uni.redirectTo({ url: decodeURIComponent(redirect) })
}
else {
uni.navigateBack()
}
}
// ---- 密码输入框切换可见性 ----
function togglePwdVisibility(target: 'login' | 'register' | 'confirm') {
if (target === 'login')
showLoginPwd.value = !showLoginPwd.value
else if (target === 'register')
showRegisterPwd.value = !showRegisterPwd.value
else showConfirmPwd.value = !showConfirmPwd.value
}
function handleBack() {
uni.navigateBack()
}
</script>
<template>
<view
class="box-border min-h-screen w-full flex flex-col items-center justify-center bg-page3 px-6"
:class="[
systemInfo.uniPlatform ? 'pt-safe' : 'pt-12',
]"
>
<!-- 头部 Logo -->
<view
class="mb-8 mt-8 w-full flex flex-col items-center gap-y-2"
>
<image
class="h-16 w-16 rounded-2xl"
src="/static/logo.png"
mode="scaleToFill"
/>
<text class="text-xl text-gray-900 font-bold">欢迎回来</text>
<text class="text-xs text-gray-400">登录你的账号探索更多精彩</text>
</view>
<!-- Tab 切换 -->
<view class="mb-6 box-border w-full flex items-center rounded-xl bg-gray-100 p-1">
<view
class="center flex-1 rounded-lg py-2 text-sm font-medium transition-all"
:class="activeMode === 'login' ? 'bg-white text-gray-900 shadow-sm' : 'text-gray-500'"
@click="switchMode('login')"
>
登录
</view>
<view
class="center flex-1 rounded-lg py-2 text-sm font-medium transition-all"
:class="activeMode === 'register' ? 'bg-white text-gray-900 shadow-sm' : 'text-gray-500'"
@click="switchMode('register')"
>
注册
</view>
</view>
<!-- 登录表单 -->
<view v-if="activeMode === 'login'" class="w-full flex flex-col gap-y-4">
<!-- 用户名 -->
<view class="flex flex-col gap-y-1">
<view class="flex items-center rounded-xl bg-gray-100 px-4">
<wd-icon name="user" color="#9CA3AF" :size="16" />
<input
v-model="loginForm.username"
class="flex-1 py-2.5 pl-2 text-sm"
placeholder="请输入用户名"
:maxlength="30"
>
</view>
<text v-if="loginErrors.username" class="text-[11px] text-red-500">{{ loginErrors.username }}</text>
</view>
<!-- 密码 -->
<view class="flex flex-col gap-y-1">
<view class="flex items-center rounded-xl bg-gray-100 px-4">
<wd-icon name="lock" color="#9CA3AF" :size="16" />
<input
v-model="loginForm.password"
class="flex-1 py-2.5 pl-2 text-sm"
placeholder="请输入密码"
:password="!showLoginPwd"
:maxlength="30"
>
<view @click="togglePwdVisibility('login')">
<wd-icon :name="showLoginPwd ? 'view' : 'eye-close'" color="#9CA3AF" :size="16" />
</view>
</view>
<text v-if="loginErrors.password" class="text-[11px] text-red-500">{{ loginErrors.password }}</text>
</view>
<!-- 登录按钮 -->
<view
class="mt-2 h-11 w-full center rounded-xl bg-gray-900 text-sm text-white font-medium"
@click="handleLogin"
>
登录
</view>
<!-- 返回按钮 -->
<view
class="box-border h-10 w-full center gap-x-1 border border-gray-600 rounded-xl border-solid text-xs text-gray-600"
@click="handleBack"
>
暂不登录
</view>
</view>
<!-- 注册表单 -->
<view v-if="activeMode === 'register'" class="w-full flex flex-col gap-y-4">
<!-- 用户名 -->
<view class="flex flex-col gap-y-1">
<view class="flex items-center rounded-xl bg-gray-100 px-4">
<wd-icon name="user" color="#9CA3AF" :size="16" />
<input
v-model="registerForm.username"
class="flex-1 py-2.5 pl-2 text-sm"
placeholder="请输入用户名"
:maxlength="30"
>
</view>
<text v-if="registerErrors.username" class="text-[11px] text-red-500">{{ registerErrors.username }}</text>
</view>
<!-- 密码 -->
<view class="flex flex-col gap-y-1">
<view class="flex items-center rounded-xl bg-gray-100 px-4">
<wd-icon name="lock" color="#9CA3AF" :size="16" />
<input
v-model="registerForm.password"
class="flex-1 py-2.5 pl-2 text-sm"
placeholder="请输入密码(至少6位)"
:password="!showRegisterPwd"
:maxlength="30"
>
<view @click="togglePwdVisibility('register')">
<wd-icon :name="showRegisterPwd ? 'view' : 'eye-close'" color="#9CA3AF" :size="16" />
</view>
</view>
<text v-if="registerErrors.password" class="text-[11px] text-red-500">{{ registerErrors.password }}</text>
</view>
<!-- 确认密码 -->
<view class="flex flex-col gap-y-1">
<view class="flex items-center rounded-xl bg-gray-100 px-4">
<wd-icon name="lock" color="#9CA3AF" :size="16" />
<input
v-model="registerForm.confirmPassword"
class="flex-1 py-2.5 pl-2 text-sm"
placeholder="请再次输入密码"
:password="!showConfirmPwd"
:maxlength="30"
>
<view @click="togglePwdVisibility('confirm')">
<wd-icon :name="showConfirmPwd ? 'view' : 'eye-close'" color="#9CA3AF" :size="16" />
</view>
</view>
<text v-if="registerErrors.confirmPassword" class="text-[11px] text-red-500">{{ registerErrors.confirmPassword }}</text>
</view>
<!-- 注册按钮 -->
<view
class="mt-2 h-11 w-full center rounded-xl bg-gray-900 text-sm text-white font-medium"
@click="handleRegister"
>
注册
</view>
<!-- 返回按钮 -->
<view
class="box-border h-10 w-full center gap-x-1 border border-gray-600 rounded-xl border-solid text-xs text-gray-600"
@click="handleBack"
>
暂不登录
</view>
</view>
<!-- 分隔线 -->
<view class="my-6 w-full flex items-center justify-center gap-x-3">
<view class="h-px flex-1 bg-gray-100" />
<text class="text-xs text-gray-400">其他方式</text>
<view class="h-px flex-1 bg-gray-100" />
</view>
<!-- 第三方登录 & 游客访问 -->
<view class="w-full flex flex-col items-center gap-y-3">
<!-- #ifdef MP-WEIXIN -->
<view
class="h-10 w-full flex items-center justify-center gap-x-2 rounded-xl bg-[#07C160] text-sm text-white font-medium"
@click="handleWxLogin"
>
<wd-icon name="wechat" color="#FFFFFF" :size="18" />
<text>微信一键登录</text>
</view>
<!-- #endif -->
<view
class="w-full flex items-center justify-center gap-x-2 border border-gray-200 rounded-xl py-1 text-sm text-gray-600"
@click="handleGuestAccess"
>
<text>游客身份访问</text>
</view>
</view>
<!-- 底部协议提示 -->
<view class="mb-8 w-full flex flex-col items-center gap-y-1 pt-6">
<text class="text-[11px] text-gray-400">登录或注册即代表同意</text>
<view class="flex items-center gap-x-1">
<text class="text-[11px] text-gray-500 font-medium">用户协议</text>
<text class="text-[11px] text-gray-400"></text>
<text class="text-[11px] text-gray-500 font-medium">隐私政策</text>
</view>
</view>
<!-- 游客信息编辑面板 -->
<GuestInfoPanel
v-if="showGuestPanel"
@close="showGuestPanel = false"
@saved="handleGuestSaved"
/>
</view>
</template>