Improve admin Chinese UI contrast

This commit is contained in:
2026-04-27 17:11:16 +08:00
parent ea61063d02
commit d3aa8da406
8 changed files with 89 additions and 70 deletions

View File

@@ -44,7 +44,7 @@ export default function DashboardPage() {
<div className="admin-dashboard-stack"> <div className="admin-dashboard-stack">
<section className="panel dashboard-stage"> <section className="panel dashboard-stage">
<div className="dashboard-stage-copy"> <div className="dashboard-stage-copy">
<span className="header-kicker">Control overview</span> <span className="header-kicker"></span>
<h3></h3> <h3></h3>
<p className="muted"> <p className="muted">
线 线

View File

@@ -5,6 +5,20 @@ import { useState } from "react";
import { api } from "@/lib/api"; import { api } from "@/lib/api";
const fieldLabels: Record<string, string> = {
provider_code: "供应商编码",
provider_name: "供应商名称",
api_format: "接口协议",
base_url: "接口地址",
api_key: "接口密钥",
api_secret: "接口密钥补充",
webhook_secret: "回调密钥",
timeout_seconds: "超时时间(秒)",
max_retries: "最大重试次数",
status: "状态",
remark: "备注",
};
export default function ProviderAccountsPage() { export default function ProviderAccountsPage() {
const [form, setForm] = useState({ const [form, setForm] = useState({
provider_code: "openai-backup", provider_code: "openai-backup",
@@ -17,7 +31,7 @@ export default function ProviderAccountsPage() {
timeout_seconds: 120, timeout_seconds: 120,
max_retries: 3, max_retries: 3,
status: 1, status: 1,
remark: "backup route", remark: "备用线路",
}); });
const query = useQuery({ const query = useQuery({
queryKey: ["provider-accounts"], queryKey: ["provider-accounts"],
@@ -35,7 +49,7 @@ export default function ProviderAccountsPage() {
<div className="form-stack"> <div className="form-stack">
{Object.entries(form).map(([key, value]) => ( {Object.entries(form).map(([key, value]) => (
<label className="field-label" key={key}> <label className="field-label" key={key}>
{key} {fieldLabels[key] ?? key}
<input <input
value={String(value)} value={String(value)}
onChange={(event) => onChange={(event) =>
@@ -60,4 +74,3 @@ export default function ProviderAccountsPage() {
</div> </div>
); );
} }

View File

@@ -11,6 +11,15 @@ type ConfigRow = {
groupName: string; groupName: string;
}; };
const fieldLabels: Record<string, string> = {
config_key: "配置键",
config_value: "配置值",
value_type: "值类型",
group_name: "配置分组",
description: "配置说明",
is_public: "是否公开",
};
export default function SystemConfigPage() { export default function SystemConfigPage() {
const [form, setForm] = useState({ const [form, setForm] = useState({
config_key: "site.notice", config_key: "site.notice",
@@ -36,7 +45,7 @@ export default function SystemConfigPage() {
<div className="form-stack"> <div className="form-stack">
{Object.entries(form).map(([key, value]) => ( {Object.entries(form).map(([key, value]) => (
<label className="field-label" key={key}> <label className="field-label" key={key}>
{key} {fieldLabels[key] ?? key}
<input <input
value={String(value)} value={String(value)}
onChange={(event) => onChange={(event) =>

View File

@@ -33,10 +33,10 @@ export default function AdminLoginPage() {
return ( return (
<div className="admin-auth-page"> <div className="admin-auth-page">
<section className="admin-auth-copy"> <section className="admin-auth-copy">
<span className="admin-page-kicker">OPERATIONS CONSOLE</span> <span className="admin-page-kicker"></span>
<h1>AIVIDEO CONTROL SURFACE</h1> <h1>AIVideo </h1>
<p> <p>
dark console
</p> </p>
<div className="admin-auth-grid"> <div className="admin-auth-grid">
@@ -61,7 +61,7 @@ export default function AdminLoginPage() {
<section className="admin-auth-panel"> <section className="admin-auth-panel">
<form className="admin-auth-card" onSubmit={handleSubmit}> <form className="admin-auth-card" onSubmit={handleSubmit}>
<div className="admin-auth-head"> <div className="admin-auth-head">
<span className="admin-page-kicker">ADMIN ACCESS</span> <span className="admin-page-kicker"></span>
<h2></h2> <h2></h2>
<p></p> <p></p>
</div> </div>
@@ -96,7 +96,7 @@ export default function AdminLoginPage() {
{error ? <div className="inline-feedback is-error">{error}</div> : null} {error ? <div className="inline-feedback is-error">{error}</div> : null}
<button className="primary-button" type="submit"> <button className="primary-button" type="submit">
{loading ? "SIGNING IN..." : "ENTER CONSOLE"} {loading ? "登录中..." : "进入控制台"}
{loading ? null : <ArrowRight size={16} />} {loading ? null : <ArrowRight size={16} />}
</button> </button>

View File

@@ -7,10 +7,10 @@
--page-surface: #fffdf7; --page-surface: #fffdf7;
--page-surface-strong: #ffffff; --page-surface-strong: #ffffff;
--page-ink: #161816; --page-ink: #161816;
--page-ink-soft: rgba(22, 24, 22, 0.72); --page-ink-soft: #30332f;
--page-muted: rgba(22, 24, 22, 0.54); --page-muted: #625d52;
--page-border: rgba(22, 24, 22, 0.14); --page-border: rgba(22, 24, 22, 0.2);
--page-border-soft: rgba(22, 24, 22, 0.08); --page-border-soft: rgba(22, 24, 22, 0.12);
--page-accent: #00a99d; --page-accent: #00a99d;
--page-accent-hover: #008e84; --page-accent-hover: #008e84;
--page-accent-strong: #073f3b; --page-accent-strong: #073f3b;
@@ -1664,16 +1664,16 @@ p {
.admin-auth-page, .admin-auth-page,
.admin-app-shell, .admin-app-shell,
.admin-loading-shell { .admin-loading-shell {
--admin-bg: #151712; --admin-bg: #f3eee4;
--admin-bg-soft: #1f2119; --admin-bg-soft: #fffaf1;
--admin-surface: rgba(255, 249, 237, 0.055); --admin-surface: #fffdf8;
--admin-surface-hover: rgba(255, 249, 237, 0.09); --admin-surface-hover: #f0f7f5;
--admin-border: rgba(255, 249, 237, 0.12); --admin-border: #d8d0c2;
--admin-border-strong: rgba(255, 249, 237, 0.24); --admin-border-strong: #bfb5a5;
--admin-text: #fff9ed; --admin-text: #181815;
--admin-text-soft: rgba(255, 249, 237, 0.68); --admin-text-soft: #3e3a33;
--admin-text-dim: rgba(255, 249, 237, 0.48); --admin-text-dim: #6a6257;
--admin-accent: #00c2b2; --admin-accent: #007a72;
background: var(--admin-bg); background: var(--admin-bg);
color: var(--admin-text); color: var(--admin-text);
} }
@@ -1694,11 +1694,11 @@ p {
align-content: space-between; align-content: space-between;
gap: 28px; gap: 28px;
background: background:
linear-gradient(135deg, rgba(21, 23, 18, 1), rgba(41, 36, 25, 0.96)), linear-gradient(135deg, #fffdf8, #ece3d5),
repeating-linear-gradient( repeating-linear-gradient(
90deg, 90deg,
rgba(255, 249, 237, 0.04) 0, rgba(22, 24, 22, 0.045) 0,
rgba(255, 249, 237, 0.04) 1px, rgba(22, 24, 22, 0.045) 1px,
transparent 1px, transparent 1px,
transparent 86px transparent 86px
); );
@@ -1706,10 +1706,10 @@ p {
.admin-auth-copy h1 { .admin-auth-copy h1 {
margin: 0; margin: 0;
max-width: 12ch; max-width: 12em;
font-size: 64px; font-size: 64px;
line-height: 0.98; line-height: 0.98;
font-family: var(--font-mono), Consolas, monospace; font-family: var(--font-display), "PingFang SC", "Microsoft YaHei UI", sans-serif;
font-weight: 800; font-weight: 800;
letter-spacing: 0; letter-spacing: 0;
} }
@@ -1724,7 +1724,7 @@ p {
.admin-page-kicker { .admin-page-kicker {
color: var(--admin-accent); color: var(--admin-accent);
font-family: var(--font-mono), Consolas, monospace; font-family: var(--font-body), "PingFang SC", "Microsoft YaHei UI", sans-serif;
} }
.admin-auth-grid { .admin-auth-grid {
@@ -1743,7 +1743,7 @@ p {
} }
.admin-auth-info svg { .admin-auth-info svg {
color: var(--page-warm); color: var(--admin-accent);
} }
.admin-auth-info strong { .admin-auth-info strong {
@@ -1768,6 +1768,7 @@ p {
border-radius: var(--radius-card); border-radius: var(--radius-card);
border: 1px solid var(--admin-border); border: 1px solid var(--admin-border);
background: var(--admin-surface); background: var(--admin-surface);
box-shadow: var(--page-shadow-soft);
} }
.admin-auth-head { .admin-auth-head {
@@ -1795,7 +1796,7 @@ p {
.admin-app-shell .field-label select, .admin-app-shell .field-label select,
.admin-app-shell .field-label textarea { .admin-app-shell .field-label textarea {
color: var(--admin-text); color: var(--admin-text);
background: rgba(255, 249, 237, 0.05); background: #ffffff;
border-color: var(--admin-border-strong); border-color: var(--admin-border-strong);
} }
@@ -1811,15 +1812,15 @@ p {
.admin-auth-page .primary-button, .admin-auth-page .primary-button,
.admin-app-shell .primary-button { .admin-app-shell .primary-button {
background: #fff9ed; background: #181815;
color: #151712; color: #fffdf8;
box-shadow: none; box-shadow: 0 10px 24px rgba(24, 24, 21, 0.16);
} }
.admin-auth-page .ghost-button, .admin-auth-page .ghost-button,
.admin-app-shell .ghost-button, .admin-app-shell .ghost-button,
.admin-app-shell .danger-button { .admin-app-shell .danger-button {
background: transparent; background: #fffdf8;
color: var(--admin-text); color: var(--admin-text);
border-color: var(--admin-border-strong); border-color: var(--admin-border-strong);
box-shadow: none; box-shadow: none;
@@ -1831,7 +1832,7 @@ p {
.admin-auth-page .inline-feedback, .admin-auth-page .inline-feedback,
.admin-app-shell .inline-feedback { .admin-app-shell .inline-feedback {
background: rgba(255, 249, 237, 0.05); background: #fffdf8;
border-color: var(--admin-border); border-color: var(--admin-border);
color: var(--admin-text-soft); color: var(--admin-text-soft);
} }
@@ -1859,7 +1860,7 @@ p {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 18px; gap: 18px;
background: #12140f; background: #fffdf8;
} }
.admin-rail-brand { .admin-rail-brand {
@@ -1872,7 +1873,6 @@ p {
.admin-rail-kicker { .admin-rail-kicker {
color: var(--admin-text-soft); color: var(--admin-text-soft);
font-size: 11px; font-size: 11px;
font-family: var(--font-mono), Consolas, monospace;
font-weight: 800; font-weight: 800;
} }
@@ -1880,7 +1880,7 @@ p {
margin: 0; margin: 0;
font-size: 30px; font-size: 30px;
line-height: 1; line-height: 1;
font-family: var(--font-mono), Consolas, monospace; font-family: var(--font-display), "PingFang SC", "Microsoft YaHei UI", sans-serif;
font-weight: 850; font-weight: 850;
letter-spacing: 0; letter-spacing: 0;
} }
@@ -1907,7 +1907,6 @@ p {
border-radius: var(--radius-card); border-radius: var(--radius-card);
color: var(--admin-text-soft); color: var(--admin-text-soft);
font-size: 12px; font-size: 12px;
font-family: var(--font-mono), Consolas, monospace;
font-weight: 800; font-weight: 800;
} }
@@ -1941,7 +1940,6 @@ p {
.admin-rail-user span { .admin-rail-user span {
color: var(--admin-text-dim); color: var(--admin-text-dim);
font-size: 12px; font-size: 12px;
font-family: var(--font-mono), Consolas, monospace;
} }
.admin-main-shell { .admin-main-shell {
@@ -1985,7 +1983,6 @@ p {
border-radius: 999px; border-radius: 999px;
color: var(--admin-text-soft); color: var(--admin-text-soft);
font-size: 12px; font-size: 12px;
font-family: var(--font-mono), Consolas, monospace;
font-weight: 800; font-weight: 800;
} }
@@ -2004,7 +2001,7 @@ p {
.admin-loading-shell .pulse-card { .admin-loading-shell .pulse-card {
background: var(--admin-surface); background: var(--admin-surface);
border-color: var(--admin-border); border-color: var(--admin-border);
box-shadow: none; box-shadow: var(--page-shadow-soft);
color: var(--admin-text); color: var(--admin-text);
} }
@@ -2035,9 +2032,9 @@ p {
.admin-app-shell .tab-chip.active, .admin-app-shell .tab-chip.active,
.admin-app-shell .segmented-button.active { .admin-app-shell .segmented-button.active {
color: #151712; color: #fffdf8;
border-color: #fff9ed; border-color: #181815;
background: #fff9ed; background: #181815;
} }
.admin-app-shell .code-block { .admin-app-shell .code-block {

View File

@@ -34,7 +34,7 @@ export default function LoginPage() {
<div className="auth-page auth-page-user"> <div className="auth-page auth-page-user">
<section className="auth-showcase auth-showcase-user"> <section className="auth-showcase auth-showcase-user">
<div className="auth-showcase-copy"> <div className="auth-showcase-copy">
<span className="auth-showcase-kicker">AIVIDEO FOR CREATORS</span> <span className="auth-showcase-kicker"></span>
<h1></h1> <h1></h1>
<p> <p>
AIVideo AIVideo
@@ -64,7 +64,7 @@ export default function LoginPage() {
<section className="auth-form-column"> <section className="auth-form-column">
<form className="auth-form-card" onSubmit={handleSubmit}> <form className="auth-form-card" onSubmit={handleSubmit}>
<div className="auth-form-head"> <div className="auth-form-head">
<span className="auth-form-kicker">Welcome Back</span> <span className="auth-form-kicker"></span>
<h2> AIVideo</h2> <h2> AIVideo</h2>
<p></p> <p></p>
</div> </div>

View File

@@ -21,20 +21,20 @@ import { useEffect, useMemo } from "react";
import { api } from "@/lib/api"; import { api } from "@/lib/api";
const navigation = [ const navigation = [
{ href: "/admin/dashboard", label: "OVERVIEW", title: "系统总览", description: "查看平台总览、支付与任务健康度。", icon: ChartColumnBig }, { href: "/admin/dashboard", label: "系统总览", title: "系统总览", description: "查看平台总览、支付与任务健康度。", icon: ChartColumnBig },
{ href: "/admin/users", label: "USERS", title: "用户管理", description: "维护用户状态、余额与资料。", icon: Users }, { href: "/admin/users", label: "用户管理", title: "用户管理", description: "维护用户状态、余额与资料。", icon: Users },
{ href: "/admin/recharge-orders", label: "ORDERS", title: "充值订单", description: "跟踪充值流转与支付状态。", icon: Coins }, { href: "/admin/recharge-orders", label: "充值订单", title: "充值订单", description: "跟踪充值流转与支付状态。", icon: Coins },
{ href: "/admin/redeem-codes", label: "REDEEM", title: "兑换密钥", description: "管理兑换码的创建、停用和审计。", icon: KeySquare }, { href: "/admin/redeem-codes", label: "兑换码", title: "兑换密钥", description: "管理兑换码的创建、停用和审计。", icon: KeySquare },
{ href: "/admin/growth-rules", label: "GROWTH", title: "增长奖励", description: "配置注册奖励与邀请返利规则。", icon: Link2 }, { href: "/admin/growth-rules", label: "增长奖励", title: "增长奖励", description: "配置注册奖励与邀请返利规则。", icon: Link2 },
{ href: "/admin/invite-relations", label: "INVITES", title: "邀请关系", description: "查看邀请码链路与归因结果。", icon: Link2 }, { href: "/admin/invite-relations", label: "邀请关系", title: "邀请关系", description: "查看邀请码链路与归因结果。", icon: Link2 },
{ href: "/admin/provider-accounts", label: "ACCOUNTS", title: "供应商账号", description: "管理供应商账号和鉴权信息。", icon: Workflow }, { href: "/admin/provider-accounts", label: "供应商账号", title: "供应商账号", description: "管理供应商账号和鉴权信息。", icon: Workflow },
{ href: "/admin/provider-models", label: "MODELS", title: "供应商模型", description: "维护供应商模型能力与协议。", icon: Blocks }, { href: "/admin/provider-models", label: "供应商模型", title: "供应商模型", description: "维护供应商模型能力与协议。", icon: Blocks },
{ href: "/admin/video-models", label: "CATALOG", title: "平台模型", description: "定义前台可见的统一模型层。", icon: Package2 }, { href: "/admin/video-models", label: "平台模型", title: "平台模型", description: "定义前台可见的统一模型层。", icon: Package2 },
{ href: "/admin/video-model-bindings", label: "ROUTING", title: "模型绑定", description: "决定平台模型到供应商模型的路由。", icon: Workflow }, { href: "/admin/video-model-bindings", label: "模型绑定", title: "模型绑定", description: "决定平台模型到供应商模型的路由。", icon: Workflow },
{ href: "/admin/pricing-rules", label: "PRICING", title: "价格规则", description: "按模型与版本维护积分定价。", icon: Coins }, { href: "/admin/pricing-rules", label: "价格规则", title: "价格规则", description: "按模型与版本维护积分定价。", icon: Coins },
{ href: "/admin/video-tasks", label: "TASKS", title: "视频任务", description: "处理异常任务与追踪执行结果。", icon: Workflow }, { href: "/admin/video-tasks", label: "视频任务", title: "视频任务", description: "处理异常任务与追踪执行结果。", icon: Workflow },
{ href: "/admin/callback-logs", label: "CALLBACKS", title: "回调日志", description: "查看供应商回调负载与异常线索。", icon: ChartColumnBig }, { href: "/admin/callback-logs", label: "回调日志", title: "回调日志", description: "查看供应商回调负载与异常线索。", icon: ChartColumnBig },
{ href: "/admin/system-config", label: "CONFIG", title: "系统配置", description: "维护站点和策略配置。", icon: Settings2 }, { href: "/admin/system-config", label: "系统配置", title: "系统配置", description: "维护站点和策略配置。", icon: Settings2 },
]; ];
export function AdminShell({ children }: { children: React.ReactNode }) { export function AdminShell({ children }: { children: React.ReactNode }) {
@@ -71,7 +71,7 @@ export function AdminShell({ children }: { children: React.ReactNode }) {
<div className="admin-app-shell"> <div className="admin-app-shell">
<aside className="admin-rail"> <aside className="admin-rail">
<div className="admin-rail-brand"> <div className="admin-rail-brand">
<span className="admin-rail-kicker">AIVIDEO CONTROL</span> <span className="admin-rail-kicker"></span>
<h1>AIVideo</h1> <h1>AIVideo</h1>
<p></p> <p></p>
</div> </div>
@@ -108,7 +108,7 @@ export function AdminShell({ children }: { children: React.ReactNode }) {
type="button" type="button"
> >
<LogOut size={14} /> <LogOut size={14} />
SIGN OUT 退
</button> </button>
</div> </div>
</aside> </aside>
@@ -116,13 +116,13 @@ export function AdminShell({ children }: { children: React.ReactNode }) {
<main className="admin-main-shell"> <main className="admin-main-shell">
<header className="admin-page-hero"> <header className="admin-page-hero">
<div> <div>
<span className="admin-page-kicker">OPERATIONS CONSOLE</span> <span className="admin-page-kicker"></span>
<h2>{current.title}</h2> <h2>{current.title}</h2>
<p>{current.description}</p> <p>{current.description}</p>
</div> </div>
<div className="admin-page-tags"> <div className="admin-page-tags">
<span>LIVE SESSION</span> <span></span>
<span>RULES / TASKS / PRICING</span> <span> / / </span>
</div> </div>
</header> </header>

View File

@@ -39,7 +39,7 @@ export function RegisterForm({ inviteCode = "" }: { inviteCode?: string }) {
<div className="auth-page auth-page-user"> <div className="auth-page auth-page-user">
<section className="auth-showcase auth-showcase-user"> <section className="auth-showcase auth-showcase-user">
<div className="auth-showcase-copy"> <div className="auth-showcase-copy">
<span className="auth-showcase-kicker">CREATE ACCOUNT</span> <span className="auth-showcase-kicker"></span>
<h1></h1> <h1></h1>
<p> <p>
@@ -68,7 +68,7 @@ export function RegisterForm({ inviteCode = "" }: { inviteCode?: string }) {
<section className="auth-form-column"> <section className="auth-form-column">
<form className="auth-form-card" onSubmit={handleSubmit}> <form className="auth-form-card" onSubmit={handleSubmit}>
<div className="auth-form-head"> <div className="auth-form-head">
<span className="auth-form-kicker">Get Started</span> <span className="auth-form-kicker">使</span>
<h2></h2> <h2></h2>
<p></p> <p></p>
</div> </div>