auto-save 2026-05-15 17:22 (~4, -1)
This commit is contained in:
@@ -1,11 +1,5 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Claude 会话活跃 · 最近命令:claude · 1 项未提交变更 · 最近提交:auto-save 2026-05-14 01:51 (~2)",
|
||||
"ts": "2026-05-13T17:53:11Z",
|
||||
"type": "session-heartbeat"
|
||||
},
|
||||
{
|
||||
"files_changed": 5,
|
||||
"hash": "11de581",
|
||||
@@ -3251,6 +3245,13 @@
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 2 项未提交变更 · 最近提交:auto-save 2026-05-15 17:11 (~6)",
|
||||
"files_changed": 2
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-15T17:17:23+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-15 17:17 (~2)",
|
||||
"hash": "f590d51",
|
||||
"files_changed": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -591,7 +591,7 @@
|
||||
<table>
|
||||
<tbody>
|
||||
<tr><td><code>web/app/page.tsx</code></td><td>产品工作台主状态:jobs、activeJobId、按 job 隔离的 selectedFrames/详情面板状态、clipboard、ReactFlow 节点和边;负责打开/找回画布工作面板。</td></tr>
|
||||
<tr><td><code>web/app/login/page.tsx</code></td><td>生产登录页:账号密码表单、保持登录、错误/成功状态;左侧展示区改为高级产品入口页结构,使用本地 SKG 颈部按摩仪产品图、黑白/香槟金视觉、Secure Studio 胶囊和素材/声音/成片状态栏;同时保留动态角色作为 Live Studio Modules 小组件。</td></tr>
|
||||
<tr><td><code>web/app/login/page.tsx</code></td><td>生产登录页:访问账号/访问密钥表单、保持会话、错误/成功状态;左侧展示区改为高级内容入口结构,使用抽象流程视觉、黑白/香槟金视觉、Internal Access 胶囊和画面/声音/成片状态栏;同时保留动态角色作为 Live Creative Modules 小组件。</td></tr>
|
||||
<tr><td><code>web/components/login/animated-login-characters.tsx</code></td><td>登录页四个几何动态角色组件:当前以小型 Live Studio Modules 方式挂在产品区,保留鼠标眼神跟随、输入、显示密码、错误和成功状态反馈。</td></tr>
|
||||
<tr><td><code>web/components/nodes/index.tsx</code></td><td>DAG 节点定义:Input、VisualLab、Audio、Compose,以及画布工作面板 KeyframePanel / VideoFramePanel;旧 Keyframe/Storyboard/VideoGen 组件保留但不再挂主画布。</td></tr>
|
||||
<tr><td><code>web/components/audio-strip.tsx</code></td><td>底部吸附音频条:可拖拽调整高度;播放原音频时移动指针,逐个高亮英文/中文字幕节点和对应波形,并在右侧固定显示按原音频时长生成的 SKG 英文产品口播和 MiniMax 随机英文配音。</td></tr>
|
||||
@@ -944,13 +944,13 @@ SubjectAsset {
|
||||
<div class="changelog">
|
||||
<article class="change">
|
||||
<header>
|
||||
<h3>2026-05-15 · 登录页升级为高级产品入口视觉</h3>
|
||||
<h3>2026-05-15 · 登录页移除产品元素并保留动态模块</h3>
|
||||
<span class="tag rose">UI</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<p><strong>问题:</strong>上一版虽然吸收了官网元素,但仍偏浅灰卡片拼接,卡通角色舞台削弱了公司级工具和高端健康硬件的质感。</p>
|
||||
<p><strong>改动:</strong>生产登录页主视觉改为真实 SKG 颈部按摩仪产品摄影卡,采用黑白/香槟金主轴、超大标题、克制胶囊状态、素材/声音/成片三段式状态栏;几何角色组件不再抢占主视觉,但作为 <code>Live Studio Modules</code> 小组件保留,继续响应鼠标眼神跟随、输入、显示密码、错误和成功状态。新增本地静态图 <code>web/public/assets/skg-g7-pro-neck-massager.png</code>,并在生产 Nginx 放行 <code>/assets/</code>,避免登录页产品图被登录保护拦截。</p>
|
||||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>web/public/assets/skg-g7-pro-neck-massager.png</code>、<code>deploy/nginx.conf</code>、<code>RULES.md</code>、<code>docs/source-analysis.html</code>。</p>
|
||||
<p><strong>问题:</strong>登录页不应该放具体产品图,入口职责是进入内容生产系统,不是展示某个产品。</p>
|
||||
<p><strong>改动:</strong>移除登录页产品图、G7/Neck Massager 等产品文案和产品摄影卡,改为抽象流程视觉与全新入口文案:内容创作中枢、Content Production System、Creative Pipeline。四个动态几何角色作为 <code>Live Creative Modules</code> 小组件保留,继续响应鼠标眼神跟随、输入、显示密码、错误和成功状态。</p>
|
||||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||||
</div>
|
||||
</article>
|
||||
<article class="change">
|
||||
|
||||
@@ -243,39 +243,81 @@
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
.login-product-stage {
|
||||
.login-creative-stage {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-height: 300px;
|
||||
margin-top: 26px;
|
||||
}
|
||||
.login-product-stage__halo {
|
||||
.login-creative-stage__halo {
|
||||
position: absolute;
|
||||
right: 7%;
|
||||
bottom: 24px;
|
||||
width: 52%;
|
||||
height: 42px;
|
||||
right: 10%;
|
||||
bottom: 54px;
|
||||
width: 46%;
|
||||
height: 46px;
|
||||
border-radius: 50%;
|
||||
background: rgba(40, 40, 40, 0.12);
|
||||
filter: blur(18px);
|
||||
background: rgba(40, 40, 40, 0.11);
|
||||
filter: blur(20px);
|
||||
transform: perspective(500px) rotateX(58deg);
|
||||
}
|
||||
.login-product-image {
|
||||
.login-creative-orbit {
|
||||
position: absolute;
|
||||
right: 1%;
|
||||
bottom: 0;
|
||||
right: 2%;
|
||||
bottom: 8px;
|
||||
width: min(46%, 390px);
|
||||
max-height: 360px;
|
||||
object-fit: contain;
|
||||
aspect-ratio: 1;
|
||||
border: 1px solid rgba(40, 40, 40, 0.08);
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
filter:
|
||||
drop-shadow(0 32px 52px rgba(40, 40, 40, 0.18))
|
||||
drop-shadow(0 1px 0 rgba(255, 255, 255, 0.8));
|
||||
background:
|
||||
radial-gradient(circle at 50% 50%, rgba(214, 179, 106, 0.16), transparent 36%),
|
||||
linear-gradient(145deg, rgba(255, 255, 255, 0.88), rgba(244, 244, 240, 0.64));
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.9),
|
||||
0 34px 70px rgba(40, 40, 40, 0.12);
|
||||
overflow: hidden;
|
||||
}
|
||||
.login-product-caption {
|
||||
.login-creative-orbit::before,
|
||||
.login-creative-orbit::after,
|
||||
.login-creative-orbit span {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-radius: 999px;
|
||||
}
|
||||
.login-creative-orbit::before {
|
||||
inset: 17%;
|
||||
border: 1px solid rgba(40, 40, 40, 0.12);
|
||||
}
|
||||
.login-creative-orbit::after {
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 42%;
|
||||
height: 42%;
|
||||
background: linear-gradient(145deg, #18191c, #343434);
|
||||
box-shadow: 0 18px 44px rgba(40, 40, 40, 0.18);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.login-creative-orbit span:nth-child(1) {
|
||||
left: 18%;
|
||||
top: 22%;
|
||||
width: 16%;
|
||||
height: 16%;
|
||||
background: #d6b36a;
|
||||
}
|
||||
.login-creative-orbit span:nth-child(2) {
|
||||
right: 18%;
|
||||
top: 34%;
|
||||
width: 11%;
|
||||
height: 11%;
|
||||
background: #111214;
|
||||
}
|
||||
.login-creative-orbit span:nth-child(3) {
|
||||
left: 50%;
|
||||
bottom: 15%;
|
||||
width: 13%;
|
||||
height: 13%;
|
||||
background: rgba(40, 40, 40, 0.18);
|
||||
}
|
||||
.login-creative-caption {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 50px;
|
||||
@@ -284,12 +326,12 @@
|
||||
padding-top: 18px;
|
||||
color: #151515;
|
||||
}
|
||||
.login-product-caption span {
|
||||
.login-creative-caption span {
|
||||
display: block;
|
||||
color: rgba(40, 40, 40, 0.5);
|
||||
font-size: 13px;
|
||||
}
|
||||
.login-product-caption b {
|
||||
.login-creative-caption b {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
font-size: 28px;
|
||||
@@ -404,21 +446,6 @@
|
||||
border: 1px solid rgba(214, 179, 106, 0.42);
|
||||
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.3), 0 0 0 5px rgba(214, 179, 106, 0.06);
|
||||
}
|
||||
.login-product-ribbon {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: -12px;
|
||||
}
|
||||
.login-product-ribbon span {
|
||||
border: 1px solid rgba(40, 40, 40, 0.08);
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.74);
|
||||
padding: 8px 12px;
|
||||
color: rgba(40, 40, 40, 0.66);
|
||||
font-size: 12px;
|
||||
box-shadow: 0 10px 28px rgba(40, 40, 40, 0.06);
|
||||
}
|
||||
.login-skg-tile {
|
||||
border: 1px solid rgba(40, 40, 40, 0.08);
|
||||
background:
|
||||
@@ -843,21 +870,19 @@
|
||||
.login-premium-copy {
|
||||
font-size: 14px;
|
||||
}
|
||||
.login-product-stage {
|
||||
.login-creative-stage {
|
||||
min-height: 340px;
|
||||
}
|
||||
.login-product-image {
|
||||
right: -18%;
|
||||
bottom: 28px;
|
||||
.login-creative-orbit {
|
||||
right: -20%;
|
||||
bottom: 34px;
|
||||
width: 78%;
|
||||
max-height: 280px;
|
||||
padding: 14px;
|
||||
}
|
||||
.login-product-caption {
|
||||
.login-creative-caption {
|
||||
bottom: 34px;
|
||||
width: 48%;
|
||||
}
|
||||
.login-product-caption b {
|
||||
.login-creative-caption b {
|
||||
font-size: 22px;
|
||||
}
|
||||
.login-dynamic-dock {
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useEffect, useMemo, useState } from "react"
|
||||
import {
|
||||
AlertCircle,
|
||||
ArrowRight,
|
||||
BadgeCheck,
|
||||
CheckCircle2,
|
||||
Eye,
|
||||
EyeOff,
|
||||
@@ -18,9 +17,6 @@ import { AnimatedLoginCharacters, type LoginCharacterMood } from "@/components/l
|
||||
|
||||
type LoginStatus = "idle" | "loading" | "success"
|
||||
|
||||
const PRODUCT_IMAGE =
|
||||
"/assets/skg-g7-pro-neck-massager.png"
|
||||
|
||||
export default function LoginPage() {
|
||||
const [username, setUsername] = useState("")
|
||||
const [password, setPassword] = useState("")
|
||||
@@ -57,7 +53,7 @@ export default function LoginPage() {
|
||||
event.preventDefault()
|
||||
setError("")
|
||||
if (!username.trim() || !password) {
|
||||
setError("请输入账号和密码")
|
||||
setError("请输入访问账号和访问密钥")
|
||||
return
|
||||
}
|
||||
setStatus("loading")
|
||||
@@ -69,7 +65,7 @@ export default function LoginPage() {
|
||||
body: JSON.stringify({ username, password, remember }),
|
||||
})
|
||||
if (!res.ok) {
|
||||
let message = "账号或密码不正确"
|
||||
let message = "访问账号或密钥不正确"
|
||||
try {
|
||||
const data = await res.json()
|
||||
message = data?.detail || data?.error || message
|
||||
@@ -84,7 +80,7 @@ export default function LoginPage() {
|
||||
}, 420)
|
||||
} catch (err) {
|
||||
setStatus("idle")
|
||||
setError(err instanceof Error ? err.message : "登录失败,请稍后再试")
|
||||
setError(err instanceof Error ? err.message : "验证失败,请稍后再试")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,46 +93,46 @@ export default function LoginPage() {
|
||||
<div className="flex flex-wrap items-center justify-between gap-4">
|
||||
<div className="login-wordmark">
|
||||
<span className="login-wordmark__logo">SKG</span>
|
||||
<span className="login-wordmark__sub">未来健康</span>
|
||||
<span className="login-wordmark__sub">Creative OS</span>
|
||||
</div>
|
||||
<div className="login-secure-pill">
|
||||
<ShieldCheck className="h-4 w-4" />
|
||||
<span>Secure Studio</span>
|
||||
<span>Internal Access</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-10 max-w-[620px]">
|
||||
<p className="login-kicker">MARKETING CONTENT STUDIO</p>
|
||||
<h1 className="login-premium-title">营销内容工作台</h1>
|
||||
<p className="login-premium-copy">SKG 健康科技素材、产品视觉与广告视频生产入口</p>
|
||||
<p className="login-kicker">CONTENT PRODUCTION SYSTEM</p>
|
||||
<h1 className="login-premium-title">内容创作中枢</h1>
|
||||
<p className="login-premium-copy">统一进入素材拆解、画面处理、声音处理与成片生成流程。</p>
|
||||
</div>
|
||||
|
||||
<div className="login-product-stage" aria-label="SKG product visual">
|
||||
<div className="login-product-stage__halo" />
|
||||
<img className="login-product-image" src={PRODUCT_IMAGE} alt="SKG neck massager" />
|
||||
<div className="login-product-caption">
|
||||
<span>G7 Pro Fold</span>
|
||||
<b>Neck Massager</b>
|
||||
<div className="login-creative-stage" aria-label="Creative workflow visual">
|
||||
<div className="login-creative-stage__halo" />
|
||||
<div className="login-creative-orbit" aria-hidden="true">
|
||||
<span />
|
||||
<span />
|
||||
<span />
|
||||
</div>
|
||||
<div className="login-creative-caption">
|
||||
<span>Creative Pipeline</span>
|
||||
<b>Pipeline ready</b>
|
||||
</div>
|
||||
<div className="login-dynamic-dock">
|
||||
<span className="login-dynamic-dock__label">Live Studio Modules</span>
|
||||
<span className="login-dynamic-dock__label">Live Creative Modules</span>
|
||||
<AnimatedLoginCharacters mood={mood} eyeOffset={eyeOffset} />
|
||||
</div>
|
||||
<div className="login-studio-chip login-studio-chip--visual">
|
||||
<Sparkles className="h-4 w-4" />
|
||||
<span>Visual Asset Flow</span>
|
||||
</div>
|
||||
<div className="login-studio-chip login-studio-chip--review">
|
||||
<BadgeCheck className="h-4 w-4" />
|
||||
<span>Brand Review Ready</span>
|
||||
<span>Pipeline Online</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="login-premium-metrics">
|
||||
{[
|
||||
["Visual", "素材"],
|
||||
["Audio", "声音"],
|
||||
["Video", "成片"],
|
||||
["Frame Lab", "画面"],
|
||||
["Sound Lab", "声音"],
|
||||
["Final Cut", "成片"],
|
||||
].map(([label, value]) => (
|
||||
<div key={label} className="login-premium-metric">
|
||||
<span>{label}</span>
|
||||
@@ -153,13 +149,13 @@ export default function LoginPage() {
|
||||
<div className="login-auth-icon mb-4 inline-flex h-12 w-12 items-center justify-center rounded-[8px] text-white">
|
||||
<LockKeyhole className="h-5 w-5" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-white">登录</h2>
|
||||
<p className="mt-2 text-sm leading-6 text-white/55">进入 SKG 营销内容工作台</p>
|
||||
<h2 className="text-2xl font-semibold text-white">身份验证</h2>
|
||||
<p className="mt-2 text-sm leading-6 text-white/55">验证后进入内容生产环境</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<label className="block">
|
||||
<span className="mb-2 block text-sm font-medium text-white/70">账号</span>
|
||||
<span className="mb-2 block text-sm font-medium text-white/70">访问账号</span>
|
||||
<span className="flex h-12 items-center gap-3 rounded-[8px] border border-white/10 bg-black/25 px-3 text-white transition focus-within:border-[#d6b36a] focus-within:bg-black/35 focus-within:ring-2 focus-within:ring-[#d6b36a]/25">
|
||||
<UserRound className="h-4 w-4 text-white/45" />
|
||||
<input
|
||||
@@ -167,7 +163,7 @@ export default function LoginPage() {
|
||||
value={username}
|
||||
disabled={disabled}
|
||||
autoComplete="username"
|
||||
placeholder="请输入账号"
|
||||
placeholder="输入访问账号"
|
||||
onFocus={() => setActiveField("username")}
|
||||
onBlur={() => setActiveField(null)}
|
||||
onChange={(event) => {
|
||||
@@ -179,7 +175,7 @@ export default function LoginPage() {
|
||||
</label>
|
||||
|
||||
<label className="block">
|
||||
<span className="mb-2 block text-sm font-medium text-white/70">密码</span>
|
||||
<span className="mb-2 block text-sm font-medium text-white/70">访问密钥</span>
|
||||
<span className="flex h-12 items-center gap-3 rounded-[8px] border border-white/10 bg-black/25 px-3 text-white transition focus-within:border-[#d6b36a] focus-within:bg-black/35 focus-within:ring-2 focus-within:ring-[#d6b36a]/25">
|
||||
<LockKeyhole className="h-4 w-4 text-white/45" />
|
||||
<input
|
||||
@@ -188,7 +184,7 @@ export default function LoginPage() {
|
||||
disabled={disabled}
|
||||
type={showPassword ? "text" : "password"}
|
||||
autoComplete="current-password"
|
||||
placeholder="请输入密码"
|
||||
placeholder="输入访问密钥"
|
||||
onFocus={() => setActiveField("password")}
|
||||
onBlur={() => setActiveField(null)}
|
||||
onChange={(event) => {
|
||||
@@ -219,7 +215,7 @@ export default function LoginPage() {
|
||||
disabled={disabled}
|
||||
onChange={(event) => setRemember(event.target.checked)}
|
||||
/>
|
||||
<span>保持登录</span>
|
||||
<span>保持会话</span>
|
||||
</label>
|
||||
<span className="text-xs text-white/35">marketing.skg.com</span>
|
||||
</div>
|
||||
@@ -233,7 +229,7 @@ export default function LoginPage() {
|
||||
) : status === "success" ? (
|
||||
<div className="flex items-start gap-2 rounded-[8px] border border-emerald-300/30 bg-emerald-400/10 px-3 py-2 text-sm text-emerald-100">
|
||||
<CheckCircle2 className="mt-0.5 h-4 w-4 shrink-0" />
|
||||
<span>登录成功,正在进入工作台</span>
|
||||
<span>验证通过,正在打开工作台</span>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -243,7 +239,7 @@ export default function LoginPage() {
|
||||
type="submit"
|
||||
disabled={disabled}
|
||||
>
|
||||
<span>{status === "loading" ? "正在登录" : status === "success" ? "已通过" : "进入工作台"}</span>
|
||||
<span>{status === "loading" ? "验证中" : status === "success" ? "已验证" : "打开工作台"}</span>
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</button>
|
||||
</form>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 124 KiB |
Reference in New Issue
Block a user