为冰朔定制专属配图生成系统,支持三种卡片类型:
- 小红书竖版卡片 (1080×1440, 3:4)
- 即刻方卡 (1080×1080, 1:1)
- 海报 (1080×1920, 9:16)
特性:多套配色方案、多种布局风格、
Puppeteer + HTML/CSS 渲染引擎、
可部署 Web 服务 + 预览页面
使用方式:冰朔在对话里告诉铸渊内容和类型,
铸渊运行脚本生成,冰朔直接下载使用。
105 lines
3.2 KiB
JavaScript
105 lines
3.2 KiB
JavaScript
/**
|
|
* ═══════════════════════════════════════════════════
|
|
* 铸渊图片工作室 · Web 服务
|
|
* ═══════════════════════════════════════════════════
|
|
*
|
|
* 部署到服务器,冰朔可以在浏览器预览已生成的图片。
|
|
* 我在对话里生成图片后,冰朔可以直接访问链接下载。
|
|
*/
|
|
|
|
import express from 'express'
|
|
import { generate } from './generate.js'
|
|
import { join, dirname } from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
import { readdirSync, existsSync } from 'fs'
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
const OUTPUT_DIR = join(__dirname, 'output')
|
|
const PORT = process.env.PORT || 3912
|
|
|
|
const app = express()
|
|
app.use(express.json())
|
|
|
|
/* ── 静态文件服务 ── */
|
|
app.use('/output', express.static(OUTPUT_DIR))
|
|
|
|
/* ── 首页 · 预览画廊 ── */
|
|
app.get('/', (req, res) => {
|
|
let files = []
|
|
try {
|
|
if (existsSync(OUTPUT_DIR)) {
|
|
files = readdirSync(OUTPUT_DIR)
|
|
.filter(f => /\.(png|webp|jpg)$/i.test(f))
|
|
.sort()
|
|
.reverse()
|
|
}
|
|
} catch {}
|
|
|
|
const galleryHtml = files.length > 0
|
|
? files.map(f =>
|
|
`<a href="/output/${f}" target="_blank"><img src="/output/${f}" loading="lazy"></a>`
|
|
).join('\n')
|
|
: '<div class="empty">还没有生成的图片<br>在对话里告诉铸渊你想做什么图</div>'
|
|
|
|
res.send(`<!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>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: -apple-system, 'PingFang SC', 'Noto Sans SC', sans-serif;
|
|
background: #faf8f5; color: #1a1a2e; padding: 40px;
|
|
max-width: 1000px; margin: 0 auto;
|
|
}
|
|
h1 { font-size: 28px; margin-bottom: 4px; }
|
|
.sub { color: #6b7280; margin-bottom: 24px; font-size: 14px; }
|
|
.gallery {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
gap: 16px;
|
|
}
|
|
.gallery a {
|
|
display: block;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
border: 1px solid #e5e7eb;
|
|
transition: transform 0.2s;
|
|
}
|
|
.gallery a:hover { transform: scale(1.02); }
|
|
.gallery img { width: 100%; display: block; }
|
|
.empty {
|
|
grid-column: 1 / -1;
|
|
text-align: center; padding: 80px 20px;
|
|
color: #9ca3af; font-size: 16px; line-height: 2;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>🎨 铸渊图片工作室</h1>
|
|
<p class="sub">冰朔 · 你的配图我包了 · 在对话里告诉我内容就行</p>
|
|
<div class="gallery">${galleryHtml}</div>
|
|
</body>
|
|
</html>`)
|
|
})
|
|
|
|
/* ── 生成 API ── */
|
|
app.post('/api/generate', async (req, res) => {
|
|
try {
|
|
const result = await generate(req.body)
|
|
res.json({
|
|
success: true,
|
|
files: result.files,
|
|
urls: result.files.map(f => `/output/${f.split('/').pop()}`),
|
|
})
|
|
} catch (err) {
|
|
res.status(400).json({ success: false, error: err.message })
|
|
}
|
|
})
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`🎨 铸渊图片工作室运行在 http://localhost:${PORT}`)
|
|
})
|