Files
oci-portal-dash/src/components/settings/AboutTab.vue
T
Wang Defa 5464d2dfea
CI / test (push) Successful in 27s
Release / release (push) Successful in 26s
发布 0.1.0:通知渠道、告警规则与多项体验修复
2026-07-10 17:31:19 +08:00

151 lines
5.1 KiB
Vue

<script setup lang="ts">
import { NButton, NSpin } from 'naive-ui'
import { onMounted, ref } from 'vue'
import { getAbout } from '@/api/settings'
import AppLogo from '@/components/AppLogo.vue'
import { useParticles } from '@/composables/useParticles'
import { useAppStore } from '@/stores/app'
import type { AboutInfo } from '@/types/api'
// 点击 logo 在星爆 / 波浪封印两款间切换(全局生效并记忆)
const app = useAppStore()
// GitHub 仓库地址;空串时按钮禁用并显示占位
const REPO_URL = 'https://github.com/wangdefaa/oci-portal'
const info = ref<AboutInfo | null>(null)
const loading = ref(true)
const pcanvas = ref<HTMLCanvasElement | null>(null)
useParticles(pcanvas, { count: 26 })
onMounted(async () => {
try {
info.value = await getAbout()
} catch {
/* 构建信息加载失败不阻塞页面,chips 显示占位 */
} finally {
loading.value = false
}
})
function fmtBuild(t: string) {
return t ? t.replace('T', ' ').replace('Z', ' UTC') : '—'
}
function openRepo() {
if (REPO_URL) window.open(REPO_URL, '_blank', 'noopener')
}
</script>
<template>
<div class="flex max-w-[860px] flex-col gap-4">
<!-- Hero:印章 + 名称 + 版本 chips,粒子与轨道环装饰 -->
<div class="panel relative overflow-hidden px-6 py-12 text-center">
<div class="pointer-events-none absolute inset-0" aria-hidden="true">
<div class="glow" style="width: 420px; height: 420px; left: 50%; top: -180px; transform: translateX(-50%)"></div>
<div class="ring-dash spin" style="width: 380px; height: 380px; left: calc(50% - 190px); top: -60px"></div>
<canvas ref="pcanvas" class="absolute inset-0 h-full w-full"></canvas>
</div>
<div class="relative">
<button
type="button"
class="floaty logo-btn mx-auto block w-fit"
title="切换 logo 款式"
aria-label="切换 logo 款式"
@click="app.toggleLogoVariant()"
>
<AppLogo :size="84" />
</button>
<div class="mt-5 font-serif text-[34px] leading-tight font-semibold">OCI Portal</div>
<div class="mt-1 text-[13px] text-ink-3">OCI 账号批量管理面板 · 自托管</div>
<div v-if="loading" class="mt-6 flex justify-center"><NSpin size="small" /></div>
<div v-else class="mt-6 flex flex-wrap justify-center gap-2">
<span class="chip mono">{{ info?.version || 'dev' }}</span>
<span class="chip mono">构建 {{ fmtBuild(info?.buildTime ?? '') }}</span>
<span class="chip mono">{{ info?.platform || '—' }} · {{ info?.goVersion || '' }}</span>
</div>
</div>
</div>
<!-- GitHub 仓库 -->
<div class="panel flex items-center gap-3.5 px-5 py-4">
<span class="flex h-10 w-10 flex-none items-center justify-center rounded-[9px] bg-wash">
<svg class="h-5 w-5" viewBox="0 0 16 16" fill="currentColor">
<path
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
</span>
<span class="min-w-0 flex-1">
<span class="block text-[13px] font-semibold">GitHub 仓库</span>
<span class="mono mt-0.5 block truncate text-xs text-ink-3">{{ REPO_URL || 'github.com/…(待填充)' }}</span>
</span>
<NButton size="small" :disabled="!REPO_URL" @click="openRepo">前往仓库 </NButton>
</div>
</div>
</template>
<style scoped>
.chip {
display: inline-flex;
align-items: center;
border: 1px solid var(--color-line);
border-radius: 999px;
background: var(--color-card);
padding: 6px 13px;
font-size: 12px;
color: var(--color-ink-2);
box-shadow: 0 2px 8px rgba(20, 20, 19, 0.06);
}
.glow {
position: absolute;
border-radius: 50%;
background: rgba(201, 100, 66, 0.13);
filter: blur(80px);
}
.ring-dash {
position: absolute;
border-radius: 50%;
border: 1.5px dashed color-mix(in srgb, var(--color-line) 70%, var(--color-accent) 30%);
}
/* logo 即款式开关:去按钮底色,悬停轻微放大提示可点 */
.logo-btn {
cursor: pointer;
border: none;
background: none;
padding: 0;
line-height: 0;
transition: scale 0.25s ease;
}
.logo-btn:hover {
scale: 1.06;
}
.logo-btn:active {
scale: 0.96;
}
@media (prefers-reduced-motion: no-preference) {
.spin {
animation: about-sp 52s linear infinite;
}
.floaty {
animation: about-fl 7s ease-in-out infinite;
}
@keyframes about-sp {
to {
transform: rotate(360deg);
}
}
@keyframes about-fl {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-8px);
}
}
}
</style>