refactor(web): login page

This commit is contained in:
Acbox
2026-02-18 19:06:45 +08:00
parent 1294b4cf75
commit 9c338a3806
4 changed files with 117 additions and 77 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ import { computed } from 'vue'
export type Locale = 'en' | 'zh'
const i18n = createI18n<typeof en | typeof zh, Locale>({
locale: 'zh',
locale: 'en',
legacy: false,
fallbackLocale: 'en',
messages: {
+43 -3
View File
@@ -1,10 +1,33 @@
<template>
<section class="w-screen h-screen flex *:m-auto bg-linear-to-t from-[#BFA4A0] to-[#7784AC] ">
<section class="w-screen h-screen flex *:m-auto bg-background relative">
<div class="absolute top-6 right-6 flex items-center gap-2">
<Select
:model-value="language"
@update:model-value="(v) => v && setLanguage(v as Locale)"
>
<SelectTrigger class="w-28 h-9">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="en">English</SelectItem>
<SelectItem value="zh">中文</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<Button
variant="ghost"
size="icon"
@click="toggleTheme"
>
<Sun v-if="theme === 'dark'" class="size-5" />
<Moon v-else class="size-5" />
</Button>
</div>
<section class="w-full max-w-sm flex flex-col gap-10 ">
<section>
<h3
class="scroll-m-20 text-3xl tracking-wide font-semibold text-white text-center"
style="font-family: 'Source Han Serif CN', 'Noto Serif SC', 'STSong', 'SimSun', serif;"
class="scroll-m-20 text-3xl tracking-wide font-semibold text-foreground text-center"
>
{{ $t('auth.welcome') }}
</h3>
@@ -96,19 +119,36 @@ import {
FormItem,
Label,
Spinner,
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from '@memoh/ui'
import { Sun, Moon } from 'lucide-vue-next'
import { useRouter } from 'vue-router'
import { toTypedSchema } from '@vee-validate/zod'
import { useForm } from 'vee-validate'
import * as z from 'zod'
import { useUserStore } from '@/store/user'
import { useSettingsStore } from '@/store/settings'
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import { toast } from 'vue-sonner'
import { useI18n } from 'vue-i18n'
import { postAuthLogin } from '@memoh/sdk'
import type { Locale } from '@/i18n'
const router = useRouter()
const { t } = useI18n()
const settingsStore = useSettingsStore()
const { theme, language } = storeToRefs(settingsStore)
const { setLanguage, setTheme } = settingsStore
const toggleTheme = () => {
setTheme(theme.value === 'light' ? 'dark' : 'light')
}
const formSchema = toTypedSchema(z.object({
username: z.string().min(1),
+72 -72
View File
@@ -23,6 +23,78 @@
</div>
</div>
<!-- Display Settings -->
<section>
<h6 class="mb-2 flex items-center">
<FontAwesomeIcon
:icon="['fas', 'gear']"
class="mr-2"
/>
{{ $t('settings.display') }}
</h6>
<Separator />
<div class="mt-4 space-y-4">
<div class="flex items-center justify-between">
<Label>{{ $t('settings.language') }}</Label>
<Select
:model-value="language"
@update:model-value="(v) => v && setLanguage(v as Locale)"
>
<SelectTrigger class="w-40">
<SelectValue :placeholder="$t('settings.languagePlaceholder')" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="zh">
{{ $t('settings.langZh') }}
</SelectItem>
<SelectItem value="en">
{{ $t('settings.langEn') }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
<Separator />
<div class="flex items-center justify-between">
<Label>{{ $t('settings.theme') }}</Label>
<Select
:model-value="theme"
@update:model-value="(v) => v && setTheme(v as 'light' | 'dark')"
>
<SelectTrigger class="w-40">
<SelectValue :placeholder="$t('settings.themePlaceholder')" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="light">
{{ $t('settings.themeLight') }}
</SelectItem>
<SelectItem value="dark">
{{ $t('settings.themeDark') }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
</div>
</section>
<!-- Logout -->
<section>
<Separator class="mb-4" />
<ConfirmPopover
:message="$t('auth.logoutConfirm')"
@confirm="onLogout"
>
<template #trigger>
<Button>
{{ $t('auth.logout') }}
</Button>
</template>
</ConfirmPopover>
</section>
<!-- User Profile -->
<section>
<h6 class="mb-2 flex items-center">
@@ -240,78 +312,6 @@
</div>
</div>
</section>
<!-- Display Settings -->
<section>
<h6 class="mb-2 flex items-center">
<FontAwesomeIcon
:icon="['fas', 'gear']"
class="mr-2"
/>
{{ $t('settings.display') }}
</h6>
<Separator />
<div class="mt-4 space-y-4">
<div class="flex items-center justify-between">
<Label>{{ $t('settings.language') }}</Label>
<Select
:model-value="language"
@update:model-value="(v) => v && setLanguage(v as Locale)"
>
<SelectTrigger class="w-40">
<SelectValue :placeholder="$t('settings.languagePlaceholder')" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="zh">
{{ $t('settings.langZh') }}
</SelectItem>
<SelectItem value="en">
{{ $t('settings.langEn') }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
<Separator />
<div class="flex items-center justify-between">
<Label>{{ $t('settings.theme') }}</Label>
<Select
:model-value="theme"
@update:model-value="(v) => v && setTheme(v as 'light' | 'dark')"
>
<SelectTrigger class="w-40">
<SelectValue :placeholder="$t('settings.themePlaceholder')" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="light">
{{ $t('settings.themeLight') }}
</SelectItem>
<SelectItem value="dark">
{{ $t('settings.themeDark') }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
</div>
</section>
<!-- Logout -->
<section>
<Separator class="mb-4" />
<ConfirmPopover
:message="$t('auth.logoutConfirm')"
@confirm="onLogout"
>
<template #trigger>
<Button variant="outline">
{{ $t('auth.logout') }}
</Button>
</template>
</ConfirmPopover>
</section>
</div>
</section>
</template>
+1 -1
View File
@@ -11,7 +11,7 @@ export interface Settings {
export const useSettingsStore = defineStore('settings', () => {
const colorMode = useColorMode()
const i18n = useI18n()
const language = useStorage<Locale>('language', 'zh')
const language = useStorage<Locale>('language', 'en')
const theme = useStorage<'light' | 'dark'>('theme', 'light')
colorMode.value = theme.value