525 lines
21 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MODULE: cover-studio — 语言驱动封面生成器</title>
<style>
:root {
--bg: #0a0e1a;
--panel: rgba(17,22,42,0.85);
--border: rgba(110,160,230,0.18);
--border-h: rgba(150,200,255,0.4);
--text: rgba(195,215,255,0.88);
--dim: rgba(155,195,235,0.5);
--accent: rgba(100,160,220,0.9);
--green: rgba(140,220,180,0.9);
--gold: rgba(220,200,140,0.9);
--code-bg: rgba(10,14,26,0.7);
}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--text);font-family:-apple-system,'PingFang SC','Microsoft YaHei',sans-serif;min-height:100vh;line-height:1.65}
/* Repo Header — 代码仓库风格 */
.repo-header {
border-bottom: 1px solid var(--border);
padding: 28px 32px 20px;
background: rgba(12,18,36,0.6);
}
.repo-header .module-id {
font-size: 14px;
color: var(--dim);
font-family: 'SF Mono','Fira Code',monospace;
letter-spacing: 1px;
margin-bottom: 8px;
}
.repo-header .module-id span {
color: var(--green);
}
.repo-header h1 {
font-size: 26px;
font-weight: 700;
background: linear-gradient(90deg, #3b82f6, #60a5fa);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 8px;
letter-spacing: 2px;
}
.repo-header .desc {
font-size: 14px;
color: var(--dim);
}
.repo-header .meta {
display: flex;
gap: 20px;
margin-top: 12px;
font-size: 12px;
color: var(--dim);
flex-wrap: wrap;
}
.repo-header .meta span {
display: flex;
align-items: center;
gap: 5px;
}
/* Tab Bar */
.tab-bar {
display: flex;
gap: 0;
border-bottom: 1px solid var(--border);
padding: 0 32px;
background: rgba(12,18,36,0.3);
}
.tab {
padding: 12px 20px;
font-size: 13px;
color: var(--dim);
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all 0.2s;
letter-spacing: 1px;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }
/* Content */
.content { max-width: 1100px; margin: 0 auto; padding: 28px 24px 60px; }
.tab-panel { display: none; }
.tab-panel.active { display: block; }
/* Card */
.card {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 16px;
padding: 24px;
margin-bottom: 20px;
}
.card:hover { border-color: var(--border-h); }
.card-title {
font-size: 13px;
font-weight: 600;
letter-spacing: 2px;
color: var(--dim);
text-transform: uppercase;
margin-bottom: 14px;
display: flex;
align-items: center;
gap: 8px;
}
.card-title::before {
content: '';
width: 4px;
height: 14px;
background: var(--accent);
border-radius: 2px;
}
/* Code */
.code {
background: var(--code-bg);
border: 1px solid var(--border);
border-radius: 10px;
padding: 16px 20px;
font-family: 'SF Mono','Fira Code','Consolas',monospace;
font-size: 13px;
line-height: 1.7;
overflow-x: auto;
white-space: pre-wrap;
color: var(--text);
}
.code .c { color: #636e7b; }
.code .k { color: #8b5cf6; }
.code .s { color: #10b981; }
.code .n { color: #f59e0b; }
.code .f { color: #3b82f6; }
/* Use Tab — 两栏 */
.use-layout {
display: grid;
grid-template-columns: 1fr 380px;
gap: 24px;
}
@media (max-width: 860px) { .use-layout { grid-template-columns: 1fr; } }
/* Input */
.input-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px; }
select, input, textarea {
padding: 11px 14px;
background: var(--code-bg);
border: 1px solid var(--border);
border-radius: 10px;
color: var(--text);
font-size: 13px;
outline: none;
width: 100%;
font-family: inherit;
}
select:focus, input:focus, textarea:focus { border-color: var(--accent); }
textarea { min-height: 90px; resize: vertical; line-height: 1.8; }
.gen-btn {
width: 100%;
padding: 13px;
background: linear-gradient(135deg,rgba(100,160,220,0.3),rgba(130,100,200,0.2));
border: 1px solid var(--border);
border-radius: 10px;
color: var(--accent);
font-size: 14px;
font-weight: 600;
cursor: pointer;
letter-spacing: 2px;
margin-top: 8px;
}
.gen-btn:hover { border-color: var(--border-h); background: linear-gradient(135deg,rgba(100,160,220,0.5),rgba(130,100,200,0.35)); }
.gen-btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* Preview (右边) */
.preview-box { position: sticky; top: 20px; }
.preview-area {
min-height: 260px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(10,14,26,0.5);
border-radius: 10px;
border: 1px dashed var(--border);
margin-bottom: 14px;
}
.empty-hint { text-align: center; color: var(--dim); }
.empty-hint .icon { font-size: 40px; margin-bottom: 10px; opacity: 0.25; }
.empty-hint p { font-size: 13px; line-height: 2; }
.preview-wrap { position: relative; display: none; }
.preview-wrap.show { display: block; }
.preview-img { max-width: 100%; border-radius: 6px; display: block; }
.id-wm {
position: absolute; bottom: 10px; right: 10px;
background: rgba(0,0,0,0.7); padding: 5px 10px;
border-radius: 14px; font-size: 10px; font-family: monospace;
color: var(--accent); border: 1px solid rgba(100,160,220,0.3);
}
.dl-btn, .copy-btn {
display: block; width: 100%; padding: 12px;
background: linear-gradient(135deg,rgba(100,160,220,0.3),rgba(130,100,200,0.2));
border: 1px solid var(--border); border-radius: 10px;
color: var(--accent); text-align: center; text-decoration: none;
font-size: 13px; font-weight: 600; letter-spacing: 1px; cursor: pointer;
margin-bottom: 8px;
}
.dl-btn:hover, .copy-btn:hover { border-color: var(--border-h); }
/* Intent chain in README tab */
.intent-item {
display: flex; gap: 12px; padding: 14px;
background: rgba(10,14,26,0.4); border: 1px solid var(--border);
border-radius: 10px; margin-bottom: 10px;
}
.intent-item.user { border-left: 3px solid var(--green); }
.intent-item.system { border-left: 3px solid var(--accent); }
.intent-icon { font-size: 16px; flex-shrink: 0; }
.intent-who { font-size: 10px; letter-spacing: 1.5px; margin-bottom: 3px; }
.intent-item.user .intent-who { color: var(--green); }
.intent-item.system .intent-who { color: var(--accent); }
.intent-step { font-size: 13px; font-weight: 600; margin-bottom: 3px; }
.intent-detail { font-size: 12px; color: var(--dim); line-height: 1.5; }
.intent-why { font-size: 11px; color: rgba(155,195,235,0.3); margin-top: 4px; }
.design-id-card {
text-align: center; padding: 16px;
background: rgba(140,220,180,0.05);
border: 1px solid rgba(140,220,180,0.12);
border-radius: 10px; margin-bottom: 14px;
}
.design-id-card .label { font-size: 10px; color: var(--dim); letter-spacing: 2px; }
.design-id-card .value { font-size: 18px; font-weight: 700; color: var(--green); font-family: monospace; }
.loading { display: none; text-align: center; padding: 40px; }
.loading.show { display: block; }
.error { display: none; padding: 10px; background: rgba(255,100,100,0.08); border: 1px solid rgba(255,100,100,0.2); border-radius: 10px; color: rgba(255,140,140,0.9); font-size: 12px; margin-top: 10px; }
.error.show { display: block; }
/* Badges */
.badge-row { display: flex; gap: 8px; flex-wrap: wrap; margin: 12px 0; }
.badge {
padding: 4px 12px; border-radius: 12px; font-size: 11px;
border: 1px solid var(--border);
display: flex; align-items: center; gap: 4px;
}
.badge.api { border-color: var(--accent); color: var(--accent); background: rgba(100,160,220,0.08); }
.badge.free { border-color: var(--green); color: var(--green); background: rgba(140,220,180,0.08); }
.badge.mcp { border-color: var(--gold); color: var(--gold); background: rgba(220,200,140,0.08); }
footer {
text-align: center; padding: 40px 20px; font-size: 12px;
color: var(--dim); letter-spacing: 1px;
}
</style>
</head>
<body>
<!-- ── 代码仓库头 ── -->
<div class="repo-header">
<div class="module-id">📦 <span>MODULE-COVER-STUDIO</span> / v2.1 / guanghulab.com</div>
<h1>封面工作室 · 语言驱动封面生成器</h1>
<p class="desc">输入自然语言系统翻译为设计逻辑生成独一无二的封面。代码仓库公开AI 可读模块直接调用。</p>
<div class="badge-row">
<span class="badge api">🔌 REST API</span>
<span class="badge free">✅ 开源免费</span>
<span class="badge mcp">🤖 MCP Ready</span>
<span class="badge" style="color:var(--dim)">📕 小红书 1080×1440</span>
<span class="badge" style="color:var(--dim)">🖥️ 无需GPU</span>
</div>
<div class="meta">
<span>📁 仓库: guanghulab.com/code/bingshuo/guanghulab</span>
<span>📂 路径: image-studio/</span>
<span>🔢 许可证: MIT</span>
</div>
</div>
<!-- ── Tab 栏 ── -->
<div class="tab-bar">
<div class="tab active" onclick="switchTab('readme')">📄 README</div>
<div class="tab" onclick="switchTab('api')">🔌 API · 文档</div>
<div class="tab" onclick="switchTab('try')">🎨 在线使用</div>
</div>
<div class="content">
<!-- ── README Tab ── -->
<div class="tab-panel active" id="panel-readme">
<div class="card">
<div class="card-title">模块说明</div>
<p style="font-size:14px;line-height:2;color:var(--dim)">
这是一个<strong style="color:var(--text)">纯 HTML/CSS 排版渲染</strong>的封面生成工具。不依赖任何 AI 绘画模型,不需要 GPU不需要 API 密钥。
系统接收用户的自然语言描述,分析内容类型和情绪,自动推荐配色和布局,然后通过 Puppeteer + Chrome 渲染为高清 PNG。
</p>
<p style="font-size:14px;line-height:2;color:var(--dim);margin-top:12px">
<strong style="color:var(--text)">核心能力:</strong>
语言驱动排版设计 · 意图链可追溯 · 编号唯一归属验证 · 开源免费可部署
</p>
</div>
<div class="card">
<div class="card-title">快速开始 · 部署到你自己的服务器</div>
<div class="code">
<span class="c"># 克隆仓库</span>
git clone https://guanghulab.com/code/bingshuo/guanghulab.git
cd guanghulab/image-studio
<span class="c"># 安装依赖(需要 Node.js 18+</span>
npm install
<span class="c"># 启动服务</span>
node server.js
<span class="c"># 打开浏览器 → http://localhost:3912</span></div>
</div>
<div class="card">
<div class="card-title">技术栈 · 全免费开源</div>
<div class="code">
<span class="c">// 全部开源、全部免费</span>
<span class="k">渲染引擎</span>: Puppeteer + Chrome Headless <span class="c">// 免费</span>
<span class="k">Web 框架</span>: Express.js <span class="c">// 免费</span>
<span class="k">排版引擎</span>: 纯 HTML/CSS不调用任何 AI 模型) <span class="c">// 免费</span>
<span class="k">意图分析</span>: 自研文本分析引擎 <span class="c">// 免费</span>
<span class="k">配色推荐</span>: 5 种预设风格 + 动态匹配 <span class="c">// 免费</span>
<span class="c">// 不需要的东西:</span>
<span class="c">// × 不需要 GPU</span>
<span class="c">// × 不需要 API 密钥</span>
<span class="c">// × 不需要付费模型</span>
<span class="c">// × 不需要任何第三方付费服务</span></div>
</div>
<div class="card">
<div class="card-title">API 接入 · 让你的 AI 直接调用</div>
<p style="font-size:13px;color:var(--dim);margin-bottom:12px">任何编程 AIClaude、Cursor、Windsurf 等)通过 MCP 工具或 HTTP 请求直接调用此模块:</p>
<div class="code">
<span class="c">// 获取可用模板</span>
GET <span class="s">https://guanghulab.com/cover/api/templates</span>
<span class="c">// 生成封面</span>
POST <span class="s">https://guanghulab.com/cover/api/generate</span>
Content-Type: application/json
{
<span class="s">"templateId"</span>: <span class="s">"xiaohongshu"</span>,
<span class="s">"presetId"</span>: <span class="s">"tech"</span>,
<span class="s">"title"</span>: <span class="s">"零基础手搓AI做图小系统"</span>,
<span class="s">"body"</span>: <span class="s">"AI辅助 + 自己手搓 · 0经验也能开发"</span>,
<span class="s">"layout"</span>: <span class="s">"hero"</span>
}
<span class="c">// 响应</span>
{
<span class="s">"success"</span>: true,
<span class="s">"url"</span>: <span class="s">"/output/cover_xxx.png"</span>,
<span class="s">"intent_chain"</span>: [<span class="c">/* 7 步意图推理 */</span>]
}</div>
</div>
</div>
<!-- ── API Tab ── -->
<div class="tab-panel" id="panel-api">
<div class="card">
<div class="card-title">GET /api/templates</div>
<p style="font-size:13px;color:var(--dim);margin-bottom:10px">返回所有可用模板列表</p>
<div class="code"><span class="c">// 响应</span>
[
{
"id": <span class="s">"xiaohongshu"</span>,
"name": <span class="s">"小红书封面"</span>,
"sizes": { "width": 1080, "height": 1440 },
"presets": [
{ "id": <span class="s">"tech"</span>, "name": <span class="s">"科技蓝"</span> },
{ "id": <span class="s">"warm"</span>, "name": <span class="s">"奶油暖调"</span> },
<span class="c">// ...</span>
]
}
]</div>
</div>
<div class="card">
<div class="card-title">POST /api/generate</div>
<p style="font-size:13px;color:var(--dim);margin-bottom:10px">生成封面图片,返回图片 URL + 意图链</p>
<div class="code"><span class="c">// 参数</span>
{
<span class="s">"templateId"</span>: <span class="s">"xiaohongshu"</span>, <span class="c">// 模板 ID必填</span>
<span class="s">"presetId"</span>: <span class="s">"tech"</span>, <span class="c">// 预设风格(默认第一个)</span>
<span class="s">"title"</span>: <span class="s">"标题"</span>, <span class="c">// 封面标题</span>
<span class="s">"body"</span>: <span class="s">"正文"</span>, <span class="c">// 封面正文(支持 Markdown</span>
<span class="s">"layout"</span>: <span class="s">"hero"</span>, <span class="c">// default | hero | quote</span>
<span class="s">"tag"</span>: <span class="s">"教程"</span> <span class="c">// 可选标签</span>
}
<span class="c">// 响应</span>
{
<span class="s">"success"</span>: true,
<span class="s">"url"</span>: <span class="s">"/output/cover_xxx.png"</span>,
<span class="s">"filename"</span>: <span class="s">"cover_xxx.png"</span>,
<span class="s">"templateName"</span>: <span class="s">"小红书封面"</span>,
<span class="s">"presetId"</span>: <span class="s">"tech"</span>,
<span class="s">"layout"</span>: <span class="s">"hero"</span>,
<span class="s">"intent_chain"</span>: [
{ <span class="s">"icon"</span>: <span class="s">"💬"</span>, <span class="s">"step"</span>: <span class="s">"你说"</span>, <span class="s">"who"</span>: <span class="s">"用户"</span>, <span class="s">"detail"</span>: <span class="s">"..."</span>, <span class="s">"why"</span>: <span class="s">"..."</span> },
<span class="c">// ... 7 步意图推理</span>
]
}</div>
</div>
<div class="card">
<div class="card-title">MCP 接入说明</div>
<p style="font-size:13px;color:var(--dim);margin-bottom:12px">在编程 AI 的 MCP 配置中添加此 HTTP 端点AI 即可直接调用:</p>
<div class="code">{
<span class="s">"mcpServers"</span>: {
<span class="s">"cover-studio"</span>: {
<span class="s">"type"</span>: <span class="s">"http"</span>,
<span class="s">"url"</span>: <span class="s">"https://guanghulab.com/cover/api/generate"</span>,
<span class="s">"description"</span>: <span class="s">"语言驱动封面生成器"</span>
}
}
}</div>
</div>
</div>
<!-- ── 在线使用 Tab ── -->
<div class="tab-panel" id="panel-try">
<div class="use-layout">
<div>
<div class="card">
<div class="card-title">输入内容</div>
<div class="input-row">
<select id="preset"><option value="tech" selected>🔷 科技蓝</option><option value="warm">🟠 奶油暖调</option><option value="minimal">⬜ 极简黑白</option><option value="rose">🟣 玫瑰粉调</option><option value="green">🟢 文艺绿植</option></select>
<select id="layout"><option value="default">标准排版</option><option value="hero" selected>大标题封面</option><option value="quote">金句居中</option></select>
</div>
<input type="text" id="title" placeholder="标题" style="margin-bottom:10px;">
<textarea id="body" placeholder="正文..."></textarea>
<button class="gen-btn" id="btn" onclick="gen()">执行设计逻辑</button>
<div class="error" id="err"></div>
</div>
<div class="design-id-card" id="idCard" style="display:none;">
<div class="label">DESIGN ID</div>
<div class="value" id="designId">---</div>
</div>
<div class="card" id="chainCard" style="display:none;">
<div class="card-title">意图链 · 设计逻辑</div>
<div id="chainList"></div>
</div>
</div>
<div class="preview-box">
<div class="card">
<div class="card-title">封面预览</div>
<div class="preview-area" id="previewArea">
<div class="empty-hint" id="empty"><div class="icon">🎨</div><p>点击执行<br>生成封面</p></div>
<div class="loading" id="loading"><p style="color:var(--dim);font-size:12px;">编译中...</p></div>
<div class="preview-wrap" id="previewWrap"><img class="preview-img" id="previewImg" alt="封面"><div class="id-wm" id="watermark">---</div></div>
</div>
<a class="dl-btn" id="dlBtn" href="#" download style="display:none;">下载封面 PNG</a>
<button class="copy-btn" id="copyBtn" onclick="copyId()" style="display:none;">复制设计编号</button>
</div>
</div>
</div>
</div>
</div>
<footer>光湖语言世界 · 人格体的操作系统 · ICE-GL-ZY001 · 国作登字-2026-A-00037559</footer>
<script>
function switchTab(t) {
document.querySelectorAll('.tab').forEach(el => el.classList.remove('active'));
document.querySelectorAll('.tab-panel').forEach(el => el.classList.remove('active'));
event.target.classList.add('active');
document.getElementById('panel-'+t).classList.add('active');
}
let currentId = '';
async function gen() {
const title = document.getElementById('title').value.trim();
const body = document.getElementById('body').value.trim();
if(!title&&!body){showErr('请输入标题或正文');return}
document.getElementById('empty').style.display='none';
document.getElementById('previewWrap').classList.remove('show');
document.getElementById('dlBtn').style.display='none';
document.getElementById('copyBtn').style.display='none';
document.getElementById('idCard').style.display='none';
document.getElementById('chainCard').style.display='none';
document.getElementById('loading').classList.add('show');
document.getElementById('btn').disabled=true;
currentId='DSG-'+Date.now().toString(36).toUpperCase().slice(-8);
try{
const r=await fetch('/api/generate',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({templateId:'xiaohongshu',presetId:document.getElementById('preset').value,title,body,layout:document.getElementById('layout').value})});
if(!r.ok)throw new Error('生成失败');
const d=await r.json();
document.getElementById('loading').classList.remove('show');
document.getElementById('previewImg').src=d.url;
document.getElementById('previewWrap').classList.add('show');
document.getElementById('watermark').textContent=currentId;
document.getElementById('dlBtn').href=d.url;
document.getElementById('dlBtn').style.display='block';
document.getElementById('copyBtn').style.display='block';
document.getElementById('designId').textContent=currentId;
document.getElementById('idCard').style.display='block';
if(d.intent_chain){document.getElementById('chainCard').style.display='block';document.getElementById('chainList').innerHTML=d.intent_chain.map(s=>'<div class="intent-item '+(s.who==='用户'?'user':'system')+'"><div class="intent-icon">'+s.icon+'</div><div><div class="intent-who">'+s.who+'</div><div class="intent-step">'+s.step+'</div><div class="intent-detail">'+s.detail+'</div>'+(s.why?'<div class="intent-why">→ '+s.why+'</div>':'')+'</div></div>').join('')}
}catch(e){document.getElementById('loading').classList.remove('show');document.getElementById('empty').style.display='block';showErr(e.message)}
finally{document.getElementById('btn').disabled=false}
}
function showErr(m){const e=document.getElementById('err');e.textContent=m;e.classList.add('show');setTimeout(()=>e.classList.remove('show'),4000)}
function copyId(){navigator.clipboard.writeText(currentId).then(()=>{const b=document.getElementById('copyBtn');b.textContent='已复制: '+currentId;setTimeout(()=>b.textContent='复制设计编号',2000)})}
document.addEventListener('keydown',e=>{if((e.metaKey||e.ctrlKey)&&e.key==='Enter')gen()});
(function(){document.getElementById('title').value='零基础手搓AI做图小系统';document.getElementById('body').value='AI辅助 + 自己手搓 · 0经验也能开发\n\n- 开源到个人代码仓库\n- 全免费 · 无需GPU · 无需服务器\n- 语言驱动排版 · 意图透明\n- 封面也用它自己生成\n- 访问 cover.guanghulab.com 试试'})();
</script>
</body>
</html>