Skip to content

Instantly share code, notes, and snippets.

@OrangeViolin
Last active May 1, 2026 16:45
Show Gist options
  • Select an option

  • Save OrangeViolin/326807040fc6abb3c8dd80c076f66de3 to your computer and use it in GitHub Desktop.

Select an option

Save OrangeViolin/326807040fc6abb3c8dd80c076f66de3 to your computer and use it in GitHub Desktop.
Meeting Infographic Skill for Codex — 会议转写稿 → Markdown 纪要 + 暖色卡片信息图 + 可下载 PNG。触发词:/meeting

Meeting Infographic Skill

把会议录音转写稿整理成:

  • 结构化 Markdown 会议纪要
  • 暖色卡片风格 HTML 信息图
  • 可点击下载的 PNG / 可打印 PDF

支持 docx / txt / pdf / md 输入,也可以结合活动海报和二维码生成标题定调、社群 CTA 和可分享信息图。

Install

Codex:

curl -fsSL https://gist.githubusercontent.com/OrangeViolin/326807040fc6abb3c8dd80c076f66de3/raw/install.sh | bash

Claude Code:

curl -fsSL https://gist.githubusercontent.com/OrangeViolin/326807040fc6abb3c8dd80c076f66de3/raw/install.sh | bash -s -- --claude

Usage

在 Codex / Claude Code 里说:

用 $meeting-infographic 整理这个会议转写稿,生成会议纪要和信息图

或:

/meeting

然后把会议转写文件拖进去。

Files

  • SKILL.md:skill 主体说明
  • infographic-template.html:暖色卡片信息图模板
  • install.sh:一键安装脚本
  • openai.yaml:Codex skill 展示元信息
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{会议标题}} · 会议纪要</title>
<!--
============================================================
会议纪要信息图 · 暖色卡片风格模板
============================================================
使用说明:
- 替换 {{}} 占位符为实际内容
- 按需增减 section / card 数量
- 卡片网格最后一行:根据卡片数选择 r3-last1/r3-last2/r3-last3
- 标签颜色:默认珊瑚色,可加 .blue/.green/.amber/.red/.purple/.gray/.teal
- 2列布局:card-grid 加 .cols-2
- 本地二维码/图片必须先转成 data URI 再写入 img src,避免 PNG 导出失败
============================================================
-->
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700;900&family=Noto+Serif+SC:wght@600;700;900&display=swap');
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Noto Sans SC', -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', sans-serif;
background: #f5f0ea;
color: #2c2420;
display: flex;
flex-direction: column;
align-items: center;
padding: 0;
-webkit-font-smoothing: antialiased;
}
/* ====== DOWNLOAD BAR (hidden in print) ====== */
.download-bar {
position: fixed;
top: 0; left: 0; right: 0;
background: rgba(245,240,234,0.95);
backdrop-filter: blur(10px);
padding: 10px 24px;
display: flex;
justify-content: center;
gap: 12px;
z-index: 1000;
border-bottom: 1px solid #e0d6cc;
}
.download-bar button {
padding: 7px 18px;
border: 1px solid #c9bfb3;
background: #fff;
color: #5a4e42;
border-radius: 6px;
font-size: 13px;
cursor: pointer;
font-family: inherit;
transition: all 0.2s;
}
.download-bar button:hover {
background: #f0e8de;
border-color: #b5a898;
}
/* ====== PAGE WRAPPER ====== */
.page {
width: 820px;
max-width: 100%;
padding: 64px 0 40px;
}
.infographic {
background: #f5f0ea;
padding: 48px 44px 40px;
}
/* ====== HEADER ====== */
.header {
text-align: center;
margin-bottom: 10px;
}
.header h1 {
font-family: 'Noto Serif SC', 'Noto Sans SC', serif;
font-size: 28px;
font-weight: 900;
color: #1a1412;
line-height: 1.5;
letter-spacing: 0;
}
.header-sub {
font-size: 16px;
color: #5a4e42;
font-weight: 500;
margin-top: 8px;
}
.header-meta {
font-size: 13px;
color: #9a8e82;
margin-top: 12px;
padding-bottom: 32px;
border-bottom: 1px solid #e0d6cc;
}
/* ====== SECTION ====== */
.section {
margin-top: 32px;
}
.section-head {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
}
.section-emoji { font-size: 18px; line-height: 1; }
.section-title {
font-family: 'Noto Serif SC', 'Noto Sans SC', serif;
font-size: 17px;
font-weight: 700;
color: #1a1412;
}
.section-count {
display: inline-block;
padding: 2px 10px;
background: #f0e0d0;
border-radius: 100px;
font-size: 12px;
color: #9a7a5a;
margin-left: 4px;
}
/* ====== CARD GRID ====== */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border: 1px solid #e0d6cc;
border-radius: 10px;
overflow: hidden;
background: #fff;
}
.card-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.card {
padding: 20px;
border-right: 1px solid #ede6dd;
border-bottom: 1px solid #ede6dd;
background: #fff;
}
.card-grid .card:nth-child(3n) { border-right: none; }
.card-grid.cols-2 .card:nth-child(2n) { border-right: none; }
.card-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 8px;
margin-bottom: 10px;
flex-wrap: wrap;
}
.card-title {
font-size: 14.5px;
font-weight: 700;
color: #1a1412;
line-height: 1.5;
flex: 1;
min-width: 0;
}
/* ====== TAG COLORS ====== */
.card-tag {
display: inline-block;
padding: 2px 10px;
background: #c67a5c;
color: #fff;
border-radius: 4px;
font-size: 11.5px;
font-weight: 500;
white-space: nowrap;
flex-shrink: 0;
line-height: 1.6;
}
.card-tag.blue { background: #6b8fb5; }
.card-tag.green { background: #7ba67e; }
.card-tag.amber { background: #c49a5c; }
.card-tag.red { background: #c06058; }
.card-tag.purple { background: #8b7ab5; }
.card-tag.gray { background: #8a8078; }
.card-tag.teal { background: #5a9a8a; }
.card-body {
font-size: 13px;
color: #6b5e52;
line-height: 1.85;
}
.card-body strong { color: #3a302a; font-weight: 600; }
/* ====== QUOTE BOX ====== */
.quote-box {
background: #fff;
border: 1px solid #e0d6cc;
border-radius: 10px;
padding: 24px 28px;
margin-top: 16px;
}
.quote-text {
font-size: 15.5px;
font-weight: 500;
color: #3a302a;
line-height: 1.8;
padding-left: 16px;
border-left: 3px solid #c67a5c;
}
.quote-author {
font-size: 12.5px;
color: #9a8e82;
margin-top: 10px;
text-align: right;
}
/* ====== COMPACT QUOTE GRID ====== */
.quote-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.quote-card {
background: #fff;
border: 1px solid #e0d6cc;
border-radius: 10px;
padding: 16px 18px;
}
.quote-card .quote-text {
font-size: 13.5px;
font-weight: 700;
color: #3a302a;
line-height: 1.7;
padding-left: 12px;
border-left: 3px solid #c67a5c;
}
.quote-card .quote-author {
font-size: 11.5px;
color: #9a8e82;
margin-top: 10px;
text-align: left;
line-height: 1.6;
}
/* ====== JOIN / CTA PANEL ====== */
.join-panel {
display: grid;
grid-template-columns: minmax(0, 1fr) 180px;
border: 1px solid #e0d6cc;
border-radius: 10px;
overflow: hidden;
background: #fff;
}
.join-copy {
padding: 22px 24px;
border-right: 1px solid #ede6dd;
}
.join-title {
font-family: 'Noto Serif SC', 'Noto Sans SC', serif;
font-size: 18px;
font-weight: 800;
color: #1a1412;
margin-bottom: 12px;
}
.join-text {
font-size: 13px;
line-height: 1.9;
color: #6b5e52;
}
.join-text strong { color: #3a302a; font-weight: 700; }
.join-note {
margin-top: 14px;
font-size: 11.5px;
color: #b0a397;
}
.qr-wrap {
display: flex;
align-items: center;
justify-content: center;
padding: 18px;
background: #fbf8f5;
}
.qr-wrap img {
width: 136px;
height: 136px;
object-fit: contain;
border-radius: 6px;
}
/* ====== TODO PRIORITY HEADERS ====== */
.todo-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 12px;
margin-top: 20px;
}
.todo-priority-badge {
padding: 2px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.5px;
}
.todo-priority-badge.p0 { background: #c06058; color: #fff; }
.todo-priority-badge.p1 { background: #c49a5c; color: #fff; }
.todo-priority-badge.p2 { background: #6b8fb5; color: #fff; }
.todo-group-label {
font-size: 14px;
font-weight: 600;
color: #3a302a;
}
/* ====== LAST-ROW BORDER REMOVAL ====== */
/* 3-col grid */
.r3-last1 .card:nth-last-child(1) { border-bottom: none; }
.r3-last2 .card:nth-last-child(-n+2) { border-bottom: none; }
.r3-last3 .card:nth-last-child(-n+3) { border-bottom: none; }
/* 2-col grid */
.r2-last1 .card:nth-last-child(1) { border-bottom: none; }
.r2-last2 .card:nth-last-child(-n+2) { border-bottom: none; }
/* ====== FOOTER ====== */
.footer {
margin-top: 36px;
padding-top: 20px;
border-top: 1px solid #e0d6cc;
text-align: center;
font-size: 12px;
color: #9a8e82;
line-height: 1.8;
}
/* ====== PRINT ====== */
@media print {
.download-bar { display: none !important; }
.page { padding: 0; }
.infographic { padding: 36px 40px; }
@page { size: A3 portrait; margin: 10mm; }
}
@media (max-width: 720px) {
.quote-grid { grid-template-columns: 1fr; }
.join-panel { grid-template-columns: 1fr; }
.join-copy { border-right: none; border-bottom: 1px solid #ede6dd; }
}
</style>
</head>
<body>
<!-- ==================== DOWNLOAD BAR ==================== -->
<div class="download-bar">
<button onclick="window.print()">Save as PDF (Cmd/Ctrl + P)</button>
<button onclick="downloadAsPng(this)">Download as PNG</button>
</div>
<div class="page">
<div class="infographic" id="infographic">
<!-- ==================== HEADER ==================== -->
<div class="header">
<h1>{{会议标题}}</h1>
<div class="header-sub">会议纪要</div>
<div class="header-meta">{{日期}} &nbsp;·&nbsp; 参会人:{{参会人}} &nbsp;·&nbsp; {{主题简述}}</div>
</div>
<!-- ==================== KEYNOTE QUOTE (可选) ==================== -->
<div class="quote-box">
<div class="quote-text">"{{核心引言原话}}"</div>
<div class="quote-author">—— {{发言人}} · {{上下文}}</div>
</div>
<!-- ==================== 锋利金句:紧凑 2 列 (可选,3句以上优先用这个) ==================== -->
<div class="section">
<div class="section-head">
<span class="section-emoji">✦</span>
<span class="section-title">锋利金句</span>
<span class="section-count">{{N}} 句</span>
</div>
<div class="quote-grid">
<div class="quote-card">
<div class="quote-text">"{{真正犀利的原话}}"</div>
<div class="quote-author">{{发言人}} · {{为什么这句话重要}}</div>
</div>
<!-- 更多金句... -->
</div>
</div>
<!-- ==================== 数据速览 (可选) ==================== -->
<div class="section">
<div class="section-head">
<span class="section-emoji">📊</span>
<span class="section-title">{{板块标题}}</span>
<span class="section-count">{{N}} 个关键数据</span>
</div>
<div class="card-grid r3-last1">
<!-- 根据卡片总数选择 r3-last1 / r3-last2 / r3-last3 -->
<div class="card">
<div class="card-head">
<span class="card-title">{{卡片标题}}</span>
<!-- 标签可选,不需要就删掉 -->
<span class="card-tag">{{人名/类别}}</span>
</div>
<div class="card-body">{{卡片正文,支持 <strong>加粗</strong>。}}</div>
</div>
<!-- 更多卡片... -->
</div>
</div>
<!-- ==================== 议题板块 (重复) ==================== -->
<div class="section">
<div class="section-head">
<span class="section-emoji">{{emoji}}</span>
<span class="section-title">{{板块标题}}</span>
<span class="section-count">{{N}} 个{{单位}}</span>
</div>
<div class="card-grid r3-last3">
<div class="card">
<div class="card-head">
<span class="card-title">{{卡片标题}}</span>
<span class="card-tag red">{{标签}}</span>
</div>
<div class="card-body">{{内容}}</div>
</div>
<!-- 更多卡片... -->
</div>
</div>
<!-- ==================== 2列布局示例 ==================== -->
<div class="section">
<div class="section-head">
<span class="section-emoji">{{emoji}}</span>
<span class="section-title">{{板块标题}}</span>
<span class="section-count">{{N}} 个{{单位}}</span>
</div>
<div class="card-grid cols-2 r2-last2">
<div class="card">
<div class="card-head">
<span class="card-title">{{卡片标题}}</span>
<span class="card-tag purple">{{标签}}</span>
</div>
<div class="card-body">{{较长内容,2列卡片适合信息量大的内容}}</div>
</div>
<!-- 更多卡片... -->
</div>
</div>
<!-- ==================== TODO 清单 ==================== -->
<div class="section">
<div class="section-head">
<span class="section-emoji">✅</span>
<span class="section-title">TODO 行动清单</span>
<span class="section-count">{{N}} 项行动</span>
</div>
<!-- P0 组 -->
<div class="todo-header">
<span class="todo-priority-badge p0">P0</span>
<span class="todo-group-label">立即行动</span>
</div>
<div class="card-grid r3-last2">
<div class="card">
<div class="card-head">
<span class="card-title">{{任务标题}}</span>
<span class="card-tag green">{{负责人}}</span>
</div>
<div class="card-body">{{任务描述}}。<strong>{{时间要求}}</strong>。</div>
</div>
<!-- 更多卡片... -->
</div>
<!-- P1 组 -->
<div class="todo-header">
<span class="todo-priority-badge p1">P1</span>
<span class="todo-group-label">近期推进</span>
</div>
<div class="card-grid r3-last3">
<!-- 卡片... -->
</div>
<!-- P2 组 (可选) -->
<div class="todo-header">
<span class="todo-priority-badge p2">P2</span>
<span class="todo-group-label">持续跟进</span>
</div>
<div class="card-grid r3-last1">
<!-- 卡片... -->
</div>
</div>
<!-- ==================== 后续活动方向 (社群活动可选) ==================== -->
<div class="section">
<div class="section-head">
<span class="section-emoji">🧭</span>
<span class="section-title">后续活动方向</span>
<span class="section-count">{{N}} 种形态</span>
</div>
<div class="card-grid r3-last1">
<div class="card">
<div class="card-head">
<span class="card-title">聊天局</span>
<span class="card-tag green">进展</span>
</div>
<div class="card-body">互相聊聊彼此最近的进展,以及各自正在做的事情推进到哪里了。</div>
</div>
<!-- Demo 演示局 / 主题局 / 日常发掘等,按会议真实内容增删 -->
</div>
</div>
<!-- ==================== 入群 / 报名 CTA (用户提供二维码时可选) ==================== -->
<div class="section">
<div class="section-head">
<span class="section-emoji">🐟</span>
<span class="section-title">{{CTA 标题}}</span>
<span class="section-count">扫码加入</span>
</div>
<div class="join-panel">
<div class="join-copy">
<div class="join-title">{{加入组织/社群名}}</div>
<div class="join-text">{{加入理由与后续可参与的事情}}</div>
<div class="join-note">{{二维码有效期或备注}}</div>
</div>
<div class="qr-wrap">
<img src="{{二维码 data URI,不要用本地 file 路径}}" alt="{{二维码说明}}">
</div>
</div>
</div>
<!-- ==================== 共识 (可选) ==================== -->
<div class="section">
<div class="section-head">
<span class="section-emoji">🤝</span>
<span class="section-title">团队共识</span>
<span class="section-count">{{N}} 项共识</span>
</div>
<div class="card-grid r3-last2">
<div class="card">
<div class="card-head">
<span class="card-title">{{共识标题}}</span>
</div>
<div class="card-body">{{共识说明}}</div>
</div>
<!-- 更多卡片... -->
</div>
</div>
<!-- ==================== FOOTER ==================== -->
<div class="footer">
{{团队/项目名}} · 会议纪要 · {{日期}}<br>
{{备注信息}}
</div>
</div>
</div>
<!-- ==================== PNG EXPORT ==================== -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script>
async function downloadAsPng(button) {
const btn = button || event.target;
const originalText = btn ? btn.textContent : 'Download as PNG';
const el = document.getElementById('infographic');
try {
if (!window.html2canvas) {
throw new Error('html2canvas 没有加载成功,请确认当前浏览器可以访问 CDN。');
}
if (btn) {
btn.textContent = 'Generating...';
btn.disabled = true;
}
const canvas = await html2canvas(el, {
scale: 2,
backgroundColor: '#f5f0ea',
useCORS: true,
allowTaint: false,
logging: false,
windowWidth: 820
});
const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
if (!blob) {
throw new Error('浏览器没有生成 PNG 数据。');
}
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = '{{文件名}}.png';
link.href = url;
document.body.appendChild(link);
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(url), 1000);
} catch (err) {
console.error(err);
alert('PNG 下载失败:' + err.message);
} finally {
if (btn) {
btn.textContent = originalText;
btn.disabled = false;
}
}
}
</script>
</body>
</html>
#!/bin/bash
# Meeting Infographic Skill — 一键安装脚本
# 会议录音转写 → 结构化纪要 + 暖色卡片信息图
set -euo pipefail
SKILL_HOME="${CODEX_HOME:-$HOME/.codex}/skills"
if [ "${1:-}" = "--claude" ]; then
SKILL_HOME="${CLAUDE_HOME:-$HOME/.claude}/skills"
fi
SKILL_DIR="$SKILL_HOME/meeting-infographic"
REF_DIR="$SKILL_DIR/references"
AGENT_DIR="$SKILL_DIR/agents"
GIST_RAW="https://gist.githubusercontent.com/OrangeViolin/326807040fc6abb3c8dd80c076f66de3/raw"
echo "Installing meeting-infographic skill..."
echo "Target: $SKILL_DIR"
mkdir -p "$REF_DIR" "$AGENT_DIR"
curl -fsSL "$GIST_RAW/SKILL.md" -o "$SKILL_DIR/SKILL.md"
curl -fsSL "$GIST_RAW/infographic-template.html" -o "$REF_DIR/infographic-template.html"
curl -fsSL "$GIST_RAW/openai.yaml" -o "$AGENT_DIR/openai.yaml" || true
echo "Installed to $SKILL_DIR"
echo ""
echo "Usage: In Codex, say /meeting or use \$meeting-infographic with a meeting transcript."
echo "Claude Code users can run: bash install.sh --claude"
interface:
display_name: "Meeting Infographic"
short_description: "会议纪要和暖色信息图一键生成"
default_prompt: "Use $meeting-infographic to turn this meeting transcript into structured notes and an infographic."
name meeting-infographic
description 将会议录音转写稿整理为结构化会议纪要 + 暖色卡片风格信息图。支持 docx/txt/pdf/md 输入,可结合活动海报/二维码校准标题定调与入群 CTA,输出 Markdown 纪要 + 可下载 HTML 信息图。触发词:"整理会议"、"会议纪要"、"会议信息图"、"/meeting"

会议纪要信息图生成器

将会议录音转写稿(通常口语化、冗长、有重复)整理为:

  1. 结构化 Markdown 会议纪要(保留全部细节)
  2. 暖色卡片风格 HTML 信息图(可下载 PNG/PDF)

如果用户同时提供活动海报、宣传图、群二维码或补充反馈,必须把这些材料作为一等输入:海报用于校准标题和活动定调,二维码用于底部 CTA,反馈用于更新模块取舍和内容优先级。

触发词

  • "整理会议"
  • "会议纪要"
  • "会议信息图"
  • "整理会议录音"
  • "生成会议纪要"
  • "/meeting"

当用户提供会议录音文件(docx/txt/pdf)并要求整理时触发。


工作流程

输入文件/海报/二维码 → 提取文本与视觉主题 → 结构化分析 → 输出 Markdown 纪要 → 生成 HTML 信息图 → 浏览器验证下载

Step 1:提取文本

根据文件类型选择提取方式:

文件类型 提取方式
.docx macOS textutil -convert txt -stdout <文件路径>
.txt 直接用 Read 工具读取
.pdf 用 Read 工具读取(支持 PDF)
.md 直接用 Read 工具读取

Step 2:结构化分析

会议录音转写稿的特点:口语化、有语气词、有重复、说话人标记不一定准确。

分析框架

从原始文本中提取以下结构:

维度 提取内容
基本信息 会议时间、参会人员(角色/姓名)、会议主题;如有活动海报,以海报主题为主标题,转写文件名只能作来源信息
活动定调 活动海报、开场介绍、主持人口径里真正要表达的主题和气质
核心观点 每位发言人的核心主张(去掉口语废话,保留原意)
关键数据 只提取对理解会议有解释力的数字、指标、时间节点;不要为了填版面制造“关键数字”
决策与共识 只有明确达成共识/结论时才输出;闲聊、分享会、开放讨论不要硬写“会议结论”
分歧与讨论 不同意见、争论点
风险与挑战 提到的问题、担忧、风险
TODO 行动项 只有出现明确任务、负责人、时间或承诺时才提取;不要把泛泛建议包装成立即行动
金句/定调 有锋芒、反常识、判断力或情绪穿透力的原话;普通解释句不算金句
后续方向 社群活动、系列活动或开放讨论要提取后续活动形态、主题池、参与方式

分析原则

  1. 保留全部细节:不丢失任何实质性信息,口语废话可删但观点不可删
  2. 还原发言人:尽量识别每个观点是谁说的(从"角色A/B/C"或上下文推断)
  3. 谨慎推断 TODO:可从讨论中提取隐含待办,但必须有明确行动语义;没有负责人/动作/时间时不要硬生成行动清单
  4. 保留原话金句:有力量的原话保留,用引号标注;优先选择“判断更尖锐、信息差更大”的句子,而不是温和说明句
  5. 结构化归类:把散乱的讨论归入逻辑清晰的板块
  6. 尊重会议真实形态:分享会、闲聊局、社群圆桌可能没有结论、没有行动、没有关键数字;没有就删,不要为了模板完整而补
  7. 海报优先定调:当海报标题和转写文件名不一致时,以海报主题/用户补充为准,转写文件名只记录在来源字段

Step 3:输出 Markdown 会议纪要

保存到输入文件同目录,文件名 [原文件名]_会议纪要.md

纪要结构模板

# [会议主题] · 会议纪要

| 项目 | 内容 |
|------|------|
| **会议时间** | ... |
| **参会人员** | ... |
| **会议主题** | ... |

---

## 一、[第一个议题板块]
### 1.1 [子话题]
### 1.2 [子话题]

## 二、[第二个议题板块]
...

## N、TODO 清单(仅在会议存在明确行动项时生成)

### 【高优先级 · 立即行动】
| # | 事项 | 负责人 | 时间 |
|---|------|--------|------|

### 【中优先级 · 近期推进】
...

### 【长期 · 持续跟进】
...

Step 4:生成 HTML 信息图

→ 读取 references/infographic-template.html 获取完整模板。

设计风格:暖色卡片式

核心视觉语言(必须严格遵守):

要素 规范
背景 暖米色 #f5f0ea
卡片 白色 #fff,细线边框 #e0d6cc,圆角 10px
卡片布局 3列网格,卡片间用 1px 细线分隔(不是 gap),外部有圆角边框包裹
标题文字 深棕 #1a1412,思源宋体加粗
正文文字 灰棕 #6b5e52,13px,行高 1.85
强调文字 深棕 #3a302a,font-weight 600
人名标签 珊瑚色 #c67a5c 底,白字,圆角 4px
辅助标签色 #6b8fb5 / 绿 #7ba67e / 琥珀 #c49a5c / 红 #c06058 / 紫 #8b7ab5 / 灰 #8a8078 / 青 #5a9a8a
板块标题 emoji + 宋体加粗 + 计数胶囊(#f0e0d0 底,#9a7a5a 字)
页面宽度 820px,居中
引言框 白色圆角框,左侧 3px 珊瑚色竖线

信息图板块结构

根据会议内容动态生成以下板块(按需取用,不是每个都必须有)。不要为了模板完整而生成低价值板块。

  1. 页头:会议标题(宋体大号)+ 副标题 + 时间/参会人/主题
  2. 会议定调/一眼看懂:用 4-6 张卡片说明这场会真正讨论的主题
  3. 锋利金句:只放高质量原话;超过 3 句时使用紧凑 2 列 quote-grid,不要用大块留白引用框
  4. 关键数据速览:仅当数据有解释力时生成,避免“凑数字”
  5. 核心议题板块:每个议题一个 section,内含 3 列卡片网格
  6. 后续活动方向:社群活动/系列活动要提炼聊天局、Demo 演示局、主题局、日常发掘等后续形态
  7. TODO 行动清单:仅在有明确行动时生成,按优先级分组(P0/P1/P2)
  8. 共识/结论:仅在明确达成结论时生成;开放讨论不要硬写结论
  9. 入群/报名 CTA:用户提供二维码时加在底部,文案要具体说明加入后继续做什么
  10. 页脚:会议信息 + 备注

本轮固化规则:社群闲聊/活动复盘

来自 01FISH 摸鱼俱乐部 #01 复盘的固定经验:

场景 默认处理
活动海报写着明确主题 主标题、介绍、会议定调必须跟海报一致;不要沿用转写文件名里的旧主题
用户说“主题变了” 立刻重写标题、总览、会议定调、一眼看懂、页脚和下载文件名
用户说“没有结论” 删除“会议结论/共识”模块,Markdown 也同步删
用户说“这些数据没意义” 删除“关键数字/关键数据”模块,不换一批数字凑数
用户说“这些行动不要” 删除行动清单/TODO 模块,除非会议里有真正负责人和时间
金句被指出不犀利 回到转写稿找更尖锐的原话,优先选反常识、行业判断、利益格局、信息差判断
金句区域太松 改为 2 列紧凑卡片,字号略小,减少单句占用高度
社群活动有后续计划 生成“后续活动方向”,优先使用用户原话:聊天局、Demo 演示局、主题局、日常发掘
用户给群二维码 底部加“继续加入/扫码入群”CTA,二维码必须嵌入 HTML,保证 PNG 可下载

卡片 HTML 结构

每张卡片的结构:

<div class="card">
  <div class="card-head">
    <span class="card-title">卡片标题</span>
    <span class="card-tag">标签</span>        <!-- 人名/类别,可选颜色 class -->
  </div>
  <div class="card-body">
    卡片正文,支持 <strong>加粗强调</strong></div>
</div>

卡片网格最后一行去底线规则

卡片用 border-right + border-bottom 分隔,最后一行需要去掉 border-bottom。用 CSS class 控制:

  • 3列网格最后一行3张:.r3-last3nth-last-child(-n+3) 去底线
  • 3列网格最后一行2张:.r3-last2nth-last-child(-n+2) 去底线
  • 3列网格最后一行1张:.r3-last1nth-last-child(1) 去底线
  • 2列网格同理:.r2-last2 / .r2-last1

下载功能

页面顶部固定两个按钮:

  • Save as PDF:调用 window.print()
  • Download as PNG:用 html2canvas 库导出

PNG 导出必须满足:

  1. 本地图片、二维码、海报裁图必须转成 data:image/...;base64,... 内嵌进 HTML,不能直接用 file:/// 或绝对路径作为 <img src>,否则 canvas 会被污染并报 Tainted canvases may not be exported
  2. 下载逻辑使用 canvas.toBlob() + URL.createObjectURL(blob),不要用大图 toDataURL() 作为唯一方案。
  3. 下载按钮要有生成中状态和失败 alert,便于用户知道是 CDN 未加载、图片污染还是浏览器限制。
  4. 完成后用 Playwright 或浏览器手动点击一次按钮,确认真的触发下载;不要只检查 HTML 能打开。

Step 5:输出与打开

  1. HTML 信息图保存到输入文件同目录,文件名 [原文件名]_信息图.html
  2. open 命令在浏览器中打开
  3. 告知用户两个文件路径和下载方式

内容提炼原则

从口语到书面的转换

口语特征 处理方式
语气词(嗯、啊、呃) 删除
重复表述(就是就是、然后然后) 合并为一次
口头禅(对吧、是吧、你知道吗) 删除
说了一半改口的 取最终表述
跑题闲聊 如果有信息量则保留,纯闲聊删除
有力量的原话 保留原文,加引号

信息密度控制

  • Markdown 纪要:保留全部细节,宁多勿少
  • HTML 信息图:提炼精华,每张卡片 2-4 行文字,用加粗突出关键词
  • 信息图是纪要的"可视化摘要",不是完整替代

TODO 提取技巧

会议中的 TODO 经常是隐含的,注意以下信号:

信号 示例
直接分配 "这个你来做" "小王负责"
建议变承诺 "我觉得应该..." + 无人反对
时间节点 "下周之前" "月底前"
问题未解决 讨论了但没结论 → 变成待讨论 TODO
自我承诺 "我回去整理一下" "我来写个文档"

如果这些信号都不明显,不生成 TODO。社群闲聊里的“可以继续聊”“以后可以做”“有机会看看”通常只是方向,不是行动项。

金句筛选标准

金句不是“听起来顺”的句子,而是能代表观点强度的原话。

优先级从高到低:

类型 判断标准
犀利判断 说出了利益格局、行业分化、信息差、护城河、风险等关键判断
反常识 和普通预期相反,能让读者停一下
个人边界 明确表达价值观、选择、拒绝或原则
方法论 能直接迁移到行动或思考框架
温和说明 只解释功能、流程、体验,除非非常准确,否则不放进“锋利金句”

不要把“某工具对我有什么帮助”这类普通体验句当作犀利金句。比如 AI 投研讨论里,关于“公开信息被抹平、除付费数据和内部机密外已没有信息差”的判断,比泛泛的“最终投资决策回到个人内心”更适合放在锋利金句区。


标签颜色选择指南

用途 推荐颜色 class
人名(默认) 珊瑚 无(默认)
技术/工程 .blue
运营/增长 绿 .green
风险/警告 .red
重要/紧急 琥珀 .amber
产品/策略 .purple
中性/状态 .gray
正向/积极 .teal
方法论/原则 珊瑚(默认)
优先级 P0 红底白字 .p0
优先级 P1 琥珀底白字 .p1
优先级 P2 蓝底白字 .p2

适用场景

场景 适用度 说明
团队会议录音转写 ★★★★★ 最佳场景
1对1 面谈记录 ★★★★☆ 适用,板块会少一些
电话会议/线上会议 ★★★★★ 适用
演讲/分享录音 ★★★☆☆ 可用,但结构偏线性,卡片效果一般
已有结构化纪要 ★★★★☆ 跳过 Step 2,直接生成信息图

故障处理

问题 处理
docx 提取失败 尝试 textutil(macOS 内置),不行则提示用户另存为 txt
参会人无法识别 使用原始标记(角色A/B/C),在纪要中注释"身份待确认"
会议内容太短(<500字) 简化板块,3-5 张卡片即可
会议内容超长(>10000字) 分议题归类,信息图只取最核心内容,纪要保留全部
多语言混杂 保留原文语言,不强制翻译
PNG 点击无反应 用浏览器控制台/Playwright 复现;常见原因是 html2canvas CDN 未加载、canvas 被本地图片污染、浏览器拦截大 data URL
报 Tainted canvases may not be exported 把所有本地图片转成 data URI 内嵌,重新点击验证
用户说标题不对 检查是否误用了转写文件名;优先使用海报/主持人口径/用户补充主题
用户说内容太单薄 回到逐字稿补充真实人物、项目、观点和分歧,不要加空泛总结

Skill 版本:v1.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment