forked from EduCraft/curriculum-project-hub
12628c9233
- scaffold hub/database-admin as SvelteKit 2 + Svelte 5 static SPA
with aurora/glass visual style (paths.base='/database')
- add lib/{api,session,org}.ts + Aurora.svelte component
- add routes: root redirect, /admin login page, /dashboard (OWNER/ADMIN only)
- backend: replace server-rendered HTML routes with /database/config JSON endpoint
- add hub/src/database/static.ts to serve SPA under /database/*
- wire registerDatabaseSpa into plugin.ts
- exempt /database/* from silo rate-limit (same treatment as /admin/*)
- add database:dev + database:build npm scripts; update deploy scripts
- update hub/src/database/README.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
79 lines
2.9 KiB
Svelte
79 lines
2.9 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from 'svelte';
|
|
import { goto } from '$app/navigation';
|
|
import { base } from '$app/paths';
|
|
import { api, type DatabaseConfig } from '$lib/api';
|
|
import { feishuLoginHref } from '$lib/session';
|
|
import Aurora from '$lib/components/Aurora.svelte';
|
|
|
|
let config = $state<DatabaseConfig | null>(null);
|
|
let error = $state<string | null>(null);
|
|
|
|
onMount(async () => {
|
|
// Already signed in → straight to the dashboard.
|
|
try {
|
|
await api.me();
|
|
await goto(`${base}/dashboard`, { replaceState: true });
|
|
return;
|
|
} catch {
|
|
// Not signed in (401) or backend unreachable — show the login card.
|
|
}
|
|
try {
|
|
config = await api.databaseConfig();
|
|
} catch (err) {
|
|
error = err instanceof Error ? err.message : String(err);
|
|
}
|
|
});
|
|
|
|
const feishuHref = $derived(config ? feishuLoginHref(config.siloOrganizationSlug) : '#');
|
|
</script>
|
|
|
|
<Aurora />
|
|
|
|
<main class="flex min-h-screen items-center justify-center p-4">
|
|
<div class="rise glass relative w-full max-w-sm rounded-3xl border border-white/80 p-8 shadow-2xl shadow-indigo-200/50">
|
|
<div class="mb-7 text-center">
|
|
<div
|
|
class="mx-auto mb-5 flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br from-violet-500 to-cyan-400 text-2xl font-bold text-white glow-btn"
|
|
>
|
|
D
|
|
</div>
|
|
<h1 class="text-2xl font-bold tracking-tight grad-text">Database Admin</h1>
|
|
<p class="mt-2 text-sm text-slate-500">使用飞书登录以管理数据库</p>
|
|
</div>
|
|
|
|
{#if error}
|
|
<div class="mb-4 rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-600">
|
|
无法连接后端:{error}
|
|
</div>
|
|
{/if}
|
|
|
|
<a
|
|
href={feishuHref}
|
|
aria-disabled={config ? 'false' : 'true'}
|
|
class="rise-2 glow-btn group flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-violet-500 to-indigo-500 px-4 py-3.5 text-sm font-semibold text-white transition hover:from-violet-400 hover:to-indigo-400 aria-disabled:pointer-events-none aria-disabled:opacity-50"
|
|
>
|
|
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M12 2 3 7v10l9 5 9-5V7l-9-5Zm0 2.3 6.5 3.6L12 11.5 5.5 7.9 12 4.3Z" />
|
|
</svg>
|
|
使用飞书登录
|
|
</a>
|
|
|
|
{#if config?.devLoginEnabled}
|
|
<div class="relative my-6 rise-3">
|
|
<div class="absolute inset-0 flex items-center"><div class="w-full border-t border-slate-200"></div></div>
|
|
<div class="relative flex justify-center">
|
|
<span class="bg-white/70 px-3 text-[11px] font-medium uppercase tracking-[0.2em] text-slate-400">开发模式</span>
|
|
</div>
|
|
</div>
|
|
<a
|
|
href="/database/dev-login"
|
|
class="rise-3 group flex w-full items-center justify-center gap-2 rounded-xl border border-amber-300 bg-amber-50 px-4 py-3 text-sm font-semibold text-amber-700 transition hover:border-amber-400 hover:bg-amber-100"
|
|
>
|
|
<span>⚡</span> 一键登录管理员
|
|
</a>
|
|
<p class="rise-3 mt-2 text-center text-xs text-slate-400">仅开发环境可见 · 跳过飞书 OAuth</p>
|
|
{/if}
|
|
</div>
|
|
</main>
|