{"id":3486,"date":"2025-07-03T12:27:58","date_gmt":"2025-07-03T04:27:58","guid":{"rendered":"https:\/\/blog.kangyue.pro\/?p=3486"},"modified":"2025-07-04T19:40:22","modified_gmt":"2025-07-04T11:40:22","slug":"%e5%9f%ba%e4%ba%8ephp%e7%9a%84%e7%ae%a1%e7%90%86web%e4%bb%a3%e7%a0%81%e7%9a%84%e5%90%8e%e5%8f%b0","status":"publish","type":"post","link":"https:\/\/blog.kangyue.pro\/?p=3486","title":{"rendered":"\u57fa\u4e8ephp\u7684\u7ba1\u7406web\u4ee3\u7801\u7684\u540e\u53f0"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">\u89c6\u9891\u6f14\u793a<\/h1>\n\n\n\n<p><em>\u6f14\u793a\u4e86\u672c\u540e\u53f0\u7684\u4f7f\u7528\u65b9\u6cd5\uff0c\u5e76\u6dfb\u52a0\u4e00\u4e9bAI\u751f\u6210\u7684\u524d\u7aef\u5c0f\u5de5\u5177\u8fdb\u884c\u6d4b\u8bd5\u3002<\/em><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"1028\" style=\"aspect-ratio: 2072 \/ 1028;\" width=\"2072\" controls src=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/AIweb\u6f14\u793a_x264.mp4\"><\/video><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"2196\" height=\"976\" src=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/image-6.png\" alt=\"\" class=\"wp-image-3496\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/image-6.png 2196w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/image-6-768x341.png 768w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/image-6-1536x683.png 1536w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/image-6-2048x910.png 2048w\" sizes=\"auto, (max-width: 2196px) 100vw, 2196px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">\u6982\u8ff0<\/h1>\n\n\n\n<p>\u8fd9\u4e2a\u540e\u53f0\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u57fa\u4e8e PHP \u7684web\u9879\u76ee\u7ba1\u7406\u7cfb\u7edf\uff0c\u5b83\u5141\u8bb8\u7528\u6237<strong>\u521b\u5efa\u3001\u7f16\u8f91\u3001\u4fdd\u5b58\u548c\u5220\u9664\u670d\u52a1\u5668\u4e0a\u7684web\u9879\u76ee<\/strong>\u3002\u6bcf\u4e2a\u9879\u76ee\u90fd\u7531\u4e00\u4e2a\u6587\u4ef6\u5939\u8868\u793a\uff0c\u5305\u542b HTML\u3001CSS\u3001JavaScript \u548c PHP \u6587\u4ef6\uff0c\u5e76\u4e14\u53ef\u4ee5\u4e3a\u6bcf\u4e2a\u9879\u76ee\u8bbe\u7f6e\u4e00\u4e2a\u53ef\u8bfb\u7684\u540d\u79f0\u3002\u6b64\u5916\uff0c\u5b83\u8fd8\u652f\u6301\u901a\u8fc7\u62d6\u653e\u5bf9\u9879\u76ee\u5217\u8868\u8fdb\u884c\u6392\u5e8f\uff0c\u5e76\u63d0\u4f9b\u4e86\u65e5\u591c\u95f4\u6a21\u5f0f\u5207\u6362\u4ee5\u53ca\u5168\u5c4f\u7f16\u8f91\u529f\u80fd\uff0c\u65b9\u4fbf\u7528\u6237\u8fdb\u884c\u4ee3\u7801\u7ba1\u7406\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">\u622a\u56fe<\/h1>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1279\" height=\"863\" src=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/image-5.png\" alt=\"\" class=\"wp-image-3487\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/image-5.png 1279w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/07\/image-5-768x518.png 768w\" sizes=\"auto, (max-width: 1279px) 100vw, 1279px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">\u7279\u8272<\/h1>\n\n\n\n<p>\u8fd9\u4e2a\u540e\u53f0\u7ba1\u7406\u7cfb\u7edf\u5177\u6709\u4ee5\u4e0b\u7279\u8272\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u5168\u9762\u7684\u9879\u76ee\u7ba1\u7406\uff1a<\/strong> \u652f\u6301\u60a8\u65b0\u5efa\u3001\u7f16\u8f91\u3001\u4fdd\u5b58\u548c\u5220\u9664\u9879\u76ee\uff0c\u6bcf\u4e2a\u9879\u76ee\u90fd\u5bf9\u5e94\u4e00\u4e2a\u72ec\u7acb\u7684\u6587\u4ef6\u5939\uff0c\u65b9\u4fbf\u7ba1\u7406\u3002<\/li>\n\n\n\n<li><strong>\u591a\u8bed\u8a00\u4ee3\u7801\u7f16\u8f91\uff1a<\/strong> \u5185\u7f6e\u529f\u80fd\u5f3a\u5927\u7684\u4ee3\u7801\u7f16\u8f91\u5668\uff08CodeMirror\uff09\uff0c\u652f\u6301 HTML\u3001CSS\u3001JavaScript \u548c PHP \u7684\u8bed\u6cd5\u9ad8\u4eae\uff0c\u5e76\u63d0\u4f9b\u5feb\u6377\u952e\u64cd\u4f5c\u548c\u6ce8\u91ca\u529f\u80fd\u3002<\/li>\n\n\n\n<li><strong>\u53ef\u5b9a\u5236\u7684\u7528\u6237\u754c\u9762\uff1a<\/strong> \u63d0\u4f9b\u6807\u7b7e\u9875\u5f0f\u7684\u6587\u4ef6\u5207\u6362\uff0c\u4ee5\u53ca\u65e5\u95f4\/\u591c\u95f4\u6a21\u5f0f\u4e3b\u9898\u5207\u6362\uff0c\u8ba9\u60a8\u6839\u636e\u559c\u597d\u8c03\u6574\u754c\u9762\u3002<\/li>\n\n\n\n<li><strong>\u9ad8\u6548\u7684\u5de5\u4f5c\u6d41\uff1a<\/strong> \u7f16\u8f91\u5668\u53ef\u5207\u6362\u5230\u5168\u9ad8\u6a21\u5f0f\uff0c\u8ba9\u60a8\u4e13\u6ce8\u4ee3\u7801\uff1b\u5de6\u4fa7\u9879\u76ee\u5217\u8868\u652f\u6301\u62d6\u62fd\u6392\u5e8f\uff0c\u65b9\u4fbf\u60a8\u7ec4\u7ec7\u9879\u76ee\u3002<\/li>\n\n\n\n<li>*<strong>\u81ea\u9002\u5e94\u4fa7\u8fb9\u680f\uff1a<\/strong> \u5de6\u4fa7\u7684\u9879\u76ee\u5217\u8868\u533a\u57df\u80fd\u591f\u6839\u636e\u9879\u76ee\u540d\u79f0\u6587\u5b57\u7684\u957f\u5ea6\u81ea\u9002\u5e94\u5bbd\u5ea6\uff0c\u786e\u4fdd\u5185\u5bb9\u5b8c\u6574\u663e\u793a\u800c\u4e0d\u4f1a\u88ab\u622a\u65ad\u3002<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">\u90e8\u7f72\u65b9\u6cd5<\/h1>\n\n\n\n<p>\u4f7f\u7528\u8fd9\u4e2a\u540e\u53f0\u7ba1\u7406\u7cfb\u7edf\u975e\u5e38\u7b80\u5355\uff0c\u6309\u7167\u4ee5\u4e0b\u6b65\u9aa4\u5373\u53ef\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u90e8\u7f72\u5230\u670d\u52a1\u5668\uff1a<\/strong> \u5728\u670d\u52a1\u5668\u4e0a\u65b0\u5efa <code>admin.php<\/code> \u6587\u4ef6\uff08\u4ee3\u7801\u9644\u540e\uff09\u4ee5\u53ca\u5b83\u6240\u4f9d\u8d56\u7684 <code>projects_order.json<\/code> \uff08\u65b0\u5efa\u7a7a\u6587\u4ef6\u5373\u53ef\uff09\u548c\u4efb\u4f55\u9879\u76ee\u6587\u4ef6\u5939\u4e00\u8d77\uff0c\u4e0a\u4f20\u5230\u60a8\u7684 Web \u670d\u52a1\u5668\uff08\u5982 Apache, Nginx\uff09\u7684\u4efb\u610f\u4e00\u4e2a\u53ef\u8bbf\u95ee\u7684\u6587\u4ef6\u5939\u5185\u3002<\/li>\n\n\n\n<li><strong>\u8bbe\u7f6e\u7ba1\u7406\u5458\u5bc6\u7801\uff1a<\/strong> \u6253\u5f00 <code>admin.php<\/code> \u6587\u4ef6\uff0c\u627e\u5230 <code>define('ADMIN_PASSWORD', '\u6b64\u5904\u662f\u540e\u53f0\u5bc6\u7801');<\/code> \u8fd9\u4e00\u884c\u3002\u5c06 <code>'\u6b64\u5904\u662f\u540e\u53f0\u5bc6\u7801'<\/code> \u66ff\u6362\u4e3a\u60a8\u81ea\u5df1\u7684\u5b89\u5168\u5bc6\u7801\u5e76\u4fdd\u5b58\u3002<\/li>\n\n\n\n<li><strong>\u8bbf\u95ee\u540e\u53f0\uff1a<\/strong> \u5728\u6d4f\u89c8\u5668\u4e2d\u8bbf\u95ee\u8be5 PHP \u6587\u4ef6\u7684 URL\uff08\u4f8b\u5982\uff1a<code>http:\/\/yourdomain.com\/your-folder\/admin.php<\/code>\uff09\u3002\u9996\u6b21\u8bbf\u95ee\u65f6\u4f1a\u8981\u6c42\u60a8\u8f93\u5165\u521a\u624d\u8bbe\u7f6e\u7684\u7ba1\u7406\u5458\u5bc6\u7801\u3002<\/li>\n\n\n\n<li><strong>\u5f00\u59cb\u4f7f\u7528\uff1a<\/strong> \u767b\u5f55\u540e\uff0c\u60a8\u5c31\u53ef\u4ee5\u5728\u5de6\u4fa7\u7ba1\u7406\u9879\u76ee\uff0c\u53f3\u4fa7\u7f16\u8f91\u4ee3\u7801\u3002\u70b9\u51fb\u201c\u65b0\u5efa\u9879\u76ee\u201d\u521b\u5efa\u65b0\u9879\u76ee\uff0c\u6216\u8005\u70b9\u51fb\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u7f16\u8f91\u3002\u4fdd\u5b58\u540e\u5373\u53ef\u901a\u8fc7\u9879\u76ee\u6587\u4ef6\u5939\u7684 URL \u8bbf\u95ee\u60a8\u7684\u4f5c\u54c1\u3002<\/li>\n<\/ol>\n\n\n\n<h1 class=\"wp-block-heading\">\u5b8c\u6574\u7684php\u4ee3\u7801<\/h1>\n\n\n\n<p>2025\u5e747\u67084\u65e5\u66f4\u65b0\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u5206\u62c6\u7248<\/h3>\n\n\n\n<p>index.html\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-d4af64b4-d' data-attributes='{&quot;cId&quot;:&quot;d4af64b4-d&quot;,&quot;language&quot;:&quot;html&quot;,&quot;code&quot;:&quot;&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;AI \\u5c0f\\u5de5\\u5177\\u540e\\u53f0&lt;\\\/title&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/lib\\\/codemirror.min.css\\&quot; \\\/&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/theme\\\/eclipse.css\\&quot; \\\/&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/theme\\\/darcula.css\\&quot; \\\/&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;style.css\\&quot;&gt;\\n&lt;\\\/head&gt;\\n&lt;body&gt;\\n&lt;div id=\\&quot;message-display-area\\&quot; class=\\&quot;message-container\\&quot;&gt;&lt;\\\/div&gt;\\n&lt;div class=\\&quot;sidebar\\&quot;&gt;\\n    &lt;h3&gt;\\ud83d\\udcc2 \\u9879\\u76ee\\u5217\\u8868&lt;\\\/h3&gt;\\n    &lt;ul id=\\&quot;project-list\\&quot;&gt;\\n        &lt;?php foreach ($projects_data as $project): ?&gt;\\n            &lt;li data-folder-name=\\&quot;&lt;?= htmlspecialchars($project[&#039;folder_name&#039;]) ?&gt;\\&quot; &lt;?= ($project[&#039;folder_name&#039;] === $edit_folder_name) ? &#039;class=\\&quot;active\\&quot;&#039; : &#039;&#039; ?&gt;&gt;\\n                &lt;span class=\\&quot;name-links\\&quot;&gt;\\n                    &lt;a href=\\&quot;?edit=&lt;?= urlencode($project[&#039;folder_name&#039;]) ?&gt;\\&quot;&gt;\\u270f\\ufe0f&lt;?= htmlspecialchars($project[&#039;project_name&#039;]) ?&gt;&lt;\\\/a&gt;\\n                &lt;\\\/span&gt;\\n                &lt;span&gt;\\n                    &lt;a href=\\&quot;..\\\/&lt;?= htmlspecialchars($project[&#039;folder_name&#039;]) ?&gt;\\\/\\&quot; target=\\&quot;_blank\\&quot; title=\\&quot;\\u8bbf\\u95ee\\u9879\\u76ee\\u6587\\u4ef6\\u5939\\&quot;&gt;\\ud83c\\udf10&lt;\\\/a&gt;\\n                    &lt;a href=\\&quot;javascript:void(0);\\&quot; onclick=\\&quot;deleteProject(&#039;&lt;?= urlencode($project[&#039;folder_name&#039;]) ?&gt;&#039;)\\&quot; title=\\&quot;\\u5220\\u9664\\u9879\\u76ee\\&quot;&gt;\\ud83d\\uddd1\\ufe0f&lt;\\\/a&gt;\\n                &lt;\\\/span&gt;\\n            &lt;\\\/li&gt;\\n        &lt;?php endforeach; ?&gt;\\n    &lt;\\\/ul&gt;\\n    &lt;button id=\\&quot;new-project-btn\\&quot; title=\\&quot;\\u65b0\\u5efa\\u9879\\u76ee\\&quot;&gt;\\uff0b \\u65b0\\u5efa\\u9879\\u76ee&lt;\\\/button&gt;\\n&lt;\\\/div&gt;\\n&lt;div class=\\&quot;container\\&quot;&gt;\\n    &lt;div class=\\&quot;main\\&quot;&gt;\\n        &lt;h2&gt;&lt;?= $page_h2_title ?&gt;&lt;\\\/h2&gt;\\n        &lt;?php if (!empty($success_message)): ?&gt;\\n            &lt;p class=\\&quot;message success\\&quot;&gt;&lt;?= $success_message ?&gt;&lt;\\\/p&gt;\\n        &lt;?php endif; ?&gt;\\n        &lt;?php if (!empty($error_message)): ?&gt;\\n            &lt;p class=\\&quot;message error\\&quot;&gt;&lt;?= $error_message ?&gt;&lt;\\\/p&gt;\\n        &lt;?php endif; ?&gt;\\n        &lt;form method=\\&quot;post\\&quot; id=\\&quot;form\\&quot;&gt;\\n            &lt;?php if ($edit_mode): ?&gt;\\n                &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;original_folder\\&quot; value=\\&quot;&lt;?= htmlspecialchars($edit_folder_name) ?&gt;\\&quot;&gt;\\n            &lt;?php endif; ?&gt;\\n\\n            &lt;div class=\\&quot;project-info-row\\&quot;&gt;\\n                &lt;div class=\\&quot;input-group\\&quot;&gt;\\n                    &lt;label&gt;\\u2728 \\u9879\\u76ee\\u540d\\u79f0\\uff1a&lt;\\\/label&gt;\\n                    &lt;input type=\\&quot;text\\&quot; name=\\&quot;project_name\\&quot; value=\\&quot;&lt;?= htmlspecialchars($input_project_name) ?&gt;\\&quot; required \\\/&gt;\\n                &lt;\\\/div&gt;\\n                &lt;div class=\\&quot;input-group\\&quot;&gt;\\n                    &lt;label&gt;\\ud83d\\udcc1 \\u6587\\u4ef6\\u5939\\u540d (\\u9650\\u82f1\\u6570\\u3001\\u4e0b\\u5212\\u7ebf\\u3001\\u77ed\\u5212\\u7ebf)\\uff1a&lt;\\\/label&gt;\\n                    &lt;input type=\\&quot;text\\&quot; name=\\&quot;folder\\&quot; value=\\&quot;&lt;?= htmlspecialchars($input_folder) ?&gt;\\&quot; required \\\/&gt;\\n                &lt;\\\/div&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div class=\\&quot;tabs\\&quot;&gt;\\n                &lt;div class=\\&quot;tab active\\&quot; data-tab=\\&quot;html\\&quot;&gt;\\u270f\\ufe0f HTML&lt;\\\/div&gt;\\n                &lt;div class=\\&quot;tab\\&quot; data-tab=\\&quot;css\\&quot;&gt;\\ud83c\\udfa8 CSS&lt;\\\/div&gt;\\n                &lt;div class=\\&quot;tab\\&quot; data-tab=\\&quot;js\\&quot;&gt;\\ud83e\\udde0 JavaScript&lt;\\\/div&gt;\\n                &lt;div class=\\&quot;tab\\&quot; data-tab=\\&quot;php\\&quot;&gt;\\ud83d\\udc18 PHP&lt;\\\/div&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div id=\\&quot;html\\&quot; class=\\&quot;editor-container active\\&quot;&gt;\\n                &lt;div class=\\&quot;btn-bar\\&quot;&gt;\\n                    &lt;div class=\\&quot;left-buttons\\&quot;&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-html-comment\\&quot;&gt;\\u6ce8\\u91ca\\\/\\u53d6\\u6d88\\u6ce8\\u91ca&lt;\\\/button&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;button type=\\&quot;button\\&quot; id=\\&quot;toggle-full-height\\&quot; data-target=\\&quot;html\\&quot;&gt;\\u5168\\u9ad8&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;textarea name=\\&quot;html\\&quot;&gt;&lt;?= htmlspecialchars($input_html) ?&gt;&lt;\\\/textarea&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div id=\\&quot;css\\&quot; class=\\&quot;editor-container\\&quot;&gt;\\n                &lt;div class=\\&quot;btn-bar\\&quot;&gt;\\n                    &lt;div class=\\&quot;left-buttons\\&quot;&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-css-comment\\&quot;&gt;\\u6ce8\\u91ca\\\/\\u53d6\\u6d88\\u6ce8\\u91ca&lt;\\\/button&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;button type=\\&quot;button\\&quot; id=\\&quot;toggle-full-height\\&quot; data-target=\\&quot;css\\&quot;&gt;\\u5168\\u9ad8&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;textarea name=\\&quot;css\\&quot;&gt;&lt;?= htmlspecialchars($input_css) ?&gt;&lt;\\\/textarea&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div id=\\&quot;js\\&quot; class=\\&quot;editor-container\\&quot;&gt;\\n                &lt;div class=\\&quot;btn-bar\\&quot;&gt;\\n                    &lt;div class=\\&quot;left-buttons\\&quot;&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-js-comment\\&quot;&gt;\\u6ce8\\u91ca\\\/\\u53d6\\u6d88\\u6ce8\\u91ca&lt;\\\/button&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;button type=\\&quot;button\\&quot; id=\\&quot;toggle-full-height\\&quot; data-target=\\&quot;js\\&quot;&gt;\\u5168\\u9ad8&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;textarea name=\\&quot;js\\&quot;&gt;&lt;?= htmlspecialchars($input_js) ?&gt;&lt;\\\/textarea&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div id=\\&quot;php\\&quot; class=\\&quot;editor-container\\&quot;&gt;\\n                &lt;div class=\\&quot;btn-bar\\&quot;&gt;\\n                    &lt;div class=\\&quot;left-buttons\\&quot;&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-php-comment\\&quot;&gt;\\u6ce8\\u91ca\\\/\\u53d6\\u6d88\\u6ce8\\u91ca&lt;\\\/button&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;button type=\\&quot;button\\&quot; id=\\&quot;toggle-full-height\\&quot; data-target=\\&quot;php\\&quot;&gt;\\u5168\\u9ad8&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;textarea name=\\&quot;php\\&quot;&gt;&lt;?= htmlspecialchars($input_php) ?&gt;&lt;\\\/textarea&gt;\\n            &lt;\\\/div&gt;\\n        &lt;\\\/form&gt;\\n    &lt;\\\/div&gt;\\n&lt;\\\/div&gt;\\n\\n&lt;button id=\\&quot;submit-btn\\&quot; type=\\&quot;submit\\&quot; form=\\&quot;form\\&quot;&gt;\\ud83d\\udcbe \\u4fdd\\u5b58\\u9879\\u76ee&lt;\\\/button&gt;\\n&lt;button id=\\&quot;toggle-dark\\&quot; title=\\&quot;\\u5207\\u6362\\u65e5\\u591c\\u95f4\\u6a21\\u5f0f\\&quot;&gt;\\ud83c\\udf19 \\u591c\\u95f4\\u6a21\\u5f0f&lt;\\\/button&gt;\\n\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/lib\\\/codemirror.min.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/htmlmixed\\\/htmlmixed.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/xml\\\/xml.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/css\\\/css.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/javascript\\\/javascript.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/clike\\\/clike.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/php\\\/php.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/addon\\\/comment\\\/comment.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/keymap\\\/sublime.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/sortablejs@1.15.2\\\/Sortable.min.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;script.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;\\\/body&gt;\\n&lt;\\\/html&gt;&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:10,&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>index.php\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-2b2d43f2-8' data-attributes='{&quot;cId&quot;:&quot;2b2d43f2-8&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\nsession_start();\\ndefine(&#039;ADMIN_PASSWORD&#039;, &#039;kangyue01.&#039;);\\n\\\/\\\/ \\u4fee\\u6539 BASE_DIR \\u4ee5\\u6307\\u5411\\u7236\\u76ee\\u5f55\\ndefine(&#039;BASE_DIR&#039;, dirname(__DIR__));\\ndefine(&#039;PROJECT_META_FILE&#039;, &#039;.project_meta.json&#039;); \\\/\\\/ New metadata file\\ndefine(&#039;PROJECTS_ORDER_FILE&#039;, &#039;projects_order.json&#039;); \\\/\\\/ \\u65b0\\u589e\\uff1a\\u9879\\u76ee\\u6392\\u5e8f\\u6587\\u4ef6\\n\\n\\\/\\\/ \\u767b\\u5f55\\u9a8c\\u8bc1\\nif (!isset($_SESSION[&#039;logged_in&#039;])) {\\n    if ($_SERVER[&#039;REQUEST_METHOD&#039;] === &#039;POST&#039; &amp;&amp; isset($_POST[&#039;password&#039;])) {\\n        if ($_POST[&#039;password&#039;] === ADMIN_PASSWORD) {\\n            $_SESSION[&#039;logged_in&#039;] = true;\\n            header(\\&quot;Location: \\&quot; . $_SERVER[&#039;PHP_SELF&#039;]);\\n            exit;\\n        } else {\\n            $login_error = \\&quot;\\u5bc6\\u7801\\u9519\\u8bef\\&quot;;\\n        }\\n    }\\n\\n    \\\/\\\/ New login interface HTML and CSS\\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;meta name=\\&quot;viewport\\&quot; content=\\&quot;width=device-width, initial-scale=1.0\\&quot;&gt;\\n        &lt;title&gt;\\u7ba1\\u7406\\u5458\\u767b\\u5f55&lt;\\\/title&gt;\\n        &lt;style&gt;\\n            body {\\n                font-family: &#039;Segoe UI&#039;, Tahoma, Geneva, Verdana, sans-serif;\\n                display: flex;\\n                justify-content: center;\\n                align-items: center;\\n                min-height: 100vh;\\n                background-color: #f0f2f5;\\n                margin: 0;\\n            }\\n            .login-container {\\n                background: #fff;\\n                padding: 40px;\\n                border-radius: 10px;\\n                box-shadow: 0 8px 25px rgba(0,0,0,0.15);\\n                text-align: center;\\n                max-width: 400px;\\n                width: 90%;\\n            }\\n            h2 {\\n                color: #34495e;\\n                margin-bottom: 25px;\\n                font-size: 1.8em;\\n            }\\n            input[type=\\&quot;password\\&quot;] {\\n                width: calc(100% - 22px);\\n                padding: 12px;\\n                margin-bottom: 20px;\\n                border: 1px solid #ced4da;\\n                border-radius: 6px;\\n                font-size: 1em;\\n                box-sizing: border-box;\\n            }\\n            button {\\n                padding: 12px 30px;\\n                background-color: #007bff;\\n                color: white;\\n                border: none;\\n                border-radius: 6px;\\n                cursor: pointer;\\n                font-size: 1.1em;\\n                font-weight: 600;\\n                transition: background-color 0.3s ease, transform 0.2s ease;\\n                box-shadow: 0 4px 10px rgba(0,0,0,0.1);\\n            }\\n            button:hover {\\n                background-color: #0056b3;\\n                transform: translateY(-2px);\\n                box-shadow: 0 6px 15px rgba(0,0,0,0.2);\\n            }\\n            .error {\\n                color: #dc3545;\\n                margin-top: 15px;\\n                font-weight: bold;\\n            }\\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;\\u540e\\u53f0\\u7ba1\\u7406\\u767b\\u5f55&lt;\\\/h2&gt;\\n            &lt;form method=\\&quot;POST\\&quot;&gt;\\n                &lt;input type=\\&quot;password\\&quot; name=\\&quot;password\\&quot; placeholder=\\&quot;\\u8bf7\\u8f93\\u5165\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\&quot; required autocomplete=\\&quot;off\\&quot;&gt;\\n                &lt;button type=\\&quot;submit\\&quot;&gt;\\u767b\\u5f55&lt;\\\/button&gt;\\n            &lt;\\\/form&gt;\\n            &lt;?php if (isset($login_error)): ?&gt;\\n                &lt;p class=\\&quot;error\\&quot;&gt;&lt;?= htmlspecialchars($login_error) ?&gt;&lt;\\\/p&gt;\\n            &lt;?php endif; ?&gt;\\n        &lt;\\\/div&gt;\\n    &lt;\\\/body&gt;\\n    &lt;\\\/html&gt;\\n    &lt;?php\\n    exit;\\n}\\n\\n\\\/\\\/ Function to read project metadata\\nfunction readProjectMetadata($folder_path) {\\n    $meta_file = $folder_path . DIRECTORY_SEPARATOR . PROJECT_META_FILE;\\n    if (file_exists($meta_file)) {\\n        $content = file_get_contents($meta_file);\\n        $data = json_decode($content, true);\\n        if (json_last_error() === JSON_ERROR_NONE) {\\n            return $data;\\n        }\\n    }\\n    return [&#039;name&#039; =&gt; basename($folder_path)]; \\\/\\\/ Default values, order is now external\\n}\\n\\n\\\/\\\/ Function to write project metadata\\nfunction writeProjectMetadata($folder_path, $data) {\\n    $meta_file = $folder_path . DIRECTORY_SEPARATOR . PROJECT_META_FILE;\\n    file_put_contents($meta_file, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));\\n}\\n\\n\\\/\\\/ \\u65b0\\u589e\\uff1a\\u8bfb\\u53d6\\u9879\\u76ee\\u6392\\u5e8f\\nfunction readProjectsOrder() {\\n    $order_file = BASE_DIR . DIRECTORY_SEPARATOR . PROJECTS_ORDER_FILE;\\n    if (file_exists($order_file)) {\\n        $content = file_get_contents($order_file);\\n        $data = json_decode($content, true);\\n        if (json_last_error() === JSON_ERROR_NONE &amp;&amp; is_array($data)) {\\n            return $data;\\n        }\\n    }\\n    return []; \\\/\\\/ \\u9ed8\\u8ba4\\u8fd4\\u56de\\u7a7a\\u6570\\u7ec4\\n}\\n\\n\\\/\\\/ \\u65b0\\u589e\\uff1a\\u5199\\u5165\\u9879\\u76ee\\u6392\\u5e8f\\nfunction writeProjectsOrder($order_array) {\\n    $order_file = BASE_DIR . DIRECTORY_SEPARATOR . PROJECTS_ORDER_FILE;\\n    file_put_contents($order_file, json_encode($order_array, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));\\n}\\n\\n\\n\\\/\\\/ Handle project reordering via AJAX\\nif (isset($_POST[&#039;action&#039;]) &amp;&amp; $_POST[&#039;action&#039;] === &#039;reorder_projects&#039;) {\\n    $new_order = json_decode($_POST[&#039;order&#039;], true);\\n    if (json_last_error() === JSON_ERROR_NONE &amp;&amp; is_array($new_order)) {\\n        writeProjectsOrder($new_order); \\\/\\\/ \\u76f4\\u63a5\\u5199\\u5165\\u65b0\\u7684\\u6392\\u5e8f\\u5230 projects_order.json\\n        echo json_encode([&#039;status&#039; =&gt; &#039;success&#039;]);\\n    } else {\\n        echo json_encode([&#039;status&#039; =&gt; &#039;error&#039;, &#039;message&#039; =&gt; &#039;Invalid order data.&#039;]);\\n    }\\n    exit;\\n}\\n\\n\\n\\\/\\\/ Error and success messages initialization\\n$error_message = &#039;&#039;;\\n$success_message = &#039;&#039;;\\n\\n\\\/\\\/ --- BEGIN: Updated Logic for State and Input Initialization ---\\n\\n\\\/\\\/ Determine state: is it a new project via URL parameter, or an edit?\\n$is_new_project_url_state = isset($_GET[&#039;new&#039;]);\\n\\n$edit_mode = false;\\n$edit_folder_name = &#039;&#039;; \\\/\\\/ Will hold the folder name if in edit mode\\n$edit_project_name = &#039;&#039;; \\\/\\\/ Will hold the project name if in edit mode\\n\\n\\\/\\\/ PHP variables to hold form input values (used for pre-filling or retaining on error)\\n$input_folder = $_POST[&#039;folder&#039;] ?? &#039;&#039;;\\n$input_project_name = $_POST[&#039;project_name&#039;] ?? &#039;&#039;;\\n$input_html = $_POST[&#039;html&#039;] ?? &#039;&#039;;\\n$input_css = $_POST[&#039;css&#039;] ?? &#039;&#039;;\\n$input_js = $_POST[&#039;js&#039;] ?? &#039;&#039;;\\n$input_php = $_POST[&#039;php&#039;] ?? &#039;&#039;;\\n\\n\\\/\\\/ If $_GET[&#039;edit&#039;] is set AND we are NOT in a &#039;?new=1&#039; state\\nif (isset($_GET[&#039;edit&#039;]) &amp;&amp; !$is_new_project_url_state) {\\n    $edit_mode = true;\\n    $edit_folder_name = basename($_GET[&#039;edit&#039;]);\\n    $edit_path = BASE_DIR . DIRECTORY_SEPARATOR . $edit_folder_name;\\n\\n    \\\/\\\/ Load existing project data\\n    $project_meta_data = readProjectMetadata($edit_path);\\n    $edit_project_name = $project_meta_data[&#039;name&#039;] ?? $edit_folder_name; \\\/\\\/ Get project name from meta or folder name\\n\\n    \\\/\\\/ Load file contents\\n    $input_html = @file_get_contents(\\&quot;$edit_path\\\/index.html\\&quot;);\\n    $input_css = @file_get_contents(\\&quot;$edit_path\\\/style.css\\&quot;);\\n    $input_js = @file_get_contents(\\&quot;$edit_path\\\/script.js\\&quot;);\\n    $input_php = @file_get_contents(\\&quot;$edit_path\\\/index.php\\&quot;);\\n\\n    \\\/\\\/ Pre-fill form fields with existing data. Only override $_POST values if it&#039;s not a POST request.\\n    if ($_SERVER[&#039;REQUEST_METHOD&#039;] !== &#039;POST&#039;) {\\n        $input_folder = $edit_folder_name;\\n        $input_project_name = $edit_project_name;\\n    }\\n}\\n\\\/\\\/ If it&#039;s a fresh load (no POST) AND we are either in &#039;?new=1&#039; state OR no parameters are present\\nelseif ($_SERVER[&#039;REQUEST_METHOD&#039;] !== &#039;POST&#039; || $is_new_project_url_state) {\\n    \\\/\\\/ Initialize form fields to empty for a new project or initial page load\\n    $input_folder = &#039;&#039;;\\n    $input_project_name = &#039;&#039;;\\n    $input_html = &#039;&#039;;\\n    $input_css = &#039;&#039;;\\n    $input_js = &#039;&#039;;\\n    $input_php = &#039;&#039;;\\n}\\n\\\/\\\/ Note: If it&#039;s a POST request and !empty($error_message), the $input_* variables will retain $_POST values from the beginning.\\n\\\/\\\/ This is the desired behavior for displaying errors with user input preserved.\\n\\n\\n\\\/\\\/ Determine the title to display in H2\\n$page_h2_title = ($edit_mode ? \\&quot;\\u7f16\\u8f91\\u9879\\u76ee\\uff1a\\&quot;.htmlspecialchars($edit_project_name) : \\&quot;\\u521b\\u5efa\\u65b0\\u9879\\u76ee\\&quot;);\\n\\n\\\/\\\/ --- END: Updated Logic for State and Input Initialization ---\\n\\n\\n\\\/\\\/ Collect all existing project names for duplication checks\\n$all_existing_project_names = [];\\n$project_dirs_scan = array_filter(glob(BASE_DIR . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\nforeach ($project_dirs_scan as $dir) {\\n    $folder_name = basename($dir);\\n    \\\/\\\/ Exclude script&#039;s own folder, .git, and any non-directory entries\\n    if ($folder_name === basename(dirname(__DIR__)) || $folder_name === &#039;.git&#039; || !is_dir($dir) || $folder_name === &#039;admin&#039;) { \\\/\\\/ Exclude &#039;admin&#039; folder\\n        continue;\\n    }\\n    $meta = readProjectMetadata($dir);\\n    $proj_name = $meta[&#039;name&#039;] ?? $folder_name;\\n\\n    \\\/\\\/ Add to list, excluding the current project&#039;s name if we are in edit mode\\n    \\\/\\\/ $edit_project_name will be empty if not in edit mode or in &#039;?new=1&#039; state, so this condition handles both.\\n    if (!$edit_mode || ($edit_mode &amp;&amp; $proj_name !== $edit_project_name)) {\\n        $all_existing_project_names[] = $proj_name;\\n    }\\n}\\n\\n\\n\\\/\\\/ Save file\\nif ($_SERVER[&#039;REQUEST_METHOD&#039;] === &#039;POST&#039; &amp;&amp; isset($_POST[&#039;folder&#039;], $_POST[&#039;project_name&#039;], $_POST[&#039;html&#039;], $_POST[&#039;css&#039;], $_POST[&#039;js&#039;], $_POST[&#039;php&#039;])) {\\n    $folder = preg_replace(&#039;\\\/[^a-zA-Z0-9_\\\\-]\\\/&#039;, &#039;&#039;, $_POST[&#039;folder&#039;]);\\n    $project_name = trim($_POST[&#039;project_name&#039;]);\\n\\n    \\\/\\\/ Basic validation for project name and folder name format\\n    if (empty($project_name)) {\\n        $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u540d\\u79f0\\u4e0d\\u80fd\\u4e3a\\u7a7a\\uff01\\&quot;;\\n    } elseif (empty($folder)) {\\n        $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u6587\\u4ef6\\u5939\\u540d\\u4e0d\\u80fd\\u4e3a\\u7a7a\\u6216\\u5305\\u542b\\u975e\\u6cd5\\u5b57\\u7b26\\uff01\\&quot;;\\n    } else {\\n        $original = $_POST[&#039;original_folder&#039;] ?? &#039;&#039;;\\n        $original = preg_replace(&#039;\\\/[^a-zA-Z0-9_\\\\-]\\\/&#039;, &#039;&#039;, $original);\\n\\n        $old_path = BASE_DIR . DIRECTORY_SEPARATOR . $original;\\n        $new_path = BASE_DIR . DIRECTORY_SEPARATOR . $folder;\\n\\n        \\\/\\\/ --- \\u5f00\\u59cb\\uff1a\\u7efc\\u5408\\u91cd\\u590d\\u6027\\u68c0\\u67e5 ---\\n        \\\/\\\/ \\u573a\\u666f1\\uff1a\\u521b\\u5efa\\u65b0\\u9879\\u76ee (empty($original) \\u4e3a\\u771f)\\n        if (empty($original)) {\\n            if (is_dir($new_path)) {\\n                $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u6587\\u4ef6\\u5939 &#039;{$folder}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u8bf7\\u66f4\\u6362\\u540d\\u79f0\\u3002\\&quot;;\\n            } elseif (in_array($project_name, $all_existing_project_names)) {\\n                $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u540d\\u79f0 &#039;{$project_name}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u8bf7\\u66f4\\u6362\\u540d\\u79f0\\u3002\\&quot;;\\n            }\\n        }\\n        \\\/\\\/ \\u573a\\u666f2\\uff1a\\u7f16\\u8f91\\u73b0\\u6709\\u9879\\u76ee\\n        else { \\\/\\\/ !empty($original), \\u6b63\\u5728\\u7f16\\u8f91\\u73b0\\u6709\\u9879\\u76ee\\n            \\\/\\\/ \\u68c0\\u67e5\\u6587\\u4ef6\\u5939\\u540d\\u662f\\u5426\\u6539\\u53d8\\u5e76\\u4e14\\u65b0\\u6587\\u4ef6\\u5939\\u540d\\u662f\\u5426\\u5df2\\u5b58\\u5728\\n            if ($folder !== $original) {\\n                if (is_dir($new_path)) {\\n                    $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u76ee\\u6807\\u6587\\u4ef6\\u5939 &#039;{$folder}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u65e0\\u6cd5\\u91cd\\u547d\\u540d\\u3002\\&quot;;\\n                }\\n            }\\n            \\\/\\\/ \\u68c0\\u67e5\\u9879\\u76ee\\u540d\\u79f0\\u662f\\u5426\\u6539\\u53d8\\uff0c\\u4e14\\u65b0\\u540d\\u79f0\\u662f\\u5426\\u88ab\\u5176\\u4ed6\\u9879\\u76ee\\u4f7f\\u7528\\n            \\\/\\\/ $all_existing_project_names \\u5df2\\u7ecf\\u6392\\u9664\\u4e86\\u5f53\\u524d\\u6b63\\u5728\\u7f16\\u8f91\\u7684\\u9879\\u76ee\\u7684\\u65e7\\u540d\\u79f0\\n            if (empty($error_message) &amp;&amp; $project_name !== $edit_project_name &amp;&amp; in_array($project_name, $all_existing_project_names)) {\\n                 $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u540d\\u79f0 &#039;{$project_name}&#039; \\u5df2\\u88ab\\u5176\\u4ed6\\u9879\\u76ee\\u4f7f\\u7528\\uff0c\\u8bf7\\u66f4\\u6362\\u540d\\u79f0\\u3002\\&quot;;\\n            }\\n        }\\n        \\\/\\\/ --- \\u7ed3\\u675f\\uff1a\\u7efc\\u5408\\u91cd\\u590d\\u6027\\u68c0\\u67e5 ---\\n\\n        if (empty($error_message)) { \\\/\\\/ \\u53ea\\u6709\\u5728\\u6240\\u6709\\u521d\\u6b65\\u9a8c\\u8bc1\\u901a\\u8fc7\\u540e\\u624d\\u7ee7\\u7eed\\n            \\\/\\\/ \\u73b0\\u6709\\u6587\\u4ef6\\u5939\\u91cd\\u547d\\u540d\\\/\\u521b\\u5efa\\u903b\\u8f91\\n            if (!empty($original) &amp;&amp; $folder !== $original &amp;&amp; is_dir($old_path)) {\\n                if (!rename($old_path, $new_path)) {\\n                    $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u65e0\\u6cd5\\u91cd\\u547d\\u540d\\u6587\\u4ef6\\u5939 &#039;{$original}&#039; \\u5230 &#039;{$folder}&#039;\\u3002\\&quot;;\\n                } else {\\n                    \\\/\\\/ \\u5982\\u679c\\u6587\\u4ef6\\u5939\\u91cd\\u547d\\u540d\\u6210\\u529f\\uff0c\\u66f4\\u65b0 projects_order.json \\u4e2d\\u7684\\u6587\\u4ef6\\u5939\\u540d\\n                    $current_order = readProjectsOrder();\\n                    $index = array_search($original, $current_order);\\n                    if ($index !== false) {\\n                        $current_order[$index] = $folder;\\n                        writeProjectsOrder($current_order);\\n                    }\\n                }\\n            } elseif (!is_dir($new_path)) { \\\/\\\/ \\u8fd9\\u4e2a\\u5757\\u7528\\u4e8e\\u4e3a\\u65b0\\u9879\\u76ee\\u6216\\u91cd\\u547d\\u540d\\u7684\\u9879\\u76ee\\u521b\\u5efa\\u5168\\u65b0\\u6587\\u4ef6\\u5939\\n                if (!mkdir($new_path, 0777, true)) {\\n                    $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u65e0\\u6cd5\\u521b\\u5efa\\u6587\\u4ef6\\u5939 &#039;{$folder}&#039;\\u3002\\&quot;;\\n                }\\n            }\\n\\n            if (empty($error_message)) { \\\/\\\/ \\u53ea\\u6709\\u5728\\u6587\\u4ef6\\u5939\\u64cd\\u4f5c\\u6210\\u529f\\u540e\\u624d\\u7ee7\\u7eed\\n                \\\/\\\/ \\u5b9a\\u4e49\\u8981\\u5904\\u7406\\u7684\\u6587\\u4ef6\\u53ca\\u5176\\u5185\\u5bb9\\n                $files_to_process = [\\n                    &#039;index.html&#039; =&gt; $_POST[&#039;html&#039;],\\n                    &#039;style.css&#039; =&gt; $_POST[&#039;css&#039;],\\n                    &#039;script.js&#039; =&gt; $_POST[&#039;js&#039;],\\n                    &#039;index.php&#039; =&gt; $_POST[&#039;php&#039;]\\n                ];\\n\\n                $conflict_detected = false;\\n                \\\/\\\/ \\u4ec5\\u5f53\\u662f\\u521b\\u5efa\\u65b0\\u9879\\u76ee (empty($original) \\u4e3a\\u771f) \\u65f6\\uff0c\\u624d\\u68c0\\u67e5\\u6587\\u4ef6\\u51b2\\u7a81\\n                \\\/\\\/ \\u5982\\u679c\\u76ee\\u6807\\u6587\\u4ef6\\u5b58\\u5728\\uff08\\u65e0\\u8bba\\u662f\\u5426\\u4e3a\\u7a7a\\uff09\\uff0c\\u5e76\\u4e14\\u6211\\u4eec\\u6709\\u65b0\\u5185\\u5bb9\\u8981\\u5199\\u5165\\uff0c\\u5219\\u8ba4\\u4e3a\\u662f\\u51b2\\u7a81\\uff0c\\u5e76\\u63d0\\u793a\\u7528\\u6237\\n                if (empty($original)) { \\\/\\\/ \\u53ea\\u5728\\u521b\\u5efa\\u65b0\\u9879\\u76ee\\u65f6\\u68c0\\u67e5\\u6587\\u4ef6\\u51b2\\u7a81\\n                    foreach ($files_to_process as $filename =&gt; $content) {\\n                        $file_path = \\&quot;$new_path\\\/$filename\\&quot;;\\n                        \\\/\\\/ \\u5982\\u679c\\u76ee\\u6807\\u6587\\u4ef6\\u5b58\\u5728\\uff0c\\u5e76\\u4e14\\u6211\\u4eec\\u6709\\u65b0\\u5185\\u5bb9\\u8981\\u5199\\u5165\\uff0c\\u5219\\u8ba4\\u4e3a\\u662f\\u51b2\\u7a81\\n                        if (file_exists($file_path) &amp;&amp; !empty($content)) {\\n                            $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u6587\\u4ef6 &#039;{$filename}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u5e76\\u5c1d\\u8bd5\\u5199\\u5165\\u65b0\\u5185\\u5bb9\\uff0c\\u8bf7\\u624b\\u52a8\\u5904\\u7406\\u6216\\u6e05\\u7a7a\\u6587\\u4ef6\\u5185\\u5bb9\\u3002\\&quot;;\\n                            $conflict_detected = true;\\n                            break;\\n                        }\\n                    }\\n                }\\n\\n                if (!$conflict_detected) {\\n                    foreach ($files_to_process as $filename =&gt; $content) {\\n                        $file_path = \\&quot;$new_path\\\/$filename\\&quot;;\\n\\n                        \\\/\\\/ === \\u6c49\\u5b57\\u4e71\\u7801\\u4fee\\u590d\\u548cUTF-8\\u58f0\\u660e\\u65b0\\u589e\\u4ee3\\u7801\\u5f00\\u59cb ===\\n                        \\\/\\\/ \\u5bf9\\u4e8e HTML \\u6587\\u4ef6\\uff0c\\u5982\\u679c\\u5185\\u5bb9\\u4e0d\\u4e3a\\u7a7a\\u4e14\\u4e0d\\u5305\\u542b UTF-8 meta \\u6807\\u7b7e\\uff0c\\u5219\\u6dfb\\u52a0\\n                        if ($filename === &#039;index.html&#039; &amp;&amp; !empty($content)) {\\n                            if (strpos($content, &#039;&lt;meta charset=\\&quot;UTF-8\\&quot;&gt;&#039;) === false &amp;&amp; strpos($content, &#039;&lt;meta charset=\\&quot;utf-8\\&quot;&gt;&#039;) === false) {\\n                                \\\/\\\/ \\u5c1d\\u8bd5\\u5728 &lt;head&gt; \\u6807\\u7b7e\\u5185\\u6dfb\\u52a0\\n                                if (preg_match(&#039;\\\/&lt;head&gt;\\\/i&#039;, $content)) {\\n                                    $content = preg_replace(&#039;\\\/&lt;head&gt;\\\/i&#039;, &#039;&lt;head&gt;&lt;meta charset=\\&quot;UTF-8\\&quot;&gt;&#039;, $content, 1);\\n                                } else {\\n                                    \\\/\\\/ \\u5982\\u679c\\u6ca1\\u6709head\\u6807\\u7b7e\\uff0c\\u5219\\u5c1d\\u8bd5\\u5728 &lt;!DOCTYPE html&gt; \\u540e\\u6216\\u6587\\u4ef6\\u5f00\\u5934\\u6dfb\\u52a0\\u4e00\\u4e2a\\u57fa\\u672c\\u7ed3\\u6784\\n                                    if (strpos(trim($content), &#039;&lt;!DOCTYPE html&gt;&#039;) === 0) {\\n                                        $content = preg_replace(&#039;\\\/(&lt;\\\\!DOCTYPE html&gt;)\\\/i&#039;, \\&quot;$1\\\\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;Document&lt;\\\/title&gt;\\\\n&lt;\\\/head&gt;\\\\n&lt;body&gt;\\&quot;, $content, 1) . \\&quot;\\\\n&lt;\\\/body&gt;\\\\n&lt;\\\/html&gt;\\&quot;;\\n                                    } elseif (strpos(trim($content), &#039;&lt;html&#039;) === 0) {\\n                                         $content = preg_replace(&#039;\\\/(&lt;html[^&gt;]*&gt;)\\\/i&#039;, \\&quot;$1\\\\n&lt;head&gt;\\\\n    &lt;meta charset=\\\\\\&quot;UTF-8\\\\\\&quot;&gt;\\\\n    &lt;title&gt;Document&lt;\\\/title&gt;\\\\n&lt;\\\/head&gt;\\&quot;, $content, 1);\\n                                    } else { \\\/\\\/ \\u6700\\u574f\\u60c5\\u51b5\\uff0c\\u76f4\\u63a5\\u5728\\u6587\\u4ef6\\u5f00\\u5934\\u6dfb\\u52a0\\n                                        $content = \\&quot;&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;Document&lt;\\\/title&gt;\\\\n&lt;\\\/head&gt;\\\\n&lt;body&gt;\\\\n\\&quot; . $content . \\&quot;\\\\n&lt;\\\/body&gt;\\\\n&lt;\\\/html&gt;\\&quot;;\\n                                    }\\n                                }\\n                            }\\n                        }\\n\\n                        \\\/\\\/ \\u5bf9\\u4e8e PHP \\u6587\\u4ef6\\uff0c\\u5982\\u679c\\u5185\\u5bb9\\u4e0d\\u4e3a\\u7a7a\\u4e14\\u4e0d\\u5305\\u542b UTF-8 header\\uff0c\\u5219\\u6dfb\\u52a0\\n                        if ($filename === &#039;index.php&#039; &amp;&amp; !empty($content)) {\\n                            if (strpos($content, \\&quot;header(&#039;Content-Type: text\\\/html; charset=utf-8&#039;);\\&quot;) === false) {\\n                                \\\/\\\/ \\u786e\\u4fdd\\u5728 &lt;?php \\u6807\\u7b7e\\u4e4b\\u540e\\u6dfb\\u52a0\\n                                if (strpos(trim($content), &#039;&lt;?php&#039;) === 0) {\\n                                    \\\/\\\/ \\u627e\\u5230\\u7b2c\\u4e00\\u4e2a\\u975e\\u6ce8\\u91ca\\u6216\\u7a7a\\u683c\\u7684 &lt;?php \\u4e4b\\u540e\\u7684\\u4f4d\\u7f6e\\u63d2\\u5165\\n                                    \\\/\\\/ \\u4f7f\\u7528\\u53cc\\u5f15\\u53f7\\u5b57\\u7b26\\u4e32\\uff0c\\u907f\\u514d\\u5355\\u5f15\\u53f7\\u8f6c\\u4e49\\u95ee\\u9898\\n                                    $content = preg_replace(&#039;\\\/&lt;\\\\?php\\\/&#039;, \\&quot;&lt;?php\\\\nheader(&#039;Content-Type: text\\\/html; charset=utf-8&#039;);\\&quot;, $content, 1);\\n                                } else {\\n                                    \\\/\\\/ \\u5982\\u679c\\u4e0d\\u662f\\u4ee5 &lt;?php \\u5f00\\u5934\\uff0c\\u5219\\u5728\\u6587\\u4ef6\\u6700\\u5f00\\u5934\\u6dfb\\u52a0\\n                                    $content = \\&quot;&lt;?php\\\\nheader(&#039;Content-Type: text\\\/html; charset=utf-8&#039;);\\\\n?&gt;\\&quot; . $content;\\n                                }\\n                            }\\n                        }\\n                        \\\/\\\/ === \\u6c49\\u5b57\\u4e71\\u7801\\u4fee\\u590d\\u548cUTF-8\\u58f0\\u660e\\u65b0\\u589e\\u4ee3\\u7801\\u7ed3\\u675f ===\\n\\n                        if (!empty($content)) {\\n                            file_put_contents($file_path, $content);\\n                        } elseif (file_exists($file_path)) {\\n                            \\\/\\\/ If content is empty and file exists, delete it\\n                            unlink($file_path);\\n                        }\\n                    }\\n\\n                    \\\/\\\/ Save project metadata\\n                    $current_meta = readProjectMetadata($new_path);\\n                    $current_meta[&#039;name&#039;] = $project_name;\\n                    writeProjectMetadata($new_path, $current_meta);\\n\\n                    \\\/\\\/ \\u65b0\\u589e\\uff1a\\u5982\\u679c\\u9879\\u76ee\\u662f\\u65b0\\u5efa\\u7684\\uff0c\\u5c06\\u5176\\u6dfb\\u52a0\\u5230 projects_order.json \\u7684\\u672b\\u5c3e\\n                    $current_order = readProjectsOrder();\\n                    if (!in_array($folder, $current_order)) {\\n                        $current_order[] = $folder;\\n                        writeProjectsOrder($current_order);\\n                    }\\n\\n                    $success_message = \\&quot;\\u2705 \\u9879\\u76ee &#039;{$project_name}&#039; (\\u6587\\u4ef6\\u5939: {$folder}) \\u5df2\\u4fdd\\u5b58\\uff01\\&quot;;\\n\\n                    \\\/\\\/ Re-read data to ensure latest content is displayed if AJAX reloads content\\n                    \\\/\\\/ This is crucial for the AJAX update to reflect the saved state.\\n                    $edit_mode = true; \\\/\\\/ Stay in edit mode after saving a new project\\n                    $edit_folder_name = $folder;\\n                    $edit_project_name = $project_name;\\n\\n                    $input_html = @file_get_contents(\\&quot;$new_path\\\/index.html\\&quot;);\\n                    $input_css = @file_get_contents(\\&quot;$new_path\\\/style.css\\&quot;);\\n                    $input_js = @file_get_contents(\\&quot;$new_path\\\/script.js\\&quot;);\\n                    $input_php = @file_get_contents(\\&quot;$new_path\\\/index.php\\&quot;);\\n                    $input_folder = $folder;\\n                    $input_project_name = $project_name;\\n                    $page_h2_title = \\&quot;\\u7f16\\u8f91\\u9879\\u76ee\\uff1a\\&quot;.htmlspecialchars($edit_project_name); \\\/\\\/ Update title for saved project\\n\\n                }\\n            }\\n        }\\n    }\\n}\\n\\n\\\/\\\/ Delete project\\nif (isset($_GET[&#039;delete&#039;])) {\\n    if (isset($_POST[&#039;admin_password&#039;]) &amp;&amp; $_POST[&#039;admin_password&#039;] === ADMIN_PASSWORD) {\\n        $del = basename($_GET[&#039;delete&#039;]);\\n        $target = BASE_DIR . DIRECTORY_SEPARATOR . $del;\\n        if (is_dir($target)) {\\n            \\\/\\\/ Function to recursively delete directory contents\\n            function deleteDir($dir) {\\n                $files = array_diff(scandir($dir), array(&#039;.&#039;, &#039;..&#039;));\\n                foreach ($files as $file) {\\n                    (is_dir(\\&quot;$dir\\\/$file\\&quot;)) ? deleteDir(\\&quot;$dir\\\/$file\\&quot;) : unlink(\\&quot;$dir\\\/$file\\&quot;);\\n                }\\n                return rmdir($dir);\\n            }\\n            deleteDir($target);\\n\\n            \\\/\\\/ \\u4ece projects_order.json \\u4e2d\\u79fb\\u9664\\u88ab\\u5220\\u9664\\u7684\\u9879\\u76ee\\n            $current_order = readProjectsOrder();\\n            $current_order = array_diff($current_order, [$del]);\\n            writeProjectsOrder(array_values($current_order)); \\\/\\\/ array_values \\u91cd\\u65b0\\u7d22\\u5f15\\u6570\\u7ec4\\n\\n            \\\/\\\/ Redirect back to admin page, clear GET parameters\\n            header(\\&quot;Location: \\&quot; . strtok($_SERVER[&#039;PHP_SELF&#039;], &#039;?&#039;));\\n            exit;\\n        }\\n    } else {\\n        $error_message = \\&quot;\\u274c \\u5220\\u9664\\u5931\\u8d25\\uff1a\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\u9519\\u8bef\\uff01\\&quot;;\\n    }\\n}\\n\\n\\n\\\/\\\/ Get all project folders and their metadata for display\\n$project_dirs_display = array_filter(glob(BASE_DIR . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\n$all_project_folders = [];\\nforeach ($project_dirs_display as $dir) {\\n    $folder_name = basename($dir);\\n    \\\/\\\/ \\u6392\\u9664\\u811a\\u672c\\u81ea\\u5df1\\u7684\\u6587\\u4ef6\\u5939 (.git) \\u4ee5\\u53ca\\u65b0\\u7684 &#039;admin&#039; \\u6587\\u4ef6\\u5939\\n    if ($folder_name === basename(dirname(__DIR__)) || $folder_name === &#039;.git&#039; || $folder_name === &#039;admin&#039;) {\\n        continue;\\n    }\\n    $all_project_folders[] = $folder_name;\\n}\\n\\n$ordered_project_folders = readProjectsOrder();\\n$projects_data = [];\\n\\n\\\/\\\/ \\u5c06\\u5df2\\u6392\\u5e8f\\u7684\\u9879\\u76ee\\u6dfb\\u52a0\\u5230 projects_data\\nforeach ($ordered_project_folders as $folder_name) {\\n    if (in_array($folder_name, $all_project_folders)) {\\n        $project_path = BASE_DIR . DIRECTORY_SEPARATOR . $folder_name;\\n        $meta = readProjectMetadata($project_path);\\n        $projects_data[] = [\\n            &#039;folder_name&#039; =&gt; $folder_name,\\n            &#039;project_name&#039; =&gt; $meta[&#039;name&#039;] ?? $folder_name,\\n        ];\\n        \\\/\\\/ \\u4ece all_project_folders \\u4e2d\\u79fb\\u9664\\u5df2\\u5904\\u7406\\u7684\\uff0c\\u4ee5\\u4fbf\\u540e\\u7eed\\u6dfb\\u52a0\\u672a\\u6392\\u5e8f\\u7684\\u65b0\\u9879\\u76ee\\n        $all_project_folders = array_diff($all_project_folders, [$folder_name]);\\n    }\\n}\\n\\n\\\/\\\/ \\u5c06 projects_order.json \\u4e2d\\u6ca1\\u6709\\uff0c\\u4f46\\u5b9e\\u9645\\u5b58\\u5728\\u7684\\u9879\\u76ee\\u6dfb\\u52a0\\u5230 projects_data \\u7684\\u672b\\u5c3e\\nforeach ($all_project_folders as $folder_name) {\\n    $project_path = BASE_DIR . DIRECTORY_SEPARATOR . $folder_name;\\n    $meta = readProjectMetadata($project_path);\\n    $projects_data[] = [\\n        &#039;folder_name&#039; =&gt; $folder_name,\\n        &#039;project_name&#039; =&gt; $meta[&#039;name&#039;] ?? $folder_name,\\n    ];\\n}\\n\\n\\\/\\\/ \\u73b0\\u5728 projects_data \\u5df2\\u7ecf\\u6309\\u7167 projects_order.json \\u6392\\u5e8f\\uff0c\\u5e76\\u4e14\\u5305\\u542b\\u4e86\\u6240\\u6709\\u5b9e\\u9645\\u5b58\\u5728\\u7684\\u9879\\u76ee\\u3002\\n\\n\\\/\\\/ Include the HTML file\\ninclude &#039;index.html&#039;;\\n?&gt;&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:10,&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>script.js\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-d9536cc8-d' data-attributes='{&quot;cId&quot;:&quot;d9536cc8-d&quot;,&quot;code&quot;:&quot;const tabs = document.querySelectorAll(&#039;.tab&#039;);\\nconst tabContents = {\\n    html: document.getElementById(&#039;html&#039;),\\n    css: document.getElementById(&#039;css&#039;),\\n    js: document.getElementById(&#039;js&#039;),\\n    php: document.getElementById(&#039;php&#039;),\\n};\\n\\nconst editors = {}; \\\/\\\/ Defined in global scope\\n\\ntabs.forEach(tab =&gt; {\\n    tab.addEventListener(&#039;click&#039;, () =&gt; {\\n        tabs.forEach(t =&gt; t.classList.remove(&#039;active&#039;));\\n        tab.classList.add(&#039;active&#039;);\\n\\n        Object.values(tabContents).forEach(tc =&gt; tc.classList.remove(&#039;active&#039;));\\n        tabContents[tab.dataset.tab].classList.add(&#039;active&#039;);\\n        editors[tab.dataset.tab].refresh();\\n        editors[tab.dataset.tab].focus();\\n    });\\n});\\n\\nfunction initEditor(textareaElement, mode, initialContent) {\\n    const editor = CodeMirror.fromTextArea(textareaElement, {\\n        mode,\\n        theme: \\&quot;eclipse\\&quot;,\\n        lineNumbers: true,\\n        lineWrapping: true,\\n        keyMap: \\&quot;sublime\\&quot;,\\n        extraKeys: { \\&quot;Ctrl-\\\/\\&quot;: \\&quot;toggleComment\\&quot;, \\&quot;Cmd-\\\/\\&quot;: \\&quot;toggleComment\\&quot; }, \\\/\\\/ \\u79fb\\u9664 Ctrl-F \\u548c Cmd-F \\u7ed1\\u5b9a\\n        scrollbarStyle: \\&quot;native\\&quot;,\\n        autofocus: false\\n    });\\n    editor.setValue(initialContent || &#039;&#039;);\\n    return editor;\\n}\\n\\n\\\/\\\/ Get initial content from PHP variables (these will be injected by PHP into index.html)\\nconst initialData = {\\n    folder: document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value,\\n    project_name: document.querySelector(&#039;input[name=\\&quot;project_name\\&quot;]&#039;).value,\\n    html: document.querySelector(&#039;textarea[name=\\&quot;html\\&quot;]&#039;).value,\\n    css: document.querySelector(&#039;textarea[name=\\&quot;css\\&quot;]&#039;).value,\\n    js: document.querySelector(&#039;textarea[name=\\&quot;js\\&quot;]&#039;).value,\\n    php: document.querySelector(&#039;textarea[name=\\&quot;php\\&quot;]&#039;).value\\n};\\n\\neditors.html = initEditor(document.querySelector(&#039;#html textarea&#039;), &#039;htmlmixed&#039;, initialData.html);\\neditors.css = initEditor(document.querySelector(&#039;#css textarea&#039;), &#039;css&#039;, initialData.css);\\neditors.js = initEditor(document.querySelector(&#039;#js textarea&#039;), &#039;javascript&#039;, initialData.js);\\neditors.php = initEditor(document.querySelector(&#039;#php textarea&#039;), &#039;application\\\/x-httpd-php&#039;, initialData.php);\\n\\n\\n\\\/\\\/ --- \\u6539\\u8fdb1 &amp; 2: AJAX\\u4fdd\\u5b58 &amp; Ctrl+S\\u4fdd\\u5b58 ---\\ndocument.getElementById(&#039;submit-btn&#039;).addEventListener(&#039;click&#039;, function(e) {\\n    e.preventDefault(); \\\/\\\/ \\u963b\\u6b62\\u9ed8\\u8ba4\\u7684\\u8868\\u5355\\u63d0\\u4ea4\\n\\n    \\\/\\\/ \\u4fdd\\u5b58\\u6240\\u6709CodeMirror\\u5185\\u5bb9\\u56detextarea\\uff0c\\u4ee5\\u4fbf\\u83b7\\u53d6\\u6700\\u65b0\\u503c\\u8fdb\\u884c\\u6bd4\\u8f83\\n    Object.values(editors).forEach(editor =&gt; editor.save());\\n\\n    const form = document.getElementById(&#039;form&#039;);\\n\\n    \\\/\\\/ \\u83b7\\u53d6\\u5f53\\u524d\\u8868\\u5355\\u548c\\u7f16\\u8f91\\u5668\\u4e2d\\u7684\\u503c\\n    const currentFolder = document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value;\\n    const currentProjectName = document.querySelector(&#039;input[name=\\&quot;project_name\\&quot;]&#039;).value;\\n    const currentHtml = document.querySelector(&#039;#html textarea&#039;).value;\\n    const currentCss = document.querySelector(&#039;#css textarea&#039;).value;\\n    const currentJs = document.querySelector(&#039;#js textarea&#039;).value;\\n    const currentPhp = document.querySelector(&#039;#php textarea&#039;).value;\\n\\n    \\\/\\\/ \\u68c0\\u67e5\\u662f\\u5426\\u6709\\u4efb\\u4f55\\u66f4\\u6539\\n    let hasChanges = false;\\n    if (currentFolder !== initialData.folder ||\\n        currentProjectName !== initialData.project_name ||\\n        currentHtml !== initialData.html ||\\n        currentCss !== initialData.css ||\\n        currentJs !== initialData.js ||\\n        currentPhp !== initialData.php) {\\n        hasChanges = true;\\n    }\\n\\n    const messageDisplayArea = document.getElementById(&#039;message-display-area&#039;); \\\/\\\/ \\u83b7\\u53d6\\u6d88\\u606f\\u5bb9\\u5668\\n\\n    if (!hasChanges) {\\n        \\\/\\\/ \\u5982\\u679c\\u6ca1\\u6709\\u66f4\\u6539\\uff0c\\u663e\\u793a\\u63d0\\u793a\\u6d88\\u606f\\u5e76\\u963b\\u6b62\\u4fdd\\u5b58\\u64cd\\u4f5c\\n        messageDisplayArea.innerHTML = &#039;&#039;; \\\/\\\/ \\u6e05\\u9664\\u65e7\\u6d88\\u606f\\n        const noChangeMessage = document.createElement(&#039;p&#039;);\\n        noChangeMessage.classList.add(&#039;message&#039;, &#039;info&#039;);\\n        noChangeMessage.textContent = &#039;\\u2139\\ufe0f \\u6ca1\\u6709\\u68c0\\u6d4b\\u5230\\u4efb\\u4f55\\u66f4\\u6539\\uff0c\\u65e0\\u9700\\u4fdd\\u5b58\\u3002&#039;;\\n        messageDisplayArea.appendChild(noChangeMessage);\\n        setTimeout(() =&gt; {\\n            noChangeMessage.classList.add(&#039;fade-out&#039;);\\n            noChangeMessage.addEventListener(&#039;transitionend&#039;, () =&gt; noChangeMessage.remove(), { once: true });\\n        }, 1000); \\\/\\\/ 1\\u79d2\\u540e\\u6d88\\u5931\\n        return; \\\/\\\/ \\u505c\\u6b62\\u51fd\\u6570\\u6267\\u884c\\uff0c\\u4e0d\\u53d1\\u9001 AJAX \\u8bf7\\u6c42\\n    }\\n\\n    \\\/\\\/ --- \\u73b0\\u6709\\u4ee3\\u7801\\uff1a\\u5982\\u679c\\u68c0\\u6d4b\\u5230\\u66f4\\u6539\\uff0c\\u5219\\u7ee7\\u7eed\\u53d1\\u9001 AJAX \\u8bf7\\u6c42 ---\\n    const formData = new FormData(form);\\n\\n    fetch(form.action, {\\n        method: &#039;POST&#039;,\\n        body: formData\\n    })\\n    .then(response =&gt; response.text())\\n    .then(html =&gt; {\\n        const parser = new DOMParser();\\n        const doc = parser.parseFromString(html, &#039;text\\\/html&#039;);\\n\\n        messageDisplayArea.innerHTML = &#039;&#039;; \\\/\\\/ \\u6e05\\u9664\\u65e7\\u6d88\\u606f\\n\\n        const messageSuccess = doc.querySelector(&#039;.message.success&#039;);\\n        const messageError = doc.querySelector(&#039;.message.error&#039;);\\n\\n        let messageElement = null;\\n\\n        if (messageSuccess) {\\n            messageElement = messageSuccess;\\n        } else if (messageError) {\\n            messageElement = messageError;\\n        }\\n\\n        if (messageElement) {\\n            messageDisplayArea.appendChild(messageElement);\\n            setTimeout(() =&gt; {\\n                messageElement.classList.add(&#039;fade-out&#039;);\\n                messageElement.addEventListener(&#039;transitionend&#039;, () =&gt; messageElement.remove(), { once: true });\\n            }, 1000);\\n        }\\n\\n        \\\/\\\/ --- \\u65b0\\u589e\\uff1a\\u4fdd\\u5b58\\u5f53\\u524d\\u6240\\u6709\\u7f16\\u8f91\\u5668\\u7684\\u5149\\u6807\\u4f4d\\u7f6e ---\\n        const cursorPositions = {};\\n        const scrollPositions = {};\\n        for (const key in editors) {\\n            if (editors.hasOwnProperty(key)) {\\n                cursorPositions[key] = editors[key].getCursor();\\n                scrollPositions[key] = editors[key].getScrollInfo(); \\\/\\\/ \\u4fdd\\u5b58\\u6eda\\u52a8\\u4fe1\\u606f\\n            }\\n        }\\n        \\\/\\\/ --- \\u7ed3\\u675f\\u65b0\\u589e ---\\n\\n        \\\/\\\/ Update CodeMirror editor content\\n        editors.html.setValue(doc.querySelector(&#039;textarea[name=\\&quot;html\\&quot;]&#039;).value);\\n        editors.css.setValue(doc.querySelector(&#039;textarea[name=\\&quot;css\\&quot;]&#039;).value);\\n        editors.js.setValue(doc.querySelector(&#039;textarea[name=\\&quot;js\\&quot;]&#039;).value);\\n        editors.php.setValue(doc.querySelector(&#039;textarea[name=\\&quot;php\\&quot;]&#039;).value);\\n\\n        \\\/\\\/ --- \\u65b0\\u589e\\uff1a\\u6062\\u590d\\u6240\\u6709\\u7f16\\u8f91\\u5668\\u7684\\u5149\\u6807\\u4f4d\\u7f6e ---\\n        for (const key in editors) {\\n            if (editors.hasOwnProperty(key)) {\\n                editors[key].setCursor(cursorPositions[key]);\\n                \\\/\\\/ \\u6062\\u590d\\u6eda\\u52a8\\u4f4d\\u7f6e\\n                editors[key].scrollTo(scrollPositions[key].left, scrollPositions[key].top);\\n            }\\n        }\\n        \\\/\\\/ --- \\u7ed3\\u675f\\u65b0\\u589e ---\\n\\n        \\\/\\\/ Update initialData to reflect the newly saved state\\n        initialData.folder = doc.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value;\\n        initialData.project_name = doc.querySelector(&#039;input[name=\\&quot;project_name\\&quot;]&#039;).value;\\n        initialData.html = doc.querySelector(&#039;textarea[name=\\&quot;html\\&quot;]&#039;).value;\\n        initialData.css = doc.querySelector(&#039;textarea[name=\\&quot;css\\&quot;]&#039;).value;\\n        initialData.js = doc.querySelector(&#039;textarea[name=\\&quot;js\\&quot;]&#039;).value;\\n        initialData.php = doc.querySelector(&#039;textarea[name=\\&quot;php\\&quot;]&#039;).value;\\n\\n        \\\/\\\/ Update project name and folder name input fields\\n        document.querySelector(&#039;input[name=\\&quot;project_name\\&quot;]&#039;).value = initialData.project_name;\\n        document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value = initialData.folder;\\n\\n        \\\/\\\/ Update H2 title\\n        const newH2Title = doc.querySelector(&#039;.main h2&#039;).textContent;\\n        document.querySelector(&#039;.main h2&#039;).textContent = newH2Title;\\n\\n        \\\/\\\/ Refresh sidebar project list\\n        const newProjectListHTML = doc.getElementById(&#039;project-list&#039;).innerHTML;\\n        document.getElementById(&#039;project-list&#039;).innerHTML = newProjectListHTML;\\n\\n        \\\/\\\/ --- \\u6539\\u8fdb SortableJS \\u91cd\\u65b0\\u7ed1\\u5b9a\\u903b\\u8f91 ---\\n        \\\/\\\/ \\u6bcf\\u6b21DOM\\u5185\\u5bb9\\u66f4\\u65b0\\u540e\\uff0c\\u90fd\\u83b7\\u53d6\\u4e00\\u4e2a\\u65b0\\u7684DOM\\u5143\\u7d20\\u5f15\\u7528\\uff0c\\u786e\\u4fdd\\u64cd\\u4f5c\\u7684\\u662f\\u6700\\u65b0\\u7684\\u5143\\u7d20\\n        const projectListElement = document.getElementById(&#039;project-list&#039;); \\n        if (projectListElement) {\\n            \\\/\\\/ \\u5982\\u679c\\u8be5\\u5143\\u7d20\\u4e0a\\u5df2\\u6709 Sortable \\u5b9e\\u4f8b\\uff0c\\u5219\\u5148\\u9500\\u6bc1\\n            if (projectListElement.sortable) { \\n                projectListElement.sortable.destroy(); \\\/\\\/ \\u9500\\u6bc1\\u73b0\\u6709\\u5b9e\\u4f8b\\n            }\\n\\n            \\\/\\\/ \\u91cd\\u65b0\\u521b\\u5efa Sortable \\u5b9e\\u4f8b\\n            Sortable.create(projectListElement, { \\\/\\\/ \\u4f7f\\u7528\\u6700\\u65b0\\u7684 projectListElement \\u5f15\\u7528\\n                animation: 150,\\n                ghostClass: &#039;sortable-ghost&#039;,\\n                chosenClass: &#039;sortable-chosen&#039;,\\n                onEnd: function (evt) {\\n                    const newOrder = [];\\n                    \\\/\\\/ \\u5728 onEnd \\u4e2d\\uff0c\\u786e\\u4fdd\\u4f7f\\u7528 evt.from \\u6216\\u518d\\u6b21\\u83b7\\u53d6 projectListElement \\u6765\\u904d\\u5386\\u5b50\\u5143\\u7d20\\n                    Array.from(projectListElement.children).forEach(li =&gt; { \\\/\\\/ \\u786e\\u4fdd\\u8fd9\\u91cc\\u4e5f\\u662f\\u4f7f\\u7528 projectListElement\\n                        newOrder.push(li.dataset.folderName);\\n                    });\\n\\n                    fetch(window.location.href, {\\n                        method: &#039;POST&#039;,\\n                        headers: { &#039;Content-Type&#039;: &#039;application\\\/x-www-form-urlencoded&#039; },\\n                        body: new URLSearchParams({ action: &#039;reorder_projects&#039;, order: JSON.stringify(newOrder) })\\n                    })\\n                    .then(response =&gt; response.json())\\n                    .then(data =&gt; {\\n                        if (data.status === &#039;success&#039;) {\\n                            console.log(&#039;Project order updated successfully.&#039;);\\n                        } else {\\n                            console.error(&#039;Error updating project order:&#039;, data.message);\\n                        }\\n                    })\\n                    .catch(error =&gt; console.error(&#039;Network error during reorder:&#039;, error));\\n                },\\n            });\\n        } else {\\n            console.error(\\&quot;Error: project-list element not found during AJAX rebind. SortableJS not re-initialized.\\&quot;);\\n        }\\n\\n        \\\/\\\/ Re-highlight the current active project\\n        const currentFolderFromResponse = doc.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value;\\n        document.querySelectorAll(&#039;#project-list li&#039;).forEach(li =&gt; {\\n            li.classList.remove(&#039;active&#039;);\\n            if (li.dataset.folderName === currentFolderFromResponse) {\\n                li.classList.add(&#039;active&#039;);\\n            }\\n        });\\n\\n    })\\n    .catch(error =&gt; {\\n        console.error(&#039;Error saving project:&#039;, error);\\n        \\\/\\\/ Error message also displayed via the new mechanism\\n        messageDisplayArea.innerHTML = &#039;&#039;;\\n        const errorDiv = document.createElement(&#039;p&#039;);\\n        errorDiv.classList.add(&#039;message&#039;, &#039;error&#039;);\\n        errorDiv.textContent = `\\u274c \\u4fdd\\u5b58\\u9879\\u76ee\\u65f6\\u53d1\\u751f\\u9519\\u8bef: ${error.message || error}`;\\n        messageDisplayArea.appendChild(errorDiv);\\n        setTimeout(() =&gt; {\\n            errorDiv.classList.add(&#039;fade-out&#039;);\\n            errorDiv.addEventListener(&#039;transitionend&#039;, () =&gt; errorDiv.remove(), { once: true });\\n        }, 1000);\\n    });\\n});\\n\\ndocument.addEventListener(&#039;keydown&#039;, function(event) {\\n    \\\/\\\/ Check for Ctrl+S (Windows\\\/Linux) or Cmd+S (macOS)\\n    if ((event.ctrlKey || event.metaKey) &amp;&amp; event.key === &#039;s&#039;) {\\n        event.preventDefault(); \\\/\\\/ Prevent default browser save dialog\\n        document.getElementById(&#039;submit-btn&#039;).click(); \\\/\\\/ Trigger the save button click event\\n    }\\n});\\n\\n\\\/\\\/ Comment buttons binding\\ndocument.getElementById(&#039;btn-html-comment&#039;).onclick = () =&gt; editors.html.execCommand(&#039;toggleComment&#039;);\\ndocument.getElementById(&#039;btn-css-comment&#039;).onclick = () =&gt; editors.css.execCommand(&#039;toggleComment&#039;);\\ndocument.getElementById(&#039;btn-js-comment&#039;).onclick = () =&gt; editors.js.execCommand(&#039;toggleComment&#039;);\\ndocument.getElementById(&#039;btn-php-comment&#039;).onclick = () =&gt; editors.php.execCommand(&#039;toggleComment&#039;);\\n\\n\\n\\\/\\\/ Day\\\/Night mode switch\\nconst toggleBtn = document.getElementById(&#039;toggle-dark&#039;);\\nlet darkMode = localStorage.getItem(&#039;darkMode&#039;) === &#039;true&#039;;\\n\\nfunction applyDarkMode(isDark) {\\n    document.body.classList.toggle(&#039;dark&#039;, isDark);\\n    toggleBtn.textContent = isDark ? &#039;\\u2600\\ufe0f \\u65e5\\u95f4\\u6a21\\u5f0f&#039; : &#039;\\ud83c\\udf19 \\u591c\\u95f4\\u6a21\\u5f0f&#039;;\\n    Object.values(editors).forEach(editor =&gt; {\\n        editor.setOption(&#039;theme&#039;, isDark ? &#039;darcula&#039; : &#039;eclipse&#039;);\\n    });\\n}\\n\\napplyDarkMode(darkMode);\\n\\ntoggleBtn.addEventListener(&#039;click&#039;, () =&gt; {\\n    darkMode = !darkMode;\\n    applyDarkMode(darkMode);\\n    localStorage.setItem(&#039;darkMode&#039;, darkMode);\\n});\\n\\n\\\/\\\/ --- \\u6539\\u8fdb3: \\u5168\\u9ad8\\\/\\u534a\\u9ad8\\u6309\\u94ae\\u6587\\u5b57\\u5207\\u6362 ---\\ndocument.querySelectorAll(&#039;#toggle-full-height&#039;).forEach(button =&gt; {\\n    button.addEventListener(&#039;click&#039;, function() {\\n        const targetTab = this.dataset.target;\\n        const editorContainer = tabContents[targetTab];\\n        editorContainer.classList.toggle(&#039;full-height&#039;);\\n\\n        \\\/\\\/ Toggle button text\\n        if (editorContainer.classList.contains(&#039;full-height&#039;)) {\\n            this.textContent = &#039;\\u534a\\u9ad8&#039;; \\\/\\\/ Change to \\&quot;Half Height\\&quot;\\n        } else {\\n            this.textContent = &#039;\\u5168\\u9ad8&#039;; \\\/\\\/ Change back to \\&quot;Full Height\\&quot;\\n        }\\n\\n        document.body.classList.toggle(&#039;full-height-active&#039;, editorContainer.classList.contains(&#039;full-height&#039;));\\n\\n        editors[targetTab].refresh(); \\\/\\\/ Refresh editor to adapt to new size\\n    });\\n});\\n\\n\\n\\\/\\\/ New project button event\\ndocument.getElementById(&#039;new-project-btn&#039;).addEventListener(&#039;click&#039;, () =&gt; {\\n    \\\/\\\/ Redirect to URL with ?new=1 parameter, let PHP handle reset and highlight\\n    window.location.href = location.pathname + &#039;?new=1&#039;;\\n});\\n\\n\\\/\\\/ Delete project confirmation\\nfunction deleteProject(folderName) {\\n    const password = prompt(`\\u786e\\u5b9a\\u8981\\u5220\\u9664\\u9879\\u76ee &#039;${decodeURIComponent(folderName)}&#039; \\u5417\\uff1f\\\\n\\u8bf7\\u8f93\\u5165\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\u786e\\u8ba4\\u5220\\u9664:`);\\n    if (password === &#039;kangyue01.&#039;) { \\\/\\\/ Hardcoded password from PHP constant\\n        \\\/\\\/ Create a temporary form to submit a POST request for deletion\\n        const form = document.createElement(&#039;form&#039;);\\n        form.method = &#039;POST&#039;;\\n        form.action = `?delete=${encodeURIComponent(folderName)}`;\\n\\n        const input = document.createElement(&#039;input&#039;);\\n        input.type = &#039;hidden&#039;;\\n        input.name = &#039;admin_password&#039;;\\n        input.value = password;\\n        form.appendChild(input);\\n\\n        document.body.appendChild(form);\\n        form.submit();\\n    } else if (password !== null) { \\\/\\\/ If user entered password but it&#039;s incorrect\\n        alert(&#039;\\u5bc6\\u7801\\u9519\\u8bef\\uff0c\\u65e0\\u6cd5\\u5220\\u9664\\u9879\\u76ee\\u3002&#039;);\\n    }\\n}\\n\\n\\\/\\\/ Initialize SortableJS\\nconst projectList = document.getElementById(&#039;project-list&#039;);\\nSortable.create(projectList, {\\n    animation: 150,\\n    ghostClass: &#039;sortable-ghost&#039;,\\n    chosenClass: &#039;sortable-chosen&#039;,\\n    onEnd: function (evt) {\\n        const newOrder = [];\\n        Array.from(projectList.children).forEach(li =&gt; {\\n            newOrder.push(li.dataset.folderName);\\n        });\\n\\n        \\\/\\\/ Send new order to server via AJAX\\n        fetch(window.location.href, {\\n            method: &#039;POST&#039;,\\n            headers: {\\n                &#039;Content-Type&#039;: &#039;application\\\/x-www-form-urlencoded&#039;,\\n            },\\n            body: new URLSearchParams({\\n                action: &#039;reorder_projects&#039;,\\n                order: JSON.stringify(newOrder)\\n            })\\n        })\\n        .then(response =&gt; response.json())\\n        .then(data =&gt; {\\n            if (data.status === &#039;success&#039;) {\\n                \\\/\\\/ Optionally show a success message or re-fetch list\\n                console.log(&#039;Project order updated successfully.&#039;);\\n            } else {\\n                console.error(&#039;Error updating project order:&#039;, data.message);\\n            }\\n        })\\n        .catch(error =&gt; {\\n            console.error(&#039;Network error during reorder:&#039;, error);\\n        });\\n    },\\n});&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:10,&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;language&quot;:&quot;javascript&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>style.css\uff1a<\/p>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-965ec36f-c' data-attributes='{&quot;cId&quot;:&quot;965ec36f-c&quot;,&quot;language&quot;:&quot;css&quot;,&quot;code&quot;:&quot;* { box-sizing: border-box; }\\nhtml, body {\\n    margin: 0; padding: 0; height: 100%;\\n    overflow: hidden;\\n    font-family: sans-serif;\\n    background: #f0f0f0;\\n    color: #000;\\n    transition: background-color 0.3s, color 0.3s;\\n}\\nbody.dark {\\n    background: #1e1e1e;\\n    color: #ddd;\\n}\\nbody, #app {\\n    display: flex;\\n    height: 100vh;\\n    overflow: hidden;\\n}\\n.sidebar {\\n    \\\/* \\u79fb\\u9664\\u6216\\u6ce8\\u91ca\\u6389 width \\u5c5e\\u6027 *\\\/\\n    \\\/* width: 220px; *\\\/\\n\\n    \\\/* \\u8a2d\\u7f6e\\u6700\\u5c0f\\u5bec\\u5ea6\\uff0c\\u4ee5\\u78ba\\u4fdd\\u5728\\u6c92\\u6709\\u8db3\\u5920\\u5167\\u5bb9\\u6642\\u4e0d\\u6703\\u904e\\u7a84 *\\\/\\n    min-width: fit-content; \\\/* \\u6216\\u4f60\\u53ef\\u4ee5\\u8a2d\\u5b9a\\u4e00\\u500b\\u50cf\\u7d20\\u503c\\uff0c\\u4f8b\\u5982\\uff1amin-width: 180px; *\\\/\\n\\n    \\\/* \\u78ba\\u4fdd\\u5167\\u5bb9\\u4e0d\\u6703\\u6536\\u7e2e\\uff0c\\u9019\\u6a23\\u6587\\u5b57\\u5c31\\u4e0d\\u6703\\u56e0\\u70ba\\u7a7a\\u9593\\u4e0d\\u8db3\\u800c\\u6298\\u884c *\\\/\\n    flex-shrink: 0;\\n\\n    \\\/* \\u8a2d\\u7f6e\\u521d\\u59cb\\u57fa\\u790e\\u5bec\\u5ea6\\u70ba\\u5167\\u5bb9\\u6240\\u9700\\uff0c\\u4e26\\u5141\\u8a31\\u5176\\u589e\\u9577 *\\\/\\n    flex-basis: auto; \\\/* \\u8b93\\u5167\\u5bb9\\u6c7a\\u5b9a\\u5176\\u57fa\\u790e\\u5bec\\u5ea6 *\\\/\\n\\n    background: #333;\\n    color: white;\\n    padding: 20px;\\n    overflow-y: auto;\\n    \\\/* flex-shrink: 0;  \\u4fdd\\u7559\\u9019\\u500b\\uff0c\\u56e0\\u70ba\\u5b83\\u5f88\\u91cd\\u8981\\uff0c\\u53ef\\u4ee5\\u9632\\u6b62\\u5074\\u6b04\\u6536\\u7e2e *\\\/\\n    display: flex;\\n    flex-direction: column;\\n    position: relative;\\n    user-select: none;\\n}\\n.sidebar h3 {\\n    margin-top: 0;\\n    font-size: 18px;\\n    user-select: none;\\n}\\n.sidebar ul {\\n    list-style: none;\\n    padding: 0;\\n    margin: 0;\\n    flex-grow: 1;\\n    \\\/* \\u4fee\\u6539\\u6b64\\u884c\\uff0c\\u589e\\u52a0\\u5e95\\u90e8\\u7559\\u767d\\uff0c\\u786e\\u4fdd\\u4e0d\\u4f1a\\u88ab\\u6309\\u94ae\\u906e\\u6321 *\\\/\\n    margin-bottom: 70px; \\\/* \\u7ed9\\u4e88\\u8db3\\u591f\\u7684\\u7a7a\\u95f4\\uff0c\\u786e\\u4fdd\\u6309\\u94ae\\u9ad8\\u5ea6\\u52a0\\u4e0a\\u4e00\\u4e9b\\u95f4\\u8ddd *\\\/\\n}\\n\\n.sidebar li {\\n    display: flex;\\n    justify-content: space-between;\\n    align-items: center;\\n    padding: 6px 0;\\n    border-bottom: 1px solid #444;\\n    cursor: grab; \\\/* Indicate draggable *\\\/\\n}\\n.sidebar li.active {\\n    background-color: #555; \\\/* Highlight active project background *\\\/\\n    border-radius: 4px;\\n   \\\/* padding-left: 8px;  Adjust padding for highlight *\\\/\\n}\\n.sidebar li.active a {\\n    color: white !important;\\n    font-weight: bold;\\n}\\n.sidebar a {\\n    color: #ddd;\\n    text-decoration: none;\\n    margin-right: 6px;\\n}\\n.sidebar a:hover {\\n    color: #fff;\\n}\\n\\n\\n\\\/* Sortable.js ghost and chosen styles *\\\/\\n.sortable-ghost {\\n    opacity: 0.2;\\n    background: #f0f0f0;\\n    border: 1px dashed #007bff;\\n}\\n.sortable-chosen {\\n    background-color: #444;\\n}\\n\\n.container {\\n    flex: 1;\\n    display: flex;\\n    flex-direction: column;\\n    padding: 20px;\\n    overflow: hidden;\\n}\\n.main {\\n    flex: 1;\\n    overflow: hidden;\\n    display: flex;\\n    flex-direction: column;\\n    color: inherit;\\n}\\nh2 {\\n    margin: 0 0 8px 0;\\n    font-weight: normal;\\n    user-select: none;\\n}\\nform {\\n    margin-top: 0;\\n    flex: 1;\\n    display: flex;\\n    flex-direction: column;\\n    overflow: hidden;\\n}\\nlabel {\\n    font-weight: bold;\\n    margin-top: 10px;\\n    display: block;\\n    user-select: none;\\n}\\ninput[type=\\&quot;text\\&quot;] {\\n    width: 100%;\\n    padding: 6px;\\n    font-size: 14px;\\n    margin-top: 4px;\\n    box-sizing: border-box;\\n    background: white;\\n    border: 1px solid #ccc;\\n    color: #000;\\n}\\nbody.dark input[type=\\&quot;text\\&quot;] {\\n    background: #333;\\n    border-color: #555;\\n    color: #ddd;\\n}\\n\\n\\\/* \\u65b0\\u589e\\uff1a\\u9879\\u76ee\\u540d\\u79f0\\u548c\\u6587\\u4ef6\\u5939\\u540d\\u5728\\u540c\\u4e00\\u884c *\\\/\\n.project-info-row {\\n    display: flex;\\n    gap: 20px; \\\/* \\u4e24\\u4e2a\\u8f93\\u5165\\u7ec4\\u4e4b\\u95f4\\u7684\\u95f4\\u8ddd *\\\/\\n    margin-bottom: 10px; \\\/* \\u4e0e\\u4e0b\\u65b9\\u5143\\u7d20\\u7684\\u95f4\\u8ddd *\\\/\\n    flex-wrap: wrap; \\\/* \\u5c0f\\u5c4f\\u5e55\\u65f6\\u5141\\u8bb8\\u6362\\u884c *\\\/\\n}\\n\\n.project-info-row .input-group {\\n    flex: 1; \\\/* \\u6bcf\\u4e2a\\u8f93\\u5165\\u7ec4\\u5e73\\u5747\\u5206\\u914d\\u53ef\\u7528\\u7a7a\\u95f4 *\\\/\\n    min-width: 280px; \\\/* \\u786e\\u4fdd\\u5728\\u5c0f\\u5c4f\\u5e55\\u4e0a\\u4e5f\\u6709\\u6700\\u5c0f\\u5bbd\\u5ea6 *\\\/\\n}\\n\\n.project-info-row label {\\n    margin-top: 0; \\\/* \\u79fb\\u9664\\u4e0a\\u65b9\\u7684 margin *\\\/\\n    margin-bottom: 5px; \\\/* \\u6807\\u7b7e\\u548c\\u8f93\\u5165\\u6846\\u4e4b\\u95f4\\u7684\\u95f4\\u8ddd *\\\/\\n}\\n.project-info-row input[type=\\&quot;text\\&quot;] {\\n    margin-top: 0; \\\/* \\u79fb\\u9664\\u4e0a\\u65b9\\u7684 margin *\\\/\\n}\\n\\n\\\/* Tab navigation *\\\/\\n.tabs {\\n    display: flex;\\n    border-bottom: 2px solid #ccc;\\n    user-select: none;\\n    margin-top: 8px;\\n}\\nbody.dark .tabs {\\n    border-color: #555;\\n}\\n.tab {\\n    padding: 8px 16px;\\n    cursor: pointer;\\n    border: 1px solid transparent;\\n    border-bottom: none;\\n    background: #eee;\\n    color: #000;\\n    margin-right: 6px;\\n    border-radius: 6px 6px 0 0;\\n    transition: background-color 0.3s;\\n    font-size: 14px;\\n    display: flex;\\n    align-items: center;\\n    gap: 6px;\\n    flex-shrink: 0;\\n}\\nbody.dark .tab {\\n    background: #333;\\n    color: #ddd;\\n}\\n.tab.active {\\n    background: white;\\n    border-color: #ccc #ccc white;\\n    font-weight: bold;\\n}\\nbody.dark .tab.active {\\n    background: #1e1e1e;\\n    border-color: #555 #555 #1e1e1e;\\n    font-weight: bold;\\n}\\n\\n.btn-bar {\\n    margin: 6px 0 12px 0;\\n    user-select: none;\\n    display: flex;\\n    justify-content: space-between;\\n    align-items: center;\\n}\\n.btn-bar .left-buttons button {\\n    margin-right: 8px;\\n}\\n\\n.btn-bar button {\\n    padding: 6px 12px;\\n    cursor: pointer;\\n    border-radius: 4px;\\n    border: 1px solid #666;\\n    background: #f5f5f5;\\n    font-size: 14px;\\n    user-select: none;\\n}\\nbody.dark .btn-bar button {\\n    background: #444;\\n    border-color: #888;\\n    color: #ddd;\\n}\\n.btn-bar button:hover {\\n    background: #ddd;\\n}\\nbody.dark .btn-bar button:hover {\\n    background: #666;\\n}\\n#toggle-full-height {\\n    padding: 4px 8px;\\n    border-radius: 4px;\\n    background: #f0f0f0;\\n    color: #666;\\n    border: 1px solid #ccc;\\n    font-size: 12px;\\n    cursor: pointer;\\n    user-select: none;\\n    transition: background-color 0.2s, color 0.2s;\\n}\\nbody.dark #toggle-full-height {\\n    background: #333;\\n    color: #ccc;\\n    border-color: #555;\\n}\\n#toggle-full-height:hover {\\n    background: #e0e0e0;\\n    color: #333;\\n}\\nbody.dark #toggle-full-height:hover {\\n    background: #444;\\n    color: #eee;\\n}\\n\\n\\\/* Editor container *\\\/\\n.editor-container {\\n    flex: 1;\\n    display: none;\\n    flex-direction: column;\\n    min-height: 0;\\n    transition: height 0.3s ease-in-out;\\n}\\n.editor-container.active {\\n    display: flex;\\n}\\n.CodeMirror {\\n    height: 100%;\\n    border: 1px solid #ccc;\\n    font-size: 14px;\\n    line-height: 1.4em;\\n}\\nbody.dark .CodeMirror {\\n    border-color: #555;\\n    background: #1e1e1e;\\n    color: #ddd;\\n}\\n.CodeMirror-scroll {\\n    overflow-x: hidden !important;\\n    overflow-y: scroll !important;\\n    margin-right: -17px;\\n    padding-right: 17px;\\n    padding-bottom: 20px; \\\/* \\u65b0\\u589e\\uff1a\\u589e\\u52a0\\u5e95\\u90e8\\u586b\\u5145\\uff0c\\u786e\\u4fdd\\u6700\\u540e\\u4e00\\u884c\\u53ef\\u89c1 *\\\/\\n}\\n\\n\\\/* Full height mode styles *\\\/\\n.editor-container.full-height {\\n    position: fixed;\\n    top: 0;\\n    left: 220px; \\\/* \\u4fa7\\u8fb9\\u680f\\u5bbd\\u5ea6 *\\\/\\n    right: 0;\\n    bottom: 0;\\n    z-index: 999;\\n    background: #f0f0f0;\\n    padding: 20px;\\n    display: flex !important;\\n    width: auto;\\n}\\nbody.dark .editor-container.full-height {\\n    background: #1e1e1e;\\n}\\n\\n\\\/* \\u65b0\\u589e\\uff1a\\u786e\\u4fddCodeMirror\\u641c\\u7d22\\u5bf9\\u8bdd\\u6846\\u5728\\u5168\\u9ad8\\u6a21\\u5f0f\\u4e0b\\u4e5f\\u80fd\\u663e\\u793a *\\\/\\n.CodeMirror-dialog, .CodeMirror-dialog.CodeMirror-dialog-top {\\n    z-index: 10000 !important; \\\/* \\u786e\\u4fdd\\u9ad8\\u4e8e\\u5176\\u4ed6\\u6240\\u6709\\u5143\\u7d20 *\\\/\\n    position: fixed; \\\/* \\u4fdd\\u6301\\u56fa\\u5b9a\\u4f4d\\u7f6e *\\\/\\n    top: auto; \\\/* \\u653e\\u5728\\u5e95\\u90e8 *\\\/\\n    bottom: 20px;\\n    left: 50%;\\n    transform: translateX(-50%);\\n    background: rgba(0,0,0,0.8); \\\/* \\u7a0d\\u5fae\\u900f\\u660e\\u7684\\u80cc\\u666f *\\\/\\n    color: #fff;\\n    padding: 8px 12px;\\n    border-radius: 4px;\\n}\\n.CodeMirror-dialog input {\\n    background: #fff;\\n    color: #000;\\n    border: 1px solid #ccc;\\n    padding: 4px;\\n    border-radius: 3px;\\n}\\nbody.dark .CodeMirror-dialog input {\\n    background: #222;\\n    color: #eee;\\n    border-color: #555;\\n}\\n\\n\\\/* \\u9690\\u85cf\\u5168\\u9ad8\\u6a21\\u5f0f\\u4e0b\\u7684\\u975e\\u5fc5\\u8981\\u5143\\u7d20\\uff0c\\u5305\\u62ec\\u641c\\u7d22\\u6309\\u94ae\\u4ee5\\u5916\\u7684\\u5176\\u4ed6\\u6309\\u94ae *\\\/\\n.full-height-active h2,\\n.full-height-active label,\\n.full-height-active input[type=\\&quot;text\\&quot;],\\n.full-height-active .tabs,\\n.full-height-active #submit-btn,\\n.full-height-active #toggle-dark,\\n.full-height-active .project-info-row, \\\/* \\u9690\\u85cf\\u9879\\u76ee\\u4fe1\\u606f\\u884c *\\\/\\n.full-height-active .editor-container.full-height .left-buttons { \\\/* \\u9690\\u85cf\\u9664\\u4e86\\u5168\\u9ad8\\u6309\\u94ae\\u5916\\u7684\\u5176\\u4ed6\\u6309\\u94ae *\\\/\\n    display: none !important;\\n}\\n\\\/* \\u786e\\u4fdd\\u5168\\u9ad8\\u65f6\\u53ea\\u663e\\u793a\\u5168\\u9ad8\\u5207\\u6362\\u6309\\u94ae *\\\/\\n.full-height-active .editor-container.full-height #toggle-full-height {\\n    display: block !important;\\n    position: absolute; \\\/* \\u76f8\\u5bf9\\u4e8e\\u5bb9\\u5668\\u5b9a\\u4f4d *\\\/\\n    top: 20px;\\n    right: 20px;\\n    left: auto; \\\/* \\u79fb\\u9664 left: 20px *\\\/\\n    transform: none; \\\/* \\u79fb\\u9664 transform *\\\/\\n    z-index: 10001; \\\/* \\u786e\\u4fdd\\u5b83\\u5728\\u6700\\u9876\\u5c42\\uff0c\\u907f\\u514d\\u88ab\\u5176\\u4ed6\\u5143\\u7d20\\u8986\\u76d6 *\\\/\\n}\\n\\n\\n\\\/* Success and error messages *\\\/\\n\\\/* \\u65b0\\u589e\\uff1a\\u6d88\\u606f\\u5bb9\\u5668\\uff0c\\u7528\\u4e8e\\u5c45\\u4e2d\\u663e\\u793a\\u6d88\\u606f *\\\/\\n.message-container {\\n    position: fixed;\\n    top: 50%;\\n    left: 50%;\\n    transform: translate(-50%, -50%);\\n    z-index: 99999; \\\/* \\u786e\\u4fdd\\u9ad8\\u4e8e\\u6240\\u6709\\u5176\\u4ed6\\u5143\\u7d20\\uff0c\\u5305\\u62ec\\u5168\\u9ad8\\u7f16\\u8f91\\u5668\\u548cCodeMirror\\u5bf9\\u8bdd\\u6846 *\\\/\\n    display: flex;\\n    justify-content: center;\\n    align-items: center;\\n    width: 100%; \\\/* \\u5141\\u8bb8\\u5b50\\u5143\\u7d20\\u5c45\\u4e2d *\\\/\\n    pointer-events: none; \\\/* \\u5141\\u8bb8\\u70b9\\u51fb\\u7a7f\\u900f\\u5bb9\\u5668 *\\\/\\n}\\n\\n\\\/* \\u4fee\\u6539\\uff1a\\u6d88\\u606f\\u6846\\u672c\\u8eab\\u7684\\u6837\\u5f0f *\\\/\\n.message {\\n    margin: 0; \\\/* \\u79fb\\u9664\\u65e7\\u7684 margin-top\\uff0c\\u56e0\\u4e3a\\u73b0\\u5728\\u7531 message-container \\u5c45\\u4e2d *\\\/\\n    padding: 15px 30px; \\\/* \\u589e\\u52a0\\u5185\\u8fb9\\u8ddd *\\\/\\n    border-radius: 8px; \\\/* \\u66f4\\u5706\\u6da6\\u7684\\u8fb9\\u89d2 *\\\/\\n    font-weight: bold;\\n    font-size: 1.1em; \\\/* \\u7a0d\\u5fae\\u589e\\u5927\\u5b57\\u4f53 *\\\/\\n    user-select: none;\\n    box-shadow: 0 4px 15px rgba(0,0,0,0.2); \\\/* \\u6dfb\\u52a0\\u9634\\u5f71 *\\\/\\n    text-align: center;\\n    pointer-events: auto; \\\/* \\u6d88\\u606f\\u6846\\u672c\\u8eab\\u53ef\\u4ee5\\u88ab\\u70b9\\u51fb *\\\/\\n    min-width: 200px; \\\/* \\u786e\\u4fdd\\u6700\\u5c0f\\u5bbd\\u5ea6 *\\\/\\n    transition: opacity 0.5s ease-out; \\\/* \\u6dfb\\u52a0\\u8fc7\\u6e21\\u6548\\u679c *\\\/\\n    opacity: 1; \\\/* \\u521d\\u59cb\\u5b8c\\u5168\\u53ef\\u89c1 *\\\/\\n}\\n\\n\\\/* \\u65b0\\u589e\\uff1a\\u6de1\\u51fa\\u6548\\u679c *\\\/\\n.message.fade-out {\\n    opacity: 0;\\n}\\n\\n\\\/* \\u6210\\u529f\\u6d88\\u606f\\u7684\\u989c\\u8272 *\\\/\\n.success {\\n    color: #155724; \\\/* \\u6df1\\u7eff\\u8272 *\\\/\\n    background-color: #d4edda; \\\/* \\u6d45\\u7eff\\u8272 *\\\/\\n    border: 1px solid #c3e6cb;\\n}\\n\\\/* \\u9519\\u8bef\\u6d88\\u606f\\u7684\\u989c\\u8272 *\\\/\\n.error {\\n    color: #721c24; \\\/* \\u6df1\\u7ea2\\u8272 *\\\/\\n    background-color: #f8d7da; \\\/* \\u6d45\\u7ea2\\u8272 *\\\/\\n    border: 1px solid #f5c6cb;\\n}\\n\\\/* \\u4fe1\\u606f\\u6d88\\u606f\\u7684\\u989c\\u8272 *\\\/\\n.message.info {\\n    color: #004085;\\n    background-color: #cce5ff;\\n    border: 1px solid #b8daff;\\n}\\n\\n\\\/* \\u5f3a\\u5236\\u8bbe\\u7f6e CodeMirror \\u6ce8\\u91ca\\u7684\\u989c\\u8272\\u4e3a\\u7070\\u8272 *\\\/\\n.CodeMirror .cm-comment {\\n    color: #888 !important; \\\/* \\u7070\\u8272 *\\\/\\n}\\n\\\/* \\u53ef\\u9009\\uff1a\\u5982\\u679c\\u4f60\\u4f7f\\u7528\\u6df1\\u8272\\u6a21\\u5f0f\\uff0c\\u53ef\\u80fd\\u9700\\u8981\\u4e0d\\u540c\\u7684\\u7070\\u8272 *\\\/\\nbody.dark .CodeMirror .cm-comment {\\n    color: #777 !important; \\\/* \\u6df1\\u8272\\u6a21\\u5f0f\\u4e0b\\u7684\\u6df1\\u7070\\u8272 *\\\/\\n}\\n\\n\\\/* Day\\\/Night toggle button *\\\/\\n#toggle-dark {\\n    position: fixed;\\n    top: 10px;\\n    right: 10px;\\n    padding: 8px 16px;\\n    background: rgba(0,0,0,0.6);\\n    color: #fff;\\n    border-radius: 20px;\\n    cursor: pointer;\\n    font-size: 14px;\\n    backdrop-filter: saturate(180%) blur(10px);\\n    transition: background-color 0.3s;\\n    user-select: none;\\n    z-index: 1000;\\n}\\n#toggle-dark:hover {\\n    background: rgba(0,0,0,0.8);\\n}\\nbody.dark #toggle-dark {\\n    background: rgba(255,255,255,0.15);\\n    color: #eee;\\n}\\nbody.dark #toggle-dark:hover {\\n    background: rgba(255,255,255,0.3);\\n}\\n\\n\\\/* New project button - sidebar bottom *\\\/\\n#new-project-btn {\\n    \\\/* \\u5c06 position \\u4ece absolute \\u4fee\\u6539\\u4e3a sticky *\\\/\\n    position: sticky;\\n    bottom: 20px; \\\/* \\u8ddd\\u79bb\\u5e95\\u90e820px *\\\/\\n    left: 20px; \\\/* \\u8ddd\\u79bb\\u5de6\\u4fa720px *\\\/\\n    \\\/* \\u6dfb\\u52a0 align-self \\u4ee5\\u786e\\u4fdd\\u5728 flex \\u5bb9\\u5668\\u4e2d\\u9760\\u5e95\\u90e8\\u5bf9\\u9f50 *\\\/\\n    align-self: flex-end; \\\/* \\u6216\\u8005\\u4f7f\\u7528 margin-top: auto; \\u653e\\u5728 ul \\u540e *\\\/\\n\\n    background: rgba(51, 51, 51, 0.8);\\n    color: #ddd;\\n    border: 1px solid rgba(68, 68, 68, 0.8);\\n    border-radius: 4px;\\n    padding: 8px 12px;\\n    font-size: 14px;\\n    cursor: pointer;\\n    z-index: 1000;\\n    user-select: none;\\n    transition: background-color 0.3s, border-color 0.3s;\\n    width: calc(100% - 40px);\\n    text-align: center;\\n}\\n\\n#new-project-btn:hover {\\n    background: rgba(68, 68, 68, 0.9);\\n    border-color: rgba(85, 85, 85, 0.9);\\n}\\n\\n\\\/* Save project button - floating *\\\/\\n#submit-btn {\\n    position: fixed;\\n    bottom: 25px;\\n    right: 55px;\\n    padding: 15px 25px;\\n    background: rgba(33,150,243,0.7);\\n    color: white;\\n    border: none;\\n    border-radius: 30px;\\n    font-size: 18px;\\n    cursor: pointer;\\n    z-index: 1000;\\n    user-select: none;\\n    transition: background-color 0.3s, box-shadow 0.3s;\\n    backdrop-filter: none;\\n    box-shadow: 0 4px 8px rgba(0,0,0,0.2);\\n    text-shadow: 0 1px 2px rgba(0,0,0,0.3);\\n}\\n#submit-btn:hover {\\n    background: rgba(11,125,218,0.9);\\n    box-shadow: 0 6px 12px rgba(0,0,0,0.3);\\n}&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:10,&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\">\u5355\u6587\u4ef6\u7248<\/h3>\n\n\n\n<p>2025\u5e747\u67084\u65e5\u65b0\u589e\u6548\u679c\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u4e00\u6b21\u6027\u4fdd\u5b58\u6210\u529f\uff0c\u800c\u65e0\u9700\u5237\u65b0<\/li>\n\n\n\n<li>\u6210\u529f\/\u5931\u8d25\u7684\u63d0\u793a\u8bed2\u79d2\u540e\u6d88\u5931<\/li>\n\n\n\n<li>\u4ee3\u7801\u7f16\u8f91\u6846\u652f\u6301\u641c\u7d22\u5173\u952e\u8bcd<\/li>\n\n\n\n<li>\u70b9\u51fb\u5168\u9ad8\u540e\uff0c\u6309\u94ae\u540d\u79f0\u53d8\u4e3a\u534a\u9ad8<\/li>\n<\/ul>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-e7bb227f-f' data-attributes='{&quot;cId&quot;:&quot;e7bb227f-f&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\nsession_start();\\ndefine(&#039;ADMIN_PASSWORD&#039;, &#039;\\u540e\\u53f0\\u5bc6\\u7801&#039;);\\ndefine(&#039;BASE_DIR&#039;, __DIR__);\\ndefine(&#039;PROJECT_META_FILE&#039;, &#039;.project_meta.json&#039;); \\\/\\\/ New metadata file\\ndefine(&#039;PROJECTS_ORDER_FILE&#039;, &#039;projects_order.json&#039;); \\\/\\\/ \\u65b0\\u589e\\uff1a\\u9879\\u76ee\\u6392\\u5e8f\\u6587\\u4ef6\\n\\n\\\/\\\/ \\u767b\\u5f55\\u9a8c\\u8bc1\\nif (!isset($_SESSION[&#039;logged_in&#039;])) {\\n    if ($_SERVER[&#039;REQUEST_METHOD&#039;] === &#039;POST&#039; &amp;&amp; isset($_POST[&#039;password&#039;])) {\\n        if ($_POST[&#039;password&#039;] === ADMIN_PASSWORD) {\\n            $_SESSION[&#039;logged_in&#039;] = true;\\n            header(\\&quot;Location: \\&quot; . $_SERVER[&#039;PHP_SELF&#039;]);\\n            exit;\\n        } else {\\n            $login_error = \\&quot;\\u5bc6\\u7801\\u9519\\u8bef\\&quot;;\\n        }\\n    }\\n\\n    \\\/\\\/ New login interface HTML and CSS\\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;meta name=\\&quot;viewport\\&quot; content=\\&quot;width=device-width, initial-scale=1.0\\&quot;&gt;\\n        &lt;title&gt;\\u7ba1\\u7406\\u5458\\u767b\\u5f55&lt;\\\/title&gt;\\n        &lt;style&gt;\\n            body {\\n                font-family: &#039;Segoe UI&#039;, Tahoma, Geneva, Verdana, sans-serif;\\n                display: flex;\\n                justify-content: center;\\n                align-items: center;\\n                min-height: 100vh;\\n                background-color: #f0f2f5;\\n                margin: 0;\\n            }\\n            .login-container {\\n                background: #fff;\\n                padding: 40px;\\n                border-radius: 10px;\\n                box-shadow: 0 8px 25px rgba(0,0,0,0.15);\\n                text-align: center;\\n                max-width: 400px;\\n                width: 90%;\\n            }\\n            h2 {\\n                color: #34495e;\\n                margin-bottom: 25px;\\n                font-size: 1.8em;\\n            }\\n            input[type=\\&quot;password\\&quot;] {\\n                width: calc(100% - 22px);\\n                padding: 12px;\\n                margin-bottom: 20px;\\n                border: 1px solid #ced4da;\\n                border-radius: 6px;\\n                font-size: 1em;\\n                box-sizing: border-box;\\n            }\\n            button {\\n                padding: 12px 30px;\\n                background-color: #007bff;\\n                color: white;\\n                border: none;\\n                border-radius: 6px;\\n                cursor: pointer;\\n                font-size: 1.1em;\\n                font-weight: 600;\\n                transition: background-color 0.3s ease, transform 0.2s ease;\\n                box-shadow: 0 4px 10px rgba(0,0,0,0.1);\\n            }\\n            button:hover {\\n                background-color: #0056b3;\\n                transform: translateY(-2px);\\n                box-shadow: 0 6px 15px rgba(0,0,0,0.2);\\n            }\\n            .error {\\n                color: #dc3545;\\n                margin-top: 15px;\\n                font-weight: bold;\\n            }\\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;\\u540e\\u53f0\\u7ba1\\u7406\\u767b\\u5f55&lt;\\\/h2&gt;\\n            &lt;form method=\\&quot;POST\\&quot;&gt;\\n                &lt;input type=\\&quot;password\\&quot; name=\\&quot;password\\&quot; placeholder=\\&quot;\\u8bf7\\u8f93\\u5165\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\&quot; required autocomplete=\\&quot;off\\&quot;&gt;\\n                &lt;button type=\\&quot;submit\\&quot;&gt;\\u767b\\u5f55&lt;\\\/button&gt;\\n            &lt;\\\/form&gt;\\n            &lt;?php if (isset($login_error)): ?&gt;\\n                &lt;p class=\\&quot;error\\&quot;&gt;&lt;?= htmlspecialchars($login_error) ?&gt;&lt;\\\/p&gt;\\n            &lt;?php endif; ?&gt;\\n        &lt;\\\/div&gt;\\n    &lt;\\\/body&gt;\\n    &lt;\\\/html&gt;\\n    &lt;?php\\n    exit;\\n}\\n\\n\\\/\\\/ Function to read project metadata\\nfunction readProjectMetadata($folder_path) {\\n    $meta_file = $folder_path . DIRECTORY_SEPARATOR . PROJECT_META_FILE;\\n    if (file_exists($meta_file)) {\\n        $content = file_get_contents($meta_file);\\n        $data = json_decode($content, true);\\n        if (json_last_error() === JSON_ERROR_NONE) {\\n            return $data;\\n        }\\n    }\\n    return [&#039;name&#039; =&gt; basename($folder_path)]; \\\/\\\/ Default values, order is now external\\n}\\n\\n\\\/\\\/ Function to write project metadata\\nfunction writeProjectMetadata($folder_path, $data) {\\n    $meta_file = $folder_path . DIRECTORY_SEPARATOR . PROJECT_META_FILE;\\n    file_put_contents($meta_file, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));\\n}\\n\\n\\\/\\\/ \\u65b0\\u589e\\uff1a\\u8bfb\\u53d6\\u9879\\u76ee\\u6392\\u5e8f\\nfunction readProjectsOrder() {\\n    $order_file = BASE_DIR . DIRECTORY_SEPARATOR . PROJECTS_ORDER_FILE;\\n    if (file_exists($order_file)) {\\n        $content = file_get_contents($order_file);\\n        $data = json_decode($content, true);\\n        if (json_last_error() === JSON_ERROR_NONE &amp;&amp; is_array($data)) {\\n            return $data;\\n        }\\n    }\\n    return []; \\\/\\\/ \\u9ed8\\u8ba4\\u8fd4\\u56de\\u7a7a\\u6570\\u7ec4\\n}\\n\\n\\\/\\\/ \\u65b0\\u589e\\uff1a\\u5199\\u5165\\u9879\\u76ee\\u6392\\u5e8f\\nfunction writeProjectsOrder($order_array) {\\n    $order_file = BASE_DIR . DIRECTORY_SEPARATOR . PROJECTS_ORDER_FILE;\\n    file_put_contents($order_file, json_encode($order_array, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));\\n}\\n\\n\\n\\\/\\\/ Handle project reordering via AJAX\\nif (isset($_POST[&#039;action&#039;]) &amp;&amp; $_POST[&#039;action&#039;] === &#039;reorder_projects&#039;) {\\n    $new_order = json_decode($_POST[&#039;order&#039;], true);\\n    if (json_last_error() === JSON_ERROR_NONE &amp;&amp; is_array($new_order)) {\\n        writeProjectsOrder($new_order); \\\/\\\/ \\u76f4\\u63a5\\u5199\\u5165\\u65b0\\u7684\\u6392\\u5e8f\\u5230 projects_order.json\\n        echo json_encode([&#039;status&#039; =&gt; &#039;success&#039;]);\\n    } else {\\n        echo json_encode([&#039;status&#039; =&gt; &#039;error&#039;, &#039;message&#039; =&gt; &#039;Invalid order data.&#039;]);\\n    }\\n    exit;\\n}\\n\\n\\n\\\/\\\/ Error and success messages initialization\\n$error_message = &#039;&#039;;\\n$success_message = &#039;&#039;;\\n\\n\\\/\\\/ --- BEGIN: Updated Logic for State and Input Initialization ---\\n\\n\\\/\\\/ Determine state: is it a new project via URL parameter, or an edit?\\n$is_new_project_url_state = isset($_GET[&#039;new&#039;]); \\n\\n$edit_mode = false;\\n$edit_folder_name = &#039;&#039;; \\\/\\\/ Will hold the folder name if in edit mode\\n$edit_project_name = &#039;&#039;; \\\/\\\/ Will hold the project name if in edit mode\\n\\n\\\/\\\/ PHP variables to hold form input values (used for pre-filling or retaining on error)\\n$input_folder = $_POST[&#039;folder&#039;] ?? &#039;&#039;;\\n$input_project_name = $_POST[&#039;project_name&#039;] ?? &#039;&#039;;\\n$input_html = $_POST[&#039;html&#039;] ?? &#039;&#039;;\\n$input_css = $_POST[&#039;css&#039;] ?? &#039;&#039;;\\n$input_js = $_POST[&#039;js&#039;] ?? &#039;&#039;;\\n$input_php = $_POST[&#039;php&#039;] ?? &#039;&#039;;\\n\\n\\\/\\\/ If $_GET[&#039;edit&#039;] is set AND we are NOT in a &#039;?new=1&#039; state\\nif (isset($_GET[&#039;edit&#039;]) &amp;&amp; !$is_new_project_url_state) {\\n    $edit_mode = true;\\n    $edit_folder_name = basename($_GET[&#039;edit&#039;]);\\n    $edit_path = BASE_DIR . DIRECTORY_SEPARATOR . $edit_folder_name;\\n    \\n    \\\/\\\/ Load existing project data\\n    $project_meta_data = readProjectMetadata($edit_path);\\n    $edit_project_name = $project_meta_data[&#039;name&#039;] ?? $edit_folder_name; \\\/\\\/ Get project name from meta or folder name\\n\\n    \\\/\\\/ Load file contents\\n    $input_html = @file_get_contents(\\&quot;$edit_path\\\/index.html\\&quot;);\\n    $input_css = @file_get_contents(\\&quot;$edit_path\\\/style.css\\&quot;);\\n    $input_js = @file_get_contents(\\&quot;$edit_path\\\/script.js\\&quot;);\\n    $input_php = @file_get_contents(\\&quot;$edit_path\\\/index.php\\&quot;);\\n\\n    \\\/\\\/ Pre-fill form fields with existing data. Only override $_POST values if it&#039;s not a POST request.\\n    if ($_SERVER[&#039;REQUEST_METHOD&#039;] !== &#039;POST&#039;) {\\n        $input_folder = $edit_folder_name;\\n        $input_project_name = $edit_project_name;\\n    }\\n} \\n\\\/\\\/ If it&#039;s a fresh load (no POST) AND we are either in &#039;?new=1&#039; state OR no parameters are present\\nelseif ($_SERVER[&#039;REQUEST_METHOD&#039;] !== &#039;POST&#039; || $is_new_project_url_state) {\\n    \\\/\\\/ Initialize form fields to empty for a new project or initial page load\\n    $input_folder = &#039;&#039;;\\n    $input_project_name = &#039;&#039;;\\n    $input_html = &#039;&#039;;\\n    $input_css = &#039;&#039;;\\n    $input_js = &#039;&#039;;\\n    $input_php = &#039;&#039;;\\n}\\n\\\/\\\/ Note: If it&#039;s a POST request and !empty($error_message), the $input_* variables will retain $_POST values from the beginning.\\n\\\/\\\/ This is the desired behavior for displaying errors with user input preserved.\\n\\n\\n\\\/\\\/ Determine the title to display in H2\\n$page_h2_title = ($edit_mode ? \\&quot;\\u7f16\\u8f91\\u9879\\u76ee\\uff1a\\&quot;.htmlspecialchars($edit_project_name) : \\&quot;\\u521b\\u5efa\\u65b0\\u9879\\u76ee\\&quot;);\\n\\n\\\/\\\/ --- END: Updated Logic for State and Input Initialization ---\\n\\n\\n\\\/\\\/ Collect all existing project names for duplication checks\\n$all_existing_project_names = [];\\n$project_dirs_scan = array_filter(glob(BASE_DIR . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\nforeach ($project_dirs_scan as $dir) {\\n    $folder_name = basename($dir);\\n    \\\/\\\/ Exclude script&#039;s own folder, .git, and any non-directory entries\\n    if ($folder_name === basename(BASE_DIR) || $folder_name === &#039;.git&#039; || !is_dir($dir)) {\\n        continue;\\n    }\\n    $meta = readProjectMetadata($dir);\\n    $proj_name = $meta[&#039;name&#039;] ?? $folder_name;\\n    \\n    \\\/\\\/ Add to list, excluding the current project&#039;s name if we are in edit mode\\n    \\\/\\\/ $edit_project_name will be empty if not in edit mode or in &#039;?new=1&#039; state, so this condition handles both.\\n    if (!$edit_mode || ($edit_mode &amp;&amp; $proj_name !== $edit_project_name)) {\\n        $all_existing_project_names[] = $proj_name;\\n    }\\n}\\n\\n\\n\\\/\\\/ Save file\\nif ($_SERVER[&#039;REQUEST_METHOD&#039;] === &#039;POST&#039; &amp;&amp; isset($_POST[&#039;folder&#039;], $_POST[&#039;project_name&#039;], $_POST[&#039;html&#039;], $_POST[&#039;css&#039;], $_POST[&#039;js&#039;], $_POST[&#039;php&#039;])) {\\n    $folder = preg_replace(&#039;\\\/[^a-zA-Z0-9_\\\\-]\\\/&#039;, &#039;&#039;, $_POST[&#039;folder&#039;]);\\n    $project_name = trim($_POST[&#039;project_name&#039;]);\\n    \\n    \\\/\\\/ Basic validation for project name and folder name format\\n    if (empty($project_name)) {\\n        $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u540d\\u79f0\\u4e0d\\u80fd\\u4e3a\\u7a7a\\uff01\\&quot;;\\n    } elseif (empty($folder)) {\\n        $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u6587\\u4ef6\\u5939\\u540d\\u4e0d\\u80fd\\u4e3a\\u7a7a\\u6216\\u5305\\u542b\\u975e\\u6cd5\\u5b57\\u7b26\\uff01\\&quot;;\\n    } else {\\n        $original = $_POST[&#039;original_folder&#039;] ?? &#039;&#039;;\\n        $original = preg_replace(&#039;\\\/[^a-zA-Z0-9_\\\\-]\\\/&#039;, &#039;&#039;, $original);\\n\\n        $old_path = BASE_DIR . DIRECTORY_SEPARATOR . $original;\\n        $new_path = BASE_DIR . DIRECTORY_SEPARATOR . $folder;\\n\\n        \\\/\\\/ --- \\u5f00\\u59cb\\uff1a\\u7efc\\u5408\\u91cd\\u590d\\u6027\\u68c0\\u67e5 ---\\n        \\\/\\\/ \\u573a\\u666f1\\uff1a\\u521b\\u5efa\\u65b0\\u9879\\u76ee (empty($original) \\u4e3a\\u771f)\\n        if (empty($original)) {\\n            if (is_dir($new_path)) {\\n                $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u6587\\u4ef6\\u5939 &#039;{$folder}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u8bf7\\u66f4\\u6362\\u540d\\u79f0\\u3002\\&quot;;\\n            } elseif (in_array($project_name, $all_existing_project_names)) {\\n                $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u540d\\u79f0 &#039;{$project_name}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u8bf7\\u66f4\\u6362\\u540d\\u79f0\\u3002\\&quot;;\\n            }\\n        } \\n        \\\/\\\/ \\u573a\\u666f2\\uff1a\\u7f16\\u8f91\\u73b0\\u6709\\u9879\\u76ee\\n        else { \\\/\\\/ !empty($original), \\u6b63\\u5728\\u7f16\\u8f91\\u73b0\\u6709\\u9879\\u76ee\\n            \\\/\\\/ \\u68c0\\u67e5\\u6587\\u4ef6\\u5939\\u540d\\u662f\\u5426\\u6539\\u53d8\\u5e76\\u4e14\\u65b0\\u6587\\u4ef6\\u5939\\u540d\\u662f\\u5426\\u5df2\\u5b58\\u5728\\n            if ($folder !== $original) {\\n                if (is_dir($new_path)) {\\n                    $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u76ee\\u6807\\u6587\\u4ef6\\u5939 &#039;{$folder}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u65e0\\u6cd5\\u91cd\\u547d\\u540d\\u3002\\&quot;;\\n                }\\n            }\\n            \\\/\\\/ \\u68c0\\u67e5\\u9879\\u76ee\\u540d\\u79f0\\u662f\\u5426\\u6539\\u53d8\\uff0c\\u4e14\\u65b0\\u540d\\u79f0\\u662f\\u5426\\u88ab\\u5176\\u4ed6\\u9879\\u76ee\\u4f7f\\u7528\\n            \\\/\\\/ $all_existing_project_names \\u5df2\\u7ecf\\u6392\\u9664\\u4e86\\u5f53\\u524d\\u6b63\\u5728\\u7f16\\u8f91\\u7684\\u9879\\u76ee\\u7684\\u65e7\\u540d\\u79f0\\n            if (empty($error_message) &amp;&amp; $project_name !== $edit_project_name &amp;&amp; in_array($project_name, $all_existing_project_names)) {\\n                 $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u540d\\u79f0 &#039;{$project_name}&#039; \\u5df2\\u88ab\\u5176\\u4ed6\\u9879\\u76ee\\u4f7f\\u7528\\uff0c\\u8bf7\\u66f4\\u6362\\u540d\\u79f0\\u3002\\&quot;;\\n            }\\n        }\\n        \\\/\\\/ --- \\u7ed3\\u675f\\uff1a\\u7efc\\u5408\\u91cd\\u590d\\u6027\\u68c0\\u67e5 ---\\n\\n        if (empty($error_message)) { \\\/\\\/ \\u53ea\\u6709\\u5728\\u6240\\u6709\\u521d\\u6b65\\u9a8c\\u8bc1\\u901a\\u8fc7\\u540e\\u624d\\u7ee7\\u7eed\\n            \\\/\\\/ \\u73b0\\u6709\\u6587\\u4ef6\\u5939\\u91cd\\u547d\\u540d\\\/\\u521b\\u5efa\\u903b\\u8f91\\n            if (!empty($original) &amp;&amp; $folder !== $original &amp;&amp; is_dir($old_path)) {\\n                if (!rename($old_path, $new_path)) {\\n                    $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u65e0\\u6cd5\\u91cd\\u547d\\u540d\\u6587\\u4ef6\\u5939 &#039;{$original}&#039; \\u5230 &#039;{$folder}&#039;\\u3002\\&quot;;\\n                } else {\\n                    \\\/\\\/ \\u5982\\u679c\\u6587\\u4ef6\\u5939\\u91cd\\u547d\\u540d\\u6210\\u529f\\uff0c\\u66f4\\u65b0 projects_order.json \\u4e2d\\u7684\\u6587\\u4ef6\\u5939\\u540d\\n                    $current_order = readProjectsOrder();\\n                    $index = array_search($original, $current_order);\\n                    if ($index !== false) {\\n                        $current_order[$index] = $folder;\\n                        writeProjectsOrder($current_order);\\n                    }\\n                }\\n            } elseif (!is_dir($new_path)) { \\\/\\\/ \\u8fd9\\u4e2a\\u5757\\u7528\\u4e8e\\u4e3a\\u65b0\\u9879\\u76ee\\u6216\\u91cd\\u547d\\u540d\\u7684\\u9879\\u76ee\\u521b\\u5efa\\u5168\\u65b0\\u6587\\u4ef6\\u5939\\n                if (!mkdir($new_path, 0777, true)) {\\n                    $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u65e0\\u6cd5\\u521b\\u5efa\\u6587\\u4ef6\\u5939 &#039;{$folder}&#039;\\u3002\\&quot;;\\n                }\\n            }\\n\\n            if (empty($error_message)) { \\\/\\\/ \\u53ea\\u6709\\u5728\\u6587\\u4ef6\\u5939\\u64cd\\u4f5c\\u6210\\u529f\\u540e\\u624d\\u7ee7\\u7eed\\n                \\\/\\\/ \\u5b9a\\u4e49\\u8981\\u5904\\u7406\\u7684\\u6587\\u4ef6\\u53ca\\u5176\\u5185\\u5bb9\\n                $files_to_process = [\\n                    &#039;index.html&#039; =&gt; $_POST[&#039;html&#039;],\\n                    &#039;style.css&#039; =&gt; $_POST[&#039;css&#039;],\\n                    &#039;script.js&#039; =&gt; $_POST[&#039;js&#039;],\\n                    &#039;index.php&#039; =&gt; $_POST[&#039;php&#039;]\\n                ];\\n\\n                $conflict_detected = false;\\n                \\\/\\\/ \\u4ec5\\u5f53\\u662f\\u521b\\u5efa\\u65b0\\u9879\\u76ee (empty($original) \\u4e3a\\u771f) \\u65f6\\uff0c\\u624d\\u68c0\\u67e5\\u6587\\u4ef6\\u51b2\\u7a81\\n                \\\/\\\/ \\u5982\\u679c\\u76ee\\u6807\\u6587\\u4ef6\\u5b58\\u5728\\uff08\\u65e0\\u8bba\\u662f\\u5426\\u4e3a\\u7a7a\\uff09\\uff0c\\u5e76\\u4e14\\u6211\\u4eec\\u6709\\u65b0\\u5185\\u5bb9\\u8981\\u5199\\u5165\\uff0c\\u5219\\u8ba4\\u4e3a\\u662f\\u51b2\\u7a81\\uff0c\\u5e76\\u63d0\\u793a\\u7528\\u6237\\n                if (empty($original)) { \\\/\\\/ \\u53ea\\u5728\\u521b\\u5efa\\u65b0\\u9879\\u76ee\\u65f6\\u68c0\\u67e5\\u6587\\u4ef6\\u51b2\\u7a81\\n                    foreach ($files_to_process as $filename =&gt; $content) {\\n                        $file_path = \\&quot;$new_path\\\/$filename\\&quot;;\\n                        \\\/\\\/ \\u5982\\u679c\\u76ee\\u6807\\u6587\\u4ef6\\u5b58\\u5728\\uff0c\\u5e76\\u4e14\\u6211\\u4eec\\u6709\\u65b0\\u5185\\u5bb9\\u8981\\u5199\\u5165\\uff0c\\u5219\\u8ba4\\u4e3a\\u662f\\u51b2\\u7a81\\n                        if (file_exists($file_path) &amp;&amp; !empty($content)) {\\n                            $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u6587\\u4ef6 &#039;{$filename}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u5e76\\u5c1d\\u8bd5\\u5199\\u5165\\u65b0\\u5185\\u5bb9\\uff0c\\u8bf7\\u624b\\u52a8\\u5904\\u7406\\u6216\\u6e05\\u7a7a\\u6587\\u4ef6\\u5185\\u5bb9\\u3002\\&quot;;\\n                            $conflict_detected = true;\\n                            break;\\n                        }\\n                    }\\n                }\\n                \\n                if (!$conflict_detected) {\\n                    foreach ($files_to_process as $filename =&gt; $content) {\\n                        $file_path = \\&quot;$new_path\\\/$filename\\&quot;;\\n\\n                        \\\/\\\/ === \\u6c49\\u5b57\\u4e71\\u7801\\u4fee\\u590d\\u548cUTF-8\\u58f0\\u660e\\u65b0\\u589e\\u4ee3\\u7801\\u5f00\\u59cb ===\\n                        \\\/\\\/ \\u5bf9\\u4e8e HTML \\u6587\\u4ef6\\uff0c\\u5982\\u679c\\u5185\\u5bb9\\u4e0d\\u4e3a\\u7a7a\\u4e14\\u4e0d\\u5305\\u542b UTF-8 meta \\u6807\\u7b7e\\uff0c\\u5219\\u6dfb\\u52a0\\n                        if ($filename === &#039;index.html&#039; &amp;&amp; !empty($content)) {\\n                            if (strpos($content, &#039;&lt;meta charset=\\&quot;UTF-8\\&quot;&gt;&#039;) === false &amp;&amp; strpos($content, &#039;&lt;meta charset=\\&quot;utf-8\\&quot;&gt;&#039;) === false) {\\n                                \\\/\\\/ \\u5c1d\\u8bd5\\u5728 &lt;head&gt; \\u6807\\u7b7e\\u5185\\u6dfb\\u52a0\\n                                if (preg_match(&#039;\\\/&lt;head&gt;\\\/i&#039;, $content)) {\\n                                    $content = preg_replace(&#039;\\\/&lt;head&gt;\\\/i&#039;, &#039;&lt;head&gt;&lt;meta charset=\\&quot;UTF-8\\&quot;&gt;&#039;, $content, 1);\\n                                } else {\\n                                    \\\/\\\/ \\u5982\\u679c\\u6ca1\\u6709head\\u6807\\u7b7e\\uff0c\\u5219\\u5c1d\\u8bd5\\u5728 &lt;!DOCTYPE html&gt; \\u540e\\u6216\\u6587\\u4ef6\\u5f00\\u5934\\u6dfb\\u52a0\\u4e00\\u4e2a\\u57fa\\u672c\\u7ed3\\u6784\\n                                    if (strpos(trim($content), &#039;&lt;!DOCTYPE html&gt;&#039;) === 0) {\\n                                        $content = preg_replace(&#039;\\\/(&lt;\\\\!DOCTYPE html&gt;)\\\/i&#039;, \\&quot;$1\\\\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;Document&lt;\\\/title&gt;\\\\n&lt;\\\/head&gt;\\\\n&lt;body&gt;\\&quot;, $content, 1) . \\&quot;\\\\n&lt;\\\/body&gt;\\\\n&lt;\\\/html&gt;\\&quot;;\\n                                    } elseif (strpos(trim($content), &#039;&lt;html&#039;) === 0) {\\n                                         $content = preg_replace(&#039;\\\/(&lt;html[^&gt;]*&gt;)\\\/i&#039;, \\&quot;$1\\\\n&lt;head&gt;\\\\n    &lt;meta charset=\\\\\\&quot;UTF-8\\\\\\&quot;&gt;\\\\n    &lt;title&gt;Document&lt;\\\/title&gt;\\\\n&lt;\\\/head&gt;\\&quot;, $content, 1);\\n                                    } else { \\\/\\\/ \\u6700\\u574f\\u60c5\\u51b5\\uff0c\\u76f4\\u63a5\\u5728\\u6587\\u4ef6\\u5f00\\u5934\\u6dfb\\u52a0\\n                                        $content = \\&quot;&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;Document&lt;\\\/title&gt;\\\\n&lt;\\\/head&gt;\\\\n&lt;body&gt;\\\\n\\&quot; . $content . \\&quot;\\\\n&lt;\\\/body&gt;\\\\n&lt;\\\/html&gt;\\&quot;;\\n                                    }\\n                                }\\n                            }\\n                        }\\n\\n                        \\\/\\\/ \\u5bf9\\u4e8e PHP \\u6587\\u4ef6\\uff0c\\u5982\\u679c\\u5185\\u5bb9\\u4e0d\\u4e3a\\u7a7a\\u4e14\\u4e0d\\u5305\\u542b UTF-8 header\\uff0c\\u5219\\u6dfb\\u52a0\\n                        if ($filename === &#039;index.php&#039; &amp;&amp; !empty($content)) {\\n                            if (strpos($content, \\&quot;header(&#039;Content-Type: text\\\/html; charset=utf-8&#039;);\\&quot;) === false) {\\n                                \\\/\\\/ \\u786e\\u4fdd\\u5728 &lt;?php \\u6807\\u7b7e\\u4e4b\\u540e\\u6dfb\\u52a0\\n                                if (strpos(trim($content), &#039;&lt;?php&#039;) === 0) {\\n                                    \\\/\\\/ \\u627e\\u5230\\u7b2c\\u4e00\\u4e2a\\u975e\\u6ce8\\u91ca\\u6216\\u7a7a\\u683c\\u7684 &lt;?php \\u4e4b\\u540e\\u7684\\u4f4d\\u7f6e\\u63d2\\u5165\\n                                    \\\/\\\/ \\u4f7f\\u7528\\u53cc\\u5f15\\u53f7\\u5b57\\u7b26\\u4e32\\uff0c\\u907f\\u514d\\u5355\\u5f15\\u53f7\\u8f6c\\u4e49\\u95ee\\u9898\\n                                    $content = preg_replace(&#039;\\\/&lt;\\\\?php\\\/&#039;, \\&quot;&lt;?php\\\\nheader(&#039;Content-Type: text\\\/html; charset=utf-8&#039;);\\&quot;, $content, 1);\\n                                } else {\\n                                    \\\/\\\/ \\u5982\\u679c\\u4e0d\\u662f\\u4ee5 &lt;?php \\u5f00\\u5934\\uff0c\\u5219\\u5728\\u6587\\u4ef6\\u6700\\u5f00\\u5934\\u6dfb\\u52a0\\n                                    $content = \\&quot;&lt;?php\\\\nheader(&#039;Content-Type: text\\\/html; charset=utf-8&#039;);\\\\n?&gt;\\&quot; . $content;\\n                                }\\n                            }\\n                        }\\n                        \\\/\\\/ === \\u6c49\\u5b57\\u4e71\\u7801\\u4fee\\u590d\\u548cUTF-8\\u58f0\\u660e\\u65b0\\u589e\\u4ee3\\u7801\\u7ed3\\u675f ===\\n\\n                        if (!empty($content)) {\\n                            file_put_contents($file_path, $content);\\n                        } elseif (file_exists($file_path)) {\\n                            \\\/\\\/ If content is empty and file exists, delete it\\n                            unlink($file_path);\\n                        }\\n                    }\\n                    \\n                    \\\/\\\/ Save project metadata\\n                    $current_meta = readProjectMetadata($new_path);\\n                    $current_meta[&#039;name&#039;] = $project_name;\\n                    writeProjectMetadata($new_path, $current_meta);\\n\\n                    \\\/\\\/ \\u65b0\\u589e\\uff1a\\u5982\\u679c\\u9879\\u76ee\\u662f\\u65b0\\u5efa\\u7684\\uff0c\\u5c06\\u5176\\u6dfb\\u52a0\\u5230 projects_order.json \\u7684\\u672b\\u5c3e\\n                    $current_order = readProjectsOrder();\\n                    if (!in_array($folder, $current_order)) {\\n                        $current_order[] = $folder;\\n                        writeProjectsOrder($current_order);\\n                    }\\n\\n                    $success_message = \\&quot;\\u2705 \\u9879\\u76ee &#039;{$project_name}&#039; (\\u6587\\u4ef6\\u5939: {$folder}) \\u5df2\\u4fdd\\u5b58\\uff01\\&quot;;\\n\\n                    \\\/\\\/ Re-read data to ensure latest content is displayed if AJAX reloads content\\n                    \\\/\\\/ This is crucial for the AJAX update to reflect the saved state.\\n                    $edit_mode = true; \\\/\\\/ Stay in edit mode after saving a new project\\n                    $edit_folder_name = $folder;\\n                    $edit_project_name = $project_name;\\n\\n                    $input_html = @file_get_contents(\\&quot;$new_path\\\/index.html\\&quot;);\\n                    $input_css = @file_get_contents(\\&quot;$new_path\\\/style.css\\&quot;);\\n                    $input_js = @file_get_contents(\\&quot;$new_path\\\/script.js\\&quot;);\\n                    $input_php = @file_get_contents(\\&quot;$new_path\\\/index.php\\&quot;);\\n                    $input_folder = $folder;\\n                    $input_project_name = $project_name;\\n                    $page_h2_title = \\&quot;\\u7f16\\u8f91\\u9879\\u76ee\\uff1a\\&quot;.htmlspecialchars($edit_project_name); \\\/\\\/ Update title for saved project\\n\\n                }\\n            }\\n        }\\n    }\\n}\\n\\n\\\/\\\/ Delete project\\nif (isset($_GET[&#039;delete&#039;])) {\\n    if (isset($_POST[&#039;admin_password&#039;]) &amp;&amp; $_POST[&#039;admin_password&#039;] === ADMIN_PASSWORD) {\\n        $del = basename($_GET[&#039;delete&#039;]);\\n        $target = BASE_DIR . DIRECTORY_SEPARATOR . $del;\\n        if (is_dir($target)) {\\n            \\\/\\\/ Function to recursively delete directory contents\\n            function deleteDir($dir) {\\n                $files = array_diff(scandir($dir), array(&#039;.&#039;, &#039;..&#039;));\\n                foreach ($files as $file) {\\n                    (is_dir(\\&quot;$dir\\\/$file\\&quot;)) ? deleteDir(\\&quot;$dir\\\/$file\\&quot;) : unlink(\\&quot;$dir\\\/$file\\&quot;);\\n                }\\n                return rmdir($dir);\\n            }\\n            deleteDir($target);\\n\\n            \\\/\\\/ \\u4ece projects_order.json \\u4e2d\\u79fb\\u9664\\u88ab\\u5220\\u9664\\u7684\\u9879\\u76ee\\n            $current_order = readProjectsOrder();\\n            $current_order = array_diff($current_order, [$del]);\\n            writeProjectsOrder(array_values($current_order)); \\\/\\\/ array_values \\u91cd\\u65b0\\u7d22\\u5f15\\u6570\\u7ec4\\n\\n            \\\/\\\/ Redirect back to admin page, clear GET parameters\\n            header(\\&quot;Location: \\&quot; . strtok($_SERVER[&#039;PHP_SELF&#039;], &#039;?&#039;));\\n            exit;\\n        }\\n    } else {\\n        $error_message = \\&quot;\\u274c \\u5220\\u9664\\u5931\\u8d25\\uff1a\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\u9519\\u8bef\\uff01\\&quot;;\\n    }\\n}\\n\\n\\n\\\/\\\/ Get all project folders and their metadata for display\\n$project_dirs_display = array_filter(glob(BASE_DIR . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\n$all_project_folders = [];\\nforeach ($project_dirs_display as $dir) {\\n    $folder_name = basename($dir);\\n    if ($folder_name === basename(BASE_DIR) || $folder_name === &#039;.git&#039;) { \\\/\\\/ Skip the current directory itself and .git\\n        continue;\\n    }\\n    $all_project_folders[] = $folder_name;\\n}\\n\\n$ordered_project_folders = readProjectsOrder();\\n$projects_data = [];\\n\\n\\\/\\\/ \\u5c06\\u5df2\\u6392\\u5e8f\\u7684\\u9879\\u76ee\\u6dfb\\u52a0\\u5230 projects_data\\nforeach ($ordered_project_folders as $folder_name) {\\n    if (in_array($folder_name, $all_project_folders)) {\\n        $project_path = BASE_DIR . DIRECTORY_SEPARATOR . $folder_name;\\n        $meta = readProjectMetadata($project_path);\\n        $projects_data[] = [\\n            &#039;folder_name&#039; =&gt; $folder_name,\\n            &#039;project_name&#039; =&gt; $meta[&#039;name&#039;] ?? $folder_name,\\n        ];\\n        \\\/\\\/ \\u4ece all_project_folders \\u4e2d\\u79fb\\u9664\\u5df2\\u5904\\u7406\\u7684\\uff0c\\u4ee5\\u4fbf\\u540e\\u7eed\\u6dfb\\u52a0\\u672a\\u6392\\u5e8f\\u7684\\u65b0\\u9879\\u76ee\\n        $all_project_folders = array_diff($all_project_folders, [$folder_name]);\\n    }\\n}\\n\\n\\\/\\\/ \\u5c06 projects_order.json \\u4e2d\\u6ca1\\u6709\\uff0c\\u4f46\\u5b9e\\u9645\\u5b58\\u5728\\u7684\\u9879\\u76ee\\u6dfb\\u52a0\\u5230 projects_data \\u7684\\u672b\\u5c3e\\nforeach ($all_project_folders as $folder_name) {\\n    $project_path = BASE_DIR . DIRECTORY_SEPARATOR . $folder_name;\\n    $meta = readProjectMetadata($project_path);\\n    $projects_data[] = [\\n        &#039;folder_name&#039; =&gt; $folder_name,\\n        &#039;project_name&#039; =&gt; $meta[&#039;name&#039;] ?? $folder_name,\\n    ];\\n}\\n\\n\\\/\\\/ \\u73b0\\u5728 projects_data \\u5df2\\u7ecf\\u6309\\u7167 projects_order.json \\u6392\\u5e8f\\uff0c\\u5e76\\u4e14\\u5305\\u542b\\u4e86\\u6240\\u6709\\u5b9e\\u9645\\u5b58\\u5728\\u7684\\u9879\\u76ee\\u3002\\n\\n?&gt;\\n\\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;AI \\u5c0f\\u5de5\\u5177\\u540e\\u53f0&lt;\\\/title&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/lib\\\/codemirror.min.css\\&quot; \\\/&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/theme\\\/eclipse.css\\&quot; \\\/&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/theme\\\/darcula.css\\&quot; \\\/&gt;\\n    &lt;link rel=\\&quot;stylesheet\\&quot; href=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/addon\\\/dialog\\\/dialog.css\\&quot;&gt;\\n    &lt;style&gt;\\n        * { box-sizing: border-box; }\\n        html, body {\\n            margin: 0; padding: 0; height: 100%;\\n            overflow: hidden;\\n            font-family: sans-serif;\\n            background: #f0f0f0;\\n            color: #000;\\n            transition: background-color 0.3s, color 0.3s;\\n        }\\n        body.dark {\\n            background: #1e1e1e;\\n            color: #ddd;\\n        }\\n        body, #app {\\n            display: flex;\\n            height: 100vh;\\n            overflow: hidden;\\n        }\\n        .sidebar {\\n            width: 220px;\\n            background: #333;\\n            color: white;\\n            padding: 20px;\\n            overflow-y: auto;\\n            flex-shrink: 0;\\n            display: flex;\\n            flex-direction: column;\\n            position: relative;\\n            user-select: none; \\\/* Prevent text selection during drag *\\\/\\n        }\\n        .sidebar h3 {\\n            margin-top: 0;\\n            font-size: 18px;\\n            user-select: none;\\n        }\\n        .sidebar ul {\\n            list-style: none;\\n            padding: 0;\\n            margin: 0;\\n            flex-grow: 1;\\n            margin-bottom: 70px;\\n        }\\n        .sidebar li {\\n            display: flex;\\n            justify-content: space-between;\\n            align-items: center;\\n            padding: 6px 0;\\n            border-bottom: 1px solid #444;\\n            cursor: grab; \\\/* Indicate draggable *\\\/\\n        }\\n        .sidebar li.active {\\n            background-color: #555; \\\/* Highlight active project background *\\\/\\n            border-radius: 4px;\\n           \\\/* padding-left: 8px;  Adjust padding for highlight *\\\/\\n        }\\n        .sidebar li.active a {\\n            color: white !important;\\n            font-weight: bold;\\n        }\\n        .sidebar a {\\n            color: #ddd;\\n            text-decoration: none;\\n            margin-right: 6px;\\n        }\\n        .sidebar a:hover {\\n            color: #fff;\\n        }\\n        \\n        \\n        .sidebar {\\n    \\\/* \\u79fb\\u9664\\u6216\\u6ce8\\u91ca\\u6389 width \\u5c5e\\u6027 *\\\/\\n    \\\/* width: 220px; *\\\/ \\n    \\n    \\\/* \\u8a2d\\u7f6e\\u6700\\u5c0f\\u5bec\\u5ea6\\uff0c\\u4ee5\\u78ba\\u4fdd\\u5728\\u6c92\\u6709\\u8db3\\u5920\\u5167\\u5bb9\\u6642\\u4e0d\\u6703\\u904e\\u7a84 *\\\/\\n    min-width: fit-content; \\\/* \\u6216\\u4f60\\u53ef\\u4ee5\\u8a2d\\u5b9a\\u4e00\\u500b\\u50cf\\u7d20\\u503c\\uff0c\\u4f8b\\u5982\\uff1amin-width: 180px; *\\\/\\n    \\n    \\\/* \\u78ba\\u4fdd\\u5167\\u5bb9\\u4e0d\\u6703\\u6536\\u7e2e\\uff0c\\u9019\\u6a23\\u6587\\u5b57\\u5c31\\u4e0d\\u6703\\u56e0\\u70ba\\u7a7a\\u9593\\u4e0d\\u8db3\\u800c\\u6298\\u884c *\\\/\\n    flex-shrink: 0; \\n    \\n    \\\/* \\u8a2d\\u7f6e\\u521d\\u59cb\\u57fa\\u790e\\u5bec\\u5ea6\\u70ba\\u5167\\u5bb9\\u6240\\u9700\\uff0c\\u4e26\\u5141\\u8a31\\u5176\\u589e\\u9577 *\\\/\\n    flex-basis: auto; \\\/* \\u8b93\\u5167\\u5bb9\\u6c7a\\u5b9a\\u5176\\u57fa\\u790e\\u5bec\\u5ea6 *\\\/\\n\\n    background: #333;\\n    color: white;\\n    padding: 20px;\\n    overflow-y: auto;\\n    \\\/* flex-shrink: 0;  \\u4fdd\\u7559\\u9019\\u500b\\uff0c\\u56e0\\u70ba\\u5b83\\u5f88\\u91cd\\u8981\\uff0c\\u53ef\\u4ee5\\u9632\\u6b62\\u5074\\u6b04\\u6536\\u7e2e *\\\/\\n    display: flex;\\n    flex-direction: column;\\n    position: relative;\\n    user-select: none;\\n}\\n        \\n        \\n        \\\/* Sortable.js ghost and chosen styles *\\\/\\n        .sortable-ghost {\\n            opacity: 0.2;\\n            background: #f0f0f0;\\n            border: 1px dashed #007bff;\\n        }\\n        .sortable-chosen {\\n            background-color: #444;\\n        }\\n\\n        .container {\\n            flex: 1;\\n            display: flex;\\n            flex-direction: column;\\n            padding: 20px;\\n            overflow: hidden;\\n        }\\n        .main {\\n            flex: 1;\\n            overflow: hidden;\\n            display: flex;\\n            flex-direction: column;\\n            color: inherit;\\n        }\\n        h2 {\\n            margin: 0 0 8px 0;\\n            font-weight: normal;\\n            user-select: none;\\n        }\\n        form {\\n            margin-top: 0;\\n            flex: 1;\\n            display: flex;\\n            flex-direction: column;\\n            overflow: hidden;\\n        }\\n        label {\\n            font-weight: bold;\\n            margin-top: 10px;\\n            display: block;\\n            user-select: none;\\n        }\\n        input[type=\\&quot;text\\&quot;] {\\n            width: 100%;\\n            padding: 6px;\\n            font-size: 14px;\\n            margin-top: 4px;\\n            box-sizing: border-box;\\n            background: white;\\n            border: 1px solid #ccc;\\n            color: #000;\\n        }\\n        body.dark input[type=\\&quot;text\\&quot;] {\\n            background: #333;\\n            border-color: #555;\\n            color: #ddd;\\n        }\\n\\n        \\\/* Tab navigation *\\\/\\n        .tabs {\\n            display: flex;\\n            border-bottom: 2px solid #ccc;\\n            user-select: none;\\n            margin-top: 8px;\\n        }\\n        body.dark .tabs {\\n            border-color: #555;\\n        }\\n        .tab {\\n            padding: 8px 16px;\\n            cursor: pointer;\\n            border: 1px solid transparent;\\n            border-bottom: none;\\n            background: #eee;\\n            color: #000;\\n            margin-right: 6px;\\n            border-radius: 6px 6px 0 0;\\n            transition: background-color 0.3s;\\n            font-size: 14px;\\n            display: flex;\\n            align-items: center;\\n            gap: 6px;\\n            flex-shrink: 0;\\n        }\\n        body.dark .tab {\\n            background: #333;\\n            color: #ddd;\\n        }\\n        .tab.active {\\n            background: white;\\n            border-color: #ccc #ccc white;\\n            font-weight: bold;\\n        }\\n        body.dark .tab.active {\\n            background: #1e1e1e;\\n            border-color: #555 #555 #1e1e1e;\\n            font-weight: bold;\\n        }\\n\\n        .btn-bar {\\n            margin: 6px 0 12px 0;\\n            user-select: none;\\n            display: flex;\\n            justify-content: space-between;\\n            align-items: center;\\n        }\\n        .btn-bar .left-buttons button {\\n            margin-right: 8px;\\n        }\\n\\n        .btn-bar button {\\n            padding: 6px 12px;\\n            cursor: pointer;\\n            border-radius: 4px;\\n            border: 1px solid #666;\\n            background: #f5f5f5;\\n            font-size: 14px;\\n            user-select: none;\\n        }\\n        body.dark .btn-bar button {\\n            background: #444;\\n            border-color: #888;\\n            color: #ddd;\\n        }\\n        .btn-bar button:hover {\\n            background: #ddd;\\n        }\\n        body.dark .btn-bar button:hover {\\n            background: #666;\\n        }\\n        #toggle-full-height {\\n            padding: 4px 8px;\\n            border-radius: 4px;\\n            background: #f0f0f0;\\n            color: #666;\\n            border: 1px solid #ccc;\\n            font-size: 12px;\\n            cursor: pointer;\\n            user-select: none;\\n            transition: background-color 0.2s, color 0.2s;\\n        }\\n        body.dark #toggle-full-height {\\n            background: #333;\\n            color: #ccc;\\n            border-color: #555;\\n        }\\n        #toggle-full-height:hover {\\n            background: #e0e0e0;\\n            color: #333;\\n        }\\n        body.dark #toggle-full-height:hover {\\n            background: #444;\\n            color: #eee;\\n        }\\n        \\n        \\\/* Editor container *\\\/\\n        .editor-container {\\n            flex: 1;\\n            display: none;\\n            flex-direction: column;\\n            min-height: 0;\\n            transition: height 0.3s ease-in-out;\\n        }\\n        .editor-container.active {\\n            display: flex;\\n        }\\n        .CodeMirror {\\n            height: 100%;\\n            border: 1px solid #ccc;\\n            font-size: 14px;\\n            line-height: 1.4em;\\n        }\\n        body.dark .CodeMirror {\\n            border-color: #555;\\n            background: #1e1e1e;\\n            color: #ddd;\\n        }\\n        .CodeMirror-scroll {\\n            overflow-x: hidden !important;\\n            overflow-y: scroll !important;\\n            margin-right: -17px;\\n            padding-right: 17px;\\n        }\\n\\n        \\\/* Full height mode styles *\\\/\\n        .editor-container.full-height {\\n            position: fixed;\\n            top: 0;\\n            left: 220px;\\n            right: 0;\\n            bottom: 0;\\n            z-index: 999;\\n            background: #f0f0f0;\\n            padding: 20px;\\n            display: flex !important;\\n            width: auto;\\n        }\\n        body.dark .editor-container.full-height {\\n            background: #1e1e1e;\\n        }\\n        \\\/* Hide unnecessary elements in full height mode, but keep sidebar *\\\/\\n        .full-height-active h2,\\n        .full-height-active .message,\\n        .full-height-active label,\\n        .full-height-active input[type=\\&quot;text\\&quot;],\\n        .full-height-active .tabs {\\n            display: none !important;\\n        }\\n        .full-height-active .editor-container.full-height .btn-bar {\\n            position: absolute;\\n            top: 20px;\\n            left: 20px;\\n            right: 20px;\\n            background: transparent;\\n            z-index: 1000;\\n            padding: 0;\\n            margin: 0;\\n            justify-content: space-between;\\n        }\\n        .full-height-active .editor-container.full-height .CodeMirror {\\n            margin-top: 40px;\\n        }\\n        .full-height-active .editor-container.full-height #toggle-full-height {\\n            display: block !important;\\n        }\\n        \\\/* \\u65b0\\u589e\\uff1a\\u5728\\u5168\\u9ad8\\u6a21\\u5f0f\\u4e0b\\u9690\\u85cf\\u65e5\\u591c\\u95f4\\u6a21\\u5f0f\\u6309\\u94ae *\\\/\\n        .full-height-active #toggle-dark {\\n            display: none !important;\\n        }\\n\\n\\n        \\\/* Success and error messages *\\\/\\n        .message {\\n            margin-top: 10px;\\n            padding: 8px 12px;\\n            border-radius: 4px;\\n            font-weight: bold;\\n            user-select: none;\\n        }\\n        .success {\\n            color: green;\\n            background-color: #e6ffe6;\\n            border: 1px solid #aaffaa;\\n        }\\n        .error {\\n            color: red;\\n            background-color: #ffe6e6;\\n            border: 1px solid #ffaaaa;\\n        }\\n\\n        \\\/* Day\\\/Night toggle button *\\\/\\n        #toggle-dark {\\n            position: fixed;\\n            top: 10px;\\n            right: 10px;\\n            padding: 8px 16px;\\n            background: rgba(0,0,0,0.6);\\n            color: #fff;\\n            border-radius: 20px;\\n            cursor: pointer;\\n            font-size: 14px;\\n            backdrop-filter: saturate(180%) blur(10px);\\n            transition: background-color 0.3s;\\n            user-select: none;\\n            z-index: 1000;\\n        }\\n        #toggle-dark:hover {\\n            background: rgba(0,0,0,0.8);\\n        }\\n        body.dark #toggle-dark {\\n            background: rgba(255,255,255,0.15);\\n            color: #eee;\\n        }\\n        body.dark #toggle-dark:hover {\\n            background: rgba(255,255,255,0.3);\\n        }\\n\\n        \\\/* New project button - sidebar bottom *\\\/\\n        #new-project-btn {\\n            position: absolute;\\n            bottom: 20px;\\n            left: 20px;\\n            background: rgba(51, 51, 51, 0.8);\\n            color: #ddd;\\n            border: 1px solid rgba(68, 68, 68, 0.8);\\n            border-radius: 4px;\\n            padding: 8px 12px;\\n            font-size: 14px;\\n            cursor: pointer;\\n            z-index: 1000;\\n            user-select: none;\\n            transition: background-color 0.3s, border-color 0.3s;\\n            width: calc(100% - 40px);\\n            text-align: center;\\n        }\\n        #new-project-btn:hover {\\n            background: rgba(68, 68, 68, 0.9);\\n            border-color: rgba(85, 85, 85, 0.9);\\n        }\\n\\n        \\\/* Save project button - floating *\\\/\\n        #submit-btn {\\n            position: fixed;\\n            bottom: 25px;\\n            right: 55px;\\n            padding: 15px 25px;\\n            background: rgba(33,150,243,0.7);\\n            color: white;\\n            border: none;\\n            border-radius: 30px;\\n            font-size: 18px;\\n            cursor: pointer;\\n            z-index: 1000;\\n            user-select: none;\\n            transition: background-color 0.3s, box-shadow 0.3s;\\n            backdrop-filter: none;\\n            box-shadow: 0 4px 8px rgba(0,0,0,0.2);\\n            text-shadow: 0 1px 2px rgba(0,0,0,0.3);\\n        }\\n        #submit-btn:hover {\\n            background: rgba(11,125,218,0.9);\\n            box-shadow: 0 6px 12px rgba(0,0,0,0.3);\\n        }\\n    &lt;\\\/style&gt;\\n&lt;\\\/head&gt;\\n&lt;body&gt;\\n&lt;div class=\\&quot;sidebar\\&quot;&gt;\\n    &lt;h3&gt;\\ud83d\\udcc2 \\u9879\\u76ee\\u5217\\u8868&lt;\\\/h3&gt;\\n    &lt;ul id=\\&quot;project-list\\&quot;&gt;\\n        &lt;?php foreach ($projects_data as $project): ?&gt;\\n            &lt;li data-folder-name=\\&quot;&lt;?= htmlspecialchars($project[&#039;folder_name&#039;]) ?&gt;\\&quot; &lt;?= ($project[&#039;folder_name&#039;] === $edit_folder_name) ? &#039;class=\\&quot;active\\&quot;&#039; : &#039;&#039; ?&gt;&gt;\\n                &lt;span class=\\&quot;name-links\\&quot;&gt;\\n                    &lt;a href=\\&quot;?edit=&lt;?= urlencode($project[&#039;folder_name&#039;]) ?&gt;\\&quot;&gt;\\u270f\\ufe0f&lt;?= htmlspecialchars($project[&#039;project_name&#039;]) ?&gt;&lt;\\\/a&gt;\\n                &lt;\\\/span&gt;\\n                &lt;span&gt;\\n                    &lt;a href=\\&quot;&lt;?= htmlspecialchars($project[&#039;folder_name&#039;]) ?&gt;\\\/\\&quot; target=\\&quot;_blank\\&quot; title=\\&quot;\\u8bbf\\u95ee\\u9879\\u76ee\\u6587\\u4ef6\\u5939\\&quot;&gt;\\ud83c\\udf10&lt;\\\/a&gt;\\n                    &lt;a href=\\&quot;javascript:void(0);\\&quot; onclick=\\&quot;deleteProject(&#039;&lt;?= urlencode($project[&#039;folder_name&#039;]) ?&gt;&#039;)\\&quot; title=\\&quot;\\u5220\\u9664\\u9879\\u76ee\\&quot;&gt;\\ud83d\\uddd1\\ufe0f&lt;\\\/a&gt;\\n                &lt;\\\/span&gt;\\n            &lt;\\\/li&gt;\\n        &lt;?php endforeach; ?&gt;\\n    &lt;\\\/ul&gt;\\n    &lt;button id=\\&quot;new-project-btn\\&quot; title=\\&quot;\\u65b0\\u5efa\\u9879\\u76ee\\&quot;&gt;\\uff0b \\u65b0\\u5efa\\u9879\\u76ee&lt;\\\/button&gt;\\n&lt;\\\/div&gt;\\n&lt;div class=\\&quot;container\\&quot;&gt;\\n    &lt;div class=\\&quot;main\\&quot;&gt;\\n        &lt;h2&gt;&lt;?= $page_h2_title ?&gt;&lt;\\\/h2&gt;\\n        &lt;?php if (!empty($success_message)): ?&gt;\\n            &lt;p class=\\&quot;message success\\&quot;&gt;&lt;?= $success_message ?&gt;&lt;\\\/p&gt;\\n        &lt;?php endif; ?&gt;\\n        &lt;?php if (!empty($error_message)): ?&gt;\\n            &lt;p class=\\&quot;message error\\&quot;&gt;&lt;?= $error_message ?&gt;&lt;\\\/p&gt;\\n        &lt;?php endif; ?&gt;\\n        &lt;form method=\\&quot;post\\&quot; id=\\&quot;form\\&quot;&gt;\\n            &lt;?php if ($edit_mode): ?&gt;\\n                &lt;input type=\\&quot;hidden\\&quot; name=\\&quot;original_folder\\&quot; value=\\&quot;&lt;?= htmlspecialchars($edit_folder_name) ?&gt;\\&quot;&gt;\\n            &lt;?php endif; ?&gt;\\n            &lt;label&gt;\\u2728 \\u9879\\u76ee\\u540d\\u79f0\\uff1a&lt;\\\/label&gt;\\n            &lt;input type=\\&quot;text\\&quot; name=\\&quot;project_name\\&quot; value=\\&quot;&lt;?= htmlspecialchars($input_project_name) ?&gt;\\&quot; required \\\/&gt;\\n            &lt;label&gt;\\ud83d\\udcc1 \\u6587\\u4ef6\\u5939\\u540d (\\u9650\\u82f1\\u6570\\u3001\\u4e0b\\u5212\\u7ebf\\u3001\\u77ed\\u5212\\u7ebf)\\uff1a&lt;\\\/label&gt;\\n            &lt;input type=\\&quot;text\\&quot; name=\\&quot;folder\\&quot; value=\\&quot;&lt;?= htmlspecialchars($input_folder) ?&gt;\\&quot; required \\\/&gt;\\n\\n            &lt;div class=\\&quot;tabs\\&quot;&gt;\\n                &lt;div class=\\&quot;tab active\\&quot; data-tab=\\&quot;html\\&quot;&gt;\\u270f\\ufe0f HTML&lt;\\\/div&gt;\\n                &lt;div class=\\&quot;tab\\&quot; data-tab=\\&quot;css\\&quot;&gt;\\ud83c\\udfa8 CSS&lt;\\\/div&gt;\\n                &lt;div class=\\&quot;tab\\&quot; data-tab=\\&quot;js\\&quot;&gt;\\ud83e\\udde0 JavaScript&lt;\\\/div&gt;\\n                &lt;div class=\\&quot;tab\\&quot; data-tab=\\&quot;php\\&quot;&gt;\\ud83d\\udc18 PHP&lt;\\\/div&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div id=\\&quot;html\\&quot; class=\\&quot;editor-container active\\&quot;&gt;\\n                &lt;div class=\\&quot;btn-bar\\&quot;&gt;\\n                    &lt;div class=\\&quot;left-buttons\\&quot;&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-html-comment\\&quot;&gt;\\u6ce8\\u91ca\\\/\\u53d6\\u6d88\\u6ce8\\u91ca&lt;\\\/button&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-html-search\\&quot;&gt;\\u641c\\u7d22&lt;\\\/button&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;button type=\\&quot;button\\&quot; id=\\&quot;toggle-full-height\\&quot; data-target=\\&quot;html\\&quot;&gt;\\u5168\\u9ad8&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;textarea name=\\&quot;html\\&quot;&gt;&lt;?= htmlspecialchars($input_html) ?&gt;&lt;\\\/textarea&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div id=\\&quot;css\\&quot; class=\\&quot;editor-container\\&quot;&gt;\\n                &lt;div class=\\&quot;btn-bar\\&quot;&gt;\\n                    &lt;div class=\\&quot;left-buttons\\&quot;&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-css-comment\\&quot;&gt;\\u6ce8\\u91ca\\\/\\u53d6\\u6d88\\u6ce8\\u91ca&lt;\\\/button&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-css-search\\&quot;&gt;\\u641c\\u7d22&lt;\\\/button&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;button type=\\&quot;button\\&quot; id=\\&quot;toggle-full-height\\&quot; data-target=\\&quot;css\\&quot;&gt;\\u5168\\u9ad8&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;textarea name=\\&quot;css\\&quot;&gt;&lt;?= htmlspecialchars($input_css) ?&gt;&lt;\\\/textarea&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div id=\\&quot;js\\&quot; class=\\&quot;editor-container\\&quot;&gt;\\n                &lt;div class=\\&quot;btn-bar\\&quot;&gt;\\n                    &lt;div class=\\&quot;left-buttons\\&quot;&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-js-comment\\&quot;&gt;\\u6ce8\\u91ca\\\/\\u53d6\\u6d88\\u6ce8\\u91ca&lt;\\\/button&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-js-search\\&quot;&gt;\\u641c\\u7d22&lt;\\\/button&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;button type=\\&quot;button\\&quot; id=\\&quot;toggle-full-height\\&quot; data-target=\\&quot;js\\&quot;&gt;\\u5168\\u9ad8&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;textarea name=\\&quot;js\\&quot;&gt;&lt;?= htmlspecialchars($input_js) ?&gt;&lt;\\\/textarea&gt;\\n            &lt;\\\/div&gt;\\n\\n            &lt;div id=\\&quot;php\\&quot; class=\\&quot;editor-container\\&quot;&gt;\\n                &lt;div class=\\&quot;btn-bar\\&quot;&gt;\\n                    &lt;div class=\\&quot;left-buttons\\&quot;&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-php-comment\\&quot;&gt;\\u6ce8\\u91ca\\\/\\u53d6\\u6d88\\u6ce8\\u91ca&lt;\\\/button&gt;\\n                        &lt;button type=\\&quot;button\\&quot; id=\\&quot;btn-php-search\\&quot;&gt;\\u641c\\u7d22&lt;\\\/button&gt;\\n                    &lt;\\\/div&gt;\\n                    &lt;button type=\\&quot;button\\&quot; id=\\&quot;toggle-full-height\\&quot; data-target=\\&quot;php\\&quot;&gt;\\u5168\\u9ad8&lt;\\\/button&gt;\\n                &lt;\\\/div&gt;\\n                &lt;textarea name=\\&quot;php\\&quot;&gt;&lt;?= htmlspecialchars($input_php) ?&gt;&lt;\\\/textarea&gt;\\n            &lt;\\\/div&gt;\\n        &lt;\\\/form&gt;\\n    &lt;\\\/div&gt;\\n&lt;\\\/div&gt;\\n\\n&lt;button id=\\&quot;submit-btn\\&quot; type=\\&quot;submit\\&quot; form=\\&quot;form\\&quot;&gt;\\ud83d\\udcbe \\u4fdd\\u5b58\\u9879\\u76ee&lt;\\\/button&gt;\\n&lt;button id=\\&quot;toggle-dark\\&quot; title=\\&quot;\\u5207\\u6362\\u65e5\\u591c\\u95f4\\u6a21\\u5f0f\\&quot;&gt;\\ud83c\\udf19 \\u591c\\u95f4\\u6a21\\u5f0f&lt;\\\/button&gt;\\n\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/lib\\\/codemirror.min.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/htmlmixed\\\/htmlmixed.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/xml\\\/xml.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/css\\\/css.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/javascript\\\/javascript.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/clike\\\/clike.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/mode\\\/php\\\/php.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/addon\\\/comment\\\/comment.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/keymap\\\/sublime.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/addon\\\/search\\\/searchcursor.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/addon\\\/search\\\/match-highlighter.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/addon\\\/dialog\\\/dialog.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/addon\\\/search\\\/jump-to-line.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/codemirror@5.65.15\\\/addon\\\/search\\\/search.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script src=\\&quot;https:\\\/\\\/cdn.jsdelivr.net\\\/npm\\\/sortablejs@1.15.2\\\/Sortable.min.js\\&quot;&gt;&lt;\\\/script&gt;\\n&lt;script&gt;\\n    const tabs = document.querySelectorAll(&#039;.tab&#039;);\\n    const tabContents = {\\n        html: document.getElementById(&#039;html&#039;),\\n        css: document.getElementById(&#039;css&#039;),\\n        js: document.getElementById(&#039;js&#039;),\\n        php: document.getElementById(&#039;php&#039;),\\n    };\\n\\n    const editors = {}; \\\/\\\/ Defined in global scope\\n\\n    tabs.forEach(tab =&gt; {\\n        tab.addEventListener(&#039;click&#039;, () =&gt; {\\n            tabs.forEach(t =&gt; t.classList.remove(&#039;active&#039;));\\n            tab.classList.add(&#039;active&#039;);\\n\\n            Object.values(tabContents).forEach(tc =&gt; tc.classList.remove(&#039;active&#039;));\\n            tabContents[tab.dataset.tab].classList.add(&#039;active&#039;);\\n            editors[tab.dataset.tab].refresh();\\n            editors[tab.dataset.tab].focus();\\n        });\\n    });\\n\\n    function initEditor(textareaElement, mode, initialContent) {\\n        const editor = CodeMirror.fromTextArea(textareaElement, {\\n            mode,\\n            theme: \\&quot;eclipse\\&quot;,\\n            lineNumbers: true,\\n            lineWrapping: true,\\n            keyMap: \\&quot;sublime\\&quot;,\\n            extraKeys: { \\&quot;Ctrl-\\\/\\&quot;: \\&quot;toggleComment\\&quot;, \\&quot;Cmd-\\\/\\&quot;: \\&quot;toggleComment\\&quot;, \\&quot;Ctrl-F\\&quot;: \\&quot;find\\&quot;, \\&quot;Cmd-F\\&quot;: \\&quot;find\\&quot; }, \\\/\\\/ Add Cmd-\\\/ for Mac and Ctrl\\\/Cmd+F for find\\n            scrollbarStyle: \\&quot;native\\&quot;,\\n            autofocus: false\\n        });\\n        editor.setValue(initialContent || &#039;&#039;);\\n        return editor;\\n    }\\n\\n    \\\/\\\/ Get initial content from PHP variables\\n    const initialData = {\\n        folder: &lt;?= json_encode($input_folder) ?&gt;,\\n        project_name: &lt;?= json_encode($input_project_name) ?&gt;,\\n        html: &lt;?= json_encode($input_html) ?&gt;,\\n        css: &lt;?= json_encode($input_css) ?&gt;,\\n        js: &lt;?= json_encode($input_js) ?&gt;,\\n        php: &lt;?= json_encode($input_php) ?&gt;\\n    };\\n\\n    editors.html = initEditor(document.querySelector(&#039;#html textarea&#039;), &#039;htmlmixed&#039;, initialData.html);\\n    editors.css = initEditor(document.querySelector(&#039;#css textarea&#039;), &#039;css&#039;, initialData.css);\\n    editors.js = initEditor(document.querySelector(&#039;#js textarea&#039;), &#039;javascript&#039;, initialData.js);\\n    editors.php = initEditor(document.querySelector(&#039;#php textarea&#039;), &#039;application\\\/x-httpd-php&#039;, initialData.php);\\n\\n    \\\/\\\/ Set folder and project name inputs after editor initialization\\n    document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value = initialData.folder;\\n    document.querySelector(&#039;input[name=\\&quot;project_name\\&quot;]&#039;).value = initialData.project_name;\\n\\n    \\\/\\\/ --- \\u6539\\u8fdb1 &amp; 2: AJAX\\u4fdd\\u5b58 &amp; Ctrl+S\\u4fdd\\u5b58 ---\\n    document.getElementById(&#039;submit-btn&#039;).addEventListener(&#039;click&#039;, function(e) {\\n        e.preventDefault(); \\\/\\\/ \\u963b\\u6b62\\u9ed8\\u8ba4\\u7684\\u8868\\u5355\\u63d0\\u4ea4\\n\\n        Object.values(editors).forEach(editor =&gt; editor.save()); \\\/\\\/ \\u5c06CodeMirror\\u5185\\u5bb9\\u4fdd\\u5b58\\u56detextarea\\n\\n        const form = document.getElementById(&#039;form&#039;);\\n        const formData = new FormData(form);\\n\\n        fetch(form.action, {\\n            method: &#039;POST&#039;,\\n            body: formData\\n        })\\n        .then(response =&gt; response.text()) \\\/\\\/ \\u83b7\\u53d6\\u5b8c\\u6574\\u7684HTML\\u54cd\\u5e94\\n        .then(html =&gt; {\\n            const parser = new DOMParser();\\n            const doc = parser.parseFromString(html, &#039;text\\\/html&#039;);\\n\\n            const messageSuccess = doc.querySelector(&#039;.message.success&#039;);\\n            const messageError = doc.querySelector(&#039;.message.error&#039;);\\n            const mainContainer = document.querySelector(&#039;.main&#039;);\\n\\n            \\\/\\\/ \\u6e05\\u9664\\u73b0\\u6709\\u6d88\\u606f\\n            document.querySelectorAll(&#039;.message&#039;).forEach(msg =&gt; msg.remove());\\n\\n            \\\/\\\/ \\u6dfb\\u52a0\\u65b0\\u6d88\\u606f\\n            if (messageSuccess) {\\n                mainContainer.prepend(messageSuccess);\\n                \\\/\\\/ \\ud83d\\udc47 \\u5c06\\u81ea\\u52a8\\u6d88\\u5931\\u4ee3\\u7801\\u6dfb\\u52a0\\u5230\\u8fd9\\u91cc (\\u6210\\u529f\\u6d88\\u606f)\\n                setTimeout(() =&gt; {\\n                    messageSuccess.remove();\\n                }, 2000); \\\/\\\/ 2000\\u6beb\\u79d2 = 2\\u79d2\\n                \\n                \\\/\\\/ \\u66f4\\u65b0CodeMirror\\u7f16\\u8f91\\u5668\\u5185\\u5bb9\\n                editors.html.setValue(doc.querySelector(&#039;textarea[name=\\&quot;html\\&quot;]&#039;).value);\\n                editors.css.setValue(doc.querySelector(&#039;textarea[name=\\&quot;css\\&quot;]&#039;).value);\\n                editors.js.setValue(doc.querySelector(&#039;textarea[name=\\&quot;js\\&quot;]&#039;).value);\\n                editors.php.setValue(doc.querySelector(&#039;textarea[name=\\&quot;php\\&quot;]&#039;).value);\\n                \\n                \\\/\\\/ \\u66f4\\u65b0\\u9879\\u76ee\\u540d\\u79f0\\u548c\\u6587\\u4ef6\\u5939\\u540d\\u79f0\\u8f93\\u5165\\u6846\\n                document.querySelector(&#039;input[name=\\&quot;project_name\\&quot;]&#039;).value = doc.querySelector(&#039;input[name=\\&quot;project_name\\&quot;]&#039;).value;\\n                document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value = doc.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value;\\n\\n                \\\/\\\/ \\u66f4\\u65b0H2\\u6807\\u9898\\n                const newH2Title = doc.querySelector(&#039;.main h2&#039;).textContent;\\n                document.querySelector(&#039;.main h2&#039;).textContent = newH2Title;\\n\\n                \\\/\\\/ \\u5237\\u65b0\\u4fa7\\u8fb9\\u680f\\u9879\\u76ee\\u5217\\u8868\\n                const newProjectListHTML = doc.getElementById(&#039;project-list&#039;).innerHTML;\\n                document.getElementById(&#039;project-list&#039;).innerHTML = newProjectListHTML;\\n\\n                \\\/\\\/ \\u91cd\\u65b0\\u7ed1\\u5b9aSortable.js\\n                Sortable.create(projectList, {\\n                    animation: 150,\\n                    ghostClass: &#039;sortable-ghost&#039;,\\n                    chosenClass: &#039;sortable-chosen&#039;,\\n                    onEnd: function (evt) {\\n                        const newOrder = [];\\n                        Array.from(projectList.children).forEach(li =&gt; {\\n                            newOrder.push(li.dataset.folderName);\\n                        });\\n                        \\n                        fetch(window.location.href, {\\n                            method: &#039;POST&#039;,\\n                            headers: { &#039;Content-Type&#039;: &#039;application\\\/x-www-form-urlencoded&#039; },\\n                            body: new URLSearchParams({ action: &#039;reorder_projects&#039;, order: JSON.stringify(newOrder) })\\n                        })\\n                        .then(response =&gt; response.json())\\n                        .then(data =&gt; {\\n                            if (data.status === &#039;success&#039;) {\\n                                console.log(&#039;Project order updated successfully.&#039;);\\n                            } else {\\n                                console.error(&#039;Error updating project order:&#039;, data.message);\\n                            }\\n                        })\\n                        .catch(error =&gt; console.error(&#039;Network error during reorder:&#039;, error));\\n                    },\\n                });\\n\\n                \\\/\\\/ \\u91cd\\u65b0\\u9ad8\\u4eae\\u5f53\\u524d\\u6d3b\\u8dc3\\u9879\\u76ee\\n                const currentFolder = document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value;\\n                document.querySelectorAll(&#039;#project-list li&#039;).forEach(li =&gt; {\\n                    li.classList.remove(&#039;active&#039;);\\n                    if (li.dataset.folderName === currentFolder) {\\n                        li.classList.add(&#039;active&#039;);\\n                    }\\n                });\\n\\n            } else if (messageError) {\\n                mainContainer.prepend(messageError);\\n                    setTimeout(() =&gt; {\\n                    messageError.remove();\\n                }, 2000); \\\/\\\/ 2000\\u6beb\\u79d2 = 2\\u79d2\\n                \\n            }\\n        })\\n        .catch(error =&gt; {\\n            console.error(&#039;Error saving project:&#039;, error);\\n            alert(&#039;\\u4fdd\\u5b58\\u9879\\u76ee\\u65f6\\u53d1\\u751f\\u9519\\u8bef\\u3002&#039;);\\n        });\\n    });\\n\\n    document.addEventListener(&#039;keydown&#039;, function(event) {\\n        \\\/\\\/ \\u68c0\\u67e5Ctrl+S (Windows\\\/Linux) \\u6216 Cmd+S (macOS)\\n        if ((event.ctrlKey || event.metaKey) &amp;&amp; event.key === &#039;s&#039;) {\\n            event.preventDefault(); \\\/\\\/ \\u963b\\u6b62\\u6d4f\\u89c8\\u5668\\u9ed8\\u8ba4\\u7684\\u4fdd\\u5b58\\u5bf9\\u8bdd\\u6846\\n            document.getElementById(&#039;submit-btn&#039;).click(); \\\/\\\/ \\u89e6\\u53d1\\u4fdd\\u5b58\\u6309\\u94ae\\u7684\\u70b9\\u51fb\\u4e8b\\u4ef6\\n        }\\n    });\\n\\n    \\\/\\\/ Comment buttons binding\\n    document.getElementById(&#039;btn-html-comment&#039;).onclick = () =&gt; editors.html.execCommand(&#039;toggleComment&#039;);\\n    document.getElementById(&#039;btn-css-comment&#039;).onclick = () =&gt; editors.css.execCommand(&#039;toggleComment&#039;);\\n    document.getElementById(&#039;btn-js-comment&#039;).onclick = () =&gt; editors.js.execCommand(&#039;toggleComment&#039;);\\n    document.getElementById(&#039;btn-php-comment&#039;).onclick = () =&gt; editors.php.execCommand(&#039;toggleComment&#039;);\\n\\n    \\\/\\\/ --- \\u6539\\u8fdb4: \\u641c\\u7d22\\u529f\\u80fd\\u6309\\u94ae\\u7ed1\\u5b9a ---\\n    document.getElementById(&#039;btn-html-search&#039;).onclick = () =&gt; editors.html.execCommand(&#039;find&#039;);\\n    document.getElementById(&#039;btn-css-search&#039;).onclick = () =&gt; editors.css.execCommand(&#039;find&#039;);\\n    document.getElementById(&#039;btn-js-search&#039;).onclick = () =&gt; editors.js.execCommand(&#039;find&#039;);\\n    document.getElementById(&#039;btn-php-search&#039;).onclick = () =&gt; editors.php.execCommand(&#039;find&#039;);\\n\\n\\n    \\\/\\\/ Day\\\/Night mode switch\\n    const toggleBtn = document.getElementById(&#039;toggle-dark&#039;);\\n    let darkMode = localStorage.getItem(&#039;darkMode&#039;) === &#039;true&#039;;\\n\\n    function applyDarkMode(isDark) {\\n        document.body.classList.toggle(&#039;dark&#039;, isDark);\\n        toggleBtn.textContent = isDark ? &#039;\\u2600\\ufe0f \\u65e5\\u95f4\\u6a21\\u5f0f&#039; : &#039;\\ud83c\\udf19 \\u591c\\u95f4\\u6a21\\u5f0f&#039;;\\n        Object.values(editors).forEach(editor =&gt; {\\n            editor.setOption(&#039;theme&#039;, isDark ? &#039;darcula&#039; : &#039;eclipse&#039;);\\n        });\\n    }\\n\\n    applyDarkMode(darkMode);\\n\\n    toggleBtn.addEventListener(&#039;click&#039;, () =&gt; {\\n        darkMode = !darkMode;\\n        applyDarkMode(darkMode);\\n        localStorage.setItem(&#039;darkMode&#039;, darkMode);\\n    });\\n\\n    \\\/\\\/ --- \\u6539\\u8fdb3: \\u5168\\u9ad8\\\/\\u534a\\u9ad8\\u6309\\u94ae\\u6587\\u5b57\\u5207\\u6362 ---\\n    document.querySelectorAll(&#039;#toggle-full-height&#039;).forEach(button =&gt; {\\n        button.addEventListener(&#039;click&#039;, function() {\\n            const targetTab = this.dataset.target;\\n            const editorContainer = tabContents[targetTab];\\n            editorContainer.classList.toggle(&#039;full-height&#039;);\\n            \\n            \\\/\\\/ \\u5207\\u6362\\u6309\\u94ae\\u6587\\u5b57\\n            if (editorContainer.classList.contains(&#039;full-height&#039;)) {\\n                this.textContent = &#039;\\u534a\\u9ad8&#039;; \\\/\\\/ Change to \\&quot;Half Height\\&quot;\\n            } else {\\n                this.textContent = &#039;\\u5168\\u9ad8&#039;; \\\/\\\/ Change back to \\&quot;Full Height\\&quot;\\n            }\\n\\n            document.body.classList.toggle(&#039;full-height-active&#039;, editorContainer.classList.contains(&#039;full-height&#039;));\\n\\n            editors[targetTab].refresh(); \\\/\\\/ \\u5237\\u65b0\\u7f16\\u8f91\\u5668\\u4ee5\\u9002\\u5e94\\u65b0\\u5c3a\\u5bf8\\n        });\\n    });\\n\\n\\n    \\\/\\\/ New project button event\\n    document.getElementById(&#039;new-project-btn&#039;).addEventListener(&#039;click&#039;, () =&gt; {\\n        \\\/\\\/ \\u91cd\\u5b9a\\u5411\\u5230\\u5e26 ?new=1 \\u53c2\\u6570\\u7684URL\\uff0c\\u8ba9PHP\\u7aef\\u5904\\u7406\\u91cd\\u7f6e\\u548c\\u9ad8\\u4eae\\n        window.location.href = location.pathname + &#039;?new=1&#039;;\\n    });\\n\\n    \\\/\\\/ Delete project confirmation\\n    function deleteProject(folderName) {\\n        const password = prompt(`\\u786e\\u5b9a\\u8981\\u5220\\u9664\\u9879\\u76ee &#039;${decodeURIComponent(folderName)}&#039; \\u5417\\uff1f\\\\n\\u8bf7\\u8f93\\u5165\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\u786e\\u8ba4\\u5220\\u9664:`);\\n        if (password === &#039;&lt;?= ADMIN_PASSWORD ?&gt;&#039;) { \\\/\\\/ \\u4f7f\\u7528 PHP \\u5e38\\u91cf\\u8fdb\\u884c\\u5bf9\\u6bd4\\n            \\\/\\\/ \\u521b\\u5efa\\u4e00\\u4e2a\\u4e34\\u65f6\\u7684 form \\u8fdb\\u884c POST \\u8bf7\\u6c42\\u4ee5\\u5220\\u9664\\n            const form = document.createElement(&#039;form&#039;);\\n            form.method = &#039;POST&#039;;\\n            form.action = `?delete=${encodeURIComponent(folderName)}`;\\n\\n            const input = document.createElement(&#039;input&#039;);\\n            input.type = &#039;hidden&#039;;\\n            input.name = &#039;admin_password&#039;;\\n            input.value = password;\\n            form.appendChild(input);\\n\\n            document.body.appendChild(form);\\n            form.submit();\\n        } else if (password !== null) { \\\/\\\/ \\u5982\\u679c\\u7528\\u6237\\u8f93\\u5165\\u4e86\\u5bc6\\u7801\\u4f46\\u5bc6\\u7801\\u9519\\u8bef\\n            alert(&#039;\\u5bc6\\u7801\\u9519\\u8bef\\uff0c\\u65e0\\u6cd5\\u5220\\u9664\\u9879\\u76ee\\u3002&#039;);\\n        }\\n    }\\n\\n    \\\/\\\/ Initialize SortableJS\\n    const projectList = document.getElementById(&#039;project-list&#039;);\\n    Sortable.create(projectList, {\\n        animation: 150,\\n        ghostClass: &#039;sortable-ghost&#039;,\\n        chosenClass: &#039;sortable-chosen&#039;,\\n        onEnd: function (evt) {\\n            const newOrder = [];\\n            Array.from(projectList.children).forEach(li =&gt; {\\n                newOrder.push(li.dataset.folderName);\\n            });\\n            \\n            \\\/\\\/ Send new order to server via AJAX\\n            fetch(window.location.href, {\\n                method: &#039;POST&#039;,\\n                headers: {\\n                    &#039;Content-Type&#039;: &#039;application\\\/x-www-form-urlencoded&#039;,\\n                },\\n                body: new URLSearchParams({\\n                    action: &#039;reorder_projects&#039;,\\n                    order: JSON.stringify(newOrder)\\n                })\\n            })\\n            .then(response =&gt; response.json())\\n            .then(data =&gt; {\\n                if (data.status === &#039;success&#039;) {\\n                    \\\/\\\/ Optionally show a success message or re-fetch list\\n                    console.log(&#039;Project order updated successfully.&#039;);\\n                } else {\\n                    console.error(&#039;Error updating project order:&#039;, data.message);\\n                }\\n            })\\n            .catch(error =&gt; {\\n                console.error(&#039;Network error during reorder:&#039;, error);\\n            });\\n        },\\n    });\\n\\n&lt;\\\/script&gt;\\n&lt;\\\/body&gt;\\n&lt;\\\/html&gt;&quot;,&quot;codeTypo&quot;:{&quot;desktop&quot;:9,&quot;tablet&quot;:15,&quot;mobile&quot;:14},&quot;width&quot;:{&quot;desktop&quot;:&quot;100%&quot;,&quot;tablet&quot;:&quot;99.9%&quot;,&quot;mobile&quot;:&quot;100%&quot;},&quot;height&quot;:{&quot;desktop&quot;:&quot;500px&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;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","protected":false},"excerpt":{"rendered":"<p>\u89c6\u9891\u6f14\u793a \u6f14\u793a\u4e86\u672c\u540e\u53f0\u7684\u4f7f\u7528\u65b9\u6cd5\uff0c\u5e76\u6dfb\u52a0\u4e00\u4e9bAI\u751f\u6210\u7684\u524d\u7aef\u5c0f\u5de5\u5177\u8fdb\u884c\u6d4b\u8bd5\u3002 \u6982\u8ff0 \u8fd9\u4e2a\u540e\u53f0\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u57fa\u4e8e 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-3486","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/3486","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=3486"}],"version-history":[{"count":10,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/3486\/revisions"}],"predecessor-version":[{"id":3524,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/3486\/revisions\/3524"}],"wp:attachment":[{"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3486"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3486"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3486"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}