用cf works部署一个"阅后即焚毁"服务
用cf works部署一个"阅后即焚毁"服务
直接上代码
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
if (request.method === 'POST' && url.pathname === '/create') {
return await createDocument(request);
} else if (request.method === 'GET' && url.pathname.startsWith('/doc/')) {
return await getDocument(url.pathname.replace('/doc/', ''));
} else if (request.method === 'POST' && url.pathname.startsWith('/delete/')) {
return await deleteDocument(url.pathname.replace('/delete/', ''));
} else {
return new Response(renderHTML(), {
headers: { 'Content-Type': 'text/html; charset=UTF-8' }
});
}
}
async function createDocument(request) {
const { markdown, views, expiration } = await request.json();
const viewsInt = views ? parseInt(views) : null;
const expirationMs = expiration ? Date.now() + parseInt(expiration) * 60 * 1000 : null;
if (views !== "" && (isNaN(viewsInt) || viewsInt < 0)) {
return new Response(JSON.stringify({ error: '访问次数必须是非负整数' }), {
status: 400,
headers: { 'Content-Type': 'application/json; charset=UTF-8' }
});
}
const id = generateId();
const data = { markdown, views: viewsInt, expiration: expirationMs };
await works_data.put(id, JSON.stringify(data));
const link = `${new URL(request.url).origin}/doc/${id}`;
return new Response(JSON.stringify({ link }), {
headers: { 'Content-Type': 'application/json; charset=UTF-8' }
});
}
async function getDocument(id) {
const value = await works_data.get(id);
if (!value) {
const errorMessage = encodeBase64('不存在或已被焚毁。');
return new Response(renderHTML(errorMessage, true, 0, true), {
headers: { 'Content-Type': 'text/html; charset=UTF-8' }
});
}
const data = JSON.parse(value);
if (data.expiration && Date.now() > data.expiration) {
await works_data.delete(id);
const errorMessage = encodeBase64('文档已过期。');
return new Response(renderHTML(errorMessage, true, 0, true), {
headers: { 'Content-Type': 'text/html; charset=UTF-8' }
});
}
if (data.views !== null) {
data.views -= 1;
if (data.views <= 0) {
await works_data.delete(id);
} else {
await works_data.put(id, JSON.stringify(data));
}
}
const encodedMarkdown = encodeBase64(data.markdown);
const remainingTime = data.expiration ? Math.max(0, data.expiration - Date.now()) : null;
return new Response(renderHTML(encodedMarkdown, true, data.views, false, remainingTime, id), {
headers: { 'Content-Type': 'text/html; charset=UTF-8' }
});
}
async function deleteDocument(id) {
await works_data.delete(id);
return new Response(JSON.stringify({ success: true }), {
headers: { 'Content-Type': 'application/json; charset=UTF-8' }
});
}
function generateId() {
return Math.random().toString(36).substr(2, 10);
}
function encodeBase64(str) {
return btoa(String.fromCharCode(...new TextEncoder().encode(str)));
}
function decodeBase64(str) {
return new TextDecoder().decode(new Uint8Array(atob(str).split('').map(char => char.charCodeAt(0))));
}
function formatRemainingTime(ms) {
if (ms === null) return '不限时';
const minutes = Math.floor(ms / 60000);
const seconds = Math.floor((ms % 60000) / 1000);
return `${minutes}分${seconds}秒`;
}
function renderHTML(markdown = '', isDocPage = false, remainingViews = 0, isError = false, remainingTime = null, docId = '') {
return `
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>分享你的文档</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAIABJREFUeF7tfQuUXMV55ndvd89bmtGMNDN6owcgsIRkxNMoBttgm6whBic4WRszLRY2QTNeo5Hwnt3Nxsme7FmMRjpmRs6xE+ixSZzdJDZZx8bZEBscJB4CjJAl9AAh0BsxGs1D8+rue+/6vz2t6Ud136q69/ZjVOXD0Tmeevz11f36r7/+v/7SoIpCQCGQEwFNYaMQUAjkRkARRH0dCoE8CCiCqM9DIaAIor4BhYAcAkqDyOGmWl0kCCiCXCQLraYph4AiiBxuqtVFgoAiyEWy0GqacggogsjhplpdJAgoglwkC62mKYeAIogcbqrVRYKAIojEQm/ZELlN1zDHstBsamaDRBfTsomu6UcDuv7a1751357pMkFFEM6V3NL+xO0a9NuhoQ0WZnA2uziraVofLPNF08L/3Lx9/SvlDIIiiMPqbWvvvcmE1QHgi+W80MWS3YT5p5t77v9GscZ3O64iSB4Et2yIfFPTsNktyKq99nRnT9vd5YiDIkiOVdvaEfmxZeGOclzUUpTZMM3PPPLt+/+lFGXLJ5MiCAOdre2R5yzglnJbzBKX90QgEF/7tW898EGJy5kmniJIxmrJkKO6JrS7WIteURWsY40dHY+fF5UpV188/dB40ZjRZMTMhbnqW5bVtWn7+k08/ZVKHUWQlJWQIQc1v2v9aixYUvjTXk0PIBiaCWhTy2gaURgxYW5AD1QiEKoV/i5NYwJGbORCu5GhKH74xBsY7B/P6ksDfrGxJ/wp4UGK2EARZBJ8J3I0rlyG/r2HmUtVHIJoCFbOgKYFL8hkWXHEJ4aEPyfqI1g5U7idZRqIRwez2r37Vh9++rf7WP0NdPaEZwkPVMQGiiAAnMjRfONKtN54FfZs/UHJECQQqoMeqEiRx7LJYVmG4OdERJsJTQsItss93uj5KJ549CVmfxZwxaae8AHBwYpW/aInCC85aIVKhSB6sBqBYHXaR2NEh2GaMeEPKVBRB11PJRpfF7Stou1VrtL9x79k/skEPrG5J/w83yjFr3VRE8SJHC03rgL9lyylQBDSGqQ9UothjMGMjQl/TUQyIptoMeKjMOPZNkZqP4ogoqiWWH1RchRWg9DvlpWFGG2DghUZRrkZhRGVMMr1CpD2EC28hwCKIKLIllB9GXIUkiCB6kYYY/1ZiBE5ND3FKM9hJDtBbRPNNsrFNhAJo5wOAbLJmzmmIojTKpTo32XJUSiCEDn0ynrEBt8HLPMCinQES0exqSU+MShulFtAsIqM8imi8S4VkcMy41zVFUG4YCqtSm7IUSiChBqW2KCZsVEYIwmnM8tHQb4O2u6IFhbRePoQHU8RhAfVEqrjlhyFIEhSeyRhiw8ds7dBwYr06HoykMlQFi16sAqBYI1oM5jGOIyY2HiKIMIwF6+BF+QoBEGS2iOJlEUaIno+zUdBR7l0pCtadD2EQAbRePogGeISnnlFEB50S6COV+TwkyBaqAbB2ma20WwaAP16W6Ztb9hGsuVsJKdCnzDKSQvpQitiWWbCUy44Hg2iCCIEdXEqe0kOPwiih2oRqG4iI8MZIIqxGj1rb3dEC23RND0k2swmI69Rntm5Iogw3IVt4ESOZPiIiFReOQp18l5XzUo7suWVw4yehzl+jvvDlTfK83vKneRVBHFCqIh/94McfmiQQNUs6FV8UcBkCxhEDAFjWQ9WIhCUiNCVPARIXXJFkCISIN/QfpHDD4Ik5xGomQPSKrmKMXYWpmCUrqaFJu0OsYWiLVXCGShfKBzmW//lWWYHKhZLHlfXLf0kh58ESU488xSLjOPY4FHyighhQ0Y5nVhpmphRTh7y+MQALAmjPCmgHTpfMQNbH/lHRRChVfO5st/k8JsgduBg1SwgOOUtN0ZOSwUhZoak8EIfjw7DkogIvtC/piEYogOBILZufloRhBd4v+sVghx+EiQtQreq3oaLbI34pCddBL9AqAZ6oEqkiV2XJ0LXqdPUAwFFECe0CvT3ro7Iz2Dhs7mGkzmtytWXV6dYqf3Tr23CUz4ZOBissrVIfOgoKDhQpOh6JQIVEkZ5xrVZkTGTdfVQNQKBqdB5RRAZFD1u81j7E9/Qof9JIcjhiwZJ2ZIk50BGsqUH7BMrkUJ+jsyQFJ72tvNxIvvaLE/bC+QIhBAIpYfDKIKIIOhD3UKTww+C0EelB1IceJaFeIycc2SUi3jL6dpsvbhRTuORM1D4mu7Ugmq6jkCIxk4PnVcE8eGj5+1y60NPLbf0OOV8bWS18XJblex//OwgDn3vp0wR13/9RtTWiV1bZV2blTWS6cSKYq1EixEbhmmIX9NNoQeCFXVML70iiOhqeFi/qz3yOADKl5tVmq5ajvm3XufhaImujv/8VfS/+XZWv/WNVfjKw9cLjUd3wDNv88kayfLXZsdgxsWv6aZOlCKDKUKYVRRBhD4J7ypv6XjySs3SmDllZi6bj9lXX+HdYABig+cx1ncOfb86yOz30lXN+Ow9/GPauazo2mzKbb7M3FK8E5DPZRUDaQ83xWlsRRA36Lpo62R7uOhaqultX1iBFWta+NqSUW478LzKZZVy+sUngR3DZefOErttm9Y7z4GAIgjngnhdras9shfAR7zuV6a/q9ctxE2fWcrdNCtwUNpIls1lBTt8XfT4OHWC5J1PeOnzRyArgnB/Ft5VfOze79fq9YZ4Cg/vREjrqeN/3MzdMznvyImXWkSvsSbbFitCl8bnDZ1XBOH+NLyruO0PI5eYQRzxrke5nkIVOj7fthqtC/nSdbJu8xlxOSM50yHHOwPZa7qp/Yt46RVBeFfGw3pbHopcq+nY5WGXwl1d8dFW3Hr35dztWLf5pI1yn3NZ5ZuUk1Ge2VYRhPsT8a7iY+2RW3TgOe96dO6prr4ScxfVo3leHZpaarH4UqbrJWdHzFxWMbrG6jx22t4/MySFs7l9bdb2lAsOmNJ/VjgMx9iKIBwgeV0lH0FE7AGv5crVn2e5rOzMJmyHnNNcbM+8wZfLitmXriMYpAhdjmvBKR0ogjitjA9/LyeCsFLsUIpQ05TJZSUZoRsblbrDnm53ZGaR51tYRRA+nDytVS4EYfkJZI1k6VxWHlybzecpd1pYRRAnhHz4ezkQJOEnoNSeU7f5SGvIJJjmccixYKZLTxTX5aaIGuXKSHeDtkdty4Eg9o26lAjdRDg5X8LnNKMcOgL2wzai12ZNxGi8lLy+ovAnXpwS99KnjqM0iCjqHtQvdYKwAgdlPde8DrlMWGUjgqf6mQyHSckiL7N0iiAyqLlsU8oEYd3mM+IjMOO5X2ESOf3igc7p1SeePrKfduNplV1HEUQON1etSpUgCT9BulddJuEzgSNtlHtxbZbxtJvsgimCyCLnol1JEsS+NlsPulmXLLIJn+WNcg9yWUl66XMtpyKIiw9dtmkpEiRzS2Ib5XTXwr42y194o2Sze5R93TbF6tCD9ruH4gcCueenCMK/9p7VLDWCUBYPCh5MLbIJn+Wvzco9pJMqs+yBQL6FVQTx7LPn76iUCMJ+9Uku4bNIlGwqWrIRwal9yI7ttGqKIE4I+fB3Pwhy7PAAzpwYghEXCObT9Kz3Au10PRJZCSnGScvxTnlVTQiLljejqTU9pQ5BmxkRLDMPOlzI9SxCMKSjZeEsLFo+R2olFUGkYHPXyGuC/MN338CpY+4SNbubEV/rj336Ctxw24qpQ4AM56Of81h06Rz87oPr+ARNqaUIIgyZ+wZeEuTI/j785AfM3A/uBfWhh44/vxOhigCgaYiPU4LpRNbFQszjCw/chMWX0QtY/EURhB8rz2p6SZA3dh7Hjn8+7Jlsfnf05Yc/ieZ59ci8pluIedx85yqs/a3lQlNUBBGCy5vKXhLkwO4P8OwPD3gjWAF6eeC/fRa1tZRkOj2XVSHmcfsfrMUVVy8SmqUiiBBc3lT2kiAT43F8f9sujI+6ySzozbycell65Vzced9a5uu2fs+jrr4K4c23IVQ5larISV76uyIID0oe1/GSICTaub5RvPDMYcRj+Z16idt0qYmkLLnUOZrmmC4nE7KGplrc/DsroSPx0i2rcM1DYuyKyiBuuXMVGmbnfv0q1xIrgnj88fN05zVBeMbMvjYr6bnW9MS12ZSkcTzjUx1Z52Oyf3kvPa+E2fUUQeSxk25ZaIIwc1lJX5utzfKd8ADhSYQuvaqbw9fCI4NMHUUQGdRctikkQehZgsw3L2QTTLOIxgOFbERwat+yya155MtXRxHELYIS7QtFELI5AnYmj5Rrs5Lh5KykcTxTt6zJHLo8lXPUcXtt1sXQykh3A55s20IRJDN4L/E0Mt3xFghHIbNeC0xeXRW7NksP6MTt3Fli46Xiat9RoVefMh62kcVetJ3SIKKIeVC/EARhZfKQNZJlo2TdX5udPBBweW3WzZIpgrhBT7Kt1wR571A/Xv+3ozhzYhjxuNj9DckpFLQZHc+u+OgCUCxXoYsiSKERB+AlQQb7x/H9bfSK2/QvH//cSlxz86UFnagiSEHhTgzmJUH2vnoKz/34UBFmUfghFy6bjd/7w98q6MCKIAWF23uC7H7xOF74WfkEK7qBe868etz78CfddCHcVhFEGDL3DbzUIKePDeHvv/uGe6HKoIfVH1uKT921uqCSKoIUFG7vNQj1+MIzR7D7paNFmEnhhmxqmYl7/mgdqmsrCzeoClb0HutvdvQu0yzjXl3TZ8NCqwY0sUaxgFtY/7/o8wfJXFanjvZfCFa0KIdufFx4cuQMpHfPRQtd0c0MXxftg5yB9F+uMnfRLARDYk8XiMrAqp9Lg2jA8+x11Y7Dsl63gH2btoef9UIGL/pw8dapF8MD33nwOzXDFRVdOrQvW7DEw0YnxRAhiKZpdhgJkSRZTEPuaWT5XFaG/aCmmyLrpXczJm/bXAThaU8kMmD+9eae+5/gqe9nnaISZMuGv1qsa4HeXFpBZOIiBMmM0LVgwJgYBr3GJFIoFCURkiL6C23Znnny0MsWOxyGXpuFmJdedjzRdm4IkhxL0/DUxu7wV0TH9rJ+0Qiy7WuRBiuO5yxgjRcT4iUIO5cVfaziF6cCklGysg/pXMDJgh3CkisjiWs8g1WAxFYzdVwvCEL9kTbZ2BP+hOs5SXZQNIJ0dUS2wcLXJOXOasZDED1QYWcQTC2y4eSyUbJmbAyGkX5tVhQDv3JZ2XLQ++eVdcC4u+2fVwRJyKQ91Nnd9heiOHlRvygEeeyhyB26jh97MYFkH04EYQXvSb/6xCAaz1xMI2onXXBTZJNbc49ZUUsZtIHYGGCIPxeXHMdTglAeMBN3bv52+J+45+FRxaIQpKu9958A63O55qAFdVTW1zD/PH6W/YHlJ4iOYGX6bb7kK0zCCdfspHEVGVdwOVbDMmGaE6IBwRc6DlUGMO+SRixYNl98bA7x7Cr08E9oEnfTAKLyZM5FkPpLW5nSxIbGQGtrxhPpjLKL9pPOnrY7eKfiVb2CE6SrvfdOwPq/rAkEKkNoXLkQNa31OcnxwctvM/+WjyDZCaZNGBPkKHy9LBLHpU545bWL8el7rvZq/RP9kMYIVgB6KLtfet9Ewh7JRZCWGy5FVRP7sDI2OoFz+45j7EyuZH7a73T2tHm683ACsggEifwUwG+zBJu77nJU5NAcVJ9+YUQJQv4JshdSixEdxuF9p8oqcVyq/OFHbsOsOdIn4lNd0fNuwUrA1ogORZAoMgQhCeLjMZzecQDGBPOE75nOnvC/cxLVy78XlCBb2iOf14CnWROYsagJjavy514SJYgerEAgmGGUx8dgxsdQiIRrXi5Ual933ncDlq+c6133RBTaWrGOqwWJkRRKliDUfuDQKQy+fZo5Pwu4a1NP+B+9m3z+ngpKkK3tvc9YsG6X0R6iGiThKSdypL42OwEjOmIPX4iEa34t4hcf+jjmL2EGGrgbkrZYFZM2CPmEJuRfynVDEGMihlMvsLWIBu1nG3vamDsQd5Nnty4YQbZ+9Xt3Wab5I1ntIUaQ7Ico7Wuz9LDN5DVWvxOu+bFY1CelH/3Sf/oENN2npUueYklqDi80iJMW0XT97o2P38fciXiNu08oZ4vZ1R75ZwCfkdUeIgTJzmVlIh49n+W55km4lp00jm8J7OTSLu6U0yiZY9fMqMQnP38Vauqq+ISQqZX0g9hPScvfiXejQUjs+FgUp3cezGWL/L/OnvBnZaYn2qYgBOlq7/0CYP2DG+3BSxCWnyAz4TMvSLIOOdn0QKlyefXaLO9c0+rRq1nkB3FR3BLE1iIHT2LwnQ9ySKH9bmdP2w9diMjVtEAEifwLgNvcaA8egjA95ZNGORcaKZWkc1nFx0EEcVPoWTcKiSlaIaNdMC4tU1YvCEJa5NSOgzCjzBOtZzt7wp/2GyPfCdLVHvk9AH/nVns4EeSrf/6prIcoM19h4gWTRTSeton0QO4e5ClmLiueOfLW8YIgzloE93T2hP+eVyaZer4TZGt777MWrFvdag8ngjz86OfSgvfsxGuUy0pwH21HyYZmgkLixYqF+PgQKDJYttgnb3QsnZKwTravYrfziiC2FnnhIMxYthbRoP3rxp425s7Eq/mLfgVC4279au89lmn9Hy+0hxNBNj5219QwlmWfWImHk9PpV51UlGw8dh70Prp8yT55k++r+C29IoitRQ6cxOBhti2i6doXNz7extyheIGCvwRpj/zcApjZApy85qzJ5XMUphJE2igP1oCMfNFixEZBeXTdlOyTNze9FbctneBte4QdEZIv1CSX1PHRCZzacSiHFsEvNvaEP+XXjH0jyNYNkd+3NPytV9qDV4OQl1zmGqvs3l80QjdQNQvG+Lk0WGQPBPz6KFz1awHx2BAe/68/Z3YjQ5CEFjmBwcNnmH1qFv5g4/bw/3Yld47GvhFkS3vkud9cdmHeH5fRHjwEEf1Yk5gk76eLAky/lPEJ/nsTgepG6JX1iA0cuTCU7IGAqKyFqk+RChS13P3Hv/SUIPGRCZzaSbZIto33mxupz2/y6VKVLwTZ2h759xbwNyyE6hbNRtOqhVLrlW+L9fCjd8Agu0PUKNfo6iqFwgtemyU7Jzp04bVZngmFGpbY1cyJIRhjZ+0xpcbmGawIdVKfa/CaIDSdc/tPYOjdHFoE+NLGnvAPvJ62LwTpao9Q5oqbWcLKag8nDULHvOJGOUV5y11dFbVzAjVzoNuxYYkSGzxin1hpPJG0Xq+6D/0l79cku/aDILYWoRMtg3lS+MvOnjBzx+Jmup4TZEtH75c0y/prpvZY0Iim1Yul5RWN5nUaSNZTLnMTMak9kjJZ8XFoFO80DQolu0hsNadCU/wgCEE1sP8EBnNoEUvTvrypu425c5GF2XOCdLVH/g0AMxGsG+3hpEGcrtxmAlQoo5zGDdQ2Qw/VZq+Ry3vfsovudTu6X2NmJL3wiyCx8+M4tfMQLPbNwxc6e8If93J+nhJky4bIvZqG77MErJ3fiNlr5LWHlwRJGOUzhK+uyj6kk6k9LuBjxICYu7AULz8Gmb5yHXH7RRCSsf+t4xg+8iFTXMvCVzZtDz8lMxdWG08J0tUe2QHgJtZAbrWHVwRhJY3jBTM+QUY5fy4rImKgtiW/nUHXWct0q5UvlMdPgthaZMdBWAYzj9nOzp7wOt41darnGUG2bHjyPk3TelkD1sybhTkfvcRJFse/e2GDyDrkRNID2cSomQ1NJB2pyywijuB5XMEp7sxPgtBUzr11HEM5tYjVtmn7+u95MWXPCNLVEdkJCx/zS3t4oUFYz6vxgMj72iwRQ6+alXZaxdN/Wp2yIAq9FT+Q90jdb4LYWuSFg6D3HLOKhhc7u8PMnYzoenhCkK6OSBssRJi2R+sszF7rXnu4JYisUU7xVRRnla94QozUASjUnLZdrmK7RD8F/vo8R9x+E8S2RfYdx/B7bFsEGsKd3WHmjoZ/pnZmR/elqz3yEoAb/NQebgiiBSajZOmeg0Cxjy8pwbSD81ELhBKag3VSJTDehao0HtkmJUgQ3iPuQhAkOjyG0zsOsbUI8HJnT/hGGfhT27gmSNeGyHpoYGbhrmmpx5xrlrqV8UJ7KRtEm4yS1aYyufMKJPraLBElUN0kZntkClPCRrtJz0NwJpMrBEESWuQYht/rYy+phfs7t4ef5F1vVj3XBNnaHnnZAq73W3vIahBpozw+Cvq1lCk2UWqaxbzkLpMkyMgp0sZ+uz06wN2kUASJDY/h5I6DgJl9f14DXtnYE2bubHgn4oogW9t777dg/RVrsOqWejR7qD1kCCKbx5Z3G5EPZDu5NW25KI1OvjivEidGco4Jo5z/eYhCEcRJi2jQ/sPGnjbpd0ZcEaSrI7ILFq5lao+bLkNFA8N7zEtdRj2RLZZslKzT8SWP+FkHAlXsVKq2jeEyOQKPPG7r8BjlmWMUkiDRoTHbL8K0FTW82tkdvk4WA2mCdHVEHoCF7zK1R/NMNF+7TFamnO3oaO/kL/dn/b12ZgXWb56yxyhKNlg5U9hTDlBMETkD+X8pM4VhZZEHZQlhBSWWQaiJrDb9m+5X0X8mO0pg/ic+gmANR6pTwa+nf+9xDL+f80Trwc7u8F8KdmlXlyfIhshr0LCWNWjrjZehstFb7ZEch34pooPpwF+9biFu+kzyMED+6qqoUZ41d01HMERXdhkHAplapAy2VpkRuiIf2N5XT+K5H6cnGvf60CZVnujQqO0XYRYLr3duD18jIn+yrhRBtnU8eatpacyHFqtnz0Dz9ctlZOFqMzEwgsFDp0HGWXVVAC0LZuD2L155oW0xjPLk4Hmjg+kqLyWKTpYS1x50ryY+kX7zkWuBUirtfvEEzvWN4PipMVjVVWi4zMN8wgxhzv76GM4fZZ9o6Zp128Pd6/9VdA5SBOnqiPwvWPg6a7CWG5ejqpECAf0vd95A26ipInt1VfYmYtrYjCzyWQgktUgZaA9Rozzfau98awRnh+SzvfB+SbSzsG0RVtHwaGd3+D/z9uVKg3Tl2F7Ruw9057hQJZUgsi++emKU6xX2zUDHktQiJa49ZIzyUiAIydD3xnsYOcnQfJLbLGENsvXhv6u2YiPMGO2GFfNQv6zF8TvxqkKSIPZrs/Sss+i1WXjw2qwWnLw2y+ml9+CBTK/wY/Uja5SXCkGIHEQSphIJ1dZs3HaPUE5VYYI89kd/eZUeCL7JEmDBrStBr0QVqiQIIp/LyvVrsy7GLhRGIuOIJqHg7btQWyyShxLMnfjFW5YZN7K+bdOIr978Fw/s4ZWb6gkTZEtH5G7NQlbSYCIGEaSQhQgia5TLpgdKnZ9sdHAhMeIeywJiE/3c1UUqFpIgJNcHr7yD8b7st00sDV/Y1B1mPsGRaz7iBGnvfUSD9Whmh5UNtWi96TIR3FzX/fy6ZtBHKlpEYopy9c162k1UjlKqT3fK7ScbfCiFJsi5/Scx9G52JkYL2tc39bR9U2SKwgR5rP2Jb+jQ/0RkkHKoW1kVxNxFM9E8fwbmtNZh6ZWzc4qdOBAgo1wYvqJC8eHJQZw6eg5nPxjC6aPncOqoPxqjqJPMM7gJ808399z/DRH5hFd4uhIkE7QFSxqw5mMLsGRF+lNn9m1BcgYKhs6LLIofdffueh8vPLMPYyPTI5OKDEaKIDKoObS5fHULrrl5IRrn1NoKgx4FTbyTXj7l50+/iTdffLd8BPZJUkUQn4BtbK7B7b9/JebMmwNyRpZT+clTu3Boz4lyEtk3WRVBfIMWaGypwx33Xo+mlnTvvY9Duu5akSMdQkUQ159U/g6aWmfgc1++rixIosiRvZZFJUjTrBAuW1oHDRp0ep3J/i8hpMHOgufz5yzWfSxuYnA4hreP5E/kVg4kcSLHrPoQ5rdWYkZt4Zy6YqvBVzsQnEw4TpcJLQumZYH+986RUXzYn30YUVSCzGmsxLrrch+N8k25+LVOnB7Drt35jz9LmSRO5JjfWo2rVzUgGOAMjSn+kghLsGNXnyKIMGoCDcqVJDzkuG5NowAS5VlVEaQA61ZuJFHkmPooFEEKQBAaolxIosiR/kEoghSIIKVOktHz4/jF03vy+jnI5rgYtlWpn0RJEqSxIYjrrirMTcIC8sMe6vSHUezeP5J3WDLc5y5sRF1DdUHEOz8whtPHz6Hv1FDO8VrnVGDNFf7kBijIJCUH2bVnGP0D2Vn4i3qK1TBDx5oV5RWCIYL/h/0G9h2OiTQpat05jQF8ZFl5H+PKArj7QBQDw9mZaRRBZBHlbFcuJLmYyUFLqQjC+UH7Ua3USXKxk0MRxI+vXrBPUt/vnYgz1bhgV55WXzwvgCXzL85tVSqQSoN4+lnJd3bkRAzvn/TnFp6IVGT/XTI/CPpXFbXFKqlvIBazMDxq4vyohaHzJgoVdlZbrWNGrYYZtTpqq4XvvZUUhl4LozSI14iq/qYVAoog02o51WS8RkARxGtEVX/TCgFFkGm1nGoyXiOgCOI1oqq/aYWAIsi0Wk41Ga8RKDuC0NHnkeNx9A0YME0LDTMCWLIgiJoqvuPJofMW3jsZw+CwhYoKDc1NOpbM43+19vhpA6f6DIxPmKir1XHJvCBmzeTzGYxHLRw5EUf/YCK2p7Fex7IFIVRw+uP6B0y8fzqO8yMmqio1zGsOYn7z5FVRwS+jnOdBGJ7pNxGNWqifodl+m5m1fGswOpZYg4FhA7quYXZDAEsXBBHIAWPZEeTAkThO96VHV9I5/rUrnYMbiVyv7BlHLCM4c9nCIBa2OpPk9FkDB95NDzLUdeD6VZWorHAmKAvspnodqy5zln1swsIre7LvRl+5PITmWWIkKed5vH8ijiMn0xcwFNJww6oKBALOa/DyngmMT6S/Yju/JYBLF7F/pcqOIC/uHkeUEQh7w1WV9q9qvnJuyMSbB6NZVXijh/cfjuGD/mxv9xVLQmiZ7fCRWsDzrzGegtaAW9ZWOWYePfmhgUPvZU+8dXYAK5YreRFjAAAFGklEQVRwqqDJmZfzPH61fwK0C8gsFP3t5P0fHbew69fZPzJVFRpuWJ3yYldK52VHkOdfZb83zgMQ65eTsKiu1HD9VWyAUhciF1i0RVs8P78GmohaeOlNdqrOG1c7ayDWLyfJxkvu6TIP0qKkTTPLiqUhtDbl/5GiuDdaQ1a55Vp2Er+LiyB9Bg4cyf4VJs1DGsip5AKL7BDaB+crZH+8nIMg9OtFv2L5CgU0vpextfCaIOUwD9YWiXAgLUraNF9RBHEIsDutCGJ/P+VMdEUQh22Dqy2WIogiiNpi5VaySoMksFEaJPsbUTYIJUxQGkQR5GLVIB+9ogL1dfmdRWfOGngrw49BX0xNpYbrOIz0Nw9FcW7SyZf6G0SOysVzHU6xYhZe2p3jFGtNJSpD+Y3090/FbQdpZplVr2M1hx8ltV05z2PXngmMMk6xrlwaQrPDKdbgeRNv7J/mp1iv7ZuwLxRllnVXVyGZfzjXJuv8qInX9mUDRI42crg5lXeOxUAe6MxCjj5y+DmVnW9kOynJyXXTGucTtL5zBva+k30CRw5OcnSKlHKex953oug7l51l5NqVlY6XveKGhR2/yv6Rootia69kO2vL7pj37ICJX7+d/pEvnhfEEodj1uQHtO+dKD5MAZjCDQgcnpt0dFT72t6JtJt+In6Ik2cMHHo//SO/fEkIc52cjJPC/+qtKIZGpj6OUFDDdSsrQCQTKeU8j+FRC6/vS//IRZylh4/Fcex0uiZefXlFznChsiMIfQh0nj0wlPhQyIfhdP6d+fGcOGOArrdSaWnSUV3l/Ouf7IMcfqc+TGgRit/hCVFJHZ9+/UiTUaH4ocYG/rFNEzj+QRz0Lz0HMW9OkDuOKxODcp4H7SBIo1KhODaKSRMpFEs3MblNoy1qvq15WRJEBAxVVyHgBgFFEDfoqbbTHgFFkGm/xGqCbhBQBHGDnmo77RFQBJn2S6wm6AYBRRA36Km20x4BRZBpv8Rqgm4QUARxg55qO+0RUASZ9kusJugGgaISZMuG3gc1zfpO5gQo7INia1RRCBQbgVf3TmBkLDv2z7K0/7hpe9t3ReQTCwgCsOWrvWs103qNNcjaj1RiRo1wlyLyqroKgbwIsOK+kg0sXbtm0+Ntr4tAKPU1d3VEzsJC1ov0M+sSOafqanTpeCMR4VVdhUASAUoPRc9PUA4A+jeraOjv7A43iSImR5D2J38EaHeJDqbqKwSKh4D1dGfP+rtFx5ciyDc7epcFLOsd0cFUfYVAsRAwNG35I91th0XHlyIIDbJ1w/fusjTzR6IDqvoKgUIjoFn63Ru33/e0zLjSBLFJ0t77jAXrdpmBVRuFQCEQ0KD9bGNP22/LjuWKIDTolvZIhwb8GWX+kRVCtVMI+IDAgAX890094W43fbsmiK1JHnpqOQLxB2FpKy1Y11MSdDdCqbYKARkENIAyH+z8zQHSm5oZ+M7Gb9/r2k72hCCZkyHCGHp8gcwkVRuFgAwCuqYPdnbf94ZM23xtfCGI10Kq/hQCxUJAEaRYyKtxywIBRZCyWCYlZLEQUAQpFvJq3LJAQBGkLJZJCVksBBRBioW8GrcsEFAEKYtlUkIWCwFFkGIhr8YtCwQUQcpimZSQxUJAEaRYyKtxywIBRZCyWCYlZLEQUAQpFvJq3LJAQBGkLJZJCVksBBRBioW8GrcsEFAEKYtlUkIWCwFFkGIhr8YtCwQUQcpimZSQxUJAEaRYyKtxywKB/w+0zyjmRPeUmgAAAABJRU5ErkJggg==">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/github-markdown.min.css">
<link id="highlight-theme-light" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/github.min.css">
<link id="highlight-theme-dark" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/github-dark.min.css" disabled>
<style>
:root {
--bg-color: #fff;
--text-color: #24292e;
--link-color: #0366d6;
--border-color: #e1e4e8;
--code-bg-color: #f6f8fa;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #0d1117;
--text-color: #c9d1d9;
--link-color: #58a6ff;
--border-color: #30363d;
--code-bg-color: #161b22;
}
}
body {
font-family: Arial, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
overflow: hidden;
visibility: hidden;
}
.container {
background-color: var(--bg-color);
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 8px;
width: 80%;
max-height: 80%;
max-width: 80%;
border: 1px solid var(--border-color);
display: flex;
flex-direction: column;
resize: both; /* 允许容器调整大小 */
overflow: auto; /* 当内容溢出时显示滚动条 */
}
@media (prefers-color-scheme: dark) {
.container {
box-shadow: 0 0 10px rgba(255, 255, 255, 0.1);
}
}
textarea, input {
background-color: var(--bg-color);
color: var(--text-color);
border: 1px solid var(--border-color);
width: 100%;
margin-top: 10px;
border-radius: 4px;
padding: 10px;
box-sizing: border-box;
resize: none; /* 禁止内部元素调整大小 */
}
textarea {
height: 200px;
resize: vertical; /* 允许垂直方向调整大小 */
min-height: 100px; /* 设置最小高度 */
}
button {
background-color: var(--link-color);
color: #fff;
border: none;
padding: 10px;
cursor: pointer;
border-radius: 4px;
width: 100%;
margin-top: 10px;
}
button:hover {
opacity: 0.8;
}
#link {
margin-top: 20px;
cursor: pointer;
color: var(--link-color);
word-wrap: break-word; /* 允许长链接自动换行 */
}
#link:hover {
text-decoration: underline;
}
.markdown-body {
overflow-y: auto;
color: var(--text-color);
padding-right: 10px;
-webkit-overflow-scrolling: touch;
}
.markdown-body pre {
background-color: var(--code-bg-color);
position: relative;
}
.markdown-body pre:hover .copy-btn {
opacity: 1;
}
.copy-btn {
position: absolute;
top: 4px;
right: 8px;
width: 50px;
height: 24px;
background-color: var(--code-bg-color);
border: 1px solid var(--border-color);
color: var(--text-color);
border-radius: 4px;
cursor: pointer;
opacity: 0;
transition: opacity 0.3s;
font-size: 12px;
display: flex;
justify-content: center;
align-items: center;
transform: translateY(-6px);
}
.theme-toggle {
position: fixed;
top: 10px;
left: 10px;
cursor: pointer;
z-index: 1000;
}
.theme-toggle input {
display: none;
}
.theme-toggle label {
display: block;
width: 40px;
height: 20px;
background-color: #ccc;
border-radius: 20px;
position: relative;
transition: background-color 0.3s;
}
.theme-toggle label:before {
content: "";
display: block;
width: 16px;
height: 16px;
border-radius: 50%;
background-color: #fff;
position: absolute;
top: 2px;
left: 2px;
transition: transform 0.3s;
}
.theme-toggle input:checked + label {
background-color: #2196F3;
}
.theme-toggle input:checked + label:before {
transform: translateX(20px);
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background-color: var(--bg-color);
}
::-webkit-scrollbar-thumb {
background-color: var(--border-color);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background-color: #aaa;
}
.notification {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background-color: var(--link-color);
color: #fff;
padding: 10px 20px;
border-radius: 4px;
display: none;
z-index: 1000;
}
.form-group {
margin-bottom: 15px;
flex: 1; /* 使表单组在容器中均匀分布 */
}
.form-group label {
display: block;
font-size: 14px;
color: var(--text-color);
margin-bottom: 5px;
}
.info-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
padding: 10px;
border-radius: 4px;
background-color: var(--code-bg-color);
}
.info-container p {
margin: 0;
font-size: 14px;
color: var(--text-color);
}
.info-container button {
width: auto;
padding: 5px 10px;
margin-left: 10px;
}
/* 调整按钮的大小 */
.custom-button {
width: 200px; /* 设置按钮的宽度 */
height: 50px; /* 设置按钮的高度 */
font-size: 18px; /* 设置按钮的字体大小 */
padding: 10px 20px; /* 设置按钮的内边距 */
background-color: var(--link-color); /* 设置按钮的背景颜色 */
color: #fff; /* 设置按钮的文字颜色 */
border: none; /* 移除按钮的边框 */
border-radius: 4px; /* 设置按钮的圆角 */
cursor: pointer; /* 设置鼠标悬停时的指针样式 */
display: flex; /* 使用 flex 布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
margin: 0; /* 重置默认的 margin */
}
.custom-button:hover {
opacity: 0.8; /* 设置按钮悬停时的透明度 */
}
/* 使按钮在容器中垂直居中且靠右 */
.button-wrapper {
display: flex;
justify-content: flex-end; /* 水平靠右 */
align-items: center; /* 垂直居中 */
width: 100%;
}
</style>
</head>
<body>
<div class="theme-toggle">
<input type="checkbox" id="theme-toggle-checkbox">
<label for="theme-toggle-checkbox"></label>
</div>
<div class="container">
${isDocPage ? `
<article class="markdown-body" id="markdown-container"></article>
<div class="info-container">
<div>
<p>剩余可访问次数: ${remainingViews !== null ? remainingViews : '不限'}</p>
<p>剩余时间: ${formatRemainingTime(remainingTime)}</p>
</div>
<button class="custom-button" onclick="confirmDestruction()">已读-确认销毁</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
<script>
const debounce = (func, wait) => {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
};
const markdown = decodeBase64(${JSON.stringify(markdown)});
marked.setOptions({
gfm: true,
breaks: true,
headerIds: false,
highlight: function(code, lang) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
return hljs.highlight(code, { language }).value;
}
});
const renderMarkdown = debounce(() => {
document.getElementById('markdown-container').innerHTML = marked.parse(markdown);
hljs.highlightAll();
addCopyButtons();
}, 300);
const addCopyButtons = () => {
const preElements = document.querySelectorAll('pre');
preElements.forEach(pre => {
const copyBtn = document.createElement('button');
copyBtn.className = 'copy-btn';
copyBtn.textContent = 'Copy';
copyBtn.addEventListener('click', () => {
const code = pre.querySelector('code').innerText;
navigator.clipboard.writeText(code).then(() => {
copyBtn.textContent = 'Copied!';
setTimeout(() => {
copyBtn.textContent = 'Copy';
}, 2000);
});
});
pre.appendChild(copyBtn);
});
};
const themeToggle = document.getElementById('theme-toggle-checkbox');
const lightTheme = document.getElementById('highlight-theme-light');
const darkTheme = document.getElementById('highlight-theme-dark');
const setTheme = (isDark) => {
document.documentElement.style.setProperty('--bg-color', isDark ? '#0d1117' : '#fff');
document.documentElement.style.setProperty('--text-color', isDark ? '#c9d1d9' : '#24292e');
document.documentElement.style.setProperty('--link-color', isDark ? '#58a6ff' : '#0366d6');
document.documentElement.style.setProperty('--border-color', isDark ? '#30363d' : '#e1e4e8');
document.documentElement.style.setProperty('--code-bg-color', isDark ? '#161b22' : '#f6f8fa');
lightTheme.disabled = isDark;
darkTheme.disabled = !isDark;
};
themeToggle.addEventListener('change', (event) => {
setTheme(event.target.checked);
});
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
themeToggle.checked = prefersDark;
setTheme(prefersDark);
document.body.style.visibility = 'visible';
renderMarkdown();
function decodeBase64(str) {
const decodedStr = atob(str);
const data = new Uint8Array(decodedStr.split('').map(char => char.charCodeAt(0)));
const decoder = new TextDecoder();
return decoder.decode(data);
}
async function confirmDestruction() {
const response = await fetch('/delete/${docId}', {
method: 'POST'
});
const data = await response.json();
if (data.success) {
alert('文档已销毁');
window.location.href = '/';
} else {
alert('销毁文档时出错');
}
}
</script>
` : `
<h1>分享一个秘密文档</h1>
<div class="form-group">
<label for="markdownText">输入你的 Markdown 内容</label>
<textarea id="markdownText" placeholder="输入你的 Markdown 内容"></textarea>
</div>
<div class="form-group">
<label for="views">输入可访问次数(留空表示不限次数)</label>
<input type="number" id="views" value="5" min="0" step="1">
</div>
<div class="form-group">
<label for="expiration">输入有效时间(单位分钟,留空表示不限时)</label>
<input type="number" id="expiration" value="10" min="1" step="1">
</div>
<button onclick="createDocument()">生成分享链接</button>
<p id="link" onclick="copyLink()"></p>
<div class="notification" id="notification">链接已复制到剪贴板</div>
<script>
const debounce = (func, wait) => {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
};
const createDocument = debounce(async () => {
const markdown = document.getElementById('markdownText').value;
const views = document.getElementById('views').value;
const expiration = document.getElementById('expiration').value;
const response = await fetch('/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ markdown, views, expiration })
});
const data = await response.json();
if (data.error) {
alert(data.error);
} else {
document.getElementById('link').textContent = data.link;
}
}, 300);
const copyLink = debounce(() => {
const link = document.getElementById('link').textContent;
navigator.clipboard.writeText(link).then(() => {
showNotification();
});
}, 300);
const showNotification = () => {
const notification = document.getElementById('notification');
notification.style.display = 'block';
setTimeout(() => {
notification.style.display = 'none';
}, 2000);
};
const themeToggle = document.getElementById('theme-toggle-checkbox');
const lightTheme = document.getElementById('highlight-theme-light');
const darkTheme = document.getElementById('highlight-theme-dark');
const setTheme = (isDark) => {
document.documentElement.style.setProperty('--bg-color', isDark ? '#0d1117' : '#fff');
document.documentElement.style.setProperty('--text-color', isDark ? '#c9d1d9' : '#24292e');
document.documentElement.style.setProperty('--link-color', isDark ? '#58a6ff' : '#0366d6');
document.documentElement.style.setProperty('--border-color', isDark ? '#30363d' : '#e1e4e8');
document.documentElement.style.setProperty('--code-bg-color', isDark ? '#161b22' : '#f6f8fa');
lightTheme.disabled = isDark;
darkTheme.disabled = !isDark;
};
themeToggle.addEventListener('change', (event) => {
setTheme(event.target.checked);
});
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
themeToggle.checked = prefersDark;
setTheme(prefersDark);
document.body.style.visibility = 'visible';
</script>`}
</div>
</body>
</html>
`;
}
将kv空间绑定变量works_data即可使用
- 0
- 0
-
分享