提交说明
@@ -2,7 +2,13 @@
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/admin/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/admin/logo-150.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="author" content="YMhut" />
|
||||
<meta name="application-name" content="YMhut Box Admin" />
|
||||
<meta name="description" content="YMhut Box unified management console for update.ymhut.cn." />
|
||||
<meta name="theme-color" content="#111827" />
|
||||
<title>YMhut Unified Admin</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
@@ -2,7 +2,13 @@
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/logo-150.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="author" content="YMhut" />
|
||||
<meta name="application-name" content="YMhut Box" />
|
||||
<meta name="description" content="YMhut Box unified update, feedback, and interface source status portal for update.ymhut.cn." />
|
||||
<meta name="theme-color" content="#10231d" />
|
||||
<title>YMhut Box Service Portal</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { Activity, ArrowDownToLine, Database, HeartPulse, Network, ShieldCheck } from "lucide-vue-next";
|
||||
import { Activity, ArrowDownToLine, Box, HeartPulse, Network, ShieldCheck } from "lucide-vue-next";
|
||||
import { usePortalState } from "../state";
|
||||
|
||||
const state = usePortalState();
|
||||
@@ -37,7 +37,7 @@ const state = usePortalState();
|
||||
</section>
|
||||
|
||||
<section class="metric-grid">
|
||||
<article class="metric"><Database :size="20" /><span>数据库</span><strong>{{ state.databaseStatus.value }}</strong></article>
|
||||
<article class="metric"><Box :size="20" /><span>服务版本</span><strong>{{ state.serviceVersion.value }}</strong></article>
|
||||
<article class="metric"><Network :size="20" /><span>可见接口源</span><strong>{{ state.sourceCount.value }}</strong></article>
|
||||
<article class="metric"><HeartPulse :size="20" /><span>健康接口</span><strong>{{ state.healthyCount.value }}</strong></article>
|
||||
<article class="metric"><Activity :size="20" /><span>可用率</span><strong>{{ state.availability.value }}%</strong></article>
|
||||
|
||||
@@ -25,7 +25,6 @@ export function usePortalState() {
|
||||
const availability = computed(() => sourceCount.value ? Math.round((healthyCount.value / sourceCount.value) * 100) : 0);
|
||||
const downloadUrl = computed(() => releases.value?.download_url || bootstrap.value?.release?.download_url || packages.value[0]?.url || "");
|
||||
const appVersion = computed(() => releases.value?.app_version || bootstrap.value?.release?.app_version || latestNotice.value?.version || "未发布");
|
||||
const databaseStatus = computed(() => bootstrap.value?.health?.database?.activeProvider || bootstrap.value?.health?.database?.configProvider || "-");
|
||||
const serviceVersion = computed(() => bootstrap.value?.serviceVersion || "-");
|
||||
|
||||
async function load(force = false) {
|
||||
@@ -68,7 +67,6 @@ export function usePortalState() {
|
||||
availability,
|
||||
downloadUrl,
|
||||
appVersion,
|
||||
databaseStatus,
|
||||
serviceVersion,
|
||||
load,
|
||||
sourceStatus,
|
||||
|
||||
@@ -25,21 +25,14 @@ html { min-width: 320px; }
|
||||
body {
|
||||
margin: 0;
|
||||
min-width: 320px;
|
||||
background:
|
||||
radial-gradient(circle at 8% 6%, rgba(31, 111, 91, 0.10), transparent 30%),
|
||||
radial-gradient(circle at 90% 8%, rgba(217, 146, 39, 0.10), transparent 30%),
|
||||
linear-gradient(180deg, #f2f5ef 0%, #f8faf6 42%, #ffffff 100%);
|
||||
background: #f6f8f4;
|
||||
}
|
||||
body::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background-image:
|
||||
linear-gradient(rgba(31, 111, 91, 0.045) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(31, 111, 91, 0.045) 1px, transparent 1px);
|
||||
background-size: 42px 42px;
|
||||
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.55), transparent 70%);
|
||||
background: rgba(31, 111, 91, 0.025);
|
||||
}
|
||||
a { color: inherit; }
|
||||
button, input { font: inherit; }
|
||||
@@ -86,7 +79,7 @@ button { cursor: pointer; }
|
||||
place-items: center;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, #10231d, var(--primary));
|
||||
background: #10231d;
|
||||
box-shadow: 0 12px 26px rgba(31, 111, 91, 0.22);
|
||||
}
|
||||
.brand strong { letter-spacing: 0; }
|
||||
@@ -116,7 +109,7 @@ button { cursor: pointer; }
|
||||
}
|
||||
.admin-link {
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, #10231d, #1f6f5b);
|
||||
background: #10231d;
|
||||
box-shadow: 0 12px 28px rgba(31, 111, 91, 0.22);
|
||||
}
|
||||
.admin-link:hover { transform: translateY(-1px); box-shadow: 0 16px 36px rgba(31, 111, 91, 0.28); }
|
||||
@@ -132,24 +125,12 @@ button { cursor: pointer; }
|
||||
align-items: stretch;
|
||||
border: 1px solid rgba(255, 255, 255, 0.70);
|
||||
border-radius: 32px;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(255, 255, 255, 0.88), rgba(255, 255, 255, 0.62)),
|
||||
radial-gradient(circle at 88% 18%, rgba(31, 111, 91, 0.14), transparent 34%),
|
||||
radial-gradient(circle at 18% 82%, rgba(217, 146, 39, 0.13), transparent 30%);
|
||||
background: rgba(255, 255, 255, 0.88);
|
||||
box-shadow: var(--shadow);
|
||||
padding: clamp(28px, 5vw, 58px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -80px;
|
||||
bottom: -120px;
|
||||
width: 360px;
|
||||
height: 360px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(31, 111, 91, 0.13), transparent 68%);
|
||||
}
|
||||
.hero::after { content: none; }
|
||||
.hero-copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
@@ -225,7 +206,7 @@ p {
|
||||
.button.primary {
|
||||
color: #fff;
|
||||
border-color: transparent;
|
||||
background: linear-gradient(135deg, #10231d, #1f6f5b);
|
||||
background: #10231d;
|
||||
box-shadow: 0 16px 34px rgba(31, 111, 91, 0.24);
|
||||
}
|
||||
|
||||
@@ -329,7 +310,7 @@ p {
|
||||
margin: 0 auto 18px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.74);
|
||||
border-radius: 28px;
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.88), rgba(255, 255, 255, 0.68));
|
||||
background: rgba(255, 255, 255, 0.88);
|
||||
box-shadow: var(--shadow);
|
||||
padding: clamp(24px, 4vw, 42px);
|
||||
backdrop-filter: blur(16px);
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/setup/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/setup/logo-150.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="author" content="YMhut" />
|
||||
<meta name="application-name" content="YMhut Box Setup" />
|
||||
<meta name="description" content="YMhut Box unified management setup wizard for update.ymhut.cn." />
|
||||
<meta name="theme-color" content="#111827" />
|
||||
<title>YMhut Unified Setup</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |