30 秒把新闻变成杂志大片:0 框架前端 + 一个云函数的手搓简报术
——给被老板催截图、却被排版逼疯的打工人
“复制链接 → 等 30 秒 → 收获一张 1080×2400 的‘财经封面’,扫码还能回原文。”
如果你也厌倦了‘截图+马克笔’的祖传简报,不妨花 8 分钟读完这篇,然后永久丢掉 Photoshop。
TL;DR 能做什么
-
纯浏览器跑:拖一个 index.html到 CDN,就能对外服务——React/Vue 都不用装。 -
后端只写一次:单函数同时代理“爬虫 + LLM + 文生图”,密钥全扔环境变量,前端零暴露。 -
高亮零匹配:让 AI 直接输出 [R]…[/R]标签,前端一次replace就能标红,拒绝“正则地狱”。
序章 为什么我又造轮子
上周三晚上 10 点,投资群甩来一条 36 氪深度稿,老板只回一句:“10 分钟后简报见”。
传统 Workflow:① 全选复制 → ② Word 调字号 → ③ 截 3 屏 → ④ 微信压缩到模糊。
那一刻,我决定把“截图”这件事自动化——最好还能带点手绘杂志感,让同事误以为我偷偷报了设计班。
直觉篇 30 秒产品速览
打开 https://your-cdn.com/brief 出现极简输入框:
-
粘贴新闻 URL -
按钮文字变成“生成中…”并转圈 4 步 -
自动生成一张 1080×2400 长图,带二维码、手绘插图、红/黄高亮重点
全程不注册、不留 Cookie、不在服务器存原文——适合“即用即走”的打工人。
实战篇 前端 0 框架
1. 文件结构(按加载顺序)
index.html → 只负责骨架 & 脚本排队
styles.css → 米色背景 #f5f2e8 + 四色高亮
config.js → 示例文章,降低第一次使用门槛
prompts.js → AI 提示词模板,后续调格式只改这里
api.js → 统一 POST 到云函数,兜底 30 s 超时
download.js → PC 直接下载,移动端失败提示“请截屏”
script.js → 主流程 + 进度条 + 错误吐司
2. 核心代码(已精简至 30 行)
// api.js
export async function runPipeline(url) {
const res = await fetch('/server/multi_handler', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url, stage: 'all' })
});
return res.json(); // { markdown, images: [{url, alt}] }
}
// script.js
import { runPipeline } from './api.js';
import { saveAs } from './FileSaver.js';
async function go() {
const { markdown, images } = await runPipeline(newsUrl.value);
const html = markdownToHtml(markdown); // 自定义 marked 渲染
document.querySelector('#report').innerHTML = html;
const dataUrl = await domtoimage.toPng(document.querySelector('#report'));
saveAs(dataUrl, `brief-${Date.now()}.png`);
}
没有打包工具?直接
<script type="module">原生 ESM,IE 可以安息了。
实战篇 云函数三合一
技术选型:阿里云函数计算 + Python 3.10
单入口 multi_handler.py 根据 stage 路由:
-
stage=scrape→ 调 Unifuns 提取正文 -
stage=analyze→ 调 Gemini-2.5-Flash 输出带[R]/[Y]的 Markdown -
stage=draw→ 调 Nano Banana 生成手绘风格插图 -
stage=all→ 顺序串行,返回 JSON
def handler(event, context):
body = json.loads(event)
url, stage = body['url'], body.get('stage', 'all')
if stage in ('scrape', 'all'):
text = scrape(url)
if stage in ('analyze', 'all'):
md = analyze(text)
if stage in ('draw', 'all'):
images = draw(md)
return {'markdown': md, 'images': images}
环境变量(永远不进前端):
UNIFUNS_KEY=uf_xxx
GEMINI_KEY=gm_xxx
NANO_KEY=nb_xxx
进阶篇 方括号高亮协议
与其让 AI 生成→前端再和原文 diff,不如让模型直接打标签:
提示词末尾加死命令
“请用 [R]…[/R] 标红关键结论(每段≤3 处),用 [Y]…[/Y] 标黄趋势或风险(每段≤1 处)。禁止嵌套。”
前端一次性替换:
html = html
.replace(/\[R\](.*?)\[\/R\]/g, '<span class="red">$1</span>')
.replace(/\[Y\](.*?)\[\/Y\]/g, '<span class="yellow">$1</span>');
无嵌套、无长度漂移,100 篇测试零错位。
进阶篇 成本 & 限速
| 服务商 | 单价 | 1 万次总费用 |
|---|---|---|
| 302.ai 统一 | 0.02 元/次 | 200 元 |
| 阿里云函数 | 100 万次/月免费 | 0 元 |
| 自购 GPU 机 | 约 2 000 元/月 | 2 000 元 |
前端 5 s 防抖 + 云函数 30 s 超时,基本不会被刷爆。
结论 把轮子再推一把
-
换主题?改 CSS 变量 3 分钟搞定。 -
想接入飞书群机器人? download.js里把saveAs换成飞书 Webhook 30 行代码。 -
记得写单元测试——否则下个需求就是“为什么这条新闻插图里出现两只猫”。
常见问题解答(FAQ)
Q: 必须 302.ai 吗?A: 只要提供 OpenAI-compatible 端点即可,把 api.js 的 baseURL 换掉。
Q: 移动端导出失败怎么办?A: 安卓 WebView 对 dom-to-image 的 foreignObject 支持差,直接弹吐司“请截屏”最稳。
Q: 插图风格能换成暗黑系吗?A: 在 prompts.js 里把背景色 #f5f2e8 改成深灰,模型会跟着走。
留给你的两个脑洞
-
如果让 AI 把输出改成 Markdown+ [P]标签,是不是就能一键生成可交互的 PPT? -
当高亮颜色超过 4 种,人类还来得及读吗——或许我们该用灰度+加粗代替彩虹?
“工具做完那一刻,老板突然不催简报了他开始催周报。”
祝你也早日用 AI 把自己从截图地狱里捞出来,然后安心摸鱼。
