You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

254 lines
8.6 KiB

<script setup lang="ts">
import { request, unwrapApiBody, type ApiResponse } from '../../utils/http/factory'
import { useAuthSession } from '../../composables/useAuthSession'
const { loggedIn, user, clear } = useAuthSession()
const { allowRegister } = useGlobalConfig()
const logoutLoading = ref(false)
const features = [
{
title: '个人资料',
desc: '生平叙事、头像、社交链接与公开主页 slug,支持分块可见性。',
icon: 'i-lucide-user-round',
to: '/me/profile',
},
{
title: 'Markdown 文章',
desc: '自写内容、slug、摘要与封面,每条可公开、私密或仅链接分享。',
icon: 'i-lucide-file-text',
to: '/me/posts',
},
{
title: '时光机',
desc: '按时间轴记录里程碑事件,与文章、阅读流在同一叙事里呈现。',
icon: 'i-lucide-history',
to: '/me/timeline',
},
{
title: 'RSS 收件箱',
desc: '订阅源仅自己可见;定时拉取、去重,条目默认可再设为公开展示。',
icon: 'i-lucide-rss',
to: '/me/rss',
},
] as const
async function logout() {
logoutLoading.value = true
try {
unwrapApiBody(await request<ApiResponse<{ success: boolean }>>('/api/auth/logout', { method: 'POST' }))
clear()
await navigateTo('/login')
} finally {
logoutLoading.value = false
}
}
</script>
<template>
<div class="mx-auto max-w-6xl space-y-12 pb-4">
<!-- Hero -->
<section class="relative overflow-hidden rounded-2xl border border-default bg-gradient-to-br from-primary/5 via-default to-elevated px-6 py-12 sm:px-10 sm:py-16">
<div class="pointer-events-none absolute -right-20 -top-20 size-64 rounded-full bg-primary/10 blur-3xl" />
<div class="pointer-events-none absolute -bottom-24 -left-16 size-72 rounded-full bg-primary/5 blur-3xl" />
<div class="relative max-w-2xl space-y-4">
<UBadge color="primary" variant="subtle" size="md">
个人数据中心
</UBadge>
<h1 class="text-3xl font-bold tracking-tight text-highlighted sm:text-4xl">
把你的故事文章与阅读收进一个地方
</h1>
<p class="text-base text-muted sm:text-lg leading-relaxed">
Person Panel 面向多用户邀请制场景每位用户独立资料与订阅公开主页可只展示你愿意公开的部分RSS 在后台静默同步
</p>
<div class="flex flex-wrap gap-3 pt-2">
<template v-if="loggedIn">
<UButton to="/me" size="lg" icon="i-lucide-layout-dashboard">
进入控制台
</UButton>
<UButton
v-if="user?.publicSlug"
:to="`/@${user.publicSlug}`"
target="_blank"
size="lg"
color="neutral"
variant="outline"
icon="i-lucide-external-link"
>
预览公开主页
</UButton>
<UButton
v-else
to="/me/profile"
size="lg"
color="neutral"
variant="outline"
icon="i-lucide-link"
>
设置公开链接
</UButton>
</template>
<template v-else>
<UButton to="/login" size="lg" icon="i-lucide-log-in">
登录使用
</UButton>
<UButton
v-if="allowRegister"
to="/register"
size="lg"
color="neutral"
variant="outline"
>
注册账号
</UButton>
</template>
</div>
</div>
</section>
<!-- 已登录:摘要条 -->
<section v-if="loggedIn && user" class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
<UCard class="ring-1 ring-default/60">
<div class="flex items-start gap-3">
<UAvatar :src="user.avatar || undefined" :alt="user.username" size="md" class="ring-1 ring-default" />
<div class="min-w-0 flex-1">
<p class="text-xs font-medium text-muted">
当前用户
</p>
<p class="truncate font-semibold text-highlighted">
{{ user.nickname?.trim() || user.username }}
</p>
<p class="truncate text-xs text-muted">
@{{ user.username }} · {{ user.role === 'admin' ? '管理员' : '用户' }}
</p>
</div>
</div>
</UCard>
<UCard>
<p class="text-xs font-medium text-muted">
公开主页
</p>
<p class="mt-1 font-semibold text-highlighted">
{{ user.publicSlug ? `/@${user.publicSlug}` : '尚未设置' }}
</p>
<UButton to="/me/profile" size="xs" variant="link" class="mt-2 px-0">
去资料页配置
</UButton>
</UCard>
<UCard class="sm:col-span-2">
<p class="text-xs font-medium text-muted">
快捷入口
</p>
<div class="mt-2 flex flex-wrap gap-2">
<UButton to="/me/posts" size="xs" variant="soft">
文章
</UButton>
<UButton to="/me/timeline" size="xs" variant="soft">
时光机
</UButton>
<UButton to="/me/rss" size="xs" variant="soft">
RSS
</UButton>
<UButton to="/me/profile" size="xs" variant="soft">
资料
</UButton>
<UButton
v-if="user.role === 'admin'"
to="/me/admin/users"
size="xs"
color="primary"
variant="soft"
>
用户管理
</UButton>
</div>
</UCard>
</section>
<UAlert
v-if="loggedIn && user && !user.publicSlug"
color="warning"
variant="subtle"
title="还没有公开主页地址"
description="在「资料」中设置 public slug 后,访客即可通过 /@你的地址 访问你的公开内容。"
icon="i-lucide-alert-circle"
/>
<!-- 功能矩阵 -->
<section class="space-y-4">
<div>
<h2 class="text-xl font-semibold text-highlighted">
你能做什么
</h2>
<p class="mt-1 text-sm text-muted">
四大模块覆盖展示、创作与阅读输入;权限与可见性按条目细粒度控制。
</p>
</div>
<div class="grid gap-4 sm:grid-cols-2">
<UCard
v-for="item in features"
:key="item.title"
class="group transition-shadow hover:shadow-md"
>
<div class="flex gap-4">
<span class="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary">
<UIcon :name="item.icon" class="size-6" />
</span>
<div class="min-w-0 flex-1 space-y-2">
<h3 class="font-semibold text-highlighted">
{{ item.title }}
</h3>
<p class="text-sm leading-relaxed text-muted">
{{ item.desc }}
</p>
<UButton
v-if="loggedIn"
:to="item.to"
size="xs"
variant="link"
class="px-0"
trailing-icon="i-lucide-arrow-right"
>
打开
</UButton>
</div>
</div>
</UCard>
</div>
</section>
<!-- 访客说明 -->
<section v-if="!loggedIn" class="rounded-xl border border-dashed border-default bg-elevated/30 px-6 py-8">
<h3 class="font-semibold text-highlighted">
访客说明
</h3>
<p class="mt-2 max-w-2xl text-sm text-muted leading-relaxed">
本站默认需登录后使用控制台。若你已有账号,请点击「登录」;新账号由管理员在后台创建(邀请制)。
</p>
<div class="mt-4 flex flex-wrap gap-2">
<UButton to="/login">
登录
</UButton>
<UButton v-if="allowRegister" to="/register" color="neutral" variant="outline">
注册
</UButton>
</div>
</section>
<!-- 已登录底部操作 -->
<section v-if="loggedIn" class="flex flex-wrap items-center justify-between gap-4 rounded-xl border border-default bg-elevated/20 px-4 py-4">
<p class="text-sm text-muted">
需要退出当前会话?
</p>
<div class="flex gap-2">
<UButton to="/api/config/me" target="_blank" variant="outline" color="neutral" size="sm">
配置 API(调试)
</UButton>
<UButton color="neutral" :loading="logoutLoading" size="sm" @click="logout">
退出登录
</UButton>
</div>
</section>
</div>
</template>