{"id":4291,"date":"2026-01-07T21:14:10","date_gmt":"2026-01-07T13:14:10","guid":{"rendered":"https:\/\/blog.kangyue.pro\/?p=4291"},"modified":"2026-01-09T18:09:44","modified_gmt":"2026-01-09T10:09:44","slug":"%e4%b8%80%e4%b8%aa%e4%bc%98%e7%be%8e%e4%b8%94%e7%89%9b%e9%80%bc%e7%9a%84-python-%e7%a8%8b%e5%ba%8f%e7%ae%a1%e7%90%86%e5%b9%b3%e5%8f%b0-%e5%9f%ba%e4%ba%8ehtml%e5%92%8cphp","status":"publish","type":"post","link":"https:\/\/blog.kangyue.pro\/?p=4291","title":{"rendered":"\u4e00\u4e2a\u4f18\u7f8e\u4e14\u725b\u903c\u7684 Python \u7a0b\u5e8f\u7ba1\u7406\u5e73\u53f0\u2014\u2014\u57fa\u4e8eHTML\u548cPHP"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>\u4e00\u4e2a\u7528\u4e8e\u5b58\u653e Python \u4ee3\u7801\u7684\u5e73\u53f0\uff0c\u5177\u6709\u524d\u540e\u7aef\u9875\u9762\u3002\u53ef\u8bbe\u7f6e\u548c\u5c55\u793a\u591a\u4e2a\u9879\u76ee\uff08pyhton\u5236\u4f5c\u7684\u5c0f\u5de5\u5177\uff09\uff0c\u6bcf\u4e2a\u9879\u76ee\u90fd\u53ef\u4ee5\u8bbe\u7f6e\u3001\u4e0a\u4f20\uff1a\u4ee3\u7801\u3001\u754c\u9762\u622a\u56fe\u3001exe\u7a0b\u5e8f\uff0c\u8fd8\u53ef\u4ee5\u8bbe\u7f6e\u4e00\u53e5\u8bdd\u7b80\u4ecb\u548c\u8be6\u7ec6\u4ecb\u7ecd\uff08\u652f\u6301Makedown\uff09\u3002<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading has-text-align-center\">\u5c55\u793a<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u524d\u7aef\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.kangyue.pro\/python\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.kangyue.pro\/python\/<\/a><\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading has-text-align-center\">\u622a\u56fe<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u524d\u7aef\u9875\u9762\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1278\" height=\"918\" src=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-19.png\" alt=\"\" class=\"wp-image-4293\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-19.png 1278w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-19-768x552.png 768w\" sizes=\"auto, (max-width: 1278px) 100vw, 1278px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1262\" height=\"1382\" src=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-20.png\" alt=\"\" class=\"wp-image-4294\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-20.png 1262w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-20-768x841.png 768w\" sizes=\"auto, (max-width: 1262px) 100vw, 1262px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1278\" height=\"918\" src=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-21.png\" alt=\"\" class=\"wp-image-4295\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-21.png 1278w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-21-768x552.png 768w\" sizes=\"auto, (max-width: 1278px) 100vw, 1278px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u540e\u53f0\u9875\u9762\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1278\" height=\"918\" src=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-18.png\" alt=\"\" class=\"wp-image-4292\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-18.png 1278w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2026\/01\/image-18-768x552.png 768w\" sizes=\"auto, (max-width: 1278px) 100vw, 1278px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading has-text-align-center\">web\u6e90\u7801<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">\u524d\u53f0<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">index.php\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-691dcf6c-b' data-attributes='{&quot;cId&quot;:&quot;691dcf6c-b&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\n\\\/\\\/ \\u6839\\u76ee\\u5f55 index.php - \\u7528\\u6237\\u5c55\\u793a\\u9875\\n\\n$projectsDir = __DIR__ . &#039;\\\/projects\\\/&#039;;\\n$projectListForSidebar = [];\\n\\nif (is_dir($projectsDir)) {\\n    $dirs = array_filter(glob($projectsDir . &#039;*&#039;), &#039;is_dir&#039;);\\n    foreach ($dirs as $dir) {\\n        $name = basename($dir);\\n        $emojiFile = $dir . &#039;\\\/emoji.txt&#039;;\\n        $emoji = file_exists($emojiFile) ? file_get_contents($emojiFile) : &#039;\\ud83d\\ude80&#039;;\\n        \\n        $projectListForSidebar[] = [\\n            &#039;name&#039; =&gt; $name,\\n            &#039;emoji&#039; =&gt; $emoji\\n        ];\\n    }\\n    usort($projectListForSidebar, function($a, $b) {\\n        return strcmp($a[&#039;name&#039;], $b[&#039;name&#039;]);\\n    });\\n}\\n?&gt;\\n&lt;!DOCTYPE html&gt;\\n&lt;html lang=\\&quot;zh\\&quot;&gt;\\n&lt;head&gt;\\n    &lt;meta charset=\\&quot;UTF-8\\&quot; \\\/&gt;\\n    &lt;title&gt;Python\\u5de5\\u5177\\u5217\\u8868&lt;\\\/title&gt;\\n    &lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/marked\\\/marked.min.js\\&quot;&gt;&lt;\\\/script&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdnjs.cloudflare.com\\\/ajax\\\/libs\\\/highlight.js\\\/11.9.0\\\/styles\\\/atom-one-dark.min.css\\&quot;&gt;\\n    &lt;script src=\\&quot;https:\\\/\\\/cdnjs.cloudflare.com\\\/ajax\\\/libs\\\/highlight.js\\\/11.9.0\\\/highlight.min.js\\&quot;&gt;&lt;\\\/script&gt;\\n    \\n    &lt;style&gt;\\n        :root { --sidebar-w: 300px; --primary: #3498db; --dark: #2c3e50; }\\n        body { margin:0; font-family: \\&quot;Segoe UI\\&quot;, Tahoma, sans-serif; display: flex; height: 100vh; background-color: #f4f7f6; overflow: hidden; }\\n        \\n        \\\/* \\u4fa7\\u8fb9\\u680f *\\\/\\n        #sidebar { width: var(--sidebar-w); background: var(--dark); color: #ecf0f1; overflow-y: auto; flex-shrink: 0; }\\n        #sidebar h2 { text-align: center; padding: 25px 0; margin: 0; background: #1a252f; font-size: 1.3em; }\\n        #projectList { list-style: none; padding: 0; margin: 0; }\\n        #projectList li { padding: 15px 20px; cursor: pointer; border-bottom: 1px solid #34495e; display: flex; align-items: center; transition: 0.2s; }\\n        #projectList li:hover { background: #34495e; }\\n        #projectList li.active { background: var(--primary); color: white; }\\n        .proj-emoji-icon { font-size: 22px; margin-right: 12px; width: 25px; text-align: center; }\\n\\n        \\\/* \\u4e3b\\u5185\\u5bb9 *\\\/\\n        #main { flex: 1; padding: 30px 50px; overflow-y: auto; background-color: #fff; }\\n        .project-header { display: flex; align-items: center; gap: 20px; margin-bottom: 30px; border-bottom: 2px solid #eee; padding-bottom: 25px; }\\n        .header-emoji { font-size: 50px; }\\n        .header-text h1 { margin: 0; color: var(--dark); }\\n        .header-text .summary { color: #7f8c8d; margin-top: 5px; }\\n\\n        \\\/* \\u7248\\u672c\\u5207\\u6362\\u5668\\u6837\\u5f0f *\\\/\\n        .version-selector { margin-bottom: 20px; display: flex; align-items: center; gap: 10px; background: #f8f9fa; padding: 10px 15px; border-radius: 6px; }\\n        #versionSelect { padding: 5px 10px; border-radius: 4px; border: 1px solid #ddd; outline: none; }\\n\\n        .section { margin-bottom: 40px; }\\n        .section h3 { color: var(--dark); border-left: 4px solid var(--primary); padding-left: 12px; margin-bottom: 15px; }\\n        \\n        \\\/* \\u4ee3\\u7801\\u6846\\u9ad8\\u5ea6\\u53d7\\u9650 *\\\/\\n        \\\/* 1. \\u9650\\u5236\\u5bbd\\u5ea6\\u5e76\\u8ba9\\u53f3\\u4fa7\\u7559\\u767d *\\\/\\n        .code-block-wrapper { \\n            background: #282c34; \\n            border-radius: 8px; \\n            overflow: hidden;\\n            border: 1px solid #3e4451; \\n            box-shadow: 0 4px 12px rgba(0,0,0,0.1);\\n            \\n            \\\/* \\u4fee\\u6539\\u8fd9\\u91cc\\uff1a\\u8bbe\\u7f6e\\u6700\\u5927\\u5bbd\\u5ea6\\uff0c\\u4f8b\\u5982 80% \\u6216\\u56fa\\u5b9a\\u50cf\\u7d20 *\\\/\\n            max-width: 85%; \\n            margin-right: auto; \\\/* \\u786e\\u4fdd\\u5de6\\u5bf9\\u9f50\\uff0c\\u53f3\\u4fa7\\u81ea\\u7136\\u7559\\u767d *\\\/\\n        }\\n        \\n        \\\/* 2. \\u8fdb\\u4e00\\u6b65\\u964d\\u4f4e\\u9ad8\\u5ea6 *\\\/\\n        .code-container { \\n            max-height: 300px; \\\/* \\u539f\\u6765\\u662f 500px\\uff0c\\u6539\\u4e3a 350px \\u751a\\u81f3\\u66f4\\u4f4e *\\\/\\n            overflow-y: auto; \\n            overflow-x: auto; \\\/* \\u786e\\u4fdd\\u6a2a\\u5411\\u592a\\u957f\\u65f6\\u4e5f\\u53ef\\u4ee5\\u6eda\\u52a8 *\\\/\\n        }\\n\\n        pre { margin: 0; padding: 15px; font-family: &#039;Cascadia Code&#039;, Consolas, monospace; font-size: 14px; }\\n\\n        .screenshots-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px; }\\n        .screenshots-grid img { width: 100%; border-radius: 6px; cursor: pointer; transition: 0.2s; border: 1px solid #eee; }\\n        .screenshots-grid img:hover { transform: scale(1.03); }\\n\\n        .file-link { \\n            display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px; \\n            background: #27ae60; color: white; text-decoration: none; border-radius: 4px; font-size: 14px; font-weight: 500;\\n        }\\n        .file-link.source { background: #34495e; }\\n\\n        \\\/* 1. \\u786e\\u4fdd\\u6a21\\u6001\\u6846\\u80cc\\u666f\\u5c42\\u5f00\\u542f Flex \\u5c45\\u4e2d *\\\/\\n        .modal { \\n            display: none; \\n            position: fixed; \\n            z-index: 1000; \\n            left: 0; \\n            top: 0; \\n            width: 100%; \\n            height: 100%; \\n            background: rgba(0,0,0,0.9); \\n            \\n            \\\/* \\u6838\\u5fc3\\u4fee\\u6539\\uff1a\\u786e\\u4fdd\\u6c34\\u5e73\\u548c\\u5782\\u76f4\\u5168\\u90e8\\u5c45\\u4e2d *\\\/\\n            justify-content: center; \\n            align-items: center; \\n        }\\n        \\n        \\\/* 2. \\u4f18\\u5316\\u56fe\\u7247\\u663e\\u793a *\\\/\\n        .modal-content { \\n            max-width: 90%; \\n            max-height: 90%; \\n            object-fit: contain; \\n            \\\/* \\u79fb\\u9664\\u53ef\\u80fd\\u5b58\\u5728\\u7684 margin \\u5e72\\u6270 *\\\/\\n            margin: auto; \\n            display: block; \\n        }\\n        \\n                \\\/* \\u4ecb\\u7ecd\\u6309\\u94ae\\u6837\\u5f0f *\\\/\\n        .intro-trigger-btn {\\n            display: inline-flex;\\n            align-items: center;\\n            gap: 8px;\\n            padding: 12px 20px;\\n            background: #f8f9fa;\\n            border: 1px dashed #3498db;\\n            color: #3498db;\\n            border-radius: 8px;\\n            cursor: pointer;\\n            transition: 0.3s;\\n            font-weight: bold;\\n        }\\n        .intro-trigger-btn:hover {\\n            background: #eaf2f8;\\n            border-style: solid;\\n        }\\n        \\n        \\\/* \\u8be6\\u7ec6\\u4ecb\\u7ecd\\u5f39\\u51fa\\u5c42 (\\u4e13\\u7528) *\\\/\\n        #infoModal {\\n            display: none;\\n            position: fixed;\\n            z-index: 1001; \\\/* \\u6bd4\\u56fe\\u7247\\u5f39\\u51fa\\u5c42\\u66f4\\u9ad8 *\\\/\\n            left: 0; top: 0; width: 100%; height: 100%;\\n            background: rgba(0,0,0,0.6);\\n            justify-content: center;\\n            align-items: center;\\n        }\\n        \\n        .info-modal-content {\\n            background: white;\\n            width: 80%;\\n            max-width: 900px;\\n            height: 80vh;\\n            border-radius: 12px;\\n            display: flex;\\n            flex-direction: column;\\n            overflow: hidden;\\n            box-shadow: 0 10px 30px rgba(0,0,0,0.2);\\n            animation: modalFadeIn 0.3s ease;\\n        }\\n        \\n        @keyframes modalFadeIn {\\n            from { opacity: 0; transform: translateY(20px); }\\n            to { opacity: 1; transform: translateY(0); }\\n        }\\n        \\n        .info-modal-header {\\n            padding: 15px 25px;\\n            background: #f8f9fa;\\n            border-bottom: 1px solid #eee;\\n            display: flex;\\n            justify-content: space-between;\\n            align-items: center;\\n        }\\n        \\n        .info-modal-body {\\n            flex: 1;\\n            padding: 30px;\\n            overflow-y: auto;\\n            line-height: 1.8;\\n        }\\n        \\n        .close-info-btn {\\n            font-size: 24px;\\n            cursor: pointer;\\n            color: #999;\\n        }\\n        \\n    &lt;\\\/style&gt;\\n&lt;\\\/head&gt;\\n&lt;body&gt;\\n\\n&lt;div id=\\&quot;sidebar\\&quot;&gt;\\n    &lt;h2&gt;\\ud83d\\udee0\\ufe0fPython\\u5de5\\u5177\\u5217\\u8868&lt;\\\/h2&gt;\\n    &lt;ul id=\\&quot;projectList\\&quot;&gt;\\n        &lt;?php foreach ($projectListForSidebar as $p): ?&gt;\\n            &lt;li onclick=\\&quot;loadProject(&#039;&lt;?php echo $p[&#039;name&#039;]; ?&gt;&#039;, this)\\&quot;&gt;\\n                &lt;span class=\\&quot;proj-emoji-icon\\&quot;&gt;&lt;?php echo htmlspecialchars($p[&#039;emoji&#039;]); ?&gt;&lt;\\\/span&gt;\\n                &lt;span&gt;&lt;?php echo htmlspecialchars(str_replace(&#039;_&#039;, &#039; &#039;, $p[&#039;name&#039;])); ?&gt;&lt;\\\/span&gt;\\n            &lt;\\\/li&gt;\\n        &lt;?php endforeach; ?&gt;\\n    &lt;\\\/ul&gt;\\n&lt;\\\/div&gt;\\n\\n&lt;div id=\\&quot;main\\&quot;&gt;\\n    &lt;div id=\\&quot;welcome\\&quot; style=\\&quot;text-align: center; padding-top: 20vh; color: #bdc3c7;\\&quot;&gt;\\n        &lt;h1&gt;\\ud83d\\udc48 \\u8bf7\\u9009\\u62e9\\u4e00\\u4e2a\\u9879\\u76ee&lt;\\\/h1&gt;\\n    &lt;\\\/div&gt;\\n\\n    &lt;div id=\\&quot;projectDetail\\&quot; style=\\&quot;display: none;\\&quot;&gt;\\n        &lt;div class=\\&quot;project-header\\&quot;&gt;\\n            &lt;div id=\\&quot;displayEmoji\\&quot; class=\\&quot;header-emoji\\&quot;&gt;&lt;\\\/div&gt;\\n            &lt;div class=\\&quot;header-text\\&quot;&gt;\\n                &lt;h1 id=\\&quot;displayTitle\\&quot;&gt;&lt;\\\/h1&gt;\\n                &lt;div id=\\&quot;displaySummary\\&quot; class=\\&quot;summary\\&quot;&gt;&lt;\\\/div&gt;\\n            &lt;\\\/div&gt;\\n        &lt;\\\/div&gt;\\n\\n        &lt;div class=\\&quot;section\\&quot;&gt;\\n            &lt;h3&gt;\\u9879\\u76ee\\u4ecb\\u7ecd&lt;\\\/h3&gt;\\n            &lt;div id=\\&quot;introShort\\&quot;&gt;\\n                &lt;div class=\\&quot;intro-trigger-btn\\&quot; onclick=\\&quot;openInfoModal()\\&quot;&gt;\\n                    \\ud83d\\udcd6 \\u70b9\\u51fb\\u67e5\\u770b\\u8be6\\u7ec6\\u9879\\u76ee\\u4ecb\\u7ecd (Markdown)\\n                &lt;\\\/div&gt;\\n            &lt;\\\/div&gt;\\n        &lt;\\\/div&gt;\\n        \\n        &lt;div class=\\&quot;section\\&quot; id=\\&quot;reqSection\\&quot; style=\\&quot;display:none; margin-top: 20px;\\&quot;&gt;\\n            &lt;h3&gt;\\u73af\\u5883\\u4f9d\\u8d56&lt;\\\/h3&gt;\\n            &lt;div id=\\&quot;displayReq\\&quot; style=\\&quot;background: #f8f9fa; border: 1px solid #e9ecef; padding: 15px; border-radius: 8px; font-family: monospace; white-space: pre-wrap; line-height: 1.5; color: #555;\\&quot;&gt;\\n                &lt;\\\/div&gt;\\n        &lt;\\\/div&gt;\\n        \\n        &lt;div id=\\&quot;infoModal\\&quot; onclick=\\&quot;closeInfoModal(event)\\&quot;&gt;\\n            &lt;div class=\\&quot;info-modal-content\\&quot; onclick=\\&quot;event.stopPropagation()\\&quot;&gt;\\n                &lt;div class=\\&quot;info-modal-header\\&quot;&gt;\\n                    &lt;h3 style=\\&quot;margin:0; border:none; padding:0;\\&quot;&gt;\\u8be6\\u7ec6\\u4ecb\\u7ecd&lt;\\\/h3&gt;\\n                    &lt;span class=\\&quot;close-info-btn\\&quot; onclick=\\&quot;closeInfoModal()\\&quot;&gt;&times;&lt;\\\/span&gt;\\n                &lt;\\\/div&gt;\\n                &lt;div id=\\&quot;displayInfo\\&quot; class=\\&quot;info-modal-body markdown-body\\&quot;&gt;\\n                    &lt;\\\/div&gt;\\n            &lt;\\\/div&gt;\\n        &lt;\\\/div&gt;\\n\\n        &lt;div class=\\&quot;version-selector\\&quot; id=\\&quot;verSelector\\&quot; style=\\&quot;display:none;\\&quot;&gt;\\n            &lt;span&gt;\\u9009\\u62e9\\u7248\\u672c:&lt;\\\/span&gt;\\n            &lt;select id=\\&quot;versionSelect\\&quot; onchange=\\&quot;changeVersion()\\&quot;&gt;&lt;\\\/select&gt;\\n        &lt;\\\/div&gt;\\n\\n\\n\\n        &lt;div class=\\&quot;section\\&quot; id=\\&quot;codeSection\\&quot;&gt;\\n            &lt;h3&gt;Python \\u6e90\\u7801&lt;\\\/h3&gt;\\n            &lt;div class=\\&quot;code-block-wrapper\\&quot;&gt;\\n                &lt;div class=\\&quot;code-header\\&quot;&gt;\\n                    &lt;span class=\\&quot;code-filename\\&quot; id=\\&quot;displayFilename\\&quot;&gt;&lt;\\\/span&gt;\\n                    &lt;button onclick=\\&quot;copyCode()\\&quot; style=\\&quot;font-size:11px; cursor:pointer;\\&quot;&gt;\\u590d\\u5236&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;div class=\\&quot;code-container\\&quot;&gt;\\n                    &lt;pre&gt;&lt;code id=\\&quot;displayCode\\&quot; class=\\&quot;language-python\\&quot;&gt;&lt;\\\/code&gt;&lt;\\\/pre&gt;\\n                &lt;\\\/div&gt;\\n            &lt;\\\/div&gt;\\n            &lt;div id=\\&quot;sourceDL\\&quot; style=\\&quot;margin-top:10px;\\&quot;&gt;&lt;\\\/div&gt;\\n        &lt;\\\/div&gt;\\n\\n        &lt;div class=\\&quot;section\\&quot; id=\\&quot;ssSection\\&quot;&gt;\\n            &lt;h3&gt;\\u754c\\u9762\\u622a\\u56fe&lt;\\\/h3&gt;\\n            &lt;div class=\\&quot;screenshots-grid\\&quot; id=\\&quot;displaySS\\&quot;&gt;&lt;\\\/div&gt;\\n        &lt;\\\/div&gt;\\n\\n        &lt;div class=\\&quot;section\\&quot; id=\\&quot;dlSection\\&quot;&gt;\\n            &lt;h3&gt;exe\\u4e0b\\u8f7d&lt;\\\/h3&gt;\\n            &lt;div id=\\&quot;displayFiles\\&quot; style=\\&quot;display:flex; gap:10px; flex-wrap:wrap;\\&quot;&gt;&lt;\\\/div&gt;\\n        &lt;\\\/div&gt;\\n    &lt;\\\/div&gt;\\n&lt;\\\/div&gt;\\n\\n&lt;div id=\\&quot;imageModal\\&quot; class=\\&quot;modal\\&quot; onclick=\\&quot;this.style.display=&#039;none&#039;\\&quot;&gt;\\n    &lt;img class=\\&quot;modal-content\\&quot; id=\\&quot;modalImage\\&quot;&gt;\\n&lt;\\\/div&gt;\\n\\n&lt;script&gt;\\n    let currentProjectName = \\&quot;\\&quot;;\\n    let allVersionData = {}; \\\/\\\/ \\u5b58\\u50a8\\u5f53\\u524d\\u9879\\u76ee\\u7684\\u6240\\u6709\\u7248\\u672c\\u6570\\u636e\\n\\n    \\\/\\\/ 1. \\u52a0\\u8f7d\\u9879\\u76ee\\uff08\\u83b7\\u53d6\\u7248\\u672c\\u5217\\u8868\\uff09\\n    async function loadProject(name, el) {\\n        document.querySelectorAll(&#039;#projectList li&#039;).forEach(li =&gt; li.classList.remove(&#039;active&#039;));\\n        el.classList.add(&#039;active&#039;);\\n        currentProjectName = name;\\n\\n        const resp = await fetch(`get_details.php?project=${encodeURIComponent(name)}&amp;all_versions=1`);\\n        const data = await resp.json();\\n        \\n        \\\/\\\/ \\u6e32\\u67d3\\u8fd0\\u884c\\u73af\\u5883\\u4f9d\\u8d56\\n        const reqSection = document.getElementById(&#039;reqSection&#039;);\\n        const reqDisplay = document.getElementById(&#039;displayReq&#039;);\\n        \\n        if (reqSection &amp;&amp; reqDisplay) {\\n            if (data.requirements &amp;&amp; data.requirements.trim() !== \\&quot;\\&quot;) {\\n                reqDisplay.innerText = data.requirements; \\\/\\\/ \\u586b\\u5165\\u6587\\u5b57\\n                reqSection.style.display = &#039;block&#039;;       \\\/\\\/ \\u663e\\u793a\\u533a\\u57df\\n            } else {\\n                reqSection.style.display = &#039;none&#039;;        \\\/\\\/ \\u6ca1\\u5185\\u5bb9\\u5219\\u9690\\u85cf\\n            }\\n        }\\n        \\n        allVersionData = data; \\\/\\\/ \\u5047\\u8bbe\\u540e\\u7aef\\u8fd4\\u56de\\u4e86\\u6240\\u6709\\u7248\\u672c\\n        \\n        \\\/\\\/ \\u6e32\\u67d3\\u57fa\\u672c\\u4fe1\\u606f\\n        document.getElementById(&#039;welcome&#039;).style.display = &#039;none&#039;;\\n        document.getElementById(&#039;projectDetail&#039;).style.display = &#039;block&#039;;\\n        document.getElementById(&#039;displayTitle&#039;).innerText = name.replace(\\\/_\\\/g, &#039; &#039;);\\n        document.getElementById(&#039;displayEmoji&#039;).innerText = data.emoji || &#039;\\ud83d\\ude80&#039;;\\n        document.getElementById(&#039;displaySummary&#039;).innerText = data.summary || &#039;&#039;;\\n        document.getElementById(&#039;displayInfo&#039;).innerHTML = marked.parse(data.info || &#039;&#039;);\\n\\n        \\\/\\\/ \\u5904\\u7406\\u7248\\u672c\\u4e0b\\u62c9\\u6846\\n        const select = document.getElementById(&#039;versionSelect&#039;);\\n        select.innerHTML = &#039;&#039;;\\n        if(data.available_versions &amp;&amp; data.available_versions.length &gt; 0) {\\n            data.available_versions.forEach(v =&gt; {\\n                const opt = document.createElement(&#039;option&#039;);\\n                opt.value = v;\\n                opt.innerText = &#039;v&#039; + v;\\n                if(v === data.version) opt.selected = true;\\n                select.appendChild(opt);\\n            });\\n            document.getElementById(&#039;verSelector&#039;).style.display = &#039;flex&#039;;\\n        }\\n\\n        renderVersionDetails(data);\\n    }\\n\\n    \\\/\\\/ 2. \\u5207\\u6362\\u7248\\u672c\\n    async function changeVersion() {\\n        const v = document.getElementById(&#039;versionSelect&#039;).value;\\n        const resp = await fetch(`get_details.php?project=${encodeURIComponent(currentProjectName)}&amp;version=${v}`);\\n        const data = await resp.json();\\n        renderVersionDetails(data);\\n    }\\n\\n    \\\/\\\/ 3. \\u6e32\\u67d3\\u7279\\u5b9a\\u7248\\u672c\\u7684\\u8be6\\u60c5\\n    function renderVersionDetails(data) {\\n        \\\/\\\/ \\u6e32\\u67d3\\u4ee3\\u7801\\n        if (data.code) {\\n            document.getElementById(&#039;codeSection&#039;).style.display = &#039;block&#039;;\\n            document.getElementById(&#039;displayFilename&#039;).innerText = data.code.filename;\\n            document.getElementById(&#039;displayCode&#039;).textContent = data.code.content;\\n            document.getElementById(&#039;sourceDL&#039;).innerHTML = `&lt;a href=\\&quot;projects\\\/${currentProjectName}\\\/${data.version}\\\/${data.code.filename}\\&quot; class=\\&quot;file-link source\\&quot; download&gt;\\ud83d\\udcbe \\u4e0b\\u8f7d\\u6e90\\u7801&lt;\\\/a&gt;`;\\n            hljs.highlightAll();\\n        } else {\\n            document.getElementById(&#039;codeSection&#039;).style.display = &#039;none&#039;;\\n        }\\n\\n        \\\/\\\/ \\u6e32\\u67d3\\u622a\\u56fe\\n        const ssGrid = document.getElementById(&#039;displaySS&#039;);\\n        ssGrid.innerHTML = &#039;&#039;;\\n        if (data.screenshots &amp;&amp; data.screenshots.length &gt; 0) {\\n            data.screenshots.forEach(s =&gt; {\\n                const img = document.createElement(&#039;img&#039;);\\n                img.src = `projects\\\/${currentProjectName}\\\/${data.version}\\\/screenshots\\\/${s}`;\\n                img.onclick = () =&gt; {\\n                    document.getElementById(&#039;imageModal&#039;).style.display = &#039;flex&#039;;\\n                    document.getElementById(&#039;modalImage&#039;).src = img.src;\\n                };\\n                ssGrid.appendChild(img);\\n            });\\n            document.getElementById(&#039;ssSection&#039;).style.display = &#039;block&#039;;\\n        } else {\\n            document.getElementById(&#039;ssSection&#039;).style.display = &#039;none&#039;;\\n        }\\n\\n        \\\/\\\/ \\u6e32\\u67d3\\u4e0b\\u8f7d\\n        const dlBox = document.getElementById(&#039;displayFiles&#039;);\\n        dlBox.innerHTML = &#039;&#039;;\\n        if (data.exes &amp;&amp; data.exes.length &gt; 0) {\\n            data.exes.forEach(exe =&gt; {\\n                dlBox.innerHTML += `&lt;a href=\\&quot;projects\\\/${currentProjectName}\\\/${data.version}\\\/exe\\\/${exe}\\&quot; class=\\&quot;file-link\\&quot; download&gt;\\ud83d\\udce6 \\u4e0b\\u8f7d ${exe}&lt;\\\/a&gt;`;\\n            });\\n            document.getElementById(&#039;dlSection&#039;).style.display = &#039;block&#039;;\\n        } else {\\n            document.getElementById(&#039;dlSection&#039;).style.display = &#039;none&#039;;\\n        }\\n    }\\n\\n    function copyCode() {\\n        const code = document.getElementById(&#039;displayCode&#039;).innerText;\\n        navigator.clipboard.writeText(code);\\n        alert(&#039;\\u4ee3\\u7801\\u5df2\\u590d\\u5236\\u5230\\u526a\\u8d34\\u677f&#039;);\\n    }\\n    \\n        \\\/\\\/ --- \\u5f39\\u51fa\\u8be6\\u7ec6\\u4ecb\\u7ecd ---\\n    function openInfoModal() {\\n        const modal = document.getElementById(&#039;infoModal&#039;);\\n        if (modal) {\\n            modal.style.display = &#039;flex&#039;;\\n            document.body.style.overflow = &#039;hidden&#039;; \\n        }\\n    }\\n    \\n    function closeInfoModal() {\\n        const modal = document.getElementById(&#039;infoModal&#039;);\\n        if (modal) {\\n            modal.style.display = &#039;none&#039;;\\n            document.body.style.overflow = &#039;&#039;;\\n        }\\n    }\\n    \\n    \\n&lt;\\\/script&gt;\\n&lt;\\\/body&gt;\\n&lt;\\\/html&gt;&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:12,&quot;tablet&quot;:15,&quot;mobile&quot;:14},&quot;height&quot;:{&quot;desktop&quot;:&quot;200px&quot;,&quot;tablet&quot;:&quot;0px&quot;,&quot;mobile&quot;:&quot;0px&quot;},&quot;align&quot;:&quot;&quot;,&quot;lineNumbers&quot;:true,&quot;theme&quot;:&quot;default&quot;,&quot;clipBoard&quot;:true,&quot;wordWrap&quot;:true,&quot;width&quot;:{&quot;desktop&quot;:&quot;100%&quot;,&quot;tablet&quot;:&quot;100%&quot;,&quot;mobile&quot;:&quot;100%&quot;},&quot;padding&quot;:{&quot;top&quot;:&quot;0px&quot;,&quot;right&quot;:&quot;0px&quot;,&quot;bottom&quot;:&quot;0px&quot;,&quot;left&quot;:&quot;0px&quot;},&quot;background&quot;:{&quot;color&quot;:&quot;#d3cfcf42&quot;},&quot;layout&quot;:{&quot;align&quot;:&quot;left&quot;},&quot;border&quot;:{&quot;color&quot;:&quot;#000&quot;,&quot;style&quot;:&quot;solid&quot;,&quot;width&quot;:&quot;0px&quot;},&quot;shadow&quot;:[],&quot;alignment&quot;:&quot;center&quot;,&quot;clipBoardColors&quot;:{&quot;color&quot;:&quot;#fff&quot;,&quot;bg&quot;:&quot;#00000024&quot;}}'><\/div>\r\n\r\n\t\t\n\n\n<p class=\"wp-block-paragraph\">get_details.php\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-2ff7caaa-8' data-attributes='{&quot;cId&quot;:&quot;2ff7caaa-8&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\n\\\/\\\/ get_details.php - \\u653e\\u7f6e\\u5728\\u7f51\\u7ad9\\u6839\\u76ee\\u5f55\\nheader(&#039;Content-Type: application\\\/json&#039;);\\n\\n\\\/\\\/ 1. \\u83b7\\u53d6\\u5e76\\u6e05\\u7406\\u53c2\\u6570\\n$project = isset($_GET[&#039;project&#039;]) ? trim($_GET[&#039;project&#039;]) : &#039;&#039;;\\n$requestedVersion = isset($_GET[&#039;version&#039;]) ? trim($_GET[&#039;version&#039;]) : &#039;&#039;;\\n\\n\\\/\\\/ 2. \\u786e\\u5b9a\\u7269\\u7406\\u6839\\u8def\\u5f84\\uff08\\u4f7f\\u7528 realpath \\u786e\\u4fdd\\u8def\\u5f84\\u5b58\\u5728\\u4e14\\u5408\\u6cd5\\uff09\\n$projectsRoot = __DIR__ . &#039;\\\/projects&#039;;\\n$basePath = $projectsRoot . &#039;\\\/&#039; . $project;\\n\\n\\\/\\\/ \\u57fa\\u7840\\u5b89\\u5168\\u68c0\\u67e5\\nif (!$project || !is_dir($basePath)) {\\n    echo json_encode([\\n        &#039;error&#039; =&gt; &#039;\\u9879\\u76ee\\u76ee\\u5f55\\u4e0d\\u5b58\\u5728&#039;,\\n        &#039;debug_path&#039; =&gt; $basePath\\n    ]);\\n    exit;\\n}\\n\\n\\\/\\\/ 3. \\u83b7\\u53d6\\u7248\\u672c\\u5217\\u8868\\n$dirs = array_filter(glob($basePath . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\n$versionListNames = array_values(array_map(&#039;basename&#039;, $dirs));\\nusort($versionListNames, &#039;version_compare&#039;); \\\/\\\/ \\u5347\\u5e8f\\u6392\\u5217\\uff1a1.0, 1.1...\\n\\n\\\/\\\/ \\u786e\\u5b9a\\u5f53\\u524d\\u8981\\u663e\\u793a\\u7684\\u7248\\u672c\\n$targetVersion = $requestedVersion;\\nif (!$targetVersion || !in_array($targetVersion, $versionListNames)) {\\n    $targetVersion = !empty($versionListNames) ? end($versionListNames) : &#039;&#039;; \\\/\\\/ \\u9ed8\\u8ba4\\u53d6\\u6700\\u65b0\\u7248\\n}\\n\\n\\\/\\\/ 4. \\u521d\\u59cb\\u5316\\u54cd\\u5e94\\u7ed3\\u6784\\uff08\\u786e\\u4fdd\\u524d\\u7aef\\u6240\\u6709\\u5b57\\u6bb5\\u90fd\\u6709\\u9ed8\\u8ba4\\u503c\\uff0c\\u9632\\u6b62 JS \\u62a5\\u9519\\uff09\\n$response = [\\n    &#039;emoji&#039; =&gt; &#039;\\ud83d\\ude80&#039;,\\n    &#039;summary&#039; =&gt; &#039;&#039;,\\n    &#039;info&#039; =&gt; &#039;&#039;,\\n    &#039;requirements&#039; =&gt; &#039;&#039;,\\n    &#039;available_versions&#039; =&gt; $versionListNames,\\n    &#039;version&#039; =&gt; $targetVersion,\\n    &#039;code&#039; =&gt; [\\n        &#039;filename&#039; =&gt; &#039;\\u65e0\\u4ee3\\u7801&#039;,\\n        &#039;content&#039; =&gt; &#039;# \\u6682\\u65e0\\u4ee3\\u7801\\u5185\\u5bb9&#039;\\n    ],\\n    &#039;screenshots&#039; =&gt; [],\\n    &#039;exes&#039; =&gt; []\\n];\\n\\n\\\/\\\/ \\u8bfb\\u53d6\\u9879\\u76ee\\u7ea7\\u901a\\u7528\\u4fe1\\u606f\\nif (file_exists($basePath . &#039;\\\/emoji.txt&#039;)) $response[&#039;emoji&#039;] = file_get_contents($basePath . &#039;\\\/emoji.txt&#039;);\\nif (file_exists($basePath . &#039;\\\/summary.txt&#039;)) $response[&#039;summary&#039;] = file_get_contents($basePath . &#039;\\\/summary.txt&#039;);\\nif (file_exists($basePath . &#039;\\\/info.txt&#039;)) $response[&#039;info&#039;] = file_get_contents($basePath . &#039;\\\/info.txt&#039;);\\nif (file_exists($basePath . &#039;\\\/requirements.txt&#039;)) $response[&#039;requirements&#039;] = file_get_contents($basePath . &#039;\\\/requirements.txt&#039;);\\n\\n\\\/\\\/ 5. \\u8bfb\\u53d6\\u7279\\u5b9a\\u7248\\u672c\\u7684\\u6570\\u636e\\nif ($targetVersion) {\\n    $versionPath = $basePath . &#039;\\\/&#039; . $targetVersion;\\n    \\n    \\\/\\\/ --- \\u6838\\u5fc3\\u903b\\u8f91\\uff1a\\u7cbe\\u51c6\\u5339\\u914d [\\u9879\\u76ee\\u540d]_[\\u7248\\u672c\\u53f7].py ---\\n    $fileNamePy = \\&quot;{$project}_{$targetVersion}.py\\&quot;;\\n    $fileNamePyw = \\&quot;{$project}_{$targetVersion}.pyw\\&quot;;\\n    \\n    $fullPathPy = $versionPath . &#039;\\\/&#039; . $fileNamePy;\\n    $fullPathPyw = $versionPath . &#039;\\\/&#039; . $fileNamePyw;\\n\\n    if (file_exists($fullPathPyw)) {\\n        $response[&#039;code&#039;] = [\\n            &#039;filename&#039; =&gt; $fileNamePyw,\\n            &#039;content&#039; =&gt; file_get_contents($fullPathPyw)\\n        ];\\n    } elseif (file_exists($fullPathPy)) {\\n        $response[&#039;code&#039;] = [\\n            &#039;filename&#039; =&gt; $fileNamePy,\\n            &#039;content&#039; =&gt; file_get_contents($fullPathPy)\\n        ];\\n    } else {\\n        \\\/\\\/ \\u4fdd\\u5e95\\u65b9\\u6848\\uff1a\\u626b\\u63cf\\u8be5\\u76ee\\u5f55\\u4e0b\\u4efb\\u610f py \\u6587\\u4ef6\\n        $anyPy = glob($versionPath . \\&quot;\\\/*.{py,pyw}\\&quot;, GLOB_BRACE);\\n        if (!empty($anyPy)) {\\n            $realFile = $anyPy[0];\\n            $response[&#039;code&#039;] = [\\n                &#039;filename&#039; =&gt; basename($realFile),\\n                &#039;content&#039; =&gt; file_get_contents($realFile)\\n            ];\\n        } else {\\n            \\\/\\\/ \\u8c03\\u8bd5\\u6a21\\u5f0f\\uff1a\\u53cd\\u9988\\u627e\\u4e0d\\u5230\\u6587\\u4ef6\\u7684\\u5177\\u4f53\\u539f\\u56e0\\n            $response[&#039;code&#039;] = [\\n                &#039;filename&#039; =&gt; &#039;\\u672a\\u627e\\u5230\\u5bf9\\u5e94\\u6e90\\u7801\\u6587\\u4ef6&#039;,\\n                &#039;content&#039; =&gt; \\&quot;# \\u9519\\u8bef\\uff1a\\u7cfb\\u7edf\\u65e0\\u6cd5\\u5728\\u76ee\\u5f55\\u4e0b\\u627e\\u5230\\u4ee3\\u7801\\u6587\\u4ef6\\\\n# \\u671f\\u5f85\\u7684\\u6587\\u4ef6\\u540d: $fileNamePy\\\\n# \\u5b9e\\u9645\\u8def\\u5f84: $versionPath\\&quot;\\n            ];\\n        }\\n    }\\n\\n    \\\/\\\/ \\u626b\\u63cf\\u622a\\u56fe\\n    $ssDir = $versionPath . &#039;\\\/screenshots\\\/&#039;;\\n    if (is_dir($ssDir)) {\\n        $files = array_diff(scandir($ssDir), [&#039;.&#039;, &#039;..&#039;]);\\n        $response[&#039;screenshots&#039;] = array_values(preg_grep(&#039;\\\/\\\\.(png|jpg|jpeg|gif|webp)$\\\/i&#039;, $files));\\n    }\\n\\n    \\\/\\\/ \\u626b\\u63cf EXE\\n    $exeDir = $versionPath . &#039;\\\/exe\\\/&#039;;\\n    if (is_dir($exeDir)) {\\n        $files = array_diff(scandir($exeDir), [&#039;.&#039;, &#039;..&#039;]);\\n        $response[&#039;exes&#039;] = array_values(preg_grep(&#039;\\\/\\\\.exe$\\\/i&#039;, $files));\\n    }\\n}\\n\\n\\\/\\\/ 6. \\u8f93\\u51fa\\u6700\\u7ec8 JSON\\necho json_encode($response);&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:12,&quot;tablet&quot;:15,&quot;mobile&quot;:14},&quot;height&quot;:{&quot;desktop&quot;:&quot;200px&quot;,&quot;tablet&quot;:&quot;0px&quot;,&quot;mobile&quot;:&quot;0px&quot;},&quot;align&quot;:&quot;&quot;,&quot;lineNumbers&quot;:true,&quot;theme&quot;:&quot;default&quot;,&quot;clipBoard&quot;:true,&quot;wordWrap&quot;:true,&quot;width&quot;:{&quot;desktop&quot;:&quot;100%&quot;,&quot;tablet&quot;:&quot;100%&quot;,&quot;mobile&quot;:&quot;100%&quot;},&quot;padding&quot;:{&quot;top&quot;:&quot;0px&quot;,&quot;right&quot;:&quot;0px&quot;,&quot;bottom&quot;:&quot;0px&quot;,&quot;left&quot;:&quot;0px&quot;},&quot;background&quot;:{&quot;color&quot;:&quot;#d3cfcf42&quot;},&quot;layout&quot;:{&quot;align&quot;:&quot;left&quot;},&quot;border&quot;:{&quot;color&quot;:&quot;#000&quot;,&quot;style&quot;:&quot;solid&quot;,&quot;width&quot;:&quot;0px&quot;},&quot;shadow&quot;:[],&quot;alignment&quot;:&quot;center&quot;,&quot;clipBoardColors&quot;:{&quot;color&quot;:&quot;#fff&quot;,&quot;bg&quot;:&quot;#00000024&quot;}}'><\/div>\r\n\r\n\t\t\n\n\n<h3 class=\"wp-block-heading\">\u540e\u53f0<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><em>\u4ee5\u4e0b\u6587\u4ef6\u5747\u4f4d\u4e8e\/admin\u6587\u4ef6\u5939\u3002<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">index\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-a1aa28ed-c' data-attributes='{&quot;cId&quot;:&quot;a1aa28ed-c&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\n\\\/\\\/ get_details.php - \\u653e\\u7f6e\\u5728\\u7f51\\u7ad9\\u6839\\u76ee\\u5f55\\nheader(&#039;Content-Type: application\\\/json&#039;);\\n\\n\\\/\\\/ 1. \\u83b7\\u53d6\\u5e76\\u6e05\\u7406\\u53c2\\u6570\\n$project = isset($_GET[&#039;project&#039;]) ? trim($_GET[&#039;project&#039;]) : &#039;&#039;;\\n$requestedVersion = isset($_GET[&#039;version&#039;]) ? trim($_GET[&#039;version&#039;]) : &#039;&#039;;\\n\\n\\\/\\\/ 2. \\u786e\\u5b9a\\u7269\\u7406\\u6839\\u8def\\u5f84\\uff08\\u4f7f\\u7528 realpath \\u786e\\u4fdd\\u8def\\u5f84\\u5b58\\u5728\\u4e14\\u5408\\u6cd5\\uff09\\n$projectsRoot = __DIR__ . &#039;\\\/projects&#039;;\\n$basePath = $projectsRoot . &#039;\\\/&#039; . $project;\\n\\n\\\/\\\/ \\u57fa\\u7840\\u5b89\\u5168\\u68c0\\u67e5\\nif (!$project || !is_dir($basePath)) {\\n    echo json_encode([\\n        &#039;error&#039; =&gt; &#039;\\u9879\\u76ee\\u76ee\\u5f55\\u4e0d\\u5b58\\u5728&#039;,\\n        &#039;debug_path&#039; =&gt; $basePath\\n    ]);\\n    exit;\\n}\\n\\n\\\/\\\/ 3. \\u83b7\\u53d6\\u7248\\u672c\\u5217\\u8868\\n$dirs = array_filter(glob($basePath . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\n$versionListNames = array_values(array_map(&#039;basename&#039;, $dirs));\\nusort($versionListNames, &#039;version_compare&#039;); \\\/\\\/ \\u5347\\u5e8f\\u6392\\u5217\\uff1a1.0, 1.1...\\n\\n\\\/\\\/ \\u786e\\u5b9a\\u5f53\\u524d\\u8981\\u663e\\u793a\\u7684\\u7248\\u672c\\n$targetVersion = $requestedVersion;\\nif (!$targetVersion || !in_array($targetVersion, $versionListNames)) {\\n    $targetVersion = !empty($versionListNames) ? end($versionListNames) : &#039;&#039;; \\\/\\\/ \\u9ed8\\u8ba4\\u53d6\\u6700\\u65b0\\u7248\\n}\\n\\n\\\/\\\/ 4. \\u521d\\u59cb\\u5316\\u54cd\\u5e94\\u7ed3\\u6784\\uff08\\u786e\\u4fdd\\u524d\\u7aef\\u6240\\u6709\\u5b57\\u6bb5\\u90fd\\u6709\\u9ed8\\u8ba4\\u503c\\uff0c\\u9632\\u6b62 JS \\u62a5\\u9519\\uff09\\n$response = [\\n    &#039;emoji&#039; =&gt; &#039;\\ud83d\\ude80&#039;,\\n    &#039;summary&#039; =&gt; &#039;&#039;,\\n    &#039;info&#039; =&gt; &#039;&#039;,\\n    &#039;requirements&#039; =&gt; &#039;&#039;,\\n    &#039;available_versions&#039; =&gt; $versionListNames,\\n    &#039;version&#039; =&gt; $targetVersion,\\n    &#039;code&#039; =&gt; [\\n        &#039;filename&#039; =&gt; &#039;\\u65e0\\u4ee3\\u7801&#039;,\\n        &#039;content&#039; =&gt; &#039;# \\u6682\\u65e0\\u4ee3\\u7801\\u5185\\u5bb9&#039;\\n    ],\\n    &#039;screenshots&#039; =&gt; [],\\n    &#039;exes&#039; =&gt; []\\n];\\n\\n\\\/\\\/ \\u8bfb\\u53d6\\u9879\\u76ee\\u7ea7\\u901a\\u7528\\u4fe1\\u606f\\nif (file_exists($basePath . &#039;\\\/emoji.txt&#039;)) $response[&#039;emoji&#039;] = file_get_contents($basePath . &#039;\\\/emoji.txt&#039;);\\nif (file_exists($basePath . &#039;\\\/summary.txt&#039;)) $response[&#039;summary&#039;] = file_get_contents($basePath . &#039;\\\/summary.txt&#039;);\\nif (file_exists($basePath . &#039;\\\/info.txt&#039;)) $response[&#039;info&#039;] = file_get_contents($basePath . &#039;\\\/info.txt&#039;);\\nif (file_exists($basePath . &#039;\\\/requirements.txt&#039;)) $response[&#039;requirements&#039;] = file_get_contents($basePath . &#039;\\\/requirements.txt&#039;);\\n\\n\\\/\\\/ 5. \\u8bfb\\u53d6\\u7279\\u5b9a\\u7248\\u672c\\u7684\\u6570\\u636e\\nif ($targetVersion) {\\n    $versionPath = $basePath . &#039;\\\/&#039; . $targetVersion;\\n    \\n    \\\/\\\/ --- \\u6838\\u5fc3\\u903b\\u8f91\\uff1a\\u7cbe\\u51c6\\u5339\\u914d [\\u9879\\u76ee\\u540d]_[\\u7248\\u672c\\u53f7].py ---\\n    $fileNamePy = \\&quot;{$project}_{$targetVersion}.py\\&quot;;\\n    $fileNamePyw = \\&quot;{$project}_{$targetVersion}.pyw\\&quot;;\\n    \\n    $fullPathPy = $versionPath . &#039;\\\/&#039; . $fileNamePy;\\n    $fullPathPyw = $versionPath . &#039;\\\/&#039; . $fileNamePyw;\\n\\n    if (file_exists($fullPathPyw)) {\\n        $response[&#039;code&#039;] = [\\n            &#039;filename&#039; =&gt; $fileNamePyw,\\n            &#039;content&#039; =&gt; file_get_contents($fullPathPyw)\\n        ];\\n    } elseif (file_exists($fullPathPy)) {\\n        $response[&#039;code&#039;] = [\\n            &#039;filename&#039; =&gt; $fileNamePy,\\n            &#039;content&#039; =&gt; file_get_contents($fullPathPy)\\n        ];\\n    } else {\\n        \\\/\\\/ \\u4fdd\\u5e95\\u65b9\\u6848\\uff1a\\u626b\\u63cf\\u8be5\\u76ee\\u5f55\\u4e0b\\u4efb\\u610f py \\u6587\\u4ef6\\n        $anyPy = glob($versionPath . \\&quot;\\\/*.{py,pyw}\\&quot;, GLOB_BRACE);\\n        if (!empty($anyPy)) {\\n            $realFile = $anyPy[0];\\n            $response[&#039;code&#039;] = [\\n                &#039;filename&#039; =&gt; basename($realFile),\\n                &#039;content&#039; =&gt; file_get_contents($realFile)\\n            ];\\n        } else {\\n            \\\/\\\/ \\u8c03\\u8bd5\\u6a21\\u5f0f\\uff1a\\u53cd\\u9988\\u627e\\u4e0d\\u5230\\u6587\\u4ef6\\u7684\\u5177\\u4f53\\u539f\\u56e0\\n            $response[&#039;code&#039;] = [\\n                &#039;filename&#039; =&gt; &#039;\\u672a\\u627e\\u5230\\u5bf9\\u5e94\\u6e90\\u7801\\u6587\\u4ef6&#039;,\\n                &#039;content&#039; =&gt; \\&quot;# \\u9519\\u8bef\\uff1a\\u7cfb\\u7edf\\u65e0\\u6cd5\\u5728\\u76ee\\u5f55\\u4e0b\\u627e\\u5230\\u4ee3\\u7801\\u6587\\u4ef6\\\\n# \\u671f\\u5f85\\u7684\\u6587\\u4ef6\\u540d: $fileNamePy\\\\n# \\u5b9e\\u9645\\u8def\\u5f84: $versionPath\\&quot;\\n            ];\\n        }\\n    }\\n\\n    \\\/\\\/ \\u626b\\u63cf\\u622a\\u56fe\\n    $ssDir = $versionPath . &#039;\\\/screenshots\\\/&#039;;\\n    if (is_dir($ssDir)) {\\n        $files = array_diff(scandir($ssDir), [&#039;.&#039;, &#039;..&#039;]);\\n        $response[&#039;screenshots&#039;] = array_values(preg_grep(&#039;\\\/\\\\.(png|jpg|jpeg|gif|webp)$\\\/i&#039;, $files));\\n    }\\n\\n    \\\/\\\/ \\u626b\\u63cf EXE\\n    $exeDir = $versionPath . &#039;\\\/exe\\\/&#039;;\\n    if (is_dir($exeDir)) {\\n        $files = array_diff(scandir($exeDir), [&#039;.&#039;, &#039;..&#039;]);\\n        $response[&#039;exes&#039;] = array_values(preg_grep(&#039;\\\/\\\\.exe$\\\/i&#039;, $files));\\n    }\\n}\\n\\n\\\/\\\/ 6. \\u8f93\\u51fa\\u6700\\u7ec8 JSON\\necho json_encode($response);&quot;,&quot;theme&quot;:&quot;porple&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:12,&quot;tablet&quot;:15,&quot;mobile&quot;:14},&quot;height&quot;:{&quot;desktop&quot;:&quot;200px&quot;,&quot;tablet&quot;:&quot;0px&quot;,&quot;mobile&quot;:&quot;0px&quot;},&quot;background&quot;:{&quot;color&quot;:&quot;#d3cfcf42&quot;,&quot;type&quot;:&quot;gradient&quot;,&quot;gradient&quot;:&quot;linear-gradient(135deg,rgb(69,39,164) 0%,rgb(15,5,5) 42%,rgb(131,68,197) 100%)&quot;},&quot;align&quot;:&quot;&quot;,&quot;lineNumbers&quot;:true,&quot;clipBoard&quot;:true,&quot;wordWrap&quot;:true,&quot;width&quot;:{&quot;desktop&quot;:&quot;100%&quot;,&quot;tablet&quot;:&quot;100%&quot;,&quot;mobile&quot;:&quot;100%&quot;},&quot;padding&quot;:{&quot;top&quot;:&quot;0px&quot;,&quot;right&quot;:&quot;0px&quot;,&quot;bottom&quot;:&quot;0px&quot;,&quot;left&quot;:&quot;0px&quot;},&quot;layout&quot;:{&quot;align&quot;:&quot;left&quot;},&quot;border&quot;:{&quot;color&quot;:&quot;#000&quot;,&quot;style&quot;:&quot;solid&quot;,&quot;width&quot;:&quot;0px&quot;},&quot;shadow&quot;:[],&quot;alignment&quot;:&quot;center&quot;,&quot;clipBoardColors&quot;:{&quot;color&quot;:&quot;#fff&quot;,&quot;bg&quot;:&quot;#00000024&quot;}}'><\/div>\r\n\r\n\t\t\n\n\n<p class=\"wp-block-paragraph\">login\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-f8738380-3' data-attributes='{&quot;cId&quot;:&quot;f8738380-3&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\n\\\/\\\/ admin\\\/login.php\\nsession_start();\\n\\nif (isset($_POST[&#039;username&#039;]) &amp;&amp; isset($_POST[&#039;password&#039;])) {\\n    \\\/\\\/ \\u7b80\\u5355\\u7684\\u786c\\u7f16\\u7801\\u7528\\u6237\\u540d\\u548c\\u5bc6\\u7801 (\\u4e0d\\u5b89\\u5168\\uff0c\\u4ec5\\u4f5c\\u793a\\u4f8b)\\n    $username = &#039;admin&#039;;\\n    $password = &#039;\\u540e\\u53f0\\u5bc6\\u7801&#039;;\\n\\n    if ($_POST[&#039;username&#039;] === $username &amp;&amp; $_POST[&#039;password&#039;] === $password) {\\n        $_SESSION[&#039;loggedin&#039;] = true;\\n        $_SESSION[&#039;username&#039;] = $username;\\n        header(&#039;Location: index.php&#039;);\\n        exit;\\n    } else {\\n        $error = &#039;\\u7528\\u6237\\u540d\\u6216\\u5bc6\\u7801\\u9519\\u8bef\\u3002&#039;;\\n    }\\n}\\n\\n\\\/\\\/ \\u5982\\u679c\\u5df2\\u7ecf\\u767b\\u5f55\\uff0c\\u76f4\\u63a5\\u8df3\\u8f6c\\u5230\\u7ba1\\u7406\\u9875\\u9762\\nif (isset($_SESSION[&#039;loggedin&#039;]) &amp;&amp; $_SESSION[&#039;loggedin&#039;] === true) {\\n    header(&#039;Location: index.php&#039;);\\n    exit;\\n}\\n?&gt;\\n&lt;!DOCTYPE html&gt;\\n&lt;html lang=\\&quot;zh\\&quot;&gt;\\n&lt;head&gt;\\n    &lt;meta charset=\\&quot;UTF-8\\&quot;&gt;\\n    &lt;title&gt;\\u767b\\u5f55\\u7ba1\\u7406\\u540e\\u53f0&lt;\\\/title&gt;\\n    &lt;style&gt;\\n        body { font-family: Arial, sans-serif; background-color: #f4f4f4; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; }\\n        .login-container { background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); width: 300px; text-align: center; }\\n        .login-container h2 { margin-bottom: 20px; color: #333; }\\n        .login-container input[type=\\&quot;text\\&quot;],\\n        .login-container input[type=\\&quot;password\\&quot;] { width: calc(100% - 20px); padding: 10px; margin-bottom: 15px; border: 1px solid #ddd; border-radius: 4px; }\\n        .login-container button { width: 100%; padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1em; }\\n        .login-container button:hover { background-color: #0056b3; }\\n        .error-message { color: red; margin-bottom: 15px; }\\n    &lt;\\\/style&gt;\\n&lt;\\\/head&gt;\\n&lt;body&gt;\\n    &lt;div class=\\&quot;login-container\\&quot;&gt;\\n        &lt;h2&gt;\\u7ba1\\u7406\\u540e\\u53f0\\u767b\\u5f55&lt;\\\/h2&gt;\\n        &lt;?php if (isset($error)): ?&gt;\\n            &lt;p class=\\&quot;error-message\\&quot;&gt;&lt;?= htmlspecialchars($error) ?&gt;&lt;\\\/p&gt;\\n        &lt;?php endif; ?&gt;\\n        &lt;form method=\\&quot;post\\&quot;&gt;\\n            &lt;input type=\\&quot;text\\&quot; name=\\&quot;username\\&quot; placeholder=\\&quot;\\u7528\\u6237\\u540d\\&quot; required&gt;\\n            &lt;input type=\\&quot;password\\&quot; name=\\&quot;password\\&quot; placeholder=\\&quot;\\u5bc6\\u7801\\&quot; required&gt;\\n            &lt;button type=\\&quot;submit\\&quot;&gt;\\u767b\\u5f55&lt;\\\/button&gt;\\n        &lt;\\\/form&gt;\\n    &lt;\\\/div&gt;\\n&lt;\\\/body&gt;\\n&lt;\\\/html&gt;&quot;,&quot;theme&quot;:&quot;porple&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:12,&quot;tablet&quot;:15,&quot;mobile&quot;:14},&quot;height&quot;:{&quot;desktop&quot;:&quot;200px&quot;,&quot;tablet&quot;:&quot;0px&quot;,&quot;mobile&quot;:&quot;0px&quot;},&quot;background&quot;:{&quot;color&quot;:&quot;#d3cfcf42&quot;,&quot;type&quot;:&quot;gradient&quot;,&quot;gradient&quot;:&quot;linear-gradient(135deg,rgb(69,39,164) 0%,rgb(15,5,5) 42%,rgb(131,68,197) 100%)&quot;},&quot;align&quot;:&quot;&quot;,&quot;lineNumbers&quot;:true,&quot;clipBoard&quot;:true,&quot;wordWrap&quot;:true,&quot;width&quot;:{&quot;desktop&quot;:&quot;100%&quot;,&quot;tablet&quot;:&quot;100%&quot;,&quot;mobile&quot;:&quot;100%&quot;},&quot;padding&quot;:{&quot;top&quot;:&quot;0px&quot;,&quot;right&quot;:&quot;0px&quot;,&quot;bottom&quot;:&quot;0px&quot;,&quot;left&quot;:&quot;0px&quot;},&quot;layout&quot;:{&quot;align&quot;:&quot;left&quot;},&quot;border&quot;:{&quot;color&quot;:&quot;#000&quot;,&quot;style&quot;:&quot;solid&quot;,&quot;width&quot;:&quot;0px&quot;},&quot;shadow&quot;:[],&quot;alignment&quot;:&quot;center&quot;,&quot;clipBoardColors&quot;:{&quot;color&quot;:&quot;#fff&quot;,&quot;bg&quot;:&quot;#00000024&quot;}}'><\/div>\r\n\r\n\t\t\n\n\n<p class=\"wp-block-paragraph\">template.html\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-6a1d588c-c' data-attributes='{&quot;cId&quot;:&quot;6a1d588c-c&quot;,&quot;language&quot;:&quot;html&quot;,&quot;code&quot;:&quot;&lt;!DOCTYPE html&gt;\\n&lt;html lang=\\&quot;zh-CN\\&quot;&gt;\\n&lt;head&gt;\\n    &lt;meta charset=\\&quot;UTF-8\\&quot;&gt;\\n    &lt;title&gt;\\u9879\\u76ee\\u7ba1\\u7406\\u540e\\u53f0&lt;\\\/title&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdnjs.cloudflare.com\\\/ajax\\\/libs\\\/font-awesome\\\/6.0.0\\\/css\\\/all.min.css\\&quot;&gt;\\n    &lt;style&gt;\\n        :root { --primary: #3498db; --danger: #e74c3c; --bg: #f4f7f6; }\\n        body { font-family: &#039;Segoe UI&#039;, Tahoma, sans-serif; background: var(--bg); margin: 0; display: flex; height: 100vh; overflow: hidden; }\\n        \\n        .sidebar { width: 260px; background: #2c3e50; color: white; display: flex; flex-direction: column; z-index: 100; }\\n        .sidebar-header { padding: 15px; background: #1a252f; text-align: center; height: 50px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; }\\n        .sidebar-header h3 { margin: 0; font-size: 16px; letter-spacing: 1px; }\\n        \\n        .top-nav { position: absolute; top: 15px; right: 30px; z-index: 1000; }\\n        .logout-btn { color: #95a5a6; text-decoration: none; font-size: 14px; padding: 5px 10px; border: 1px solid #ccc; border-radius: 4px; transition: 0.3s; }\\n        .logout-btn:hover { color: var(--danger); border-color: var(--danger); background: #fff5f5; }\\n\\n        .project-list { flex: 1; overflow-y: auto; padding: 10px; }\\n        .project-item { \\n            padding: 10px 15px; margin-bottom: 5px; border-radius: 6px; \\n            cursor: pointer; display: block; transition: 0.2s; text-decoration: none; color: #bdc3c7;\\n        }\\n        .project-item:hover { background: #3e4f5f; color: white; }\\n        .project-item.active { background: var(--primary); color: white; }\\n\\n        .main-content { flex: 1; overflow-y: auto; padding: 30px; position: relative; padding-top: 60px; }\\n        .card { background: white; padding: 25px; border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.05); margin-bottom: 25px; }\\n        \\n        .project-title-area { display: flex; align-items: center; gap: 15px; margin-bottom: 25px; }\\n        #renameForm { display: none; align-items: center; gap: 10px; width: 100%; }\\n        #renameForm input { width: 300px; font-size: 1.5em; font-weight: bold; margin: 0; }\\n        \\n        .version-bar { display: flex; align-items: center; justify-content: flex-start; gap: 15px; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 8px; border: 1px solid #eee; }\\n\\n        input[type=\\&quot;text\\&quot;], textarea, select { width: 100%; padding: 10px; margin: 8px 0; border: 1px solid #ddd; border-radius: 6px; box-sizing: border-box; }\\n        textarea { height: 120px; font-family: &#039;Consolas&#039;, &#039;Monaco&#039;, monospace; line-height: 1.5; }\\n\\n        .upload-area { border: 3px dashed #ccc; background: #fafafa; padding: 40px 20px; text-align: center; border-radius: 15px; cursor: pointer; transition: 0.3s; margin: 20px 0; }\\n        .upload-area:hover, .upload-area.dragover { background: #f0f7ff; border-color: var(--primary); }\\n        .plus-icon { font-size: 50px; color: #ddd; margin-bottom: 10px; display: block; }\\n\\n        #imgModal { display: none; position: fixed; z-index: 10000; left: 0; top: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.85); justify-content: center; align-items: center; cursor: zoom-out; }\\n        #imgModal img { max-width: 95%; max-height: 95%; background: white; border-radius: 4px; box-shadow: 0 0 30px rgba(0,0,0,0.5); }\\n\\n        .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 15px; margin-top: 15px; }\\n        .preview-item { position: relative; cursor: zoom-in; transition: 0.3s; }\\n        .preview-item:hover { transform: translateY(-2px); }\\n        .preview-item img { width: 100%; height: 100px; object-fit: cover; border-radius: 8px; border: 1px solid #eee; }\\n        .delete-btn { position: absolute; top: -8px; right: -8px; background: var(--danger); color: white; border: none; border-radius: 50%; width: 24px; height: 24px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 12px; }\\n\\n        .btn { padding: 8px 16px; border-radius: 4px; border: none; cursor: pointer; font-weight: 600; display: inline-flex; align-items: center; gap: 5px; }\\n        .btn-primary { background: var(--primary); color: white; }\\n        .btn-danger { background: var(--danger); color: white; }\\n        .btn-save { background: #27ae60; color: white; width: 100%; padding: 12px; margin-top: 10px; font-size: 16px; }\\n\\n        .exe-item { background: #f1f3f5; padding: 12px; border-radius: 8px; margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; border: 1px solid #e9ecef; }\\n        .exe-info { display: flex; align-items: center; gap: 10px; }\\n        .exe-size { font-size: 12px; color: #868e96; background: #e9ecef; padding: 2px 6px; border-radius: 4px; }\\n    &lt;\\\/style&gt;\\n&lt;\\\/head&gt;\\n&lt;body&gt;\\n\\n    &lt;div class=\\&quot;top-nav\\&quot;&gt;\\n        &lt;a href=\\&quot;?logout=1\\&quot; class=\\&quot;logout-btn\\&quot;&gt;&lt;i class=\\&quot;fas fa-sign-out-alt\\&quot;&gt;&lt;\\\/i&gt; \\u9000\\u51fa\\u767b\\u5f55&lt;\\\/a&gt;\\n    &lt;\\\/div&gt;\\n\\n    &lt;div class=\\&quot;sidebar\\&quot;&gt;\\n        &lt;div class=\\&quot;sidebar-header\\&quot;&gt;&lt;h3&gt;\\u9879\\u76ee\\u7ba1\\u7406\\u540e\\u53f0&lt;\\\/h3&gt;&lt;\\\/div&gt;\\n        &lt;div class=\\&quot;project-list\\&quot;&gt;\\n            &lt;?php foreach ($projectListWithEmoji as $p): ?&gt;\\n                &lt;a href=\\&quot;?project=&lt;?= urlencode($p[&#039;name&#039;]) ?&gt;\\&quot; class=\\&quot;project-item &lt;?= $currentProject === $p[&#039;name&#039;] ? &#039;active&#039; : &#039;&#039; ?&gt;\\&quot;&gt;\\n                    &lt;?= $p[&#039;emoji&#039;] ?&gt; &lt;?= htmlspecialchars($p[&#039;name&#039;]) ?&gt;\\n                &lt;\\\/a&gt;\\n            &lt;?php endforeach; ?&gt;\\n            \\n            &lt;form method=\\&quot;POST\\&quot; style=\\&quot;margin-top: 20px; padding: 0 10px;\\&quot;&gt;\\n                &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                &lt;input type=\\&quot;text\\&quot; name=\\&quot;project_name\\&quot; placeholder=\\&quot;+ \\u65b0\\u9879\\u76ee\\u540d\\u79f0\\&quot; \\n                       oninput=\\&quot;this.value=this.value.replace(\\\/[\\\\\\\/\\\\\\\\ &amp;]\\\/g,&#039;&#039;)\\&quot;\\n                       style=\\&quot;background: #3e4f5f; border: none; color: white; font-size: 13px;\\&quot;&gt;\\n                &lt;button type=\\&quot;submit\\&quot; name=\\&quot;new_project\\&quot; class=\\&quot;btn btn-primary\\&quot; style=\\&quot;width: 100%; margin-top: 5px; font-size: 13px;\\&quot;&gt;\\u521b\\u5efa&lt;\\\/button&gt;\\n            &lt;\\\/form&gt;\\n        &lt;\\\/div&gt;\\n    &lt;\\\/div&gt;\\n\\n    &lt;div class=\\&quot;main-content\\&quot;&gt;\\n        &lt;?php if ($currentProject): ?&gt;\\n            &lt;div class=\\&quot;project-title-area\\&quot;&gt;\\n                &lt;div id=\\&quot;titleDisplay\\&quot;&gt;\\n                    &lt;h2 style=\\&quot;display:inline; margin:0;\\&quot;&gt;&lt;?= $emojiText ?&gt; &lt;?= htmlspecialchars($currentProject) ?&gt;&lt;\\\/h2&gt;\\n                    &lt;button class=\\&quot;btn\\&quot; onclick=\\&quot;toggleRename(true)\\&quot; style=\\&quot;background:none; color:var(--primary); font-size: 1.2em;\\&quot;&gt;&lt;i class=\\&quot;fas fa-edit\\&quot;&gt;&lt;\\\/i&gt;&lt;\\\/button&gt;\\n                    \\n                    &lt;form method=\\&quot;POST\\&quot; style=\\&quot;display:inline; margin-left: 10px;\\&quot; onsubmit=\\&quot;return confirm(&#039;\\u8b66\\u544a\\uff1a\\u786e\\u5b9a\\u8981\\u5f7b\\u5e95\\u5220\\u9664\\u6574\\u4e2a\\u9879\\u76ee\\u5417\\uff1f&#039;)\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;del_name\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot;&gt;\\n                        &lt;button type=\\&quot;submit\\&quot; name=\\&quot;delete_project\\&quot; class=\\&quot;btn\\&quot; style=\\&quot;background:none; color:var(--danger); font-size: 1.1em;\\&quot;&gt;&lt;i class=\\&quot;fas fa-trash-alt\\&quot;&gt;&lt;\\\/i&gt;&lt;\\\/button&gt;\\n                    &lt;\\\/form&gt;\\n                &lt;\\\/div&gt;\\n                &lt;form id=\\&quot;renameForm\\&quot; method=\\&quot;POST\\&quot;&gt;\\n                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;old_name\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot;&gt;\\n                    &lt;input type=\\&quot;text\\&quot; name=\\&quot;new_name\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot; \\n                           oninput=\\&quot;this.value=this.value.replace(\\\/[\\\\\\\/\\\\\\\\ &amp;]\\\/g,&#039;&#039;)\\&quot; required&gt;\\n                    &lt;button type=\\&quot;submit\\&quot; name=\\&quot;rename_project\\&quot; class=\\&quot;btn btn-primary\\&quot;&gt;\\u786e\\u5b9a&lt;\\\/button&gt;\\n                    &lt;button type=\\&quot;button\\&quot; class=\\&quot;btn\\&quot; onclick=\\&quot;toggleRename(false)\\&quot;&gt;\\u53d6\\u6d88&lt;\\\/button&gt;\\n                &lt;\\\/form&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div class=\\&quot;card\\&quot;&gt;\\n                &lt;form method=\\&quot;POST\\&quot;&gt;\\n                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;proj\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot;&gt;\\n                    &lt;div style=\\&quot;display:grid; grid-template-columns: 100px 1fr; gap:15px; align-items:center;\\&quot;&gt;\\n                        &lt;label&gt;\\u9879\\u76ee\\u56fe\\u6807:&lt;\\\/label&gt;&lt;input type=\\&quot;text\\&quot; name=\\&quot;emoji\\&quot; value=\\&quot;&lt;?= $emojiText ?&gt;\\&quot; placeholder=\\&quot;Emoji\\&quot;&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;label&gt;\\u5217\\u8868\\u7b80\\u4ecb:&lt;\\\/label&gt;&lt;input type=\\&quot;text\\&quot; name=\\&quot;summary\\&quot; value=\\&quot;&lt;?= htmlspecialchars($summaryText) ?&gt;\\&quot;&gt;\\n                    &lt;label&gt;\\u8be6\\u7ec6\\u4ecb\\u7ecd (Markdown):&lt;\\\/label&gt;&lt;textarea name=\\&quot;info\\&quot;&gt;&lt;?= htmlspecialchars($generalInfoText) ?&gt;&lt;\\\/textarea&gt;\\n                    &lt;label&gt;\\u8fd0\\u884c\\u73af\\u5883\\u4f9d\\u8d56:&lt;\\\/label&gt;&lt;textarea name=\\&quot;requirements\\&quot; style=\\&quot;height:60px;\\&quot;&gt;&lt;?= htmlspecialchars($requirementsText) ?&gt;&lt;\\\/textarea&gt;\\n                    &lt;button type=\\&quot;submit\\&quot; name=\\&quot;save_general_info\\&quot; class=\\&quot;btn btn-save\\&quot;&gt;\\u4fdd\\u5b58\\u6240\\u6709\\u57fa\\u7840\\u4fe1\\u606f&lt;\\\/button&gt;\\n                &lt;\\\/form&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div class=\\&quot;card\\&quot;&gt;\\n                \\n                &lt;div class=\\&quot;version-bar\\&quot;&gt;\\n                    &lt;span style=\\&quot;font-weight: bold; color: #666;\\&quot;&gt;\\u7248\\u672c\\u63a7\\u5236:&lt;\\\/span&gt;\\n                    &lt;select style=\\&quot;width:140px; margin:0;\\&quot; onchange=\\&quot;handleVersionChange(this.value)\\&quot;&gt;\\n                        &lt;?php foreach ($projectVersions as $v): ?&gt;\\n                            &lt;option value=\\&quot;&lt;?= $v ?&gt;\\&quot; &lt;?= $currentVersion === $v ? &#039;selected&#039; : &#039;&#039; ?&gt;&gt;&lt;?= $v ?&gt;&lt;\\\/option&gt;\\n                        &lt;?php endforeach; ?&gt;\\n                    &lt;\\\/select&gt;\\n                \\n                    &lt;?php if ($currentVersion): ?&gt;\\n                    &lt;form method=\\&quot;POST\\&quot; style=\\&quot;display:inline;\\&quot; onsubmit=\\&quot;return confirm(&#039;\\u8b66\\u544a\\uff1a\\u786e\\u5b9a\\u8981\\u5220\\u9664\\u7248\\u672c &lt;?= htmlspecialchars($currentVersion) ?&gt; \\u5417\\uff1f\\u6b64\\u64cd\\u4f5c\\u4e0d\\u53ef\\u64a4\\u9500\\uff01&#039;)\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;proj\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;del_version_name\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentVersion) ?&gt;\\&quot;&gt;\\n                        &lt;button type=\\&quot;submit\\&quot; name=\\&quot;delete_version\\&quot; class=\\&quot;btn\\&quot; style=\\&quot;background:none; color:var(--danger); padding: 0 5px;\\&quot;&gt;\\n                            &lt;i class=\\&quot;fas fa-trash-alt\\&quot;&gt;&lt;\\\/i&gt;\\n                        &lt;\\\/button&gt;\\n                    &lt;\\\/form&gt;\\n                    &lt;?php endif; ?&gt;\\n                    \\n                    &lt;form method=\\&quot;POST\\&quot; style=\\&quot;display:flex; gap:8px;\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;proj\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot;&gt;\\n                        &lt;input type=\\&quot;text\\&quot; name=\\&quot;version_name\\&quot; placeholder=\\&quot;\\u7248\\u672c\\u53f7\\&quot; style=\\&quot;width:90px; margin:0;\\&quot; required&gt;\\n                        &lt;button type=\\&quot;submit\\&quot; name=\\&quot;new_version\\&quot; class=\\&quot;btn btn-primary\\&quot;&gt;&lt;i class=\\&quot;fas fa-plus\\&quot;&gt;&lt;\\\/i&gt;&lt;\\\/button&gt;\\n                    &lt;\\\/form&gt;\\n                &lt;\\\/div&gt;\\n\\n                &lt;?php if ($currentVersion): ?&gt;\\n                    &lt;h4&gt;Python \\u6e90\\u7801&lt;\\\/h4&gt;\\n                    &lt;?php\\n                        \\\/\\\/ --- \\u5173\\u952e\\u4fee\\u590d\\uff1a\\u5728\\u8fd9\\u91cc\\u91cd\\u65b0\\u8bfb\\u53d6\\u4e00\\u904d\\u5185\\u5bb9\\uff0c\\u9632\\u6b62\\u540e\\u53f0\\u53d8\\u91cf\\u6ca1\\u66f4\\u65b0 ---\\n                        $vPath = \\&quot;..\\\/projects\\\/$currentProject\\\/$currentVersion\\\/\\&quot;;\\n                        $realCode = &#039;&#039;;\\n                        if (file_exists($vPath . \\&quot;main.pyw\\&quot;)) {\\n                            $realCode = file_get_contents($vPath . \\&quot;main.pyw\\&quot;);\\n                        } elseif (file_exists($vPath . \\&quot;main.py\\&quot;)) {\\n                            $realCode = file_get_contents($vPath . \\&quot;main.py\\&quot;);\\n                        } else {\\n                            \\\/\\\/ \\u5c1d\\u8bd5\\u4e0d\\u5e26 ..\\\/ \\u7684\\u8def\\u5f84\\uff08\\u53d6\\u51b3\\u4e8e\\u4f60\\u7684\\u540e\\u53f0\\u76ee\\u5f55\\u7ed3\\u6784\\uff09\\n                            $vPathAlt = \\&quot;projects\\\/$currentProject\\\/$currentVersion\\\/\\&quot;;\\n                            if (file_exists($vPathAlt . \\&quot;main.pyw\\&quot;)) $realCode = file_get_contents($vPathAlt . \\&quot;main.pyw\\&quot;);\\n                            elseif (file_exists($vPathAlt . \\&quot;main.py\\&quot;)) $realCode = file_get_contents($vPathAlt . \\&quot;main.py\\&quot;);\\n                        }\\n                    ?&gt;\\n                    \\n                    &lt;form method=\\&quot;POST\\&quot; id=\\&quot;codeForm\\&quot; onsubmit=\\&quot;clearDraft()\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;proj\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;version\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentVersion) ?&gt;\\&quot;&gt;\\n                        &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;is_pyw\\&quot; id=\\&quot;isPywFlag\\&quot; value=\\&quot;0\\&quot;&gt;\\n                        \\n                        &lt;textarea id=\\&quot;codeEditor\\&quot; name=\\&quot;code_content\\&quot; style=\\&quot;height: 400px; background: #282c34; color: #abb2bf; font-size: 14px;\\&quot;&gt;&lt;?= htmlspecialchars($codeContent) ?&gt;&lt;\\\/textarea&gt;\\n                        \\n                        &lt;button type=\\&quot;submit\\&quot; name=\\&quot;save_code\\&quot; class=\\&quot;btn btn-save\\&quot; style=\\&quot;background:#3498db\\&quot;&gt;\\u4fdd\\u5b58\\u6e90\\u7801\\u5185\\u5bb9&lt;\\\/button&gt;\\n                    &lt;\\\/form&gt;\\n\\n                    &lt;div class=\\&quot;upload-area\\&quot; id=\\&quot;dropZone\\&quot; onclick=\\&quot;document.getElementById(&#039;fileInput&#039;).click()\\&quot;&gt;\\n                        &lt;i class=\\&quot;fas fa-cloud-upload-alt plus-icon\\&quot;&gt;&lt;\\\/i&gt;\\n                        &lt;p style=\\&quot;margin:0; font-weight:bold;\\&quot;&gt;\\u62d6\\u62fd\\u6587\\u4ef6\\u3001\\u7c98\\u8d34\\u622a\\u56fe\\u3001\\u6216\\u70b9\\u51fb\\u4e0a\\u4f20&lt;\\\/p&gt;\\n                        &lt;input type=\\&quot;file\\&quot; id=\\&quot;fileInput\\&quot; multiple style=\\&quot;display:none\\&quot; onchange=\\&quot;handleFiles(this.files)\\&quot;&gt;\\n                        &lt;div id=\\&quot;uploadStatus\\&quot;&gt;&lt;\\\/div&gt;\\n                    &lt;\\\/div&gt;\\n\\n                    &lt;h4&gt;\\u622a\\u56fe\\u5c55\\u793a&lt;\\\/h4&gt;\\n                    &lt;div class=\\&quot;grid\\&quot;&gt;\\n                        &lt;?php foreach ($screenshots as $ss): ?&gt;\\n                            &lt;div class=\\&quot;preview-item\\&quot; onclick=\\&quot;showOriginal(&#039;..\\\/projects\\\/&lt;?= urlencode($currentProject) ?&gt;\\\/&lt;?= urlencode($currentVersion) ?&gt;\\\/screenshots\\\/&lt;?= urlencode($ss) ?&gt;&#039;)\\&quot;&gt;\\n                                &lt;img src=\\&quot;..\\\/projects\\\/&lt;?= ($currentProject) ?&gt;\\\/&lt;?= ($currentVersion) ?&gt;\\\/screenshots\\\/&lt;?= ($ss) ?&gt;\\&quot;&gt;\\n                                &lt;form method=\\&quot;POST\\&quot; style=\\&quot;margin:0;\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;proj\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;version\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentVersion) ?&gt;\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;type\\&quot; value=\\&quot;screenshot\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;file\\&quot; value=\\&quot;&lt;?= htmlspecialchars($ss) ?&gt;\\&quot;&gt;\\n                                    &lt;button type=\\&quot;submit\\&quot; name=\\&quot;delete_file\\&quot; class=\\&quot;delete-btn\\&quot; onclick=\\&quot;event.stopPropagation()\\&quot;&gt;&lt;i class=\\&quot;fas fa-times\\&quot;&gt;&lt;\\\/i&gt;&lt;\\\/button&gt;\\n                                &lt;\\\/form&gt;\\n                            &lt;\\\/div&gt;\\n                        &lt;?php endforeach; ?&gt;\\n                    &lt;\\\/div&gt;\\n\\n                    &lt;h4 style=\\&quot;margin-top:30px;\\&quot;&gt;\\u6267\\u884c\\u6587\\u4ef6 (EXE)&lt;\\\/h4&gt;\\n                    &lt;div id=\\&quot;exeList\\&quot;&gt;\\n                        &lt;?php foreach ($exeFiles as $exe): ?&gt;\\n                            &lt;div class=\\&quot;exe-item\\&quot;&gt;\\n                                &lt;div class=\\&quot;exe-info\\&quot;&gt;\\n                                    &lt;i class=\\&quot;fas fa-file-code\\&quot; style=\\&quot;color:#74c0fc\\&quot;&gt;&lt;\\\/i&gt;\\n                                    &lt;span&gt;&lt;?= htmlspecialchars($exe[&#039;name&#039;]) ?&gt;&lt;\\\/span&gt;\\n                                    &lt;span class=\\&quot;exe-size\\&quot;&gt;&lt;?= $exe[&#039;size&#039;] ?&gt;&lt;\\\/span&gt; &lt;\\\/div&gt;\\n                                &lt;form method=\\&quot;POST\\&quot; style=\\&quot;margin:0;\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;csrf_token\\&quot; value=\\&quot;&lt;?= $csrfToken ?&gt;\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;proj\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentProject) ?&gt;\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;version\\&quot; value=\\&quot;&lt;?= htmlspecialchars($currentVersion) ?&gt;\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;type\\&quot; value=\\&quot;exe\\&quot;&gt;\\n                                    &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;file\\&quot; value=\\&quot;&lt;?= htmlspecialchars($exe[&#039;name&#039;]) ?&gt;\\&quot;&gt;\\n                                    &lt;button type=\\&quot;submit\\&quot; name=\\&quot;delete_file\\&quot; class=\\&quot;btn btn-danger\\&quot; style=\\&quot;padding:4px 10px; font-size:12px;\\&quot;&gt;\\u5220\\u9664&lt;\\\/button&gt;\\n                                &lt;\\\/form&gt;\\n                            &lt;\\\/div&gt;\\n                        &lt;?php endforeach; ?&gt;\\n                    &lt;\\\/div&gt;\\n                &lt;?php endif; ?&gt;\\n            &lt;\\\/div&gt;\\n        &lt;?php else: ?&gt;\\n            &lt;div class=\\&quot;card\\&quot; style=\\&quot;text-align: center; padding: 100px 0;\\&quot;&gt;\\n                &lt;i class=\\&quot;fas fa-folder-open\\&quot; style=\\&quot;font-size: 60px; color: #eee; margin-bottom: 20px; display:block;\\&quot;&gt;&lt;\\\/i&gt;\\n                &lt;h3 style=\\&quot;color:#999;\\&quot;&gt;\\u8bf7\\u5728\\u4fa7\\u8fb9\\u680f\\u9009\\u62e9\\u9879\\u76ee\\u5f00\\u59cb\\u5de5\\u4f5c&lt;\\\/h3&gt;\\n            &lt;\\\/div&gt;\\n        &lt;?php endif; ?&gt;\\n    &lt;\\\/div&gt;\\n\\n    &lt;div id=\\&quot;imgModal\\&quot; onclick=\\&quot;this.style.display=&#039;none&#039;\\&quot;&gt;&lt;img id=\\&quot;modalImg\\&quot; src=\\&quot;\\&quot;&gt;&lt;\\\/div&gt;\\n\\n&lt;script&gt;\\n    \\\/\\\/ --- \\u6838\\u5fc3\\u53d8\\u91cf\\u521d\\u59cb\\u5316 ---\\n    const currentProj = &lt;?= json_encode($currentProject ?? &#039;&#039;) ?&gt;;\\n    const currentVer = &lt;?= json_encode($currentVersion ?? &#039;&#039;) ?&gt;;\\n    const draftKey = `draft_${currentProj}_${currentVer}`;\\n    \\n    const codeEditor = document.getElementById(&#039;codeEditor&#039;);\\n    const scrollContainer = document.querySelector(&#039;.main-content&#039;);\\n    \\n    \\\/\\\/ \\u5173\\u952e\\uff1a\\u786e\\u4fdd\\u4ece DOM \\u5b9e\\u65f6\\u83b7\\u53d6\\u6e32\\u67d3\\u540e\\u7684\\u4ee3\\u7801\\n    let originalCode = codeEditor ? codeEditor.value : &#039;&#039;;\\n\\n    \\\/\\\/ --- 1. \\u6eda\\u52a8\\u6761\\u4f4d\\u7f6e\\u8fd8\\u539f ---\\n    window.addEventListener(&#039;load&#039;, () =&gt; {\\n        if (scrollContainer) {\\n            const savedY = localStorage.getItem(&#039;admin_scroll_y&#039;);\\n            if (savedY) scrollContainer.scrollTo(0, parseInt(savedY));\\n            \\n            scrollContainer.addEventListener(&#039;scroll&#039;, () =&gt; {\\n                localStorage.setItem(&#039;admin_scroll_y&#039;, scrollContainer.scrollTop);\\n            });\\n        }\\n\\n        \\\/\\\/ --- 2. \\u8349\\u7a3f\\u6062\\u590d\\u903b\\u8f91 ---\\n        if (codeEditor &amp;&amp; currentProj &amp;&amp; currentVer) {\\n            const draft = localStorage.getItem(draftKey);\\n            \\\/\\\/ \\u53ea\\u6709\\u5f53\\u672c\\u5730\\u8349\\u7a3f\\u5b58\\u5728\\uff0c\\u4e14\\u5185\\u5bb9\\u786e\\u5b9e\\u548c\\u670d\\u52a1\\u5668\\u8bfb\\u51fa\\u7684\\u5185\\u5bb9\\u4e0d\\u4e00\\u6837\\u65f6\\uff0c\\u624d\\u63d0\\u793a\\n            if (draft &amp;&amp; draft.trim() !== originalCode.trim() &amp;&amp; originalCode.trim() !== \\&quot;\\&quot;) {\\n                if (confirm(&#039;\\u68c0\\u6d4b\\u5230\\u672c\\u5730\\u6709\\u672a\\u4fdd\\u5b58\\u7684\\u4ee3\\u7801\\u8349\\u7a3f\\uff0c\\u662f\\u5426\\u6062\\u590d\\uff1f&#039;)) {\\n                    codeEditor.value = draft;\\n                } else {\\n                    localStorage.removeItem(draftKey);\\n                }\\n            } else if (draft &amp;&amp; originalCode.trim() === \\&quot;\\&quot;) {\\n                \\\/\\\/ \\u5982\\u679c\\u670d\\u52a1\\u5668\\u662f\\u7a7a\\u7684\\uff0c\\u4f46\\u672c\\u5730\\u6709\\u8349\\u7a3f\\uff0c\\u76f4\\u63a5\\u6062\\u590d\\n                codeEditor.value = draft;\\n            }\\n            \\n            \\\/\\\/ \\u5b9e\\u65f6\\u5b58\\u8349\\u7a3f\\n            codeEditor.addEventListener(&#039;input&#039;, () =&gt; {\\n                localStorage.setItem(draftKey, codeEditor.value);\\n            });\\n        }\\n    });\\n\\n    \\\/\\\/ --- 3. \\u7248\\u672c\\u5207\\u6362\\u4e0e\\u8868\\u5355\\u4fdd\\u62a4 ---\\n    function handleVersionChange(newVersion) {\\n        if (codeEditor &amp;&amp; codeEditor.value !== originalCode) {\\n            if (!confirm(&#039;\\u4ee3\\u7801\\u5c1a\\u672a\\u4fdd\\u5b58\\uff0c\\u5207\\u6362\\u7248\\u672c\\u5c06\\u4e22\\u5931\\u4fee\\u6539\\u3002\\u786e\\u5b9a\\u79bb\\u5f00\\uff1f&#039;)) {\\n                document.querySelector(&#039;.version-bar select&#039;).value = currentVer;\\n                return;\\n            }\\n        }\\n        location.href = `?project=${encodeURIComponent(currentProj)}&amp;version=${encodeURIComponent(newVersion)}`;\\n    }\\n\\n    function clearDraft() {\\n        localStorage.removeItem(draftKey);\\n    }\\n\\n    \\\/\\\/ --- 4. \\u56fe\\u7247\\u4e0e\\u91cd\\u547d\\u540d UI \\u903b\\u8f91 ---\\n    function showOriginal(src) {\\n        const modal = document.getElementById(&#039;imgModal&#039;);\\n        const img = document.getElementById(&#039;modalImg&#039;);\\n        img.src = src;\\n        modal.style.display = &#039;flex&#039;;\\n    }\\n\\n    function toggleRename(show) {\\n        const titleArea = document.getElementById(&#039;titleDisplay&#039;);\\n        const renameForm = document.getElementById(&#039;renameForm&#039;);\\n        if(titleArea) titleArea.style.display = show ? &#039;none&#039; : &#039;block&#039;;\\n        if(renameForm) renameForm.style.display = show ? &#039;flex&#039; : &#039;none&#039;;\\n    }\\n\\n    \\\/\\\/ --- 5. \\u6587\\u4ef6\\u5904\\u7406\\u903b\\u8f91 (\\u7c98\\u8d34\\\/\\u62d6\\u62fd) ---\\n    window.addEventListener(&#039;paste&#039;, e =&gt; {\\n        const items = (e.clipboardData || e.originalEvent.clipboardData).items;\\n        for (let item of items) { if (item.kind === &#039;file&#039;) handleFiles([item.getAsFile()]); }\\n    });\\n\\n    const dropZone = document.getElementById(&#039;dropZone&#039;);\\n    if (dropZone) {\\n        window.addEventListener(&#039;dragover&#039;, e =&gt; { e.preventDefault(); dropZone.classList.add(&#039;dragover&#039;); });\\n        window.addEventListener(&#039;dragleave&#039;, e =&gt; { if (!e.relatedTarget) dropZone.classList.remove(&#039;dragover&#039;); });\\n        dropZone.addEventListener(&#039;drop&#039;, e =&gt; { e.preventDefault(); dropZone.classList.remove(&#039;dragover&#039;); handleFiles(e.dataTransfer.files); });\\n    }\\n\\n    async function handleFiles(files) {\\n            const status = document.getElementById(&#039;uploadStatus&#039;);\\n            if (!status) return;\\n    \\n            for (let file of files) {\\n                const ext = file.name.split(&#039;.&#039;).pop().toLowerCase();\\n                \\n                \\\/\\\/ \\u5982\\u679c\\u662f Python \\u4ee3\\u7801\\u6587\\u4ef6\\n                if (ext === &#039;py&#039; || ext === &#039;pyw&#039;) {\\n                    const reader = new FileReader();\\n                    reader.onload = function(e) {\\n                        if (codeEditor) {\\n                            \\\/\\\/ 1. \\u586b\\u5145\\u5185\\u5bb9\\n                            codeEditor.value = e.target.result;\\n                            \\n                            \\\/\\\/ 2. \\u66f4\\u65b0\\u540e\\u7f00\\u6807\\u5fd7\\n                            const isPywFlag = document.getElementById(&#039;isPywFlag&#039;);\\n                            if (isPywFlag) isPywFlag.value = (ext === &#039;pyw&#039; ? \\&quot;1\\&quot; : \\&quot;0\\&quot;);\\n                            \\n                            \\\/\\\/ 3. \\u63d0\\u793a\\u7528\\u6237\\u624b\\u52a8\\u4fdd\\u5b58\\uff0c\\u800c\\u4e0d\\u662f\\u5f3a\\u5236\\u5237\\u65b0\\n                            status.innerHTML = `&lt;span style=\\&quot;color:var(--primary)\\&quot;&gt;\\u2705 \\u5df2\\u4ece\\u6587\\u4ef6 \\&quot;${file.name}\\&quot; \\u52a0\\u8f7d\\u4ee3\\u7801\\uff0c\\u8bf7\\u70b9\\u51fb\\u4e0b\\u65b9\\u4fdd\\u5b58\\u6309\\u94ae\\u3002&lt;\\\/span&gt;`;\\n                            \\n                            \\\/\\\/ \\u540c\\u65f6\\u4e5f\\u624b\\u52a8\\u89e6\\u53d1\\u4e00\\u4e0b\\u8349\\u7a3f\\u4fdd\\u5b58\\n                            localStorage.setItem(draftKey, codeEditor.value);\\n                        }\\n                    };\\n                    reader.readAsText(file);\\n                    continue; \\\/\\\/ \\u5904\\u7406\\u5b8c\\u4ee3\\u7801\\u6587\\u4ef6\\uff0c\\u8df3\\u8fc7\\u540e\\u9762\\u7684\\u4e0a\\u4f20\\u903b\\u8f91\\n                }\\n    \\n                \\\/\\\/ \\u5982\\u679c\\u662f\\u622a\\u56fe\\u6216 EXE\\uff0c\\u8d70\\u6b63\\u5e38\\u7684\\u4e0a\\u4f20\\u6d41\\u7a0b\\n                const formData = new FormData();\\n                formData.append(&#039;csrf_token&#039;, \\&quot;&lt;?= $csrfToken ?&gt;\\&quot;);\\n                formData.append(&#039;proj&#039;, currentProj);\\n                formData.append(&#039;version&#039;, currentVer);\\n                formData.append(&#039;action&#039;, &#039;upload_files&#039;);\\n                formData.append(&#039;file[]&#039;, file);\\n                \\n                status.innerHTML = `&lt;span style=\\&quot;color:var(--primary)\\&quot;&gt;\\u4e0a\\u4f20\\u4e2d: ${file.name}...&lt;\\\/span&gt;`;\\n                try {\\n                    await fetch(&#039;index.php&#039;, { method: &#039;POST&#039;, body: formData });\\n                    location.reload(); \\\/\\\/ \\u622a\\u56fe\\u548cEXE\\u4e0a\\u4f20\\u540e\\u9700\\u8981\\u5237\\u65b0\\u9875\\u9762\\u770b\\u5230\\u6548\\u679c\\n                } catch (err) {\\n                    status.innerHTML = `&lt;span style=\\&quot;color:var(--danger)\\&quot;&gt;\\u4e0a\\u4f20\\u5931\\u8d25: ${file.name}&lt;\\\/span&gt;`;\\n                }\\n            }\\n        }\\n        \\n&lt;\\\/script&gt;\\n&lt;\\\/body&gt;\\n&lt;\\\/html&gt;&quot;,&quot;theme&quot;:&quot;porple&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:12,&quot;tablet&quot;:15,&quot;mobile&quot;:14},&quot;height&quot;:{&quot;desktop&quot;:&quot;200px&quot;,&quot;tablet&quot;:&quot;0px&quot;,&quot;mobile&quot;:&quot;0px&quot;},&quot;background&quot;:{&quot;color&quot;:&quot;#d3cfcf42&quot;,&quot;type&quot;:&quot;gradient&quot;,&quot;gradient&quot;:&quot;linear-gradient(135deg,rgb(69,39,164) 0%,rgb(15,5,5) 42%,rgb(131,68,197) 100%)&quot;},&quot;align&quot;:&quot;&quot;,&quot;lineNumbers&quot;:true,&quot;clipBoard&quot;:true,&quot;wordWrap&quot;:true,&quot;width&quot;:{&quot;desktop&quot;:&quot;100%&quot;,&quot;tablet&quot;:&quot;100%&quot;,&quot;mobile&quot;:&quot;100%&quot;},&quot;padding&quot;:{&quot;top&quot;:&quot;0px&quot;,&quot;right&quot;:&quot;0px&quot;,&quot;bottom&quot;:&quot;0px&quot;,&quot;left&quot;:&quot;0px&quot;},&quot;layout&quot;:{&quot;align&quot;:&quot;left&quot;},&quot;border&quot;:{&quot;color&quot;:&quot;#000&quot;,&quot;style&quot;:&quot;solid&quot;,&quot;width&quot;:&quot;0px&quot;},&quot;shadow&quot;:[],&quot;alignment&quot;:&quot;center&quot;,&quot;clipBoardColors&quot;:{&quot;color&quot;:&quot;#fff&quot;,&quot;bg&quot;:&quot;#00000024&quot;}}'><\/div>\r\n\r\n\t\t\n\n\n<h1 class=\"wp-block-heading has-text-align-center\">web\u6587\u4ef6\u7ed3\u6784<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">\u9879\u76ee\u6587\u4ef6\u7ed3\u6784\u6982\u89c8<\/h3>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-90cf2cbe-4' data-attributes='{&quot;cId&quot;:&quot;90cf2cbe-4&quot;,&quot;language&quot;:&quot;html&quot;,&quot;code&quot;:&quot;\\\/ (\\u7f51\\u7ad9\\u6839\\u76ee\\u5f55)\\n\\u251c\\u2500\\u2500 index.php                 # \\u516c\\u5171\\u5c55\\u793a\\u9875\\uff08\\u7528\\u6237\\u8bbf\\u95ee\\u7684\\u4e0b\\u8f7d\\u9875\\u9762\\uff09\\n\\u251c\\u2500\\u2500 login.php                 # \\u540e\\u53f0\\u767b\\u5f55\\u9875\\u9762\\n\\u251c\\u2500\\u2500 admin\\\/                    # \\u540e\\u53f0\\u7ba1\\u7406\\u76ee\\u5f55\\n\\u2502   \\u251c\\u2500\\u2500 index.php             # \\u540e\\u53f0\\u903b\\u8f91\\u6838\\u5fc3 (\\u5904\\u7406 POST\\u3001\\u6587\\u4ef6\\u5206\\u62e3\\u3001\\u7248\\u672c\\u6392\\u5e8f)\\n\\u2502   \\u2514\\u2500\\u2500 template.html         # \\u540e\\u53f0 UI \\u6a21\\u677f (\\u5305\\u542b\\u5168\\u5c40\\u7c98\\u8d34\\u3001\\u62d6\\u62fd\\u3001\\u56fe\\u7247\\u9884\\u89c8 JS)\\n\\u251c\\u2500\\u2500 projects\\\/                 # \\u9879\\u76ee\\u6570\\u636e\\u6839\\u76ee\\u5f55 (\\u9700 775\\\/777 \\u6743\\u9650)\\n\\u2502   \\u251c\\u2500\\u2500 ProjectName_A\\\/        # \\u5177\\u4f53\\u9879\\u76ee\\u6587\\u4ef6\\u5939 (\\u540d\\u79f0\\u53ef\\u7531\\u540e\\u53f0\\u4fee\\u6539)\\n\\u2502   \\u2502   \\u251c\\u2500\\u2500 emoji.txt         # \\u5b58\\u50a8\\u9879\\u76ee\\u56fe\\u6807 (\\u5982: \\ud83d\\ude80)\\n\\u2502   \\u2502   \\u251c\\u2500\\u2500 info.txt          # \\u9879\\u76ee\\u8be6\\u7ec6 Markdown \\u4ecb\\u7ecd\\n\\u2502   \\u2502   \\u251c\\u2500\\u2500 summary.txt       # \\u9879\\u76ee\\u4e00\\u53e5\\u8bdd\\u7b80\\u4ecb\\n\\u2502   \\u2502   \\u251c\\u2500\\u2500 requirements.txt  # \\u73af\\u5883\\u4f9d\\u8d56\\u8bf4\\u660e\\n\\u2502   \\u2502   \\u251c\\u2500\\u2500 v2.0\\\/             # \\u7248\\u672c\\u6587\\u4ef6\\u5939 (\\u9ad8\\u7248\\u672c)\\n\\u2502   \\u2502   \\u2502   \\u251c\\u2500\\u2500 screenshots\\\/  # \\u8be5\\u7248\\u672c\\u7684\\u622a\\u56fe\\u76ee\\u5f55 (.png, .jpg)\\n\\u2502   \\u2502   \\u2502   \\u251c\\u2500\\u2500 exe\\\/          # \\u8be5\\u7248\\u672c\\u7684\\u6267\\u884c\\u6587\\u4ef6\\u76ee\\u5f55 (.exe)\\n\\u2502   \\u2502   \\u2502   \\u2514\\u2500\\u2500 Project_v2.0.py # \\u8be5\\u7248\\u672c\\u7684\\u6e90\\u7801\\u6587\\u4ef6 (.py \\u6216 .pyw)\\n\\u2502   \\u2502   \\u2514\\u2500\\u2500 v1.0\\\/             # \\u5386\\u53f2\\u7248\\u672c\\u6587\\u4ef6\\u5939\\n\\u2502   \\u2502       \\u251c\\u2500\\u2500 screenshots\\\/\\n\\u2502   \\u2502       \\u251c\\u2500\\u2500 exe\\\/\\n\\u2502   \\u2502       \\u2514\\u2500\\u2500 Project_v1.0.py\\n\\u2502   \\u2514\\u2500\\u2500 ProjectName_B\\\/        # \\u53e6\\u4e00\\u4e2a\\u9879\\u76ee\\n\\u2514\\u2500\\u2500 assets\\\/                   # (\\u53ef\\u9009) \\u516c\\u5171\\u9759\\u6001\\u8d44\\u6e90 (CSS\\\/JS \\u5e93)\\n&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:12,&quot;tablet&quot;:15,&quot;mobile&quot;:14},&quot;align&quot;:&quot;&quot;,&quot;lineNumbers&quot;:true,&quot;theme&quot;:&quot;default&quot;,&quot;clipBoard&quot;:true,&quot;wordWrap&quot;:true,&quot;width&quot;:{&quot;desktop&quot;:&quot;100%&quot;,&quot;tablet&quot;:&quot;100%&quot;,&quot;mobile&quot;:&quot;100%&quot;},&quot;height&quot;:{&quot;desktop&quot;:&quot;0px&quot;,&quot;tablet&quot;:&quot;0px&quot;,&quot;mobile&quot;:&quot;0px&quot;},&quot;padding&quot;:{&quot;top&quot;:&quot;0px&quot;,&quot;right&quot;:&quot;0px&quot;,&quot;bottom&quot;:&quot;0px&quot;,&quot;left&quot;:&quot;0px&quot;},&quot;background&quot;:{&quot;color&quot;:&quot;#d3cfcf42&quot;},&quot;layout&quot;:{&quot;align&quot;:&quot;left&quot;},&quot;border&quot;:{&quot;color&quot;:&quot;#000&quot;,&quot;style&quot;:&quot;solid&quot;,&quot;width&quot;:&quot;0px&quot;},&quot;shadow&quot;:[],&quot;alignment&quot;:&quot;center&quot;,&quot;clipBoardColors&quot;:{&quot;color&quot;:&quot;#fff&quot;,&quot;bg&quot;:&quot;#00000024&quot;}}'><\/div>\r\n\r\n\t\t\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u5173\u952e\u76ee\u5f55\u4e0e\u6587\u4ef6\u8bf4\u660e<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">1. <code>admin\/<\/code> \u76ee\u5f55<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>index.php<\/code><\/strong>: \u626e\u6f14\u4e86\u201c\u63a7\u5236\u5668\u201d\u7684\u89d2\u8272\u3002\u5b83\u8d1f\u8d23\u626b\u63cf <code>projects\/<\/code> \u76ee\u5f55\u4e0b\u7684\u6587\u4ef6\u5939\u5e76\u8f6c\u6362\u4e3a\u9879\u76ee\u5217\u8868\uff0c\u540c\u65f6\u5904\u7406\u6240\u6709\u7684\u4e0a\u4f20\u903b\u8f91\u3002<\/li>\n\n\n\n<li><strong><code>template.html<\/code><\/strong>: \u626e\u6f14\u4e86\u201c\u89c6\u56fe\u201d\u7684\u89d2\u8272\u3002\u901a\u8fc7\u5185\u5d4c JavaScript \u76d1\u542c\u5168\u5c40 <code>paste<\/code> \u4e8b\u4ef6\u5b9e\u73b0 Ctrl+V \u4e0a\u4f20\uff0c\u5e76\u5229\u7528 <code>FileReader<\/code> API \u5b9e\u73b0 <code>.py<\/code> \u6587\u4ef6\u7684\u5373\u65f6\u8bfb\u53d6\u4e0e\u4ee3\u7801\u533a\u81ea\u52a8\u586b\u5145\u3002<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">2. <code>projects\/<\/code> \u76ee\u5f55 (\u6570\u636e\u5c42)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">\u8fd9\u662f\u7cfb\u7edf\u7684\u201c\u6570\u636e\u5e93\u201d\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5206\u5c42\u8bbe\u8ba1<\/strong>: \u91c7\u7528 <code>\u9879\u76ee -&gt; \u7248\u672c -&gt; \u9644\u4ef6<\/code> \u7684\u4e09\u7ea7\u7ed3\u6784\u3002<\/li>\n\n\n\n<li><strong>\u81ea\u52a8\u5206\u62e3<\/strong>: \u540e\u7aef\u903b\u8f91\u4f1a\u6839\u636e\u6587\u4ef6\u540e\u7f00\uff0c\u81ea\u52a8\u5c06\u4e0a\u4f20\u7684\u6587\u4ef6\u653e\u5165\u5bf9\u5e94\u7684\u5b50\u76ee\u5f55\uff1a\n<ul class=\"wp-block-list\">\n<li>\u56fe\u7247 $\\rightarrow$ <code>\/screenshots\/<\/code><\/li>\n\n\n\n<li>\u53ef\u6267\u884c\u7a0b\u5e8f $\\rightarrow$ <code>\/exe\/<\/code><\/li>\n\n\n\n<li>\u6e90\u7801 $\\rightarrow$ \u6839\u76ee\u5f55<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">3. \u547d\u540d\u7ea6\u5b9a<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u6e90\u7801\u6587\u4ef6<\/strong>: \u91c7\u7528 <code>\u9879\u76ee\u540d_\u7248\u672c\u53f7.py<\/code> \u7684\u683c\u5f0f\u81ea\u52a8\u547d\u540d\u3002<\/li>\n\n\n\n<li><strong>\u91cd\u547d\u540d\u903b\u8f91<\/strong>: \u5f53\u4f60\u5728\u540e\u53f0\u4fee\u6539\u9879\u76ee\u540d\u79f0\u65f6\uff0c<code>admin\/index.php<\/code> \u4f1a\u8c03\u7528 <code>rename()<\/code> \u51fd\u6570\u66f4\u6539\u5bf9\u5e94\u7684\u6587\u4ef6\u5939\u540d\u79f0\uff0c\u7531\u4e8e\u6240\u6709\u8def\u5f84\u90fd\u662f\u52a8\u6001\u751f\u6210\u7684\uff0c\u4fee\u6539\u540e\u524d\u53f0\u9875\u9762\u4f1a\u81ea\u52a8\u540c\u6b65\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u90e8\u7f72\u5efa\u8bae<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>\u6743\u9650\u8bbe\u7f6e<\/strong>: \u786e\u4fdd <code>projects\/<\/code> \u6587\u4ef6\u5939\u5bf9 Web \u670d\u52a1\u5668\uff08\u5982 <code>www-data<\/code> \u6216 <code>apache<\/code> \u7528\u6237\uff09\u5177\u6709<strong>\u5199\u6743\u9650<\/strong>\u3002<\/li>\n\n\n\n<li><strong>\u5b89\u5168\u9632\u62a4<\/strong>: <code>projects\/<\/code> \u76ee\u5f55\u5185\u53ef\u4ee5\u653e\u7f6e\u4e00\u4e2a\u7b80\u5355\u7684 <code>.htaccess<\/code> (\u5982\u679c\u4f60\u4f7f\u7528 Apache) \u6765\u7981\u6b62\u6267\u884c PHP \u811a\u672c\uff0c\u9632\u6b62\u6076\u610f\u4e0a\u4f20\u3002<\/li>\n<\/ol>\n\n\n\n<h1 class=\"wp-block-heading has-text-align-center\">\u8be6\u7ec6\u4ecb\u7ecd<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\ude80 \u5de5\u5177\u6838\u5fc3\u4ecb\u7ecd<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u8be5\u5c55\u793a\u7ad9\u91c7\u7528 <strong>PHP + JavaScript (Vanilla)<\/strong> \u7684\u8f7b\u91cf\u7ea7\u67b6\u6784\uff0c\u65e0\u9700\u6570\u636e\u5e93\uff0c\u5b8c\u5168\u57fa\u4e8e\u6587\u4ef6\u7cfb\u7edf\u81ea\u52a8\u6784\u5efa\u7d22\u5f15\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">1. \u81ea\u52a8\u5316\u9879\u76ee\u7ba1\u7406 (File-Based Auto-Indexing)<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u96f6\u914d\u7f6e\u6dfb\u52a0<\/strong>\uff1a\u53ea\u9700\u5728 <code>projects<\/code> \u6587\u4ef6\u5939\u4e0b\u521b\u5efa\u4e00\u4e2a\u65b0\u6587\u4ef6\u5939\uff0c\u7f51\u7ad9\u4fa7\u8fb9\u680f\u4f1a\u81ea\u52a8\u540c\u6b65\u663e\u793a\u3002<\/li>\n\n\n\n<li><strong>Emoji \u89c6\u89c9\u8bc6\u522b<\/strong>\uff1a\u901a\u8fc7\u6bcf\u4e2a\u9879\u76ee\u6839\u76ee\u5f55\u4e0b\u7684 <code>emoji.txt<\/code>\uff0c\u4e3a\u6bcf\u4e2a\u9879\u76ee\u5b9a\u4e49\u4e13\u5c5e\u56fe\u6807\uff0c\u589e\u5f3a\u8fa8\u8bc6\u5ea6\u3002<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">2. \u4e13\u4e1a\u7ea7\u4ee3\u7801\u5c55\u793a (Pro-Code Display)<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u8bed\u6cd5\u9ad8\u4eae<\/strong>\uff1a\u96c6\u6210\u4e86 <code>Highlight.js<\/code>\uff0c\u652f\u6301 Python \u7b49\u591a\u79cd\u8bed\u8a00\u7684\u81ea\u52a8\u9ad8\u4eae\uff0c\u4ee3\u7801\u6846\u91c7\u7528\u7ecf\u5178\u7684 Atom Dark \u6df1\u8272\u4e3b\u9898\u3002<\/li>\n\n\n\n<li><strong>\u5c3a\u5bf8\u4f18\u5316<\/strong>\uff1a\u4ee3\u7801\u6846\u7ecf\u8fc7\u9ad8\u5ea6\u9650\u5236\uff08\u5e26\u5185\u90e8\u6eda\u52a8\u6761\uff09\u548c\u5bbd\u5ea6\u7a84\u5316\u5904\u7406\uff0c\u786e\u4fdd\u9875\u9762\u6574\u4f53\u6bd4\u4f8b\u534f\u8c03\uff0c\u4e0d\u663e\u81c3\u80bf\u3002<\/li>\n\n\n\n<li><strong>\u4e00\u952e\u590d\u5236<\/strong>\uff1a\u5185\u7f6e\u4ee3\u7801\u590d\u5236\u529f\u80fd\uff0c\u65b9\u4fbf\u7528\u6237\u76f4\u63a5\u63d0\u53d6\u6838\u5fc3\u903b\u8f91\u3002<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">3. \u6df1\u5ea6\u4ea4\u4e92\u4f53\u9a8c (Interactive UX)<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Markdown \u5f39\u7a97\u4ecb\u7ecd<\/strong>\uff1a\u4e3a\u4e86\u4fdd\u6301\u4e3b\u9875\u6e05\u723d\uff0c\u8be6\u7ec6\u7684\u9879\u76ee\u6587\u6863\u88ab\u79fb\u5165\u4e86\u4e00\u4e2a\u4f18\u96c5\u7684\u5f39\u51fa\u5c42\u3002\u5b83\u652f\u6301\u5168\u529f\u80fd\u7684 Markdown \u6e32\u67d3\uff08\u6807\u9898\u3001\u5217\u8868\u3001\u52a0\u7c97\u7b49\uff09\u3002<\/li>\n\n\n\n<li><strong>\u591a\u7248\u672c\u5207\u6362\u7cfb\u7edf<\/strong>\uff1a\u7528\u6237\u53ef\u4ee5\u901a\u8fc7\u4e0b\u62c9\u83dc\u5355\u67e5\u770b\u9879\u76ee\u7684\u5386\u53f2\u7248\u672c\uff0c\u7cfb\u7edf\u4f1a\u81ea\u52a8\u5207\u6362\u5bf9\u5e94\u7684\u6e90\u7801\u3001\u622a\u56fe\u548c\u4e0b\u8f7d\u94fe\u63a5\u3002<\/li>\n\n\n\n<li><strong>\u5168\u5c4f\u9884\u89c8<\/strong>\uff1a\u70b9\u51fb\u754c\u9762\u9884\u89c8\u56fe\u540e\uff0c\u56fe\u7247\u4f1a\u4ee5 Flex \u5e03\u5c40\u5b8c\u7f8e\u5c45\u4e2d\u5f39\u51fa\uff0c\u63d0\u4f9b\u65e0\u5e72\u6270\u7684\u89c6\u89c9\u4f53\u9a8c\u3002<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">4. \u5b8c\u6574\u7684\u8d44\u6e90\u5206\u53d1 (Resource Distribution)<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u73af\u5883\u4f9d\u8d56\u8bf4\u660e<\/strong>\uff1a\u4e13\u95e8\u5f00\u8f9f\u4e86\u201c\u8fd0\u884c\u73af\u5883\/\u4f9d\u8d56\u201d\u533a\u57df\uff0c\u6e05\u6670\u5c55\u793a\u9879\u76ee\u8fd0\u884c\u6240\u9700\u7684 Python \u5e93\u6216\u786c\u4ef6\u8981\u6c42\u3002<\/li>\n\n\n\n<li><strong>\u591a\u7aef\u4e0b\u8f7d<\/strong>\uff1a\u533a\u5206\u4e86\u201c\u6e90\u7801\u4e0b\u8f7d\u201d\u548c\u201cEXE \u6267\u884c\u7a0b\u5e8f\u4e0b\u8f7d\u201d\uff0c\u6ee1\u8db3\u5f00\u53d1\u8005\u548c\u666e\u901a\u7528\u6237\u7684\u4e0d\u540c\u9700\u6c42\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcc2 \u76ee\u5f55\u7ed3\u6784\u53c2\u8003<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u4f60\u7684\u5de5\u5177\u901a\u8fc7\u4ee5\u4e0b\u903b\u8f91\u9a71\u52a8\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u6839\u76ee\u5f55<\/strong>\uff1a<code>index.php<\/code> (\u5c55\u793a\u4e3b\u9875), <code>get_details.php<\/code> (\u6570\u636e\u4e2d\u5fc3)\u3002<\/li>\n\n\n\n<li><strong>\u9879\u76ee\u76ee\u5f55<\/strong>\uff1a\n<ul class=\"wp-block-list\">\n<li><code>emoji.txt<\/code> (\u56fe\u6807)<\/li>\n\n\n\n<li><code>summary.txt<\/code> (\u77ed\u7b80\u4ecb)<\/li>\n\n\n\n<li><code>info.txt<\/code> (Markdown \u8be6\u7ec6\u4ecb\u7ecd)<\/li>\n\n\n\n<li><code>requirements.txt<\/code> (\u8fd0\u884c\u4f9d\u8d56)<\/li>\n\n\n\n<li><code>v1.0\/v2.0\/<\/code> (\u7248\u672c\u6587\u4ef6\u5939\uff0c\u5185\u542b <code>.py<\/code> \u6e90\u7801\u3001<code>screenshots\/<\/code>\u3001<code>exe\/<\/code>)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udf1f \u603b\u7ed3<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u8fd9\u4e2a\u5de5\u5177\u73b0\u5728\u770b\u8d77\u6765\u5c31\u50cf\u4e00\u4e2a\u8ff7\u4f60\u7684 <strong>GitHub + App Store<\/strong> \u7ed3\u5408\u4f53\u3002\u5b83\u975e\u5e38\u9002\u5408\u7528\u6765\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5c55\u793a\u4f60\u7684\u7f16\u7a0b\u8bfe\u8bbe\u6216\u5916\u5305\u9879\u76ee\u3002<\/li>\n\n\n\n<li>\u4f5c\u4e3a\u4e2a\u4eba\u6280\u672f\u535a\u5ba2\u7684\u8865\u5145\uff0c\u5b58\u653e\u53ef\u8fd0\u884c\u7684\u4ee3\u7801 Demo\u3002<\/li>\n\n\n\n<li>\u5728\u516c\u53f8\u5185\u7f51\u6216\u4e2a\u4eba\u670d\u52a1\u5668\u4e0a\u5206\u53d1\u81ea\u7814\u7684\u5c0f\u5de5\u5177\u3002<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5c55\u793a \u524d\u7aef\uff1a \u622a\u56fe \u524d\u7aef\u9875\u9762\uff1a \u540e\u53f0\u9875\u9762\uff1a web\u6e90\u7801 \u524d\u53f0 index.php\uff1a get_details.p [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4291","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/4291","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4291"}],"version-history":[{"count":6,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/4291\/revisions"}],"predecessor-version":[{"id":4341,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/4291\/revisions\/4341"}],"wp:attachment":[{"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4291"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4291"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4291"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}