30 秒把新闻变成杂志大片:0 框架前端 + 一个云函数的手搓简报术

——给被老板催截图、却被排版逼疯的打工人


“复制链接 → 等 30 秒 → 收获一张 1080×2400 的‘财经封面’,扫码还能回原文。”
如果你也厌倦了‘截图+马克笔’的祖传简报,不妨花 8 分钟读完这篇,然后永久丢掉 Photoshop。


TL;DR 能做什么

  1. 纯浏览器跑:拖一个 index.html 到 CDN,就能对外服务——React/Vue 都不用装。
  2. 后端只写一次:单函数同时代理“爬虫 + LLM + 文生图”,密钥全扔环境变量,前端零暴露。
  3. 高亮零匹配:让 AI 直接输出 [R]…[/R] 标签,前端一次 replace 就能标红,拒绝“正则地狱”。

序章 为什么我又造轮子

上周三晚上 10 点,投资群甩来一条 36 氪深度稿,老板只回一句:“10 分钟后简报见”。
传统 Workflow:① 全选复制 → ② Word 调字号 → ③ 截 3 屏 → ④ 微信压缩到模糊。
那一刻,我决定把“截图”这件事自动化——最好还能带点手绘杂志感,让同事误以为我偷偷报了设计班。


直觉篇 30 秒产品速览

打开 https://your-cdn.com/brief 出现极简输入框:

  1. 粘贴新闻 URL
  2. 按钮文字变成“生成中…”并转圈 4 步
  3. 自动生成一张 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 路由:

  1. stage=scrape → 调 Unifuns 提取正文
  2. stage=analyze → 调 Gemini-2.5-Flash 输出带 [R]/[Y] 的 Markdown
  3. stage=draw → 调 Nano Banana 生成手绘风格插图
  4. 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 超时,基本不会被刷爆。


结论 把轮子再推一把

  1. 换主题?改 CSS 变量 3 分钟搞定。
  2. 想接入飞书群机器人?download.js 里把 saveAs 换成飞书 Webhook 30 行代码。
  3. 记得写单元测试——否则下个需求就是“为什么这条新闻插图里出现两只猫”。

常见问题解答(FAQ)

Q: 必须 302.ai 吗?A: 只要提供 OpenAI-compatible 端点即可,把 api.jsbaseURL 换掉。

Q: 移动端导出失败怎么办?A: 安卓 WebView 对 dom-to-image 的 foreignObject 支持差,直接弹吐司“请截屏”最稳。

Q: 插图风格能换成暗黑系吗?A:prompts.js 里把背景色 #f5f2e8 改成深灰,模型会跟着走。


留给你的两个脑洞

  1. 如果让 AI 把输出改成 Markdown+[P] 标签,是不是就能一键生成可交互的 PPT?
  2. 当高亮颜色超过 4 种,人类还来得及读吗——或许我们该用灰度+加粗代替彩虹?

“工具做完那一刻,老板突然不催简报了他开始催周报。”
祝你也早日用 AI 把自己从截图地狱里捞出来,然后安心摸鱼。