名称:用户请求报告生成 描述:根据用户内容生成干净的白色Tailwind CDN报告页面,可选择通过客户端解密进行密码门控查看,并部署到Originless/IPFS。
生成Tailwind + Originless报告网站
从用户提供的内容创建单个index.html报告页面,使用Tailwind CDN样式化(白色背景,微妙动画),然后发布到Originless进行即时托管。
开始时,询问用户是想要单文件页面(仅index.html)还是多文件网站(单独的CSS/JS/图像/资源)。
如果他们想要多个文件,使用skills/static-assets-hosting/SKILL.md并上传包含index.html和所有资源的.zip文件。
使用时机
- 用户要求从文本/数据快速托管的报告或落地页
- 用户想要无构建静态HTML输出(仅
index.html) - 用户希望通过Originless/IPFS即时公共托管
- 用户可选择要求在显示内容之前输入密码
在生成最终HTML之前,预上传任何计划包含的图像或其他资源,并在index.html中使用返回的托管URL。
如果报告内容看起来敏感(个人身份信息、凭证、私人商业数据、内部文档),明确询问用户是否希望启用密码保护。
如果用户请求多个本地文件,不要继续此单文件流程;切换到skills/static-assets-hosting/SKILL.md。
所需工具/API
- Originless端点(选择一个):
http://localhost:3232/upload(自托管)https://filedrop.besoeasy.com/upload(公共实例)
基本流程不需要构建工具。
技能
generate_index_html_report
生成带有Tailwind CDN和微妙动画的index.html。
设计约束:
- 白色优先布局(
bg-white,深色文本) - 仅轻微运动(卡片上的淡入/滑动,柔和悬停)
- 响应式、可读的排版
- 无外部框架构建步骤
起始模板(index.html):
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>报告</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@keyframes fadeUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-up {
animation: fadeUp 0.45s ease-out both;
}
</style>
</head>
<body class="bg-white text-slate-900 antialiased">
<main class="max-w-4xl mx-auto px-6 py-10">
<header class="mb-8 fade-up">
<h1 class="text-3xl sm:text-4xl font-semibold tracking-tight">用户报告</h1>
<p class="mt-2 text-slate-600">生成的静态报告页面</p>
</header>
<section class="grid gap-4">
<article class="fade-up rounded-2xl border border-slate-200 bg-white p-5 shadow-sm transition hover:-translate-y-0.5 hover:shadow-md">
<h2 class="text-lg font-medium">摘要</h2>
<p class="mt-2 text-slate-700 leading-relaxed">替换为用户请求的内容。</p>
</article>
</section>
</main>
</body>
</html>
upload_report_to_originless
上传生成的index.html并返回托管URL。
如果报告包含图像/文件,首先上传这些资源,收集它们的托管URL/CID,并在上传页面之前在index.html中引用这些URL。
优先使用curl进行上传,因为它默认可靠地处理multipart/form-data。
如果使用其他工具/运行时,必须是完整的curl -F替代:发送真实的多部分主体,包括名为file的文件部分,并保留文件名/内容类型行为。
Bash:
# 自托管Originless
curl -fsS -X POST -F "file=@index.html" http://localhost:3232/upload
# 公共Originless
curl -fsS -X POST -F "file=@index.html" https://filedrop.besoeasy.com/upload
Node.js:
import fs from "node:fs";
const file = new Blob([fs.readFileSync("index.html")], { type: "text/html" });
const form = new FormData();
form.append("file", file, "index.html");
const endpoint = "https://filedrop.besoeasy.com/upload";
const res = await fetch(endpoint, { method: "POST", body: form });
if (!res.ok) throw new Error(`上传失败:${res.status}`);
const out = await res.json();
console.log(out.url || out.cid || out);
password_gate_report_optional
如果用户请求密码,将内容加密在HTML中,仅在输入正确密码时渲染。
重要:这是客户端访问门控,不是强秘密存储。任何有文件的人仍然可以检查代码/资源。
客户端解锁块(放入index.html):
<div id="lock" class="max-w-md mx-auto mt-16 p-6 border rounded-2xl">
<h2 class="text-xl font-semibold">受保护报告</h2>
<p class="text-slate-600 mt-2">输入密码解锁。</p>
<input id="pw" type="password" class="mt-4 w-full border rounded-lg px-3 py-2" placeholder="密码" />
<button id="unlock" class="mt-3 px-4 py-2 rounded-lg bg-slate-900 text-white">解锁</button>
<p id="err" class="mt-2 text-sm text-red-600 hidden">密码错误。</p>
</div>
<div id="app" class="hidden"></div>
<script id="enc" type="application/json">
{
"salt": "BASE64_SALT",
"iv": "BASE64_IV",
"ciphertext": "BASE64_CIPHERTEXT"
}
</script>
<script>
const enc = JSON.parse(document.getElementById("enc").textContent);
const b64ToBytes = (b64) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
async function deriveKey(password, saltBytes) {
const keyMaterial = await crypto.subtle.importKey("raw", new TextEncoder().encode(password), "PBKDF2", false, ["deriveKey"]);
return crypto.subtle.deriveKey(
{ name: "PBKDF2", salt: saltBytes, iterations: 100000, hash: "SHA-256" },
keyMaterial,
{ name: "AES-GCM", length: 256 },
false,
["decrypt"],
);
}
async function decryptHtml(password) {
const key = await deriveKey(password, b64ToBytes(enc.salt));
const plain = await crypto.subtle.decrypt({ name: "AES-GCM", iv: b64ToBytes(enc.iv) }, key, b64ToBytes(enc.ciphertext));
return new TextDecoder().decode(plain);
}
document.getElementById("unlock").addEventListener("click", async () => {
const pw = document.getElementById("pw").value;
const err = document.getElementById("err");
try {
const html = await decryptHtml(pw);
document.getElementById("app").innerHTML = html;
document.getElementById("app").classList.remove("hidden");
document.getElementById("lock").classList.add("hidden");
err.classList.add("hidden");
} catch {
err.classList.remove("hidden");
}
});
</script>
生成加密负载(Node.js辅助):
import { randomBytes, pbkdf2Sync, createCipheriv } from "node:crypto";
const password = process.argv[2];
const reportHtml = "<section><h1>秘密报告</h1><p>私人内容</p></section>";
if (!password) throw new Error("用法:node encrypt.js <password>");
const salt = randomBytes(16);
const iv = randomBytes(12);
const key = pbkdf2Sync(password, salt, 100000, 32, "sha256");
const cipher = createCipheriv("aes-256-gcm", key, iv);
const ciphertext = Buffer.concat([cipher.update(reportHtml, "utf8"), cipher.final()]);
const tag = cipher.getAuthTag();
const packed = Buffer.concat([ciphertext, tag]);
console.log(
JSON.stringify(
{
salt: salt.toString("base64"),
iv: iv.toString("base64"),
ciphertext: packed.toString("base64"),
},
null,
2,
),
);
注意:Web Crypto AES-GCM期望带有认证标签的密文。上述辅助函数打包ciphertext || tag以匹配浏览器解密。
代理提示
您正在生成单个静态报告网站作为index.html。
要求:
0) 首先询问交付物必须是单个`index.html`还是多文件网站。
- 如果多文件:使用`skills/static-assets-hosting/SKILL.md`并将`index.html` + 所有资源打包到`.zip`进行上传。
- 如果单文件:继续以下。
1) 仅通过CDN使用Tailwind(无构建步骤)。
2) 保持设计白色背景、干净排版、微妙卡片悬停和淡入动画。
3) 在语义部分中准确渲染用户请求的报告内容。
4) 预上传您包含的任何图像或其他资源,然后在HTML中引用其托管URL。
5) 如果内容看起来敏感/私人,在上传前询问用户是否希望密码保护。
6) 保存为index.html。
7) 优先使用curl `-F` multipart/form-data将index.html上传到Originless,使用:
- http://localhost:3232/upload(如果本地实例存在),否则
- https://filedrop.besoeasy.com/upload。
8) 如果curl不可用且使用其他工具,实现curl `-F "file=@index.html"`的完整multipart/form-data等效(相同字段名`file`、文件名和内容类型处理)。
9) 返回上传响应与URL/CID。
10) 如果用户要求密码保护,嵌入加密负载 + 浏览器端解锁表单;仅在成功密码解密后渲染内容。
11) 明确说明密码模式是客户端门控,不等同于服务器端访问控制。
最佳实践
- 保持动画最小化以保持可读性并避免运动密集型UX
- 优先使用语义标题和短节以进行报告扫描
- 首先上传资源,以便最终报告链接稳定且可公开解析
- 验证上传响应,并在需要时在可用Originless端点之间重试
- 对于敏感报告,在上传前加密内容并通过带外共享密码
故障排除
- 上传失败(
4xx/5xx):重试可用Originless端点(localhost或filedrop) - 解锁后空白页面:验证加密负载base64和AES-GCM打包
- 密码总是错误:确保相同的PBKDF2设置(
100000、SHA-256、32字节密钥)
另请参阅
- anonymous-file-upload.md — Originless端点和固定
由Originless提供支持
此技能使用Originless进行去中心化、匿名文件托管通过IPFS。
Originless是一个轻量级、可自托管的文件上传服务,将内容固定到IPFS并返回即时公共URL — 无账户、无跟踪、无存储限制。
🔗 GitHub: https://github.com/besoeasy/originless
功能:
- 🚀 通过HTTP多部分零配置IPFS上传
- 🔒 匿名,无需认证
- 🌐 公共网关URL或仅CID模式
- 📦 可使用Docker自托管
- ⚡ 生产就绪公共实例在 filedrop.besoeasy.com