feat: 初始化慧遇书院官网一期

This commit is contained in:
2026-08-12 18:01:17 +08:00
commit 5d31ee5743
101 changed files with 17259 additions and 0 deletions

58
app/pages/admin/login.vue Normal file
View File

@@ -0,0 +1,58 @@
<script setup lang="ts">
import {
PhArrowRight as ArrowRight,
PhEye as Eye,
PhEyeSlash as EyeSlash,
PhLockKey as LockKey,
PhUser as User,
} from '@phosphor-icons/vue'
definePageMeta({ layout: false })
const { data: publicSite } = await useFetch<{ data: { brand: { name: string; englishName: string; logo: string; subSlogan: string } } }>('/api/public/site')
const loginBrand = computed(() => publicSite.value?.data.brand ?? { name: '慧遇书院', englishName: 'HUIYU ACADEMY', logo: '/images/brand-mark-v2.png', subSlogan: '用科技与专业,陪伴每一次心灵的成长' })
useHead(() => ({ title: `后台管理登录|${loginBrand.value.name}` }))
const form = reactive({ username: 'admin', password: '' })
const showPassword = ref(false)
const loading = ref(false)
const error = ref('')
async function login() {
error.value = ''
loading.value = true
try {
await $fetch('/api/auth/login', { method: 'POST', body: form })
await navigateTo('/admin')
} catch (cause: any) {
error.value = cause?.data?.statusMessage || '登录失败,请稍后重试'
} finally {
loading.value = false
}
}
</script>
<template>
<main class="login-page">
<div class="login-brand">
<BrandLogo :src="loginBrand.logo" :name="loginBrand.name" :english-name="loginBrand.englishName" />
<div>
<h1>身心疗愈<br>科技赋能</h1>
<p>{{ loginBrand.subSlogan }}</p>
</div>
</div>
<section class="login-card">
<p class="eyebrow">HUIYU CONTENT SYSTEM</p>
<h2>后台管理登录</h2>
<p class="login-intro">欢迎回来请登录管理员账号</p>
<form @submit.prevent="login">
<label>账号</label>
<div class="field"><User :size="22" /><input v-model.trim="form.username" autocomplete="username" placeholder="请输入账号" required></div>
<label>密码</label>
<div class="field"><LockKey :size="22" /><input v-model="form.password" :type="showPassword ? 'text' : 'password'" autocomplete="current-password" placeholder="请输入密码" required><button type="button" aria-label="切换密码显示" @click="showPassword = !showPassword"><EyeSlash v-if="showPassword" :size="21" /><Eye v-else :size="21" /></button></div>
<p v-if="error" class="form-error" role="alert">{{ error }}</p>
<button class="login-submit" type="submit" :disabled="loading"><span>{{ loading ? '登录中…' : '登录后台' }}</span><ArrowRight :size="21" /></button>
</form>
<p class="security-note">安全连接已启用登录状态受保护</p>
</section>
</main>
</template>