diff --git a/frontend/index.html b/frontend/index.html index def226609..59c6a4a60 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,6 +2,7 @@ + Windup 侧视机械小鸟标志 + @@ -12,5 +18,5 @@ - + diff --git a/frontend/src/app/layout/index.tsx b/frontend/src/app/layout/index.tsx index 875867b7d..2b0d26035 100644 --- a/frontend/src/app/layout/index.tsx +++ b/frontend/src/app/layout/index.tsx @@ -40,7 +40,7 @@ export function AppShell({ children }: AppShellProps) { /** 公开页面外壳只提供认证面板与会话提醒,宣传导航由 LandingPage 自己组合。 */ export function MarketingShell({ children }: AppShellProps) { return ( -
+
{children} diff --git a/frontend/src/app/playtest-export-page.tsx b/frontend/src/app/playtest-export-page.tsx index 9d538fbcf..8cec21419 100644 --- a/frontend/src/app/playtest-export-page.tsx +++ b/frontend/src/app/playtest-export-page.tsx @@ -20,7 +20,7 @@ const renderToolbar: NonNullable = ({ ) } catch { diff --git a/frontend/src/features/account-panel/account-panel.css b/frontend/src/features/account-panel/account-panel.css index e67d3f373..176833657 100644 --- a/frontend/src/features/account-panel/account-panel.css +++ b/frontend/src/features/account-panel/account-panel.css @@ -1,11 +1,11 @@ .auth-screen { - --auth-ink: #282721; - --auth-muted: #6f6d65; - --auth-line: #cfcdc4; - --auth-paper: #f4f1e9; - --auth-control-surface: #fbfaf6; - --auth-control-surface-focus: #fff; - --auth-description: #68665f; + --auth-ink: light-dark(#282721, #e8e8e8); + --auth-muted: light-dark(#6f6d65, #adadad); + --auth-line: light-dark(#cfcdc4, #404040); + --auth-paper: light-dark(#f4f1e9, #242424); + --auth-control-surface: light-dark(#fbfaf6, #2d2d2d); + --auth-control-surface-focus: light-dark(#fff, #383838); + --auth-description: light-dark(#68665f, #adadad); --auth-motion-fast: 120ms; --auth-motion-default: 220ms; --auth-motion-slow: 360ms; @@ -73,7 +73,7 @@ .auth-screen-close:hover { border-color: var(--auth-line); color: var(--auth-ink); - background: rgb(255 255 255 / 72%); + background: light-dark(rgb(255 255 255 / 72%), rgb(56 56 56 / 72%)); transform: rotate(4deg) scale(1.04); } @@ -103,7 +103,7 @@ .auth-screen-entry-switch button:focus-visible, .auth-password-field button:focus-visible, .auth-register-back:focus-visible { - outline: 2px solid #1b1b19; + outline: 2px solid light-dark(#1b1b19, #d7d7d7); outline-offset: 3px; } @@ -209,7 +209,7 @@ .auth-register-fields .auth-screen-label { gap: 0; - color: #302f2a; + color: light-dark(#302f2a, #cecece); font-weight: 500; } @@ -232,7 +232,7 @@ grid-template-columns: 3.75rem minmax(0, 1fr); align-items: stretch; overflow: hidden; - border: 1px solid #c8c6bc; + border: 1px solid light-dark(#c8c6bc, #606060); border-radius: 0.625rem; background: var(--auth-control-surface); transform: translateZ(0); @@ -244,8 +244,8 @@ } .auth-register-field-shell:focus-within { - border-color: #3c3b35; - box-shadow: 0 0 0 3px rgb(40 39 33 / 7%); + border-color: light-dark(#3c3b35, #d7d7d7); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--auth-ink) 7%, transparent); background: var(--auth-control-surface-focus); transform: translateY(-2px); } @@ -255,7 +255,7 @@ justify-self: center; width: 1.25rem; height: 1.25rem; - color: #69675f; + color: light-dark(#69675f, #adadad); stroke-width: 1.35; transform-origin: center; transition: @@ -265,7 +265,7 @@ } .auth-register-field-shell:focus-within > svg { - color: #292821; + color: light-dark(#292821, #e8e8e8); transform: scale(1.08) rotate(-3deg); } @@ -292,7 +292,7 @@ height: 2.75rem; place-self: center; place-items: center; - color: #6c6961; + color: light-dark(#6c6961, #adadad); transition: color var(--auth-motion-fast) var(--auth-ease-enter), transform var(--auth-motion-fast) var(--auth-ease-enter); @@ -328,7 +328,7 @@ place-items: center; border: 0; border-radius: 50%; - color: #65635b; + color: light-dark(#65635b, #adadad); background: transparent; transition: color var(--auth-motion-fast) var(--auth-ease-enter), @@ -339,7 +339,7 @@ .auth-register-back:hover { color: var(--auth-ink); - background: rgb(40 39 33 / 6%); + background: color-mix(in srgb, var(--auth-ink) 6%, transparent); transform: translateX(-3px); } @@ -369,11 +369,11 @@ } .auth-register-fields .auth-screen-toast-error { - color: #873f37; + color: light-dark(#873f37, #e4ab94); } .auth-register-fields .auth-screen-toast-success { - color: #55554f; + color: light-dark(#55554f, #b6b6b6); } .auth-screen-helper, @@ -430,7 +430,7 @@ min-height: 4.25rem; border: 0; border-radius: 0; - color: #2b2a25; + color: light-dark(#2b2a25, #e8e8e8); background: var(--auth-control-surface); box-shadow: none; font-size: 0.9375rem; @@ -439,7 +439,7 @@ } .auth-screen-field::placeholder { - color: #7b7971; + color: light-dark(#7b7971, #9d9d9d); opacity: 1; } @@ -459,9 +459,9 @@ place-items: center; padding-inline: 0.75rem; border: 0; - border-left: 1px solid #d8d5cb; + border-left: 1px solid light-dark(#d8d5cb, #404040); border-radius: 0; - color: #45433d; + color: light-dark(#45433d, #cecece); background: var(--auth-control-surface); font-size: 0.8125rem; font-weight: 500; @@ -473,7 +473,7 @@ } .auth-screen-code-action:hover:not(:disabled) { - background: #f9f9f6; + background: light-dark(#f9f9f6, #383838); transform: translateY(-1px); } @@ -495,7 +495,7 @@ .auth-screen-entry-switch a, .auth-screen-entry-switch button { flex-shrink: 0; - color: #34332e; + color: light-dark(#34332e, #cecece); font-weight: 500; text-decoration: underline; text-decoration-thickness: 1px; @@ -511,9 +511,10 @@ overflow: hidden; min-height: 3.75rem; margin-top: 0; - border: 1px solid #282721; + border: 1px solid light-dark(#282721, #e8e8e8); border-radius: 0.375rem; - background: #282721; + background: light-dark(#282721, #e8e8e8); + color: light-dark(#fff, #202020); font-size: 0.9375rem; font-weight: 500; transition: @@ -523,7 +524,7 @@ } .auth-screen-submit:hover:not(:disabled) { - background: #393832; + background: light-dark(#393832, #eeeeee); transform: translateY(-1px); } @@ -548,13 +549,13 @@ .auth-screen-entry-switch { margin-top: 1.5rem; - color: #747169; + color: light-dark(#747169, #adadad); font-size: 0.875rem; } .auth-screen-entry-switch a:hover, .auth-screen-entry-switch button:hover { - color: #000; + color: light-dark(#000, #e8e8e8); text-underline-offset: 0.3em; transform: translateY(-1px); } @@ -825,15 +826,15 @@ } .auth-screen-toast-success { - border-color: #cfcfc9; - color: #33332f; - background: rgb(255 255 255 / 88%); + border-color: light-dark(#cfcfc9, #404040); + color: light-dark(#33332f, #cecece); + background: light-dark(rgb(255 255 255 / 88%), rgb(45 45 45 / 88%)); } .auth-screen-toast-error { border-color: rgb(154 71 62 / 26%); - color: #883c34; - background: rgb(255 245 243 / 96%); + color: light-dark(#883c34, #e4ab94); + background: light-dark(rgb(255 245 243 / 96%), rgb(55 40 34 / 96%)); } @media (max-width: 540px) { diff --git a/frontend/src/features/account-panel/index.tsx b/frontend/src/features/account-panel/index.tsx index 1515cc254..083ee8860 100644 --- a/frontend/src/features/account-panel/index.tsx +++ b/frontend/src/features/account-panel/index.tsx @@ -686,7 +686,7 @@ function AccountPanelDialog({ onClick={close} disabled={isExiting} aria-label="关闭账号面板" - className="auth-screen-close fixed z-[3] grid size-11 place-items-center rounded-full border border-transparent text-2xl leading-none text-[#777770]" + className="auth-screen-close fixed z-[3] grid size-11 place-items-center rounded-full border border-transparent text-2xl leading-none text-app-muted" > @@ -814,7 +814,7 @@ function AccountPanelDialog({ @@ -906,7 +906,7 @@ function AccountPanelDialog({ @@ -1079,7 +1079,7 @@ function AccountPanelDialog({ @@ -291,7 +294,10 @@ function CocosImportFeedback({ action }: { action: ReturnType +

{PHASE_LABELS[state.phase]}

) @@ -478,27 +484,35 @@ export function ExportPanel({
-

GAME ASSETS

-

资产导出

-

逐帧透明 PNG、Sprite Sheet 与动画 JSON

+

+ GAME ASSETS +

+

资产导出

+

+ 逐帧透明 PNG、Sprite Sheet 与动画 JSON +

-
当前阶段
-
{STAGE_LABELS[model.stage]}
-
已确认首帧
-
{model.firstFrames.length} 张
-
动作方向
-
{plan.length} 组
-
逐帧原图
-
+
当前阶段
+
+ {STAGE_LABELS[model.stage]} +
+
已确认首帧
+
+ {model.firstFrames.length} 张 +
+
动作方向
+
{plan.length} 组
+
逐帧原图
+
{plan.reduce((total, item) => total + item.frames.length, 0)} 张
-
每行上限
-
8 帧
+
每行上限
+
8 帧
{qualityIssueCount > 0 ? ( @@ -508,7 +522,10 @@ export function ExportPanel({ ) : null} {state.status === 'working' ? ( -

+

{PHASE_LABELS[state.phase]}

) : state.status === 'failure' ? ( @@ -523,21 +540,25 @@ export function ExportPanel({ type="button" disabled={working || cocos.working || cocosImport.working || qualityIssueCount > 0} onClick={() => void startExport()} - className="w-full rounded-lg bg-orange-500 px-3 py-2 text-xs font-semibold text-white hover:bg-orange-600 disabled:cursor-not-allowed disabled:opacity-40" + className="w-full rounded-lg bg-orange-500 dark:bg-app-accent px-3 py-2 text-xs font-semibold text-white dark:text-app-on-accent hover:bg-orange-600 dark:hover:bg-app-accent-hover disabled:cursor-not-allowed disabled:opacity-40" > {state.status === 'failure' ? '重新导出' : '导出游戏资产包'} - {plan.length === 0 ?

当前包含角色母版

: null} + {plan.length === 0 ? ( +

当前包含角色母版

+ ) : null} {enableCocosExport ? ( -
+
- + 一键导入 -

Cocos Creator 3.8 适配

+

+ Cocos Creator 3.8 适配 +

-

+

首次安装并配对插件后,可直接写入当前 2D 工程并刷新 Prefab、动画和 SpriteFrame。

@@ -545,7 +566,7 @@ export function ExportPanel({ type="button" disabled={working || cocos.working || cocosImport.working || qualityIssueCount > 0} onClick={() => void cocosImport.startImport()} - className="w-full rounded-lg bg-sky-700 px-3 py-2 text-xs font-semibold text-white hover:bg-sky-800 disabled:cursor-not-allowed disabled:opacity-40" + className="w-full rounded-lg bg-sky-700 dark:bg-app-accent px-3 py-2 text-xs font-semibold text-white dark:text-app-on-accent hover:bg-sky-800 dark:hover:bg-app-accent-hover disabled:cursor-not-allowed disabled:opacity-40" > {cocosImport.state.status === 'failure' ? '重新导入 Cocos' : '一键导入 Cocos'} @@ -559,11 +580,11 @@ export function ExportPanel({ ? cocos.state.message : '插件不可用时下载 Cocos 适配包' } - className="w-full rounded-lg border border-amber-300 bg-white px-3 py-2 text-xs font-semibold text-amber-900 hover:bg-amber-100 disabled:cursor-not-allowed disabled:opacity-40" + className="w-full rounded-lg border border-amber-300 dark:border-app-warning-line bg-white dark:bg-app-surface-raised px-3 py-2 text-xs font-semibold text-amber-900 dark:text-app-warning hover:bg-amber-100 dark:hover:bg-app-warning-soft disabled:cursor-not-allowed disabled:opacity-40" > {cocosButtonLabel} -

+

首次使用需要在 Creator 中安装全局插件并输入连接码。

@@ -656,7 +677,7 @@ export function ExportButton({ type="button" disabled={working || cocos.working || cocosImport.working} onClick={() => void cocosImport.startImport()} - className={`${pill ? 'rounded-full' : 'rounded-lg'} border border-sky-500 px-3 py-2 text-xs font-semibold text-sky-800 disabled:opacity-50 ${className}`} + className={`${pill ? 'rounded-full' : 'rounded-lg'} border border-sky-500 px-3 py-2 text-xs font-semibold text-sky-800 dark:text-app-ink-soft disabled:opacity-50 ${className}`} > {cocosImport.state.status === 'failure' ? '重新导入 Cocos' : '一键导入 Cocos'} @@ -670,7 +691,7 @@ export function ExportButton({ : '插件不可用时下载 Cocos 适配包' } onClick={() => void cocos.startExport()} - className={`${pill ? 'rounded-full' : 'rounded-lg'} border border-amber-400 px-3 py-2 text-xs font-semibold text-amber-800 disabled:opacity-50 ${className}`} + className={`${pill ? 'rounded-full' : 'rounded-lg'} border border-amber-400 dark:border-app-warning-line px-3 py-2 text-xs font-semibold text-amber-800 dark:text-app-warning disabled:opacity-50 ${className}`} > {cocos.state.status === 'working' ? PHASE_LABELS[cocos.state.phase] diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 211b0219a..722515546 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -6,6 +6,7 @@ import { userApis } from '@/entities' import { AuthSessionProvider } from '@/features/auth-session' import '@fontsource-variable/noto-serif-sc/wght.css' import './index.css' +import './system-theme.css' createRoot(document.getElementById('root')!).render( diff --git a/frontend/src/pages/history/index.tsx b/frontend/src/pages/history/index.tsx index 1b7d8783b..320219bae 100644 --- a/frontend/src/pages/history/index.tsx +++ b/frontend/src/pages/history/index.tsx @@ -33,7 +33,8 @@ const RUN_STATUS_LABELS: Readonly> = { } const RUN_STATUS_STYLES: Readonly> = { - active: 'border-sky-200 bg-sky-50 text-sky-800', + active: + 'border-sky-200 dark:border-app-line bg-sky-50 dark:bg-app-accent-muted text-sky-800 dark:text-app-ink-soft', failed: 'border-rose-200 bg-rose-50 text-rose-800', completed: 'border-emerald-200 bg-emerald-50 text-emerald-800', } @@ -109,16 +110,21 @@ export function HistoryPage({ reader }: HistoryPageProps) { return (
-
-

HISTORY

-

+
+

HISTORY

+

创作历史

-

查看每条工作流当前保存的节点进度。

+

+ 查看每条工作流当前保存的节点进度。 +

{loading ? ( -

+

正在读取历史记录...

) : error !== null ? ( @@ -129,9 +135,11 @@ export function HistoryPage({ reader }: HistoryPageProps) { {error}

) : runs.length === 0 ? ( -
-

还没有创作记录

-

+

+

+ 还没有创作记录 +

+

History 暂未接入产品入口;后端列表接口确定后再启用。

@@ -143,11 +151,13 @@ export function HistoryPage({ reader }: HistoryPageProps) {

{section.title}

- {section.runs.length} + + {section.runs.length} +
{section.runs.map((run) => ( @@ -168,20 +178,25 @@ function RunCard({ run }: { run: WorkflowRun }) { const passedCount = run.nodes.filter((node) => node.status === 'passed').length return ( -
+
{RUN_STATUS_LABELS[state]} -

工作流 {shortId(run.id)}

-

+

+ 工作流 {shortId(run.id)} +

+

版本 {run.version} · 节点 {passedCount} / {run.nodes.length}

{state === 'completed' ? '查看记录' : '继续任务'} @@ -191,10 +206,14 @@ function RunCard({ run }: { run: WorkflowRun }) { {run.nodes.map((node) => (
  • - {NODE_LABELS[node.type] ?? node.type} - {NODE_STATUS_LABELS[node.status]} + + {NODE_LABELS[node.type] ?? node.type} + + + {NODE_STATUS_LABELS[node.status]} +
  • ))} diff --git a/frontend/src/pages/landing/capabilities-rail.tsx b/frontend/src/pages/landing/capabilities-rail.tsx index cd72efa18..840386296 100644 --- a/frontend/src/pages/landing/capabilities-rail.tsx +++ b/frontend/src/pages/landing/capabilities-rail.tsx @@ -70,7 +70,7 @@ export function CapabilitiesRail() { ref={sectionRef} id="capabilities" aria-labelledby="capabilities-heading" - className="relative isolate overflow-visible scroll-mt-28 border-b border-rule pt-16 [background:linear-gradient(180deg,rgb(247_246_240/0.82),rgb(237_239_231/0.92)),#f2f1ea]" + className="relative isolate overflow-visible scroll-mt-28 border-b border-rule pt-16 [background:linear-gradient(180deg,light-dark(rgb(247_246_240/0.82),rgb(28_28_28/0.82)),light-dark(rgb(237_239_231/0.92),rgb(35_35_35/0.92))),light-dark(#f2f1ea,#1c1c1c)]" >
    @@ -265,10 +265,10 @@ export function CapabilityStory() { className="relative h-[calc(100vh_+_2500px)] motion-reduce:h-auto motion-reduce:min-h-[58rem]" style={capabilityStoryVariables} > -
    +
    @@ -309,7 +309,7 @@ export function CapabilityStory() { data-rotate="3" className={`${floatingCardClassName} h-40 w-44`} > -

    +

    角色母版素材待接入

    @@ -320,7 +320,7 @@ export function CapabilityStory() { data-rotate="2" className={`${floatingCardClassName} h-28 w-72`} > -

    +

    动作序列素材待接入

    @@ -331,32 +331,34 @@ export function CapabilityStory() { data-rotate="-3" className={`${floatingCardClassName} h-32 w-56`} > -

    +

    预览台画面待接入

    -
    +
      {productCapabilities.map((capability, index) => (