Update Match3D/image-generation docs & code

Adds/updates documentation, assets and implementation for Match3D and puzzle image generation workflows. Key changes: decision logs and pitfalls updated to prefer VectorEngine Gemini for Match3D material sheets and to require edits (multipart) for 1:1 container reference images; guidance added for when to use APIMart vs VectorEngine. .env.example clarified APIMart/Responses config. Many new public assets and PPT visuals added. Code changes across frontend and backend: updated shared contracts, server-rs match3d/puzzle/image-generation handlers, VectorEngine/OpenAI image generation clients, and multiple React components/tests to handle UI/background/container image signing, edits workflow, and puzzle UI background resolution. Added src/services/puzzle-runtime/puzzleUiBackgroundSource.ts and related test updates. Includes notes about multipart HTTP/1.1 requirement and test/verification commands in docs.
This commit is contained in:
2026-05-14 20:34:45 +08:00
parent d33c937ebc
commit 548db78ca7
103 changed files with 6687 additions and 3270 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -0,0 +1,291 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>创意工作金字塔</title>
<style>
:root {
--ink: #202938;
--muted: #566275;
--orange: #ff8a3d;
--gold: #ead51d;
--violet: #8564f4;
--green: #3fc05a;
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
width: 100%;
height: 100%;
background: #eef2f7;
font-family:
"Noto Sans SC",
"Microsoft YaHei",
"PingFang SC",
system-ui,
sans-serif;
}
.slide {
position: relative;
width: 1920px;
height: 1080px;
overflow: hidden;
color: var(--ink);
background:
radial-gradient(circle at 73% 15%, rgba(255, 138, 61, 0.1), transparent 28%),
radial-gradient(circle at 82% 88%, rgba(63, 192, 90, 0.12), transparent 31%),
linear-gradient(180deg, #fcfdff 0%, #f7f9fc 100%);
}
.slide::before {
content: "";
position: absolute;
left: 54px;
top: 54px;
width: 1812px;
height: 972px;
border: 1px solid rgba(148, 163, 184, 0.2);
border-radius: 28px;
pointer-events: none;
}
.left-rail {
position: absolute;
top: 128px;
left: 78px;
width: 440px;
display: grid;
gap: 136px;
}
.saving {
position: relative;
min-height: 116px;
color: var(--ink);
}
.saving .label {
font-size: 38px;
line-height: 1.2;
font-weight: 850;
letter-spacing: 0;
}
.saving .bar {
width: 334px;
height: 8px;
margin-top: 20px;
border-radius: 999px;
background: var(--bar-color);
}
.saving .note {
display: none;
}
.saving.creative {
--bar-color: var(--orange);
}
.saving.ai {
--bar-color: var(--gold);
}
.saving.template {
--bar-color: var(--violet);
}
.pyramid-wrap {
position: absolute;
top: 72px;
left: 500px;
width: 1360px;
height: 938px;
}
.pyramid-svg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.connector-svg {
position: absolute;
inset: 0;
pointer-events: none;
}
.layer-copy {
position: absolute;
left: 50%;
transform: translateX(-50%);
text-align: center;
color: var(--ink);
}
.layer-copy h2 {
margin: 0;
font-size: 34px;
line-height: 1.08;
font-weight: 850;
letter-spacing: 0;
}
.layer-copy h3 {
margin: 17px 0 0;
font-size: 24px;
line-height: 1.15;
font-weight: 850;
}
.layer-copy p {
margin: 12px 0 0;
color: #334155;
font-size: 22px;
line-height: 1.24;
font-weight: 650;
}
.layer-top {
top: 102px;
width: 390px;
}
.layer-top h2 {
font-size: 32px;
}
.layer-top h3 {
margin-top: 14px;
font-size: 22px;
}
.layer-top p {
font-size: 20px;
}
.layer-ai {
top: 278px;
width: 660px;
}
.layer-ai h2 {
font-size: 41px;
}
.layer-template {
top: 528px;
width: 820px;
}
.layer-platform {
top: 780px;
width: 760px;
}
.badge {
display: none;
}
</style>
</head>
<body>
<main class="slide" aria-label="创意工作金字塔">
<section class="left-rail" aria-label="工作分配说明">
<div class="saving creative">
<div class="label">聚焦关键的10%创意工作</div>
<div class="bar"></div>
</div>
<div class="saving ai">
<div class="label">省去30%工作</div>
<div class="bar"></div>
</div>
<div class="saving template">
<div class="label">省去60%工作</div>
<div class="bar"></div>
</div>
</section>
<section class="pyramid-wrap" aria-label="四层价值金字塔">
<svg class="pyramid-svg" viewBox="0 0 1360 938" role="img" aria-label="AI、模板、分发四层金字塔">
<defs>
<filter id="shadow" x="-12%" y="-10%" width="124%" height="126%">
<feDropShadow dx="0" dy="16" stdDeviation="15" flood-color="#0f172a" flood-opacity="0.1" />
</filter>
<linearGradient id="topGrad" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#fff2e7" />
<stop offset="100%" stop-color="#ffd4ad" />
</linearGradient>
<linearGradient id="aiGrad" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#fffbd1" />
<stop offset="100%" stop-color="#ffe96e" />
</linearGradient>
<linearGradient id="templateGrad" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#f1eaff" />
<stop offset="100%" stop-color="#d8c8ff" />
</linearGradient>
<linearGradient id="platformGrad" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#e9f9e8" />
<stop offset="100%" stop-color="#c7efc8" />
</linearGradient>
</defs>
<g filter="url(#shadow)">
<polygon points="680,34 560,225 800,225" fill="url(#topGrad)" stroke="#ff8a3d" stroke-width="3" />
<polygon points="560,225 408,455 952,455 800,225" fill="url(#aiGrad)" stroke="#e8c51f" stroke-width="3" />
<polygon points="408,455 238,704 1122,704 952,455" fill="url(#templateGrad)" stroke="#8564f4" stroke-width="3" />
<polygon points="238,704 52,898 1308,898 1122,704" fill="url(#platformGrad)" stroke="#35b75a" stroke-width="3" />
</g>
<path d="M680 34 L52 898 H1308 Z" fill="none" stroke="rgba(15, 23, 42, 0.11)" stroke-width="2" />
<path d="M558 228 H802" stroke="rgba(255,255,255,0.9)" stroke-width="3" />
<path d="M411 458 H949" stroke="rgba(255,255,255,0.9)" stroke-width="3" />
<path d="M241 707 H1119" stroke="rgba(255,255,255,0.9)" stroke-width="3" />
</svg>
<svg class="connector-svg" viewBox="0 0 1360 938" aria-hidden="true">
<path d="M-80 196 H490" fill="none" stroke="#ff8a3d" stroke-width="2.5" stroke-linecap="round" />
<circle cx="490" cy="196" r="5" fill="#ff8a3d" />
<path d="M-80 432 H392" fill="none" stroke="#e8c51f" stroke-width="2.5" stroke-linecap="round" />
<circle cx="392" cy="432" r="5" fill="#e8c51f" />
<path d="M-80 684 H220" fill="none" stroke="#8564f4" stroke-width="2.5" stroke-linecap="round" />
<circle cx="220" cy="684" r="5" fill="#8564f4" />
</svg>
<div class="layer-copy layer-top">
<h3>聚焦创意</h3>
<p>自然语言完成<br />高杠杆设定</p>
</div>
<div class="layer-copy layer-ai">
<h2>Harness AI</h2>
<h3>放大创意</h3>
<p>帮助创作者将设定落地为游戏内容</p>
</div>
<div class="layer-copy layer-template">
<h2>精选互动内容模板</h2>
<h3>为创意托底</h3>
<p>为内容质量、传播能力、留存能力、付费能力提供保障</p>
</div>
<div class="layer-copy layer-platform">
<h2>平台分发</h2>
<h3>为创意买单</h3>
<p>平台提供精准的分发能力</p>
</div>
</section>
<div class="badge">10% 创意 / 90% 杠杆</div>
</main>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB