{"id":3437,"date":"2025-06-30T22:19:35","date_gmt":"2025-06-30T14:19:35","guid":{"rendered":"https:\/\/blog.kangyue.pro\/?p=3437"},"modified":"2025-07-03T12:08:41","modified_gmt":"2025-07-03T04:08:41","slug":"%e4%b8%80%e4%b8%aa%e5%9f%ba%e4%ba%8ephp%e7%9a%84%e7%ae%a1%e7%90%86web%e6%96%87%e4%bb%b6%ef%bc%88html%e3%80%81css%e3%80%81js%ef%bc%89%e7%9a%84%e5%90%8e%e5%8f%b0%e9%a1%b5%e9%9d%a2","status":"publish","type":"post","link":"https:\/\/blog.kangyue.pro\/?p=3437","title":{"rendered":"\u4e00\u4e2a\u57fa\u4e8ephp\u7684\u7ba1\u7406web\u6587\u4ef6\uff08html\u3001css\u3001js\uff09\u7684\u540e\u53f0\u9875\u9762"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>\u3000\u3000\u672c\u4eba\u4e3a\u65b9\u4fbf\u7ba1\u7406\u4e00\u4e9b\u7531AI\u751f\u6210\u7684\u7f51\u9875\u7248\u5c0f\u5de5\u5177\uff0c\u53c8\u7528AI\u751f\u6210\u4e86\u8be5\u540e\u53f0\u7ba1\u7406\u9875\u9762\u3002\u4f7f\u7528\u5b83\uff0c\u901a\u8fc7\u6d4f\u89c8\u5668\u5373\u53ef\u7ba1\u7406\u4f4d\u4e8e\u670d\u52a1\u5668\u4e0a\u7684html\u3001css\u3001js\u548cphp\u6587\u4ef6\u800c\u65e0\u9700\u4f7f\u7528FTP\u6216Linux\u767b\u5f55\u9762\u677f\u3002\n\u3000\u3000\u867d\u7136\u662f\u5b83\u662f\u7531AI\u751f\u6210\uff0c\u5728\u7b2c\u4e00\u7248\u65f6\u4e5f\u5b9e\u73b0\u4e86\u57fa\u7840\u529f\u80fd\uff0c\u4f46\u529f\u80fd\u7b80\u5355\u4e14\u5b58\u5728\u8bf8\u591a\u95ee\u9898\uff1b\u7ecf\u8fc7\u7ea67\u4e2a\u5c0f\u65f6\u7684\u9010\u6b65\u5b8c\u5584\uff0c\u6700\u7ec8\u5f62\u6210\u672c\u7248\u3002\n\u3000\u3000\uff08\u5176\u6700\u521d\u7248\u672c\u7531ChatGPT\u751f\u6210\uff0c\u540e\u7eed\u4f7f\u7528ChatGPT\u4fee\u6539\u591a\u6b21\u5747\u51fa\u73b0\u5404\u7c7b\u9519\u8bef\uff1b\u6700\u7ec8\u4f7f\u7528Google\u7684Gemini\u6539\u8fdb\u6210\u529f\uff09<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>Gemini\u4e00\u53e5\u8bdd\u6982\u62ec\u672c\u5de5\u5177\uff1a<\/strong>\n\u3000\u3000\u8fd9\u662f\u4e00\u4e2a\u57fa\u4e8eWeb\u7684PHP\u540e\u53f0\u5de5\u5177\uff0c\u5b83\u63d0\u4f9b\u4e86\u4e00\u4e2a\u96c6\u6210\u7684\u4ee3\u7801\u7f16\u8f91\u5668\uff0c\u65b9\u4fbf\u7528\u6237\u521b\u5efa\u3001\u7f16\u8f91\u3001\u4fdd\u5b58\u548c\u7ba1\u7406\u5305\u542bHTML\u3001CSS\u3001JavaScript\u548cPHP\u7684\u5404\u7c7b\u5c0f\u578b\u4ee3\u7801\u9879\u76ee\uff0c\u5e76\u652f\u6301\u5168\u9ad8\u7f16\u8f91\u548c\u65e5\u591c\u95f4\u6a21\u5f0f\u5207\u6362\u3002<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">\u5927\u81f4\u4f7f\u7528\u6b65\u9aa4<\/h1>\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\/06\/image-171.png\" alt=\"\" class=\"wp-image-3481\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-171.png 2196w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-171-768x341.png 768w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-171-1536x683.png 1536w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-171-2048x910.png 2048w\" sizes=\"auto, (max-width: 2196px) 100vw, 2196px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">\u540e\u53f0\u622a\u56fe<\/h1>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1266\" height=\"849\" src=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-170.png\" alt=\"\" class=\"wp-image-3453\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-170.png 1266w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-170-768x515.png 768w\" sizes=\"auto, (max-width: 1266px) 100vw, 1266px\" \/><\/figure>\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\/06\/image-168.png\" alt=\"\" class=\"wp-image-3441\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-168.png 1279w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-168-768x518.png 768w\" sizes=\"auto, (max-width: 1279px) 100vw, 1279px\" \/><\/figure>\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\/06\/image-169.png\" alt=\"\" class=\"wp-image-3442\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-169.png 1279w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-169-768x518.png 768w\" sizes=\"auto, (max-width: 1279px) 100vw, 1279px\" \/><\/figure>\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\/06\/image-167.png\" alt=\"\" class=\"wp-image-3440\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-167.png 1279w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-167-768x518.png 768w\" sizes=\"auto, (max-width: 1279px) 100vw, 1279px\" \/><\/figure>\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\/06\/image-166.png\" alt=\"\" class=\"wp-image-3439\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-166.png 1279w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-166-768x518.png 768w\" sizes=\"auto, (max-width: 1279px) 100vw, 1279px\" \/><\/figure>\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\/06\/image-165.png\" alt=\"\" class=\"wp-image-3438\" srcset=\"https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-165.png 1279w, https:\/\/blog.kangyue.pro\/wp-content\/uploads\/2025\/06\/image-165-768x518.png 768w\" sizes=\"auto, (max-width: 1279px) 100vw, 1279px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">\u5730\u5740<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>\u672c\u9875\u9762\u7531KY\u672c\u4eba\u4f7f\u7528\uff0c\u4e3a\u4fdd\u5b89\u5168\uff0c\u4ee5\u4e0b\u94fe\u63a5\u9700\u8981\u952e\u5165\u5bc6\u7801\u624d\u80fd\u8bbf\u95ee\u7ba1\u7406\u3002<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"http:\/\/tool.kangyue.pro\/admin.php\">http:\/\/tool.kangyue.pro\/admin.php<\/a><\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">PHP\u4ee3\u7801\uff08V3.0,\u6700\u65b0\u7248\uff09<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">\u540e\u53f0<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u81ea\u9002\u5e94\u5de6\u4fa7\u680f\u5bbd\u5ea6<\/li>\n\n\n\n<li>\u56fa\u5b9a\u4ee3\u7801\u7f16\u8f91\u6846\u7684\u5927\u5c0f<\/li>\n\n\n\n<li>\u9879\u76ee\u540d\u6216\u6587\u4ef6\u5939\u540d\u91cd\u590d\u65f6\uff0c\u7ed9\u4e88\u63d0\u793a\uff08\u800c\u975e\u8986\u76d6\u65e2\u6709\u9879\u76ee\uff09<\/li>\n<\/ul>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-74dfffb4-1' data-attributes='{&quot;cId&quot;:&quot;74dfffb4-1&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\nsession_start();\\ndefine(&#039;ADMIN_PASSWORD&#039;, &#039;kangyue01.&#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            }\\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            header(\\&quot;Location: \\&quot; . $_SERVER[&#039;PHP_SELF&#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;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;\\\/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&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; }, \\\/\\\/ Add Cmd-\\\/ for Mac\\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    \\\/\\\/ Save content to textarea before form submission\\n    document.getElementById(&#039;form&#039;).addEventListener(&#039;submit&#039;, () =&gt; {\\n        Object.values(editors).forEach(editor =&gt; editor.save());\\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    \\\/\\\/ 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    \\\/\\\/ Toggle full height for editor\\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            \\\/\\\/ \\u65b0\\u589e\\uff1a\\u5207\\u6362 body \\u4e0a\\u7684\\u7c7b\\u540d\\uff0c\\u7528\\u4e8e\\u63a7\\u5236\\u65e5\\u591c\\u95f4\\u6a21\\u5f0f\\u6309\\u94ae\\u7684\\u663e\\u793a\\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;:10,&quot;tablet&quot;:15,&quot;mobile&quot;:14},&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;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\">\u9879\u76ee\u5c55\u793a\u7684\u9875\u9762<\/h3>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-3f8af058-8' data-attributes='{&quot;cId&quot;:&quot;3f8af058-8&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\n\\\/\\\/ \\u5b9a\\u4e49\\u9879\\u76ee\\u7684\\u6839\\u76ee\\u5f55\\uff0c\\u901a\\u5e38\\u5c31\\u662f\\u5f53\\u524d\\u6587\\u4ef6\\u6240\\u5728\\u7684\\u76ee\\u5f55\\ndefine(&#039;BASE_DIR&#039;, __DIR__);\\n\\\/\\\/ \\u5b9a\\u4e49\\u6392\\u5e8f\\u6587\\u4ef6\\u8def\\u5f84\\uff0c\\u786e\\u4fdd\\u4e0e\\u540e\\u53f0\\u4fdd\\u5b58\\u7684\\u6587\\u4ef6\\u540d\\u4e00\\u81f4\\ndefine(&#039;ORDER_FILE&#039;, BASE_DIR . DIRECTORY_SEPARATOR . &#039;projects_order.json&#039;);\\n\\\/\\\/ \\u65b0\\u589e\\uff1a\\u5b9a\\u4e49\\u9879\\u76ee\\u5143\\u6570\\u636e\\u6587\\u4ef6\\u8def\\u5f84\\uff0c\\u4e0e\\u540e\\u53f0\\u4e00\\u81f4\\ndefine(&#039;PROJECT_META_FILE&#039;, &#039;.project_meta.json&#039;);\\n\\n\\\/\\\/ Function to read project metadata - \\u4e0e\\u540e\\u53f0 admin2.php \\u4fdd\\u6301\\u4e00\\u81f4\\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)]; \\\/\\\/ \\u9ed8\\u8ba4\\u503c\\uff1a\\u9879\\u76ee\\u540d\\u79f0\\u4e3a\\u6587\\u4ef6\\u5939\\u540d\\n}\\n\\n\\\/\\\/ Function to read projects order - \\u4e0e\\u540e\\u53f0 admin2.php \\u4fdd\\u6301\\u4e00\\u81f4\\nfunction readProjectsOrder() {\\n    $order_file = ORDER_FILE; \\\/\\\/ \\u4f7f\\u7528\\u5b9a\\u4e49\\u7684\\u5e38\\u91cf\\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\\\/\\\/ \\u83b7\\u53d6 BASE_DIR \\u4e0b\\u7684\\u6240\\u6709\\u5b50\\u76ee\\u5f55\\u540d\\u79f0\\n$all_dirs_raw = array_filter(glob(BASE_DIR . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\n$available_physical_folders = []; \\\/\\\/ \\u5b58\\u50a8\\u5b9e\\u9645\\u5b58\\u5728\\u7684\\u6587\\u4ef6\\u5939\\u540d\\nforeach ($all_dirs_raw as $dir) {\\n    $name = basename($dir);\\n    \\\/\\\/ \\u8fc7\\u6ee4\\u6389\\u975e\\u9879\\u76ee\\u76ee\\u5f55\\uff1a\\n    \\\/\\\/ 1. \\u4ee5 \\&quot;.\\&quot; \\u5f00\\u5934\\u7684\\u9690\\u85cf\\u76ee\\u5f55\\u6216\\u6587\\u4ef6 (\\u5982 .git, .vscode \\u7b49)\\n    \\\/\\\/ 2. \\u60a8\\u7684\\u540e\\u53f0\\u7ba1\\u7406\\u811a\\u672c\\u6587\\u4ef6 (admin2.php)\\n    \\\/\\\/ 3. \\u5f53\\u524d\\u811a\\u672c\\u6240\\u5728\\u7684\\u76ee\\u5f55\\u540d\\u79f0 (\\u5982\\u679c\\u5f53\\u524d\\u811a\\u672c\\u5728\\u6839\\u76ee\\u5f55\\uff0c\\u5176basename\\u53ef\\u80fd\\u4e3a&#039;.&#039;\\uff0c\\u6216\\u8005\\u811a\\u672c\\u540d\\u672c\\u8eab)\\n    if (substr($name, 0, 1) !== &#039;.&#039; &amp;&amp;\\n        $name !== basename(__FILE__, &#039;.php&#039;) &amp;&amp; \\\/\\\/ \\u6392\\u9664\\u5f53\\u524d\\u811a\\u672c\\u7684\\u6587\\u4ef6\\u5939\\u540d\\uff0c\\u4f8b\\u5982 &#039;index&#039; \\u5982\\u679c\\u662f index.php\\n        $name !== &#039;admin2.php&#039; \\\/\\\/ \\u6392\\u9664\\u540e\\u53f0\\u7ba1\\u7406\\u811a\\u672c\\u7684\\u6587\\u4ef6\\u540d (\\u5982\\u679cadmin2.php\\u4e0e\\u6b64\\u6587\\u4ef6\\u540c\\u7ea7\\u4e14\\u5b83\\u672c\\u8eab\\u4e0d\\u662f\\u76ee\\u5f55)\\n    ) {\\n        $available_physical_folders[] = $name;\\n    }\\n}\\n\\n\\\/\\\/ \\u8bfb\\u53d6\\u81ea\\u5b9a\\u4e49\\u6392\\u5e8f\\u914d\\u7f6e (\\u73b0\\u5728\\u53ea\\u5305\\u542b\\u6587\\u4ef6\\u5939\\u540d\\u79f0\\u6570\\u7ec4)\\n$ordered_project_folders = readProjectsOrder();\\n$projects_to_display = [];\\n\\n\\\/\\\/ \\u7528\\u4e8e\\u8ddf\\u8e2a\\u5df2\\u5904\\u7406\\u7684\\u7269\\u7406\\u6587\\u4ef6\\u5939\\uff0c\\u907f\\u514d\\u91cd\\u590d\\u6dfb\\u52a0\\n$processed_physical_folders = [];\\n\\n\\\/\\\/ 1. \\u9996\\u5148\\uff0c\\u6309\\u7167 `projects_order.json` \\u4e2d\\u4fdd\\u5b58\\u7684\\u987a\\u5e8f\\u6dfb\\u52a0\\u9879\\u76ee\\nforeach ($ordered_project_folders as $folder_name_from_order) {\\n    \\\/\\\/ \\u786e\\u4fdd\\u8be5\\u6587\\u4ef6\\u5939\\u5b9e\\u9645\\u5b58\\u5728\\n    if (in_array($folder_name_from_order, $available_physical_folders)) {\\n        $project_path = BASE_DIR . DIRECTORY_SEPARATOR . $folder_name_from_order;\\n        $meta = readProjectMetadata($project_path);\\n        $projects_to_display[] = [\\n            &#039;folder_name&#039; =&gt; $folder_name_from_order,\\n            &#039;display_name&#039; =&gt; $meta[&#039;name&#039;] ?? $folder_name_from_order, \\\/\\\/ \\u4f7f\\u7528\\u5143\\u6570\\u636e\\u4e2d\\u7684\\u540d\\u79f0\\uff0c\\u5982\\u679c\\u4e0d\\u5b58\\u5728\\u5219\\u4f7f\\u7528\\u6587\\u4ef6\\u5939\\u540d\\n        ];\\n        $processed_physical_folders[] = $folder_name_from_order; \\\/\\\/ \\u6807\\u8bb0\\u4e3a\\u5df2\\u5904\\u7406\\n    }\\n}\\n\\n\\\/\\\/ 2. \\u7136\\u540e\\uff0c\\u6dfb\\u52a0\\u4efb\\u4f55\\u65b0\\u521b\\u5efa\\u7684\\u3001\\u4f46\\u4e0d\\u5728 `projects_order.json` \\u4e2d\\u7684\\u9879\\u76ee\\n\\\/\\\/    \\u8fd9\\u4e9b\\u9879\\u76ee\\u5c06\\u6309\\u5b57\\u6bcd\\u987a\\u5e8f\\u6392\\u5217\\uff0c\\u5e76\\u4ece\\u5176 .project_meta.json \\u4e2d\\u83b7\\u53d6\\u540d\\u79f0\\n$new_or_unlisted_folders = array_diff($available_physical_folders, $processed_physical_folders);\\nsort($new_or_unlisted_folders); \\\/\\\/ \\u5bf9\\u8fd9\\u4e9b\\u65b0\\u9879\\u76ee\\u6309\\u5b57\\u6bcd\\u6392\\u5e8f\\nforeach ($new_or_unlisted_folders as $folder_name) {\\n    $project_path = BASE_DIR . DIRECTORY_SEPARATOR . $folder_name;\\n    $meta = readProjectMetadata($project_path);\\n    $projects_to_display[] = [\\n        &#039;folder_name&#039; =&gt; $folder_name,\\n        &#039;display_name&#039; =&gt; $meta[&#039;name&#039;] ?? $folder_name, \\\/\\\/ \\u4ece\\u5143\\u6570\\u636e\\u4e2d\\u83b7\\u53d6\\u540d\\u79f0\\uff0c\\u5982\\u679c\\u4e0d\\u5b58\\u5728\\u5219\\u4f7f\\u7528\\u6587\\u4ef6\\u5939\\u540d\\n    ];\\n}\\n\\\/\\\/ \\u81f3\\u6b64\\uff0c$projects_to_display \\u6570\\u7ec4\\u5305\\u542b\\u4e86\\u6240\\u6709\\u8981\\u663e\\u793a\\u7684\\u9879\\u76ee\\u7684 folder_name \\u548c display_name\\uff0c\\u5e76\\u6309\\u671f\\u671b\\u7684\\u987a\\u5e8f\\u6392\\u5217\\n\\n\\n\\\/\\\/ \\u83b7\\u53d6\\u5f53\\u524d\\u7528\\u6237\\u901a\\u8fc7 URL \\u53c2\\u6570\\u9009\\u62e9\\u7684\\u9879\\u76ee\\u540d\\u79f0\\n$current_project_folder_name = $_GET[&#039;project&#039;] ?? null; \\\/\\\/ \\u4f7f\\u7528\\u66f4\\u51c6\\u786e\\u7684\\u53d8\\u91cf\\u540d\\n\\n$show_download_button = false; \\\/\\\/ \\u9ed8\\u8ba4\\u4e0d\\u663e\\u793a\\u4e0b\\u8f7d\\u6309\\u94ae\\n$show_direct_access_button = false; \\\/\\\/ \\u9ed8\\u8ba4\\u4e0d\\u663e\\u793a\\u5355\\u72ec\\u8bbf\\u95ee\\u6309\\u94ae\\n$project_has_html = false; \\\/\\\/ \\u6807\\u8bb0\\u9879\\u76ee\\u662f\\u5426\\u6709 index.html\\n$project_has_php = false;  \\\/\\\/ \\u6807\\u8bb0\\u9879\\u76ee\\u662f\\u5426\\u6709 PHP \\u6587\\u4ef6\\n\\n\\\/\\\/ \\u83b7\\u53d6\\u5f53\\u524d\\u9009\\u4e2d\\u9879\\u76ee\\u7684\\u5b9e\\u9645\\u663e\\u793a\\u540d\\u79f0\\n$current_project_display_name = &#039;&#039;;\\nforeach ($projects_to_display as $project) {\\n    if ($project[&#039;folder_name&#039;] === $current_project_folder_name) {\\n        $current_project_display_name = $project[&#039;display_name&#039;];\\n        break;\\n    }\\n}\\n\\n\\nif ($current_project_folder_name) {\\n    $project_path = BASE_DIR . DIRECTORY_SEPARATOR . basename($current_project_folder_name);\\n    \\n    if (is_dir($project_path)) {\\n        \\\/\\\/ \\u68c0\\u67e5\\u662f\\u5426\\u6709 index.html\\n        if (file_exists($project_path . DIRECTORY_SEPARATOR . &#039;index.html&#039;)) {\\n            $project_has_html = true;\\n        }\\n\\n        \\\/\\\/ \\u68c0\\u67e5\\u9879\\u76ee\\u6587\\u4ef6\\u5939\\u5185\\u662f\\u5426\\u6709 PHP \\u6587\\u4ef6\\n        $project_files = scandir($project_path);\\n        foreach ($project_files as $file) {\\n            if (pathinfo($file, PATHINFO_EXTENSION) === &#039;php&#039;) {\\n                $project_has_php = true;\\n                break;\\n            }\\n        }\\n\\n        \\\/\\\/ \\u6839\\u636e\\u662f\\u5426\\u6709 PHP \\u6587\\u4ef6\\u51b3\\u5b9a\\u662f\\u5426\\u663e\\u793a\\u4e0b\\u8f7d\\u6309\\u94ae\\n        if (!$project_has_php) {\\n            $show_download_button = true;\\n        }\\n\\n        \\\/\\\/ \\u53ea\\u8981\\u9879\\u76ee\\u6587\\u4ef6\\u5939\\u5b58\\u5728\\uff0c\\u5c31\\u53ef\\u4ee5\\u663e\\u793a\\u76f4\\u63a5\\u8bbf\\u95ee\\u6309\\u94ae\\n        $show_direct_access_button = true;\\n\\n    }\\n}\\n?&gt;\\n&lt;!DOCTYPE html&gt;\\n&lt;html lang=\\&quot;zh\\&quot;&gt;\\n&lt;head&gt;\\n  &lt;meta charset=\\&quot;UTF-8\\&quot; \\\/&gt;\\n  &lt;meta name=\\&quot;viewport\\&quot; content=\\&quot;width=device-width, initial-scale=1.0\\&quot; \\\/&gt;\\n  &lt;title&gt;\\u6211\\u7684\\u9879\\u76ee\\u5c55\\u793a&lt;\\\/title&gt;\\n  &lt;style&gt;\\n    body {\\n      font-family: &#039;Segoe UI&#039;, Tahoma, Geneva, Verdana, sans-serif;\\n      margin: 0;\\n      padding: 0;\\n      display: flex;\\n      height: 100vh;\\n      overflow: hidden;\\n      background-color: #f0f2f5;\\n      color: #333;\\n    }\\n    .sidebar {\\n      width: 280px;\\n      background-color: #2c3e50;\\n      color: #ecf0f1;\\n      padding: 20px;\\n      overflow-y: auto;\\n      flex-shrink: 0;\\n      box-shadow: 2px 0 8px rgba(0,0,0,0.2);\\n    }\\n    .sidebar h2 {\\n      text-align: center;\\n      margin-top: 0;\\n      font-size: 26px;\\n      color: #1abc9c;\\n      border-bottom: 2px solid #34495e;\\n      padding-bottom: 15px;\\n      margin-bottom: 20px;\\n    }\\n    .sidebar ul {\\n      list-style: none;\\n      padding: 0;\\n      margin: 0;\\n    }\\n    .sidebar li {\\n      margin-bottom: 8px;\\n    }\\n    .sidebar a {\\n      display: block;\\n      padding: 12px 18px;\\n      background-color: #34495e;\\n      color: #ecf0f1;\\n      text-decoration: none;\\n      border-radius: 8px;\\n      transition: background-color 0.2s ease, transform 0.1s ease;\\n      white-space: nowrap;\\n      overflow: hidden;\\n      text-overflow: ellipsis;\\n      font-size: 1.1em;\\n    }\\n    .sidebar a:hover {\\n      background-color: #1abc9c;\\n      transform: translateX(5px);\\n      box-shadow: 0 4px 10px rgba(0,0,0,0.3);\\n    }\\n    .sidebar a.active {\\n      background-color: #1abc9c;\\n      font-weight: bold;\\n      box-shadow: 0 4px 10px rgba(0,0,0,0.3);\\n    }\\n    .main-content {\\n      flex-grow: 1;\\n      display: flex;\\n      flex-direction: column;\\n      padding: 30px;\\n      overflow: hidden;\\n      position: relative;\\n    }\\n    .main-content h1 {\\n      margin-top: 0;\\n      color: #2c3e50;\\n      text-align: center;\\n      margin-bottom: 25px;\\n      font-size: 32px;\\n      font-weight: 600;\\n    }\\n    .preview-area {\\n      flex-grow: 1;\\n      border: 1px solid #ddd;\\n      background-color: #fff;\\n      overflow: hidden;\\n      border-radius: 10px;\\n      box-shadow: 0 4px 15px rgba(0,0,0,0.1);\\n      display: flex;\\n      align-items: center;\\n      justify-content: center;\\n    }\\n    .preview-area iframe {\\n      width: 100%;\\n      height: 100%;\\n      border: none;\\n      border-radius: 10px;\\n    }\\n    .empty-state {\\n        text-align: center;\\n        color: #7f8c8d;\\n        font-size: 1.4em;\\n        padding: 50px;\\n        max-width: 600px;\\n        line-height: 1.6;\\n    }\\n\\n    \\\/* \\u6309\\u94ae\\u5bb9\\u5668 - \\u653e\\u7f6e\\u5728\\u53f3\\u4e0a\\u89d2 *\\\/\\n    .action-buttons-container {\\n      position: absolute;\\n      top: 30px; \\\/* \\u8ddd\\u79bb\\u9876\\u90e8 *\\\/\\n      right: 30px; \\\/* \\u8ddd\\u79bb\\u53f3\\u4fa7 *\\\/\\n      z-index: 100;\\n      display: flex; \\\/* \\u786e\\u4fdd\\u6309\\u94ae\\u6a2a\\u5411\\u6392\\u5217 *\\\/\\n      gap: 15px; \\\/* \\u6309\\u94ae\\u4e4b\\u95f4\\u95f4\\u8ddd *\\\/\\n    }\\n\\n    .action-buttons-container button {\\n      padding: 12px 25px; \\\/* \\u6309\\u94ae\\u5927\\u5c0f\\u9002\\u4e2d *\\\/\\n      color: white;\\n      border: none;\\n      border-radius: 30px;\\n      font-size: 1.1em;\\n      font-weight: 600;\\n      cursor: pointer;\\n      box-shadow: 0 4px 10px rgba(0,0,0,0.2);\\n      transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;\\n      letter-spacing: 0.5px;\\n    }\\n    \\n    \\n    \\\/* \\u5355\\u72ec\\u8bbf\\u95ee\\u6309\\u94ae\\u6837\\u5f0f *\\\/\\n    #direct-access-btn {\\n      background-color: #2ecc71; \\\/* \\u7eff\\u8272 *\\\/\\n    }\\n    #direct-access-btn:hover {\\n      background-color: #27ae60;\\n      transform: translateY(-2px);\\n      box-shadow: 0 6px 12px rgba(0,0,0,0.3);\\n    }\\n    \\n    \\\/* \\u4e0b\\u8f7d\\u6309\\u94ae\\u6837\\u5f0f *\\\/\\n    #download-project-btn {\\n      background-color: #3498db; \\\/* \\u84dd\\u8272 *\\\/\\n    }\\n    #download-project-btn:hover {\\n      background-color: #2980b9;\\n      transform: translateY(-2px);\\n      box-shadow: 0 6px 12px rgba(0,0,0,0.3);\\n    }\\n\\n\\n\\n\\n    \\\/* \\u9488\\u5bf9\\u79fb\\u52a8\\u8bbe\\u5907\\u7684\\u54cd\\u5e94\\u5f0f\\u8bbe\\u8ba1 *\\\/\\n    @media (max-width: 768px) {\\n      body {\\n        flex-direction: column;\\n      }\\n      .sidebar {\\n        width: 100%;\\n        height: 120px;\\n        overflow-x: auto;\\n        overflow-y: hidden;\\n        white-space: nowrap;\\n        padding: 15px;\\n        box-shadow: 0 2px 8px rgba(0,0,0,0.1);\\n      }\\n      .sidebar h2 {\\n        display: none;\\n      }\\n      .sidebar ul {\\n        display: flex;\\n        align-items: center;\\n        height: 100%;\\n        margin: 0;\\n      }\\n      .sidebar li {\\n        flex-shrink: 0;\\n        margin-right: 10px;\\n        margin-bottom: 0;\\n      }\\n      .sidebar a {\\n        padding: 8px 12px;\\n        font-size: 0.9em;\\n      }\\n      .main-content {\\n        flex-grow: 1;\\n        padding: 20px;\\n      }\\n      .main-content h1 {\\n        font-size: 24px;\\n        margin-bottom: 15px;\\n      }\\n      .empty-state {\\n        font-size: 1.1em;\\n        padding: 30px;\\n      }\\n      .action-buttons-container {\\n        top: auto; \\\/* \\u53d6\\u6d88\\u9876\\u90e8\\u5b9a\\u4f4d *\\\/\\n        bottom: 15px; \\\/* \\u79fb\\u52a8\\u5230\\u53f3\\u4e0b\\u89d2 *\\\/\\n        right: 15px;\\n        gap: 10px;\\n      }\\n      .action-buttons-container button {\\n        padding: 10px 20px;\\n        font-size: 0.9em;\\n        border-radius: 25px;\\n        box-shadow: 0 3px 10px rgba(0,0,0,0.2);\\n      }\\n    }\\n  &lt;\\\/style&gt;\\n&lt;\\\/head&gt;\\n&lt;body&gt;\\n  &lt;div class=\\&quot;sidebar\\&quot;&gt;\\n    &lt;h2&gt;\\u6211\\u7684\\u9879\\u76ee&lt;\\\/h2&gt;\\n    &lt;ul&gt;\\n      &lt;?php foreach ($projects_to_display as $project): \\\/\\\/ \\u76f4\\u63a5\\u5faa\\u73af $projects_to_display \\u6570\\u7ec4\\uff0c\\u5b83\\u5df2\\u7ecf\\u6392\\u597d\\u5e8f\\u5e76\\u5305\\u542b\\u663e\\u793a\\u540d\\u79f0 ?&gt;\\n        &lt;?php\\n          \\\/\\\/ \\u786e\\u4fdd folder_name \\u548c display_name \\u5b58\\u5728\\n          $folderName = htmlspecialchars($project[&#039;folder_name&#039;] ?? &#039;&#039;);\\n          $displayName = htmlspecialchars($project[&#039;display_name&#039;] ?? $folderName); \\\/\\\/ \\u5982\\u679c\\u6ca1\\u6709\\u663e\\u793a\\u540d\\u79f0\\uff0c\\u5c31\\u7528\\u6587\\u4ef6\\u5939\\u540d\\n          $isActive = ($folderName === $current_project_folder_name) ? &#039;active&#039; : &#039;&#039;; \\\/\\\/ \\u4f7f\\u7528\\u6b63\\u786e\\u7684\\u53d8\\u91cf\\u540d\\u8fdb\\u884c\\u6bd4\\u8f83\\n        ?&gt;\\n        &lt;li&gt;\\n          &lt;a href=\\&quot;?project=&lt;?= urlencode($folderName) ?&gt;\\&quot; class=\\&quot;&lt;?= $isActive ?&gt;\\&quot;&gt;\\n            &lt;?= $displayName ?&gt;\\n          &lt;\\\/a&gt;\\n        &lt;\\\/li&gt;\\n      &lt;?php endforeach; ?&gt;\\n    &lt;\\\/ul&gt;\\n  &lt;\\\/div&gt;\\n\\n  &lt;div class=\\&quot;main-content\\&quot;&gt;\\n    &lt;h1&gt;\\n      &lt;?php if ($current_project_folder_name): ?&gt;\\n        \\u9879\\u76ee\\u9884\\u89c8\\uff1a&lt;?= htmlspecialchars($current_project_display_name) ?&gt;       &lt;?php else: ?&gt;\\n        \\u6b22\\u8fce\\uff01\\u8bf7\\u4ece\\u5de6\\u4fa7\\u9009\\u62e9\\u4e00\\u4e2a\\u9879\\u76ee\\u5f00\\u59cb\\u9884\\u89c8\\u3002\\n      &lt;?php endif; ?&gt;\\n    &lt;\\\/h1&gt;\\n\\n    &lt;div class=\\&quot;preview-area\\&quot;&gt;\\n      &lt;?php if ($current_project_folder_name): ?&gt;\\n        &lt;?php \\n        $current_project_path = BASE_DIR . DIRECTORY_SEPARATOR . basename($current_project_folder_name);\\n        $project_html_file = $current_project_path . DIRECTORY_SEPARATOR . &#039;index.html&#039;;\\n        if ($project_has_html): \\\/\\\/ \\u68c0\\u67e5\\u662f\\u5426\\u6709 index.html\\n        ?&gt;\\n          &lt;iframe src=\\&quot;.\\\/&lt;?= urlencode(basename($current_project_folder_name)) ?&gt;\\\/index.html\\&quot; frameborder=\\&quot;0\\&quot; allowfullscreen&gt;&lt;\\\/iframe&gt;\\n        &lt;?php else: ?&gt;\\n          &lt;div class=\\&quot;empty-state\\&quot;&gt;\\n            &lt;p&gt;\\u8be5\\u9879\\u76ee **&lt;?= htmlspecialchars($current_project_display_name) ?&gt;** \\u4f3c\\u4e4e\\u6ca1\\u6709 `index.html` \\u6587\\u4ef6\\u53ef\\u4f9b\\u76f4\\u63a5\\u9884\\u89c8\\u3002&lt;\\\/p&gt;\\n            &lt;?php if ($show_download_button): ?&gt;\\n                &lt;p&gt;\\u60a8\\u53ef\\u4ee5\\u70b9\\u51fb\\u53f3\\u4e0a\\u89d2\\u7684\\u201c\\u4e0b\\u8f7d\\u9879\\u76ee\\u201d\\u6309\\u94ae\\u6765\\u67e5\\u770b\\u5176\\u5185\\u5bb9\\u3002&lt;\\\/p&gt;\\n            &lt;?php elseif ($project_has_php): ?&gt;\\n                &lt;p&gt;\\u8be5\\u9879\\u76ee\\u5305\\u542b PHP \\u6587\\u4ef6\\uff0c\\u51fa\\u4e8e\\u5b89\\u5168\\u8003\\u8651\\uff0c\\u4e0d\\u63d0\\u4f9b\\u76f4\\u63a5\\u4e0b\\u8f7d\\u3002&lt;\\\/p&gt;\\n            &lt;?php endif; ?&gt;\\n              &lt;?php if ($show_direct_access_button): ?&gt;\\n                &lt;p&gt;\\u60a8\\u4e5f\\u53ef\\u4ee5\\u70b9\\u51fb\\u53f3\\u4e0a\\u89d2\\u7684\\u201c\\u5355\\u72ec\\u8bbf\\u95ee\\u201d\\u6309\\u94ae\\u76f4\\u63a5\\u6253\\u5f00\\u9879\\u76ee\\u3002&lt;\\\/p&gt;\\n            &lt;?php endif; ?&gt;\\n          &lt;\\\/div&gt;\\n        &lt;?php endif; ?&gt;\\n      &lt;?php else: ?&gt;\\n        &lt;div class=\\&quot;empty-state\\&quot;&gt;\\n          &lt;p&gt;\\u6b22\\u8fce\\u6765\\u5230\\u6211\\u7684\\u9879\\u76ee\\u5c55\\u793a\\u9875\\uff01&lt;\\\/p&gt;\\n          &lt;p&gt;\\u60a8\\u53ef\\u4ee5\\u5728\\u5de6\\u4fa7\\u7684\\u9879\\u76ee\\u5217\\u8868\\u4e2d\\u9009\\u62e9\\u4e00\\u4e2a\\u9879\\u76ee\\u6765\\u67e5\\u770b\\u5176\\u6f14\\u793a\\u6548\\u679c\\u3002&lt;\\\/p&gt;\\n          &lt;p&gt;\\uff08\\u6ce8\\uff1a\\u5305\\u542b PHP \\u6587\\u4ef6\\u7684\\u9879\\u76ee\\u4e0d\\u63d0\\u4f9b\\u4e0b\\u8f7d\\uff09&lt;\\\/p&gt;\\n        &lt;\\\/div&gt;\\n      &lt;?php endif; ?&gt;\\n    &lt;\\\/div&gt;\\n\\n    &lt;?php if ($current_project_folder_name): \\\/\\\/ \\u53ea\\u6709\\u9009\\u4e2d\\u9879\\u76ee\\u65f6\\u624d\\u663e\\u793a\\u6309\\u94ae\\u5bb9\\u5668 ?&gt;\\n\\n    &lt;div class=\\&quot;action-buttons-container\\&quot;&gt;\\n      &lt;?php if ($show_download_button): \\\/\\\/ \\u5148\\u663e\\u793a\\u4e0b\\u8f7d\\u6309\\u94ae ?&gt;\\n        &lt;button id=\\&quot;download-project-btn\\&quot; data-project-name=\\&quot;&lt;?= htmlspecialchars($current_project_folder_name) ?&gt;\\&quot;&gt;\\n          \\u4e0b\\u8f7d\\u9879\\u76ee\\n        &lt;\\\/button&gt;\\n      &lt;?php endif; ?&gt;\\n      &lt;?php if ($show_direct_access_button): \\\/\\\/ \\u518d\\u663e\\u793a\\u5355\\u72ec\\u8bbf\\u95ee\\u6309\\u94ae ?&gt;\\n        &lt;button id=\\&quot;direct-access-btn\\&quot; data-project-name=\\&quot;&lt;?= htmlspecialchars($current_project_folder_name) ?&gt;\\&quot;&gt;\\n          \\u5355\\u72ec\\u8bbf\\u95ee\\n        &lt;\\\/button&gt;\\n      &lt;?php endif; ?&gt;\\n    &lt;\\\/div&gt;\\n\\n\\n    &lt;?php endif; ?&gt;\\n  &lt;\\\/div&gt;\\n\\n  &lt;script&gt;\\n    document.addEventListener(&#039;DOMContentLoaded&#039;, () =&gt; {\\n      const downloadBtn = document.getElementById(&#039;download-project-btn&#039;);\\n      const directAccessBtn = document.getElementById(&#039;direct-access-btn&#039;);\\n\\n      if (downloadBtn) {\\n        downloadBtn.addEventListener(&#039;click&#039;, () =&gt; {\\n          const projectName = downloadBtn.dataset.projectName;\\n          if (projectName) {\\n            window.location.href = `download_project.php?project=${encodeURIComponent(projectName)}`;\\n          }\\n        });\\n      }\\n\\n      if (directAccessBtn) {\\n        directAccessBtn.addEventListener(&#039;click&#039;, () =&gt; {\\n          const projectName = directAccessBtn.dataset.projectName;\\n          if (projectName) {\\n            \\\/\\\/ \\u6784\\u5efa\\u76f4\\u63a5\\u8bbf\\u95ee\\u7684 URL\\uff0c\\u4f8b\\u5982 \\\/tool\\\/game2\\n            const baseUrl = window.location.origin + window.location.pathname.replace(&#039;index.php&#039;, &#039;&#039;);\\n            window.open(`${baseUrl}${encodeURIComponent(projectName)}\\\/`, &#039;_blank&#039;);\\n          }\\n        });\\n      }\\n    });\\n  &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;300px&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<h1 class=\"wp-block-heading\">PHP\u4ee3\u7801\uff08V2.0\uff09<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>\u6539\u8fdb\u767b\u5f55\u754c\u9762<\/em><\/li>\n\n\n\n<li><em>\u5141\u8bb8\u62d6\u62fd\u6392\u5e8f\u5e76\u5f71\u54cd\u524d\u7aef<\/em><\/li>\n<\/ul>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-03ef903a-1' data-attributes='{&quot;cId&quot;:&quot;03ef903a-1&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\nsession_start();\\ndefine(&#039;ADMIN_PASSWORD&#039;, &#039;123456&#039;);\\ndefine(&#039;BASE_DIR&#039;, __DIR__);\\ndefine(&#039;ORDER_FILE&#039;, BASE_DIR . DIRECTORY_SEPARATOR . &#039;projects_order.json&#039;); \\\/\\\/ \\u5b9a\\u4e49\\u6392\\u5e8f\\u6587\\u4ef6\\u8def\\u5f84\\n\\n\\\/\\\/ \\u767b\\u5f55\\u9a8c\\u8bc1 (\\u4e0e\\u4e4b\\u524d\\u76f8\\u540c)\\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    \\\/\\\/ \\u767b\\u5f55\\u754c\\u9762 HTML \\u548c CSS (\\u4e0e\\u4e4b\\u524d\\u76f8\\u540c)\\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\\\/\\\/ \\u9519\\u8bef\\u548c\\u6210\\u529f\\u6d88\\u606f\\u521d\\u59cb\\u5316\\n$error_message = &#039;&#039;;\\n$success_message = &#039;&#039;;\\n\\n\\\/\\\/ \\u7528\\u4e8e\\u5728\\u53d1\\u751f\\u9519\\u8bef\\u65f6\\u4fdd\\u7559\\u8868\\u5355\\u5185\\u5bb9\\n$input_folder = $_POST[&#039;folder&#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\\n\\\/\\\/ \\u4fdd\\u5b58\\u6587\\u4ef6 (\\u4e0e\\u4e4b\\u524d\\u76f8\\u540c)\\nif ($_SERVER[&#039;REQUEST_METHOD&#039;] === &#039;POST&#039; &amp;&amp; isset($_POST[&#039;folder&#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    $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    if (empty($original) &amp;&amp; is_dir($new_path)) {\\n        $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u540d &#039;{$folder}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u8bf7\\u66f4\\u6362\\u540d\\u79f0\\u3002\\&quot;;\\n    } else {\\n        if (!empty($original) &amp;&amp; $folder !== $original &amp;&amp; is_dir($old_path)) {\\n            rename($old_path, $new_path);\\n            \\\/\\\/ \\u5982\\u679c\\u91cd\\u547d\\u540d\\u4e86\\u6587\\u4ef6\\u5939\\uff0c\\u8fd8\\u9700\\u8981\\u66f4\\u65b0 projects_order.json \\u4e2d\\u7684\\u540d\\u79f0\\n            $savedOrder = [];\\n            if (file_exists(ORDER_FILE)) {\\n                $savedOrder = json_decode(file_get_contents(ORDER_FILE), true) ?: [];\\n                $found = false;\\n                foreach ($savedOrder as $key =&gt; $value) {\\n                    if ($value === $original) {\\n                        $savedOrder[$key] = $folder;\\n                        $found = true;\\n                        break;\\n                    }\\n                }\\n                if ($found) {\\n                    file_put_contents(ORDER_FILE, json_encode($savedOrder, JSON_PRETTY_PRINT));\\n                }\\n            }\\n        } elseif (!is_dir($new_path)) {\\n            mkdir($new_path, 0777, true);\\n        }\\n\\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        if (empty($original)) { \\n            foreach ($files_to_process as $filename =&gt; $content) {\\n                $file_path = \\&quot;$new_path\\\/$filename\\&quot;;\\n                if (file_exists($file_path) &amp;&amp; filesize($file_path) &gt; 0 &amp;&amp; !empty($content)) {\\n                    $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u6587\\u4ef6 &#039;{$filename}&#039; \\u5df2\\u5b58\\u5728\\u4e14\\u975e\\u7a7a\\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                if (!empty($content)) {\\n                    file_put_contents($file_path, $content);\\n                } elseif (file_exists($file_path)) {\\n                    unlink($file_path);\\n                }\\n            }\\n            $success_message = \\&quot;\\u2705 \\u9879\\u76ee\\u5df2\\u4fdd\\u5b58\\u4e3a\\uff1a$folder\\&quot;;\\n        }\\n    }\\n}\\n\\n\\\/\\\/ \\u5220\\u9664\\u9879\\u76ee (\\u4e0e\\u4e4b\\u524d\\u76f8\\u540c\\uff0c\\u4f46\\u589e\\u52a0\\u4e86\\u5220\\u9664\\u6392\\u5e8f\\u6587\\u4ef6\\u4e2d\\u5bf9\\u5e94\\u9879\\u76ee\\u7684\\u903b\\u8f91)\\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 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            \\\/\\\/ \\u5220\\u9664 projects_order.json \\u4e2d\\u5bf9\\u5e94\\u7684\\u9879\\u76ee\\n            $savedOrder = [];\\n            if (file_exists(ORDER_FILE)) {\\n                $savedOrder = json_decode(file_get_contents(ORDER_FILE), true) ?: [];\\n                $savedOrder = array_values(array_diff($savedOrder, [$del])); \\\/\\\/ \\u79fb\\u9664\\u88ab\\u5220\\u9664\\u7684\\u9879\\u76ee\\uff0c\\u5e76\\u91cd\\u65b0\\u7d22\\u5f15\\u6570\\u7ec4\\n                file_put_contents(ORDER_FILE, json_encode($savedOrder, JSON_PRETTY_PRINT));\\n            }\\n\\n            header(\\&quot;Location: \\&quot; . $_SERVER[&#039;PHP_SELF&#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\\\/\\\/ \\u7f16\\u8f91\\u9879\\u76ee\\u6216\\u9996\\u6b21\\u52a0\\u8f7d\\u65f6\\u7684\\u6570\\u636e\\u586b\\u5145 (\\u4e0e\\u4e4b\\u524d\\u76f8\\u540c)\\n$edit_mode = false;\\n$edit_folder_name = &#039;&#039;; \\n$html = &#039;&#039;;\\n$css = &#039;&#039;;\\n$js = &#039;&#039;;\\n$php = &#039;&#039;;\\n\\nif (isset($_GET[&#039;edit&#039;])) {\\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    $html = @file_get_contents(\\&quot;$edit_path\\\/index.html\\&quot;);\\n    $css = @file_get_contents(\\&quot;$edit_path\\\/style.css\\&quot;);\\n    $js = @file_get_contents(\\&quot;$edit_path\\\/script.js\\&quot;);\\n    $php = @file_get_contents(\\&quot;$edit_path\\\/index.php\\&quot;); \\n\\n    $input_folder = $edit_folder_name;\\n    $input_html = $html;\\n    $input_css = $css;\\n    $input_js = $js;\\n    $input_php = $php;\\n\\n} else {\\n    if ($_SERVER[&#039;REQUEST_METHOD&#039;] !== &#039;POST&#039; || !empty($error_message)) {\\n        $input_folder = &#039;&#039;;\\n        $input_html = &#039;&#039;;\\n        $input_css = &#039;&#039;;\\n        $input_js = &#039;&#039;;\\n        $input_php = &#039;&#039;;\\n    }\\n}\\n\\n\\\/\\\/ \\u83b7\\u53d6\\u9879\\u76ee\\u5217\\u8868\\u5e76\\u6309\\u4fdd\\u5b58\\u7684\\u987a\\u5e8f\\u6392\\u5e8f\\n$all_dirs = array_filter(glob(BASE_DIR . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\n$available_projects = [];\\nforeach ($all_dirs as $dir) {\\n    $name = basename($dir);\\n    if ($name !== basename(BASE_DIR)) { \\\/\\\/ \\u6392\\u9664\\u5f53\\u524d\\u76ee\\u5f55\\n        $available_projects[] = $name;\\n    }\\n}\\n\\n$saved_order = [];\\nif (file_exists(ORDER_FILE)) {\\n    $saved_order = json_decode(file_get_contents(ORDER_FILE), true);\\n    if (!is_array($saved_order)) { \\\/\\\/ \\u786e\\u4fdd\\u89e3\\u7801\\u6210\\u529f\\u4e14\\u4e3a\\u6570\\u7ec4\\n        $saved_order = [];\\n    }\\n}\\n\\n$projects_ordered = [];\\n$remaining_projects = $available_projects;\\n\\n\\\/\\\/ \\u5148\\u6309\\u4fdd\\u5b58\\u7684\\u987a\\u5e8f\\u6dfb\\u52a0\\u9879\\u76ee\\nforeach ($saved_order as $item) {\\n    if (in_array($item, $available_projects)) {\\n        $projects_ordered[] = $item;\\n        \\\/\\\/ \\u4ece\\u5269\\u4f59\\u9879\\u76ee\\u4e2d\\u79fb\\u9664\\u5df2\\u6392\\u5e8f\\u7684\\n        $remaining_projects = array_diff($remaining_projects, [$item]);\\n    }\\n}\\n\\n\\\/\\\/ \\u5c06\\u65b0\\u6dfb\\u52a0\\u7684\\u6216\\u672a\\u5728\\u6392\\u5e8f\\u6587\\u4ef6\\u4e2d\\u5217\\u51fa\\u7684\\u9879\\u76ee\\u6dfb\\u52a0\\u5230\\u672b\\u5c3e\\uff08\\u6309\\u5b57\\u6bcd\\u987a\\u5e8f\\uff09\\nsort($remaining_projects); \\\/\\\/ \\u5bf9\\u5269\\u4f59\\u9879\\u76ee\\u8fdb\\u884c\\u5b57\\u6bcd\\u6392\\u5e8f\\n$projects = array_merge($projects_ordered, $remaining_projects);\\n\\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;style&gt;\\n    \\\/* Sortable.js \\u62d6\\u62fd\\u6837\\u5f0f *\\\/\\n    .sortable-ghost {\\n        opacity: 0.2;\\n        background: #f0f0f0;\\n        border: 1px dashed #999;\\n    }\\n    body.dark .sortable-ghost {\\n        background: #2a2a2a;\\n        border-color: #666;\\n    }\\n    \\\/* \\u62d6\\u62fd\\u9879\\u76ee\\u65f6\\u7684\\u624b\\u578b\\u5149\\u6807 *\\\/\\n    #project-list li {\\n        cursor: grab;\\n    }\\n    #project-list li:active {\\n        cursor: grabbing;\\n    }\\n\\n    * { box-sizing: border-box; }\\n    html, body {\\n      margin: 0; padding: 0; height: 100%;\\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 {\\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    }\\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    }\\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    .container {\\n      flex: 1;\\n      display: flex;\\n      flex-direction: column;\\n      padding: 20px;\\n      overflow-y: auto; \\n    }\\n    .main {\\n      flex: 1;\\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\\n    \\\/* \\u9009\\u9879\\u5361\\u5bfc\\u822a *\\\/\\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    \\\/* \\u5168\\u9ad8\\u6309\\u94ae\\u7684\\u6837\\u5f0f *\\\/\\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    \\\/* \\u7f16\\u8f91\\u5668\\u5bb9\\u5668 *\\\/\\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    \\\/* \\u5168\\u9ad8\\u6a21\\u5f0f\\u7684\\u6837\\u5f0f *\\\/\\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    \\\/* \\u5168\\u9ad8\\u6a21\\u5f0f\\u4e0b\\u9690\\u85cf\\u4e0d\\u5fc5\\u8981\\u7684\\u5143\\u7d20\\uff0c\\u4f46\\u4fdd\\u7559\\u4fa7\\u8fb9\\u680f *\\\/\\n    .full-height-active .container &gt; *:not(.editor-container.full-height):not(#submit-btn):not(#toggle-dark) {\\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    \\\/* \\u786e\\u4fdd\\u5168\\u9ad8\\u6a21\\u5f0f\\u4e0b\\uff0c\\u5168\\u9ad8\\u6309\\u94ae\\u81ea\\u8eab\\u4ecd\\u7136\\u663e\\u793a *\\\/\\n    .full-height-active .editor-container.full-height #toggle-full-height {\\n        display: block !important;\\n    }\\n\\n\\n    \\\/* \\u6210\\u529f\\u548c\\u9519\\u8bef\\u63d0\\u793a *\\\/\\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    \\\/* \\u65e5\\u591c\\u5207\\u6362\\u6309\\u94ae *\\\/\\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    \\\/* \\u65b0\\u5efa\\u9879\\u76ee\\u6309\\u94ae-\\u5de6\\u4fa7\\u680f\\u5e95\\u90e8 *\\\/\\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    \\\/* \\u4fdd\\u5b58\\u9879\\u76ee\\u6309\\u94ae *\\\/\\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 as $name): \\\/\\\/ \\u6ce8\\u610f\\u8fd9\\u91cc\\u76f4\\u63a5\\u5faa\\u73af $projects\\uff0c\\u56e0\\u4e3a\\u5b83\\u4eec\\u5df2\\u7ecf\\u662f\\u6392\\u5e8f\\u597d\\u7684\\u540d\\u5b57 ?&gt;\\n      &lt;li data-id=\\&quot;&lt;?= htmlspecialchars($name) ?&gt;\\&quot; &lt;?= ($name === $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($name) ?&gt;\\&quot;&gt;\\u270f\\ufe0f&lt;?= htmlspecialchars($name) ?&gt;&lt;\\\/a&gt;\\n        &lt;\\\/span&gt;\\n        &lt;span&gt;\\n          &lt;a href=\\&quot;&lt;?= htmlspecialchars($name) ?&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($name) ?&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;?= $edit_mode ? \\&quot;\\u7f16\\u8f91\\u9879\\u76ee\\uff1a\\&quot;.htmlspecialchars($edit_folder_name) : \\&quot;\\u521b\\u5efa\\u65b0\\u9879\\u76ee\\&quot; ?&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;\\ud83d\\udcc1 \\u6587\\u4ef6\\u5939\\u540d\\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;\\\/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\\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 = {}; \\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; },\\n      scrollbarStyle: \\&quot;native\\&quot;,\\n      autofocus: false\\n    });\\n    editor.setValue(initialContent || &#039;&#039;); \\n    return editor;\\n  }\\n\\n  const initialData = {\\n      folder: &lt;?= json_encode($input_folder) ?&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  document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value = initialData.folder;\\n\\n\\n  document.getElementById(&#039;form&#039;).addEventListener(&#039;submit&#039;, () =&gt; {\\n    Object.values(editors).forEach(editor =&gt; editor.save());\\n  });\\n\\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  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  document.getElementById(&#039;new-project-btn&#039;).addEventListener(&#039;click&#039;, () =&gt; {\\n    history.replaceState(null, &#039;&#039;, location.pathname);\\n    document.querySelector(&#039;form&#039;).reset();\\n    \\n    editors.html.setValue(&#039;&#039;);\\n    editors.css.setValue(&#039;&#039;);\\n    editors.js.setValue(&#039;&#039;);\\n    editors.php.setValue(&#039;&#039;);\\n\\n    document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value = &#039;&#039;;\\n\\n    const origInput = document.querySelector(&#039;input[name=\\&quot;original_folder\\&quot;]&#039;);\\n    if (origInput) origInput.remove();\\n    document.querySelector(&#039;h2&#039;).textContent = \\&quot;\\u521b\\u5efa\\u65b0\\u9879\\u76ee\\&quot;;\\n    tabs.forEach(t =&gt; t.classList.remove(&#039;active&#039;));\\n    tabs[0].classList.add(&#039;active&#039;);\\n    Object.values(tabContents).forEach(tc =&gt; tc.classList.remove(&#039;active&#039;));\\n    tabContents.html.classList.add(&#039;active&#039;);\\n\\n    document.querySelectorAll(&#039;#project-list li&#039;).forEach(item =&gt; item.classList.remove(&#039;active&#039;));\\n\\n    editors.html.focus(); \\n  });\\n\\n  function deleteProject(projectName) {\\n      const password = prompt(`\\u8bf7\\u8f93\\u5165\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\u4ee5\\u5220\\u9664\\u9879\\u76ee\\uff1a[${decodeURIComponent(projectName)}]\\\\n\\\\n\\u6b64\\u64cd\\u4f5c\\u4e0d\\u53ef\\u9006\\uff0c\\u8bf7\\u518d\\u6b21\\u786e\\u8ba4\\uff01`);\\n      if (password !== null) { \\n          const form = document.createElement(&#039;form&#039;);\\n          form.method = &#039;POST&#039;;\\n          form.action = `?delete=${projectName}`;\\n          \\n          const passwordInput = document.createElement(&#039;input&#039;);\\n          passwordInput.type = &#039;hidden&#039;;\\n          passwordInput.name = &#039;admin_password&#039;;\\n          passwordInput.value = password;\\n          form.appendChild(passwordInput);\\n\\n          document.body.appendChild(form);\\n          form.submit();\\n      }\\n  }\\n\\n  const toggleFullHeightButtons = document.querySelectorAll(&#039;#toggle-full-height&#039;);\\n  let currentFullHeightEditor = null; \\n\\n  toggleFullHeightButtons.forEach(button =&gt; {\\n    button.addEventListener(&#039;click&#039;, () =&gt; {\\n      const targetId = button.dataset.target;\\n      const editorContainer = document.getElementById(targetId);\\n\\n      if (editorContainer.classList.contains(&#039;full-height&#039;)) {\\n        editorContainer.classList.remove(&#039;full-height&#039;);\\n        document.body.classList.remove(&#039;full-height-active&#039;); \\n        button.textContent = &#039;\\u5168\\u9ad8&#039;; \\n        currentFullHeightEditor = null;\\n      } else {\\n        if (currentFullHeightEditor) {\\n          currentFullHeightEditor.classList.remove(&#039;full-height&#039;);\\n          const prevButton = document.querySelector(`#toggle-full-height[data-target=\\&quot;${currentFullHeightEditor.id}\\&quot;]`);\\n          if (prevButton) prevButton.textContent = &#039;\\u5168\\u9ad8&#039;;\\n        }\\n        editorContainer.classList.add(&#039;full-height&#039;);\\n        document.body.classList.add(&#039;full-height-active&#039;); \\n        button.textContent = &#039;\\u534a\\u9ad8&#039;; \\n        currentFullHeightEditor = editorContainer; \\n        \\n        tabs.forEach(t =&gt; {\\n            if (t.dataset.tab === targetId) {\\n                t.classList.add(&#039;active&#039;);\\n            } else {\\n                t.classList.remove(&#039;active&#039;);\\n            }\\n        });\\n        \\n        editors[targetId].refresh();\\n        editors[targetId].focus();\\n      }\\n    });\\n  });\\n\\n\\n  if (!&#039;&lt;?= $edit_mode ?&gt;&#039; &amp;&amp; !&#039;&lt;?= !empty($error_message) ?&gt;&#039;) {\\n      editors.html.focus();\\n  }\\n\\n  \\\/\\\/ \\u521d\\u59cb\\u5316 Sortable.js\\n  document.addEventListener(&#039;DOMContentLoaded&#039;, (event) =&gt; {\\n    const projectList = document.getElementById(&#039;project-list&#039;);\\n    if (projectList) {\\n      new Sortable(projectList, {\\n        animation: 150, \\n        ghostClass: &#039;sortable-ghost&#039;, \\n        onEnd: function (evt) {\\n          const itemEl = evt.item;  \\n          const oldIndex = evt.oldIndex; \\n          const newIndex = evt.newIndex; \\n\\n          console.log(`\\u9879\\u76ee \\&quot;${itemEl.dataset.id}\\&quot; \\u4ece\\u7d22\\u5f15 ${oldIndex} \\u79fb\\u52a8\\u5230 ${newIndex}`);\\n\\n          const newOrder = Array.from(projectList.children).map(li =&gt; li.dataset.id);\\n          console.log(&#039;\\u65b0\\u7684\\u9879\\u76ee\\u987a\\u5e8f:&#039;, newOrder);\\n\\n          \\\/\\\/ \\u2728 \\u8fd9\\u662f\\u65b0\\u7684 AJAX \\u8bf7\\u6c42\\uff0c\\u7528\\u4e8e\\u4fdd\\u5b58\\u6392\\u5e8f\\n          fetch(&#039;save_order.php&#039;, {\\n              method: &#039;POST&#039;,\\n              headers: {\\n                  &#039;Content-Type&#039;: &#039;application\\\/json&#039;,\\n              },\\n              body: JSON.stringify({ order: newOrder }),\\n          })\\n          .then(response =&gt; response.json())\\n          .then(data =&gt; {\\n              if (data.success) {\\n                  console.log(&#039;\\u6392\\u5e8f\\u5df2\\u4fdd\\u5b58\\u6210\\u529f\\uff01&#039;);\\n                  \\\/\\\/ \\u53ef\\u4ee5\\u5728\\u8fd9\\u91cc\\u663e\\u793a\\u4e00\\u4e2a\\u6210\\u529f\\u7684\\u6d88\\u606f\\u7ed9\\u7528\\u6237\\n              } else {\\n                  console.error(&#039;\\u6392\\u5e8f\\u4fdd\\u5b58\\u5931\\u8d25\\uff1a&#039;, data.message);\\n                  \\\/\\\/ \\u53ef\\u4ee5\\u5728\\u8fd9\\u91cc\\u663e\\u793a\\u9519\\u8bef\\u6d88\\u606f\\uff0c\\u4f8b\\u5982\\uff1a\\n                  \\\/\\\/ alert(&#039;\\u4fdd\\u5b58\\u6392\\u5e8f\\u5931\\u8d25: &#039; + data.message);\\n                  \\\/\\\/ \\u8003\\u8651\\u662f\\u5426\\u9700\\u8981\\u56de\\u6eda\\u5230\\u65e7\\u7684\\u987a\\u5e8f\\n              }\\n          })\\n          .catch(error =&gt; {\\n              console.error(&#039;\\u7f51\\u7edc\\u6216\\u670d\\u52a1\\u5668\\u9519\\u8bef\\uff1a&#039;, error);\\n              \\\/\\\/ alert(&#039;\\u7f51\\u7edc\\u6216\\u670d\\u52a1\\u5668\\u9519\\u8bef\\uff0c\\u65e0\\u6cd5\\u4fdd\\u5b58\\u6392\\u5e8f\\u3002&#039;);\\n          });\\n        }\\n      });\\n    } else {\\n      console.error(\\&quot;Sortable.js \\u65e0\\u6cd5\\u627e\\u5230\\u5143\\u7d20 #project-list\\&quot;);\\n    }\\n  });\\n\\n&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;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;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<h1 class=\"wp-block-heading\">PHP\u4ee3\u7801(V1.0)<\/h1>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-2b26f394-5' data-attributes='{&quot;cId&quot;:&quot;2b26f394-5&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\nsession_start();\\ndefine(&#039;ADMIN_PASSWORD&#039;, &#039;123456&#039;);\\ndefine(&#039;BASE_DIR&#039;, __DIR__);\\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    echo &#039;&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;head&gt;&lt;meta charset=\\&quot;UTF-8\\&quot;&gt;&lt;title&gt;\\u767b\\u5f55&lt;\\\/title&gt;&lt;\\\/head&gt;&lt;body&gt;&#039;;\\n    if (isset($login_error)) echo \\&quot;&lt;p style=&#039;color:red;&#039;&gt;$login_error&lt;\\\/p&gt;\\&quot;;\\n    echo &#039;&lt;form method=\\&quot;post\\&quot;&gt;\\n        &lt;input type=\\&quot;password\\&quot; name=\\&quot;password\\&quot; placeholder=\\&quot;\\u8bf7\\u8f93\\u5165\\u5bc6\\u7801\\&quot; required&gt;\\n        &lt;button type=\\&quot;submit\\&quot;&gt;\\u8fdb\\u5165&lt;\\\/button&gt;\\n    &lt;\\\/form&gt;&lt;\\\/body&gt;&lt;\\\/html&gt;&#039;;\\n    exit;\\n}\\n\\n\\\/\\\/ \\u9519\\u8bef\\u548c\\u6210\\u529f\\u6d88\\u606f\\u521d\\u59cb\\u5316\\n$error_message = &#039;&#039;;\\n$success_message = &#039;&#039;;\\n\\n\\\/\\\/ \\u7528\\u4e8e\\u5728\\u53d1\\u751f\\u9519\\u8bef\\u65f6\\u4fdd\\u7559\\u8868\\u5355\\u5185\\u5bb9\\n$input_folder = $_POST[&#039;folder&#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\\n\\\/\\\/ \\u4fdd\\u5b58\\u6587\\u4ef6\\nif ($_SERVER[&#039;REQUEST_METHOD&#039;] === &#039;POST&#039; &amp;&amp; isset($_POST[&#039;folder&#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    $original = $_POST[&#039;original_folder&#039;] ?? &#039;&#039;; \\\/\\\/ \\u9ed8\\u8ba4\\u4e3a\\u7a7a\\u5b57\\u7b26\\u4e32\\uff0c\\u8868\\u793a\\u65b0\\u5efa\\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    \\\/\\\/ \\u68c0\\u67e5\\u662f\\u5426\\u662f\\u65b0\\u5efa\\u9879\\u76ee\\u4e14\\u6587\\u4ef6\\u5939\\u5df2\\u5b58\\u5728\\n    \\\/\\\/ \\u53ea\\u6709\\u5f53 original \\u4e3a\\u7a7a\\uff08\\u8868\\u793a\\u65b0\\u5efa\\uff09\\u4e14\\u65b0\\u6587\\u4ef6\\u5939\\u5df2\\u5b58\\u5728\\u65f6\\u624d\\u62a5\\u9519\\n    if (empty($original) &amp;&amp; is_dir($new_path)) {\\n        $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u9879\\u76ee\\u540d &#039;{$folder}&#039; \\u5df2\\u5b58\\u5728\\uff0c\\u8bf7\\u66f4\\u6362\\u540d\\u79f0\\u3002\\&quot;;\\n    } else {\\n        \\\/\\\/ \\u5982\\u679c\\u662f\\u7f16\\u8f91\\u6a21\\u5f0f\\u4e14\\u6587\\u4ef6\\u5939\\u540d\\u6539\\u53d8\\uff0c\\u5219\\u91cd\\u547d\\u540d\\n        \\\/\\\/ \\u5982\\u679c\\u662f\\u65b0\\u5efa\\u9879\\u76ee\\uff0c\\u5148\\u786e\\u4fdd\\u76ee\\u5f55\\u5b58\\u5728\\n        if (!empty($original) &amp;&amp; $folder !== $original &amp;&amp; is_dir($old_path)) {\\n            rename($old_path, $new_path);\\n        } elseif (!is_dir($new_path)) {\\n            mkdir($new_path, 0777, true);\\n        }\\n\\n        \\\/\\\/ \\u5b9a\\u4e49\\u8981\\u5904\\u7406\\u7684\\u6587\\u4ef6\\u53ca\\u5bf9\\u5e94\\u7684\\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;] \\\/\\\/ PHP\\u6587\\u4ef6\\u540d\\u9ed8\\u8ba4\\u4e3a index.php\\n        ];\\n\\n        \\\/\\\/ \\u53ea\\u6709\\u5728\\u65b0\\u5efa\\u9879\\u76ee\\u65f6\\u624d\\u68c0\\u67e5\\u6587\\u4ef6\\u51b2\\u7a81\\n        $conflict_detected = false;\\n        if (empty($original)) { \\\/\\\/ \\u4ec5\\u5728\\u65b0\\u9879\\u76ee\\u521b\\u5efa\\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                \\\/\\\/ \\u4ec5\\u5f53\\u6587\\u4ef6\\u5b58\\u5728\\u4e14\\u5185\\u5bb9\\u4e0d\\u4e3a\\u7a7a\\u65f6\\u624d\\u89c6\\u4e3a\\u51b2\\u7a81\\n                if (file_exists($file_path) &amp;&amp; filesize($file_path) &gt; 0 &amp;&amp; !empty($content)) {\\n                    $error_message = \\&quot;\\u274c \\u9519\\u8bef\\uff1a\\u6587\\u4ef6 &#039;{$filename}&#039; \\u5df2\\u5b58\\u5728\\u4e14\\u975e\\u7a7a\\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                if (!empty($content)) {\\n                    file_put_contents($file_path, $content);\\n                } elseif (file_exists($file_path)) {\\n                    \\\/\\\/ \\u5982\\u679c\\u5185\\u5bb9\\u4e3a\\u7a7a\\u4e14\\u6587\\u4ef6\\u5b58\\u5728\\uff0c\\u5219\\u5220\\u9664\\u8be5\\u6587\\u4ef6\\n                    unlink($file_path);\\n                }\\n            }\\n            $success_message = \\&quot;\\u2705 \\u9879\\u76ee\\u5df2\\u4fdd\\u5b58\\u4e3a\\uff1a$folder\\&quot;;\\n        }\\n    }\\n}\\n\\n\\\/\\\/ \\u5220\\u9664\\u9879\\u76ee\\nif (isset($_GET[&#039;delete&#039;])) {\\n    \\\/\\\/ \\u5904\\u7406 JavaScript \\u4f20\\u9012\\u8fc7\\u6765\\u7684\\u5bc6\\u7801\\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            header(\\&quot;Location: \\&quot; . $_SERVER[&#039;PHP_SELF&#039;]);\\n            exit;\\n        }\\n    } else {\\n        \\\/\\\/ \\u5bc6\\u7801\\u9519\\u8bef\\uff0c\\u91cd\\u5b9a\\u5411\\u56de\\u9875\\u9762\\u5e76\\u663e\\u793a\\u9519\\u8bef\\n        $error_message = \\&quot;\\u274c \\u5220\\u9664\\u5931\\u8d25\\uff1a\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\u9519\\u8bef\\uff01\\&quot;;\\n        \\\/\\\/ \\u4e3a\\u907f\\u514d\\u901a\\u8fc7GET\\u8bf7\\u6c42\\u76f4\\u63a5\\u663e\\u793a\\u5bc6\\u7801\\u9519\\u8bef\\uff0c\\u8fd9\\u91cc\\u91c7\\u7528session flash message\\u6216URL\\u53c2\\u6570\\u4f20\\u9012\\n        \\\/\\\/ \\u7b80\\u5316\\u5904\\u7406\\uff0c\\u76f4\\u63a5\\u8bbe\\u7f6e\\u9519\\u8bef\\u4fe1\\u606f\\uff0c\\u9875\\u9762\\u5237\\u65b0\\u540e\\u4f1a\\u6d88\\u5931\\n    }\\n}\\n\\n\\\/\\\/ \\u7f16\\u8f91\\u9879\\u76ee\\u6216\\u9996\\u6b21\\u52a0\\u8f7d\\u65f6\\u7684\\u6570\\u636e\\u586b\\u5145\\n$edit_mode = false;\\n$edit_folder_name = &#039;&#039;; \\\/\\\/ Initialize to empty string\\n$html = &#039;&#039;;\\n$css = &#039;&#039;;\\n$js = &#039;&#039;;\\n$php = &#039;&#039;;\\n\\nif (isset($_GET[&#039;edit&#039;])) {\\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    $html = @file_get_contents(\\&quot;$edit_path\\\/index.html\\&quot;);\\n    $css = @file_get_contents(\\&quot;$edit_path\\\/style.css\\&quot;);\\n    $js = @file_get_contents(\\&quot;$edit_path\\\/script.js\\&quot;);\\n    $php = @file_get_contents(\\&quot;$edit_path\\\/index.php\\&quot;); \\\/\\\/ PHP\\u6587\\u4ef6\\u540d\\u9ed8\\u8ba4\\u4e3a index.php\\n\\n    \\\/\\\/ \\u5c06\\u7f16\\u8f91\\u6a21\\u5f0f\\u4e0b\\u7684\\u5185\\u5bb9\\u8d4b\\u503c\\u7ed9 input_variables\\uff0c\\u4ee5\\u4fbf\\u5728\\u53d1\\u751f\\u9519\\u8bef\\u65f6\\u4e5f\\u80fd\\u4fdd\\u7559\\n    $input_folder = $edit_folder_name;\\n    $input_html = $html;\\n    $input_css = $css;\\n    $input_js = $js;\\n    $input_php = $php;\\n\\n} else {\\n    \\\/\\\/ \\u786e\\u4fdd\\u5728\\u65b0\\u5efa\\u9879\\u76ee\\u4e14\\u672a\\u63d0\\u4ea4\\u6570\\u636e\\u65f6\\uff0c\\u8f93\\u5165\\u6846\\u662f\\u7a7a\\u7684\\n    if ($_SERVER[&#039;REQUEST_METHOD&#039;] !== &#039;POST&#039; || !empty($error_message)) {\\n        $input_folder = &#039;&#039;;\\n        $input_html = &#039;&#039;;\\n        $input_css = &#039;&#039;;\\n        $input_js = &#039;&#039;;\\n        $input_php = &#039;&#039;;\\n    }\\n}\\n\\n$projects = array_filter(glob(BASE_DIR . &#039;\\\/*&#039;), &#039;is_dir&#039;);\\n\\\/\\\/ Remove current directory from the list if it&#039;s considered a project\\n$projects = array_filter($projects, function($dir) {\\n    return basename($dir) !== basename(BASE_DIR);\\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;style&gt;\\n    * { box-sizing: border-box; }\\n    html, body {\\n      margin: 0; padding: 0; height: 100%;\\n      overflow: hidden; \\\/* \\u7981\\u6b62\\u9875\\u9762\\u6eda\\u52a8 *\\\/\\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; \\\/* Needed for absolute positioning of new project button *\\\/\\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; \\\/* Allow list to take available space *\\\/\\n      margin-bottom: 70px; \\\/* Space for the new project button *\\\/\\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    }\\n    .sidebar li.active a {\\n      color: white !important; \\\/* Highlight active project text *\\\/\\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    .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; \\\/* Make form fill available space *\\\/\\n      display: flex;\\n      flex-direction: column;\\n      overflow: hidden; \\\/* This will make sure form itself doesn&#039;t cause overflow *\\\/\\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; \\\/* Default background *\\\/\\n      border: 1px solid #ccc;\\n      color: #000;\\n    }\\n    body.dark input[type=\\&quot;text\\&quot;] {\\n      background: #333; \\\/* Dark mode background *\\\/\\n      border-color: #555;\\n      color: #ddd;\\n    }\\n\\n\\n    \\\/* \\u9009\\u9879\\u5361\\u5bfc\\u822a *\\\/\\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; \\\/* \\u4f7f\\u6309\\u94ae\\u548c\\u5168\\u9ad8\\u6309\\u94ae\\u5de6\\u53f3\\u5bf9\\u9f50 *\\\/\\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    \\\/* \\u5168\\u9ad8\\u6309\\u94ae\\u7684\\u6837\\u5f0f *\\\/\\n    #toggle-full-height {\\n        padding: 4px 8px; \\\/* \\u8c03\\u6574\\u5927\\u5c0f *\\\/\\n        border-radius: 4px;\\n        background: #f0f0f0; \\\/* \\u4e0e\\u80cc\\u666f\\u878d\\u5408 *\\\/\\n        color: #666;\\n        border: 1px solid #ccc;\\n        font-size: 12px; \\\/* \\u5b57\\u4f53\\u5c0f\\u4e00\\u70b9 *\\\/\\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    \\\/* \\u7f16\\u8f91\\u5668\\u5bb9\\u5668 *\\\/\\n    .editor-container {\\n      flex: 1; \\\/* \\u786e\\u4fdd\\u5bb9\\u5668\\u586b\\u5145\\u53ef\\u7528\\u7a7a\\u95f4 *\\\/\\n      display: none;\\n      flex-direction: column;\\n      min-height: 0; \\\/* \\u5141\\u8bb8 flex item \\u7f29\\u5c0f *\\\/\\n      transition: height 0.3s ease-in-out; \\\/* \\u4e3a\\u5168\\u9ad8\\u5207\\u6362\\u6dfb\\u52a0\\u52a8\\u753b *\\\/\\n    }\\n    .editor-container.active {\\n      display: flex;\\n    }\\n    .CodeMirror {\\n      height: 100%; \\\/* \\u786e\\u4fdd CodeMirror \\u5b9e\\u4f8b\\u586b\\u5145\\u5176\\u5bb9\\u5668\\u7684\\u9ad8\\u5ea6 *\\\/\\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    \\\/* \\u5f3a\\u5236 CodeMirror \\u7684\\u5782\\u76f4\\u6eda\\u52a8\\u6761\\u5728\\u5185\\u5bb9\\u6ea2\\u51fa\\u65f6\\u663e\\u793a\\uff0c\\u4e14\\u6eda\\u8f6e\\u6ed1\\u52a8\\u6709\\u6548 *\\\/\\n    .CodeMirror-scroll {\\n      overflow-x: hidden !important; \\\/* \\u7ee7\\u7eed\\u9690\\u85cf\\u6c34\\u5e73\\u6eda\\u52a8\\u6761 *\\\/\\n      overflow-y: scroll !important; \\\/* \\u5f3a\\u5236\\u663e\\u793a\\u5782\\u76f4\\u6eda\\u52a8\\u6761 *\\\/\\n      margin-right: -17px; \\\/* \\u8865\\u507f\\u6eda\\u52a8\\u6761\\u5bbd\\u5ea6\\uff0c\\u907f\\u514d\\u5185\\u5bb9\\u88ab\\u6324\\u538b *\\\/\\n      padding-right: 17px; \\\/* \\u589e\\u52a0\\u5185\\u8fb9\\u8ddd\\u4ee5\\u5bb9\\u7eb3\\u6eda\\u52a8\\u6761\\uff0c\\u4f7f\\u5176\\u4e0d\\u906e\\u6321\\u5185\\u5bb9 *\\\/\\n    }\\n\\n    \\\/* \\u5168\\u9ad8\\u6a21\\u5f0f\\u7684\\u6837\\u5f0f *\\\/\\n    .editor-container.full-height {\\n        position: fixed;\\n        top: 0;\\n        left: 220px; \\\/* sidebar width *\\\/\\n        right: 0;\\n        bottom: 0;\\n        z-index: 999;\\n        background: #f0f0f0; \\\/* \\u80cc\\u666f\\u8272\\u4e0ebody\\u4fdd\\u6301\\u4e00\\u81f4 *\\\/\\n        padding: 20px; \\\/* \\u4fdd\\u6301\\u4e0econtainer\\u7684padding\\u4e00\\u81f4 *\\\/\\n        display: flex !important; \\\/* \\u786e\\u4fdd\\u5168\\u9ad8\\u65f6\\u663e\\u793a *\\\/\\n        width: auto; \\\/* \\u5141\\u8bb8\\u81ea\\u52a8\\u8ba1\\u7b97\\u5bbd\\u5ea6 *\\\/\\n    }\\n    body.dark .editor-container.full-height {\\n        background: #1e1e1e;\\n    }\\n    \\\/* \\u5168\\u9ad8\\u6a21\\u5f0f\\u4e0b\\u9690\\u85cf\\u4e0d\\u5fc5\\u8981\\u7684\\u5143\\u7d20\\uff0c\\u4f46\\u4fdd\\u7559\\u4fa7\\u8fb9\\u680f *\\\/\\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    \\\/* .full-height-active #submit-btn,  \\u4e0d\\u9690\\u85cf\\u4fdd\\u5b58\\u6309\\u94ae *\\\/\\n    .full-height-active #toggle-dark {\\n        display: none !important;\\n    }\\n    .full-height-active .editor-container.full-height .btn-bar {\\n        position: absolute;\\n        top: 20px;\\n        left: 20px; \\\/* \\u4fdd\\u6301\\u5728\\u5de6\\u4fa7 *\\\/\\n        right: 20px;\\n        background: transparent;\\n        z-index: 1000;\\n        padding: 0;\\n        margin: 0;\\n        justify-content: space-between; \\\/* \\u786e\\u4fdd\\u5de6\\u53f3\\u4e24\\u8fb9\\u5bf9\\u9f50 *\\\/\\n    }\\n    .full-height-active .editor-container.full-height .CodeMirror {\\n        margin-top: 40px; \\\/* \\u4e3a\\u9876\\u90e8\\u7684\\u6309\\u94ae\\u817e\\u51fa\\u7a7a\\u95f4 *\\\/\\n    }\\n    \\\/* \\u786e\\u4fdd\\u5168\\u9ad8\\u6a21\\u5f0f\\u4e0b\\uff0c\\u5168\\u9ad8\\u6309\\u94ae\\u81ea\\u8eab\\u4ecd\\u7136\\u663e\\u793a *\\\/\\n    .full-height-active .editor-container.full-height #toggle-full-height {\\n        display: block !important;\\n    }\\n\\n\\n    \\\/* \\u6210\\u529f\\u548c\\u9519\\u8bef\\u63d0\\u793a *\\\/\\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    \\\/* \\u65e5\\u591c\\u5207\\u6362\\u6309\\u94ae *\\\/\\n    #toggle-dark {\\n      position: fixed;\\n      top: 10px;\\n      right: 10px;\\n      padding: 8px 16px;\\n      background: rgba(0,0,0,0.6); \\\/* \\u80cc\\u666f\\u66f4\\u9ed1 *\\\/\\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); \\\/* \\u60ac\\u505c\\u65f6\\u66f4\\u9ed1 *\\\/\\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    \\\/* \\u65b0\\u5efa\\u9879\\u76ee\\u6309\\u94ae-\\u5de6\\u4fa7\\u680f\\u5e95\\u90e8 *\\\/\\n    #new-project-btn {\\n      position: absolute;\\n      bottom: 20px;\\n      left: 20px;\\n      background: rgba(51, 51, 51, 0.8); \\\/* \\u914d\\u5408\\u4fa7\\u8fb9\\u680f\\u7684\\u6df1\\u8272\\u80cc\\u666f\\uff0c\\u589e\\u52a0\\u900f\\u660e\\u5ea6 *\\\/\\n      color: #ddd;\\n      border: 1px solid rgba(68, 68, 68, 0.8); \\\/* \\u914d\\u5408\\u8fb9\\u6846\\uff0c\\u589e\\u52a0\\u900f\\u660e\\u5ea6 *\\\/\\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); \\\/* \\u60ac\\u505c\\u65f6\\u7a0d\\u6df1 *\\\/\\n      border-color: rgba(85, 85, 85, 0.9);\\n    }\\n\\n    \\\/* \\u4fdd\\u5b58\\u9879\\u76ee\\u6309\\u94ae - \\u771f\\u6b63\\u7684\\u900f\\u660e\\u6548\\u679c\\uff0c\\u65e0\\u53d1\\u767d *\\\/\\n    #submit-btn {\\n      position: fixed;\\n      bottom: 25px; \\\/* \\u5411\\u4e0a\\u79fb\\u52a8\\u4e00\\u70b9\\u70b9 *\\\/\\n      right: 55px; \\\/* \\u518d\\u5411\\u5de6\\u79fb\\u52a8\\u4e00\\u70b9\\u70b9 *\\\/\\n      padding: 15px 25px;\\n      background: rgba(33,150,243,0.7); \\\/* \\u84dd\\u8272\\uff0c\\u4f7f\\u7528\\u7b2c\\u4e00\\u7248\\u7684\\u80cc\\u666f\\u989c\\u8272\\u900f\\u660e\\u5ea6 *\\\/\\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; \\\/* \\u79fb\\u9664\\u6a21\\u7cca\\u6548\\u679c\\uff0c\\u907f\\u514d\\u53d1\\u865a *\\\/\\n      box-shadow: 0 4px 8px rgba(0,0,0,0.2);\\n      text-shadow: 0 1px 2px rgba(0,0,0,0.3); \\\/* \\u4e3a\\u6587\\u5b57\\u589e\\u52a0\\u4e00\\u70b9\\u9634\\u5f71\\uff0c\\u4f7f\\u5176\\u66f4\\u6e05\\u6670 *\\\/\\n    }\\n    #submit-btn:hover {\\n      background: rgba(11,125,218,0.9); \\\/* \\u60ac\\u505c\\u65f6\\u989c\\u8272\\u66f4\\u6df1\\uff0c\\u900f\\u660e\\u5ea6\\u964d\\u4f4e *\\\/\\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 as $dir): $name = basename($dir); ?&gt;\\n      &lt;li &lt;?= ($name === $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($name) ?&gt;\\&quot;&gt;\\u270f\\ufe0f&lt;?= htmlspecialchars($name) ?&gt;&lt;\\\/a&gt;\\n        &lt;\\\/span&gt;\\n        &lt;span&gt;\\n          &lt;a href=\\&quot;&lt;?= htmlspecialchars($name) ?&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($name) ?&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;?= $edit_mode ? \\&quot;\\u7f16\\u8f91\\u9879\\u76ee\\uff1a\\&quot;.htmlspecialchars($edit_folder_name) : \\&quot;\\u521b\\u5efa\\u65b0\\u9879\\u76ee\\&quot; ?&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;\\ud83d\\udcc1 \\u6587\\u4ef6\\u5939\\u540d\\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;\\\/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; &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; &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\\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 = {}; \\\/\\\/ \\u5b9a\\u4e49\\u5728\\u5168\\u5c40\\u4f5c\\u7528\\u57df\\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(textareaId, mode, initialContent) {\\n    const editor = CodeMirror.fromTextArea(document.querySelector(`#${textareaId} textarea`), {\\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; },\\n      scrollbarStyle: \\&quot;native\\&quot;,\\n      autofocus: false\\n    });\\n    \\\/\\\/ \\u8bbe\\u7f6e\\u521d\\u59cb\\u5185\\u5bb9\\uff0c\\u8fd9\\u4f1a\\u5728 CodeMirror \\u521d\\u59cb\\u5316\\u540e\\u7acb\\u5373\\u586b\\u5145\\n    editor.setValue(initialContent || &#039;&#039;); \\\/\\\/ \\u786e\\u4fdd\\u7a7a\\u5185\\u5bb9\\u4e0d\\u4f1a\\u5bfc\\u81f4 undefined\\n    return editor;\\n  }\\n\\n  \\\/\\\/ \\u4ece PHP \\u53d8\\u91cf\\u83b7\\u53d6\\u521d\\u59cb\\u5185\\u5bb9\\uff0c\\u7528\\u4e8e\\u5728\\u9519\\u8bef\\u65f6\\u4fdd\\u7559\\n  const initialData = {\\n      folder: &lt;?= json_encode($input_folder) ?&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(&#039;html&#039;, &#039;htmlmixed&#039;, initialData.html);\\n  editors.css = initEditor(&#039;css&#039;, &#039;css&#039;, initialData.css);\\n  editors.js = initEditor(&#039;js&#039;, &#039;javascript&#039;, initialData.js);\\n  editors.php = initEditor(&#039;php&#039;, &#039;application\\\/x-httpd-php&#039;, initialData.php);\\n\\n  \\\/\\\/ \\u5728 CodeMirror \\u5b9e\\u4f8b\\u521d\\u59cb\\u5316\\u540e\\u518d\\u8bbe\\u7f6e\\u6587\\u4ef6\\u5939\\u540d\\n  document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value = initialData.folder;\\n\\n\\n  \\\/\\\/ \\u4fdd\\u5b58\\u5185\\u5bb9\\u5230textarea\\u518d\\u63d0\\u4ea4\\u8868\\u5355\\n  document.getElementById(&#039;form&#039;).addEventListener(&#039;submit&#039;, () =&gt; {\\n    Object.values(editors).forEach(editor =&gt; editor.save());\\n  });\\n\\n  \\\/\\\/ \\u6ce8\\u91ca\\u6309\\u94ae\\u7ed1\\u5b9a\\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  \\\/\\\/ \\u65e5\\u591c\\u95f4\\u6a21\\u5f0f\\u5f00\\u5173\\n  const toggleBtn = document.getElementById(&#039;toggle-dark&#039;);\\n  let darkMode = localStorage.getItem(&#039;darkMode&#039;) === &#039;true&#039;; \\\/\\\/ \\u4ece\\u672c\\u5730\\u5b58\\u50a8\\u83b7\\u53d6\\u504f\\u597d\\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); \\\/\\\/ \\u9875\\u9762\\u52a0\\u8f7d\\u65f6\\u5e94\\u7528\\u6a21\\u5f0f\\n\\n  toggleBtn.addEventListener(&#039;click&#039;, () =&gt; {\\n    darkMode = !darkMode;\\n    applyDarkMode(darkMode);\\n    localStorage.setItem(&#039;darkMode&#039;, darkMode); \\\/\\\/ \\u4fdd\\u5b58\\u504f\\u597d\\u8bbe\\u7f6e\\n  });\\n\\n  \\\/\\\/ \\u65b0\\u5efa\\u9879\\u76ee\\u6309\\u94ae\\u4e8b\\u4ef6\\n  document.getElementById(&#039;new-project-btn&#039;).addEventListener(&#039;click&#039;, () =&gt; {\\n    \\\/\\\/ \\u6e05\\u9664\\u7f16\\u8f91\\u72b6\\u6001\\u548c\\u8868\\u5355\\n    history.replaceState(null, &#039;&#039;, location.pathname);\\n    document.querySelector(&#039;form&#039;).reset();\\n    \\n    \\\/\\\/ \\u6e05\\u7a7a\\u7f16\\u8f91\\u5668\\u5185\\u5bb9\\n    editors.html.setValue(&#039;&#039;);\\n    editors.css.setValue(&#039;&#039;);\\n    editors.js.setValue(&#039;&#039;);\\n    editors.php.setValue(&#039;&#039;);\\n\\n    \\\/\\\/ \\u6e05\\u7a7a\\u6587\\u4ef6\\u5939\\u540d\\u8f93\\u5165\\u6846\\n    document.querySelector(&#039;input[name=\\&quot;folder\\&quot;]&#039;).value = &#039;&#039;;\\n\\n    \\\/\\\/ \\u79fb\\u9664\\u9690\\u85cf\\u7684 original_folder input\\n    const origInput = document.querySelector(&#039;input[name=\\&quot;original_folder\\&quot;]&#039;);\\n    if (origInput) origInput.remove();\\n    \\\/\\\/ \\u66f4\\u65b0\\u6807\\u9898\\n    document.querySelector(&#039;h2&#039;).textContent = \\&quot;\\u521b\\u5efa\\u65b0\\u9879\\u76ee\\&quot;;\\n    \\\/\\\/ \\u5207\\u6362\\u5230 HTML \\u6807\\u7b7e\\u9875\\n    tabs.forEach(t =&gt; t.classList.remove(&#039;active&#039;));\\n    tabs[0].classList.add(&#039;active&#039;);\\n    Object.values(tabContents).forEach(tc =&gt; tc.classList.remove(&#039;active&#039;));\\n    tabContents.html.classList.add(&#039;active&#039;);\\n\\n    \\\/\\\/ \\u79fb\\u9664\\u6240\\u6709\\u9879\\u76ee\\u5217\\u8868\\u9879\\u7684\\u9ad8\\u4eae\\n    document.querySelectorAll(&#039;#project-list li&#039;).forEach(item =&gt; item.classList.remove(&#039;active&#039;));\\n\\n    editors.html.focus(); \\\/\\\/ \\u805a\\u7126\\u5230 HTML \\u7f16\\u8f91\\u5668\\n  });\\n\\n  \\\/\\\/ \\u5220\\u9664\\u9879\\u76ee\\u529f\\u80fd\\uff1a\\u5e26\\u5bc6\\u7801\\u786e\\u8ba4\\n  function deleteProject(projectName) {\\n      const password = prompt(`\\u8bf7\\u8f93\\u5165\\u7ba1\\u7406\\u5458\\u5bc6\\u7801\\u4ee5\\u5220\\u9664\\u9879\\u76ee\\uff1a[${decodeURIComponent(projectName)}]\\\\n\\\\n\\u6b64\\u64cd\\u4f5c\\u4e0d\\u53ef\\u9006\\uff0c\\u8bf7\\u518d\\u6b21\\u786e\\u8ba4\\uff01`);\\n      if (password !== null) { \\\/\\\/ \\u7528\\u6237\\u6ca1\\u6709\\u70b9\\u51fb\\u53d6\\u6d88\\n          const form = document.createElement(&#039;form&#039;);\\n          form.method = &#039;POST&#039;;\\n          form.action = `?delete=${projectName}`;\\n          \\n          const passwordInput = document.createElement(&#039;input&#039;);\\n          passwordInput.type = &#039;hidden&#039;;\\n          passwordInput.name = &#039;admin_password&#039;;\\n          passwordInput.value = password;\\n          form.appendChild(passwordInput);\\n\\n          document.body.appendChild(form);\\n          form.submit();\\n      }\\n  }\\n\\n  \\\/\\\/ \\u5168\\u9ad8\\u6a21\\u5f0f\\u903b\\u8f91\\n  const toggleFullHeightButtons = document.querySelectorAll(&#039;#toggle-full-height&#039;);\\n  let currentFullHeightEditor = null; \\\/\\\/ \\u7528\\u4e8e\\u8ddf\\u8e2a\\u5f53\\u524d\\u662f\\u5426\\u5904\\u4e8e\\u5168\\u9ad8\\u6a21\\u5f0f\\u7684\\u7f16\\u8f91\\u5668\\n\\n  toggleFullHeightButtons.forEach(button =&gt; {\\n    button.addEventListener(&#039;click&#039;, () =&gt; {\\n      const targetId = button.dataset.target;\\n      const editorContainer = document.getElementById(targetId);\\n\\n      if (editorContainer.classList.contains(&#039;full-height&#039;)) {\\n        \\\/\\\/ \\u5982\\u679c\\u5f53\\u524d\\u7f16\\u8f91\\u5668\\u5df2\\u7ecf\\u5168\\u9ad8\\uff0c\\u5219\\u9000\\u51fa\\u5168\\u9ad8\\u6a21\\u5f0f\\n        editorContainer.classList.remove(&#039;full-height&#039;);\\n        document.body.classList.remove(&#039;full-height-active&#039;); \\\/\\\/ \\u79fb\\u9664body\\u4e0a\\u7684\\u5168\\u9ad8\\u6807\\u8bb0\\n        button.textContent = &#039;\\u5168\\u9ad8&#039;; \\\/\\\/ \\u6309\\u94ae\\u6587\\u672c\\u6539\\u56de\\u201c\\u5168\\u9ad8\\u201d\\n        currentFullHeightEditor = null;\\n      } else {\\n        \\\/\\\/ \\u5426\\u5219\\uff0c\\u8fdb\\u5165\\u5168\\u9ad8\\u6a21\\u5f0f\\n        if (currentFullHeightEditor) {\\n          \\\/\\\/ \\u5982\\u679c\\u6709\\u5176\\u4ed6\\u7f16\\u8f91\\u5668\\u5904\\u4e8e\\u5168\\u9ad8\\u6a21\\u5f0f\\uff0c\\u5148\\u9000\\u51fa\\n          currentFullHeightEditor.classList.remove(&#039;full-height&#039;);\\n          const prevButton = document.querySelector(`#toggle-full-height[data-target=\\&quot;${currentFullHeightEditor.id}\\&quot;]`);\\n          if (prevButton) prevButton.textContent = &#039;\\u5168\\u9ad8&#039;;\\n        }\\n        editorContainer.classList.add(&#039;full-height&#039;);\\n        document.body.classList.add(&#039;full-height-active&#039;); \\\/\\\/ \\u6dfb\\u52a0body\\u4e0a\\u7684\\u5168\\u9ad8\\u6807\\u8bb0\\n        button.textContent = &#039;\\u534a\\u9ad8&#039;; \\\/\\\/ \\u6309\\u94ae\\u6587\\u672c\\u6539\\u4e3a\\u201c\\u534a\\u9ad8\\u201d\\n        currentFullHeightEditor = editorContainer; \\\/\\\/ \\u66f4\\u65b0\\u5f53\\u524d\\u5168\\u9ad8\\u7f16\\u8f91\\u5668\\n        \\n        \\\/\\\/ \\u6fc0\\u6d3b\\u76f8\\u5e94\\u7684tab\\uff08\\u89c6\\u89c9\\u4e0a\\uff09\\n        tabs.forEach(t =&gt; {\\n            if (t.dataset.tab === targetId) {\\n                t.classList.add(&#039;active&#039;);\\n            } else {\\n                t.classList.remove(&#039;active&#039;);\\n            }\\n        });\\n        \\n        \\\/\\\/ \\u5237\\u65b0CodeMirror\\u4ee5\\u9002\\u5e94\\u65b0\\u7684\\u5c3a\\u5bf8\\n        editors[targetId].refresh();\\n        editors[targetId].focus();\\n      }\\n    });\\n  });\\n\\n\\n  \\\/\\\/ \\u9875\\u9762\\u52a0\\u8f7d\\u65f6\\uff0c\\u5982\\u679c\\u4e0d\\u662f\\u7f16\\u8f91\\u6a21\\u5f0f\\u4e14\\u6ca1\\u6709\\u9519\\u8bef\\u4fe1\\u606f\\uff0c\\u5219\\u805a\\u7126\\u5230 HTML \\u7f16\\u8f91\\u5668\\n  \\\/\\\/ \\u5982\\u679c\\u6709\\u9519\\u8bef\\u4fe1\\u606f\\uff0c\\u5219 CodeMirror \\u5df2\\u7ecf\\u901a\\u8fc7 initialData \\u586b\\u5145\\u4e86\\u5185\\u5bb9\\uff0c\\u4e0d\\u9700\\u8981\\u989d\\u5916\\u7684\\u805a\\u7126\\n  if (!&#039;&lt;?= $edit_mode ?&gt;&#039; &amp;&amp; !&#039;&lt;?= !empty($error_message) ?&gt;&#039;) {\\n      editors.html.focus();\\n  }\\n&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;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;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<h1 class=\"wp-block-heading\">\u81ea\u5b9a\u4e49\u62d6\u62fd\u6392\u5e8f<\/h1>\n\n\n\n<p>\u4ee5\u53ca\u9879\u76ee\u540d\u4e0e\u6587\u4ef6\u5939\u540d\u5206\u522b\u8bbe\u7f6e\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6839\u76ee\u5f55\u65b0\u5efa\u6587\u4ef6\uff1aprojects_order.json\uff0c\u5185\u5bb9\u4e3a\u7a7a\u5373\u53ef\u3002<\/li>\n\n\n\n<li>\u6839\u76ee\u5f55\u7684\u6743\u9650\u8bbe\u4e3a777<\/li>\n\n\n\n<li>\u6839\u76ee\u5f55\u65b0\u5efa\u6587\u4ef6\uff1asave_order.php\uff0c\u5185\u5bb9\u5982\u4e0b\uff1a<\/li>\n<\/ul>\n\n\n\t\t<div class='wp-block-bch-code-highlight  align' id='bhcCodeHighlight-bd5e0c67-b' data-attributes='{&quot;cId&quot;:&quot;bd5e0c67-b&quot;,&quot;language&quot;:&quot;php&quot;,&quot;code&quot;:&quot;&lt;?php\\nsession_start();\\ndefine(&#039;ADMIN_PASSWORD&#039;, &#039;kangyue01.&#039;); \\\/\\\/ \\u8bf7\\u786e\\u4fdd\\u4e0e\\u4e3b\\u6587\\u4ef6\\u4e2d\\u7684\\u5bc6\\u7801\\u4e00\\u81f4\\ndefine(&#039;ORDER_FILE&#039;, __DIR__ . DIRECTORY_SEPARATOR . &#039;projects_order.json&#039;); \\\/\\\/ \\u5b9a\\u4e49\\u6392\\u5e8f\\u6587\\u4ef6\\u8def\\u5f84\\n\\nheader(&#039;Content-Type: application\\\/json&#039;); \\\/\\\/ \\u8bbe\\u7f6e\\u54cd\\u5e94\\u5934\\u4e3a JSON\\n\\n\\\/\\\/ \\u68c0\\u67e5\\u662f\\u5426\\u5df2\\u767b\\u5f55\\nif (!isset($_SESSION[&#039;logged_in&#039;])) {\\n    echo json_encode([&#039;success&#039; =&gt; false, &#039;message&#039; =&gt; &#039;\\u672a\\u767b\\u5f55\\u3002&#039;]);\\n    exit;\\n}\\n\\n\\\/\\\/ \\u68c0\\u67e5\\u8bf7\\u6c42\\u65b9\\u6cd5\\u662f\\u5426\\u4e3a POST \\u4e14\\u5305\\u542b\\u6570\\u636e\\nif ($_SERVER[&#039;REQUEST_METHOD&#039;] === &#039;POST&#039;) {\\n    $input = file_get_contents(&#039;php:\\\/\\\/input&#039;);\\n    $data = json_decode($input, true);\\n\\n    if (json_last_error() !== JSON_ERROR_NONE) {\\n        echo json_encode([&#039;success&#039; =&gt; false, &#039;message&#039; =&gt; &#039;\\u65e0\\u6548\\u7684 JSON \\u6570\\u636e\\u3002&#039;]);\\n        exit;\\n    }\\n\\n    \\\/\\\/ \\u68c0\\u67e5\\u6570\\u636e\\u662f\\u5426\\u5305\\u542b &#039;order&#039; \\u6570\\u7ec4\\n    if (isset($data[&#039;order&#039;]) &amp;&amp; is_array($data[&#039;order&#039;])) {\\n        $newOrder = [];\\n        $valid_order_items = [];\\n\\n        \\\/\\\/ \\u9a8c\\u8bc1\\u5e76\\u5904\\u7406\\u6bcf\\u4e2a\\u9879\\u76ee\\u6570\\u636e\\n        foreach ($data[&#039;order&#039;] as $item) {\\n            \\\/\\\/ \\u786e\\u4fdd\\u6bcf\\u4e2a\\u9879\\u76ee\\u90fd\\u6709 folder_name \\u548c display_name\\n            if (isset($item[&#039;folder_name&#039;]) &amp;&amp; isset($item[&#039;display_name&#039;])) {\\n                $folderName = $item[&#039;folder_name&#039;];\\n                $displayName = $item[&#039;display_name&#039;];\\n\\n                \\\/\\\/ \\u5bf9\\u6587\\u4ef6\\u5939\\u540d\\u8fdb\\u884c\\u5b89\\u5168\\u9a8c\\u8bc1\\n                if (!preg_match(&#039;\\\/^[a-zA-Z0-9_\\\\-]+$\\\/&#039;, $folderName)) {\\n                    echo json_encode([&#039;success&#039; =&gt; false, &#039;message&#039; =&gt; &#039;\\u6587\\u4ef6\\u5939\\u540d\\u79f0\\u5305\\u542b\\u975e\\u6cd5\\u5b57\\u7b26\\u3002&#039;]);\\n                    exit;\\n                }\\n                \\\/\\\/ \\u663e\\u793a\\u540d\\u79f0\\u5141\\u8bb8\\u66f4\\u591a\\u5b57\\u7b26\\uff0c\\u4f46\\u8fdb\\u884c\\u57fa\\u672c\\u6e05\\u7406\\n                $displayName = trim($displayName);\\n                $displayName = htmlspecialchars($displayName, ENT_QUOTES, &#039;UTF-8&#039;); \\\/\\\/ \\u9632\\u6b62XSS\\n\\n                $valid_order_items[] = [\\n                    &#039;folder_name&#039; =&gt; $folderName,\\n                    &#039;display_name&#039; =&gt; $displayName\\n                ];\\n            } else {\\n                echo json_encode([&#039;success&#039; =&gt; false, &#039;message&#039; =&gt; &#039;\\u6392\\u5e8f\\u6570\\u636e\\u683c\\u5f0f\\u4e0d\\u6b63\\u786e\\uff0c\\u7f3a\\u5c11 folder_name \\u6216 display_name\\u3002&#039;]);\\n                exit;\\n            }\\n        }\\n\\n        \\\/\\\/ \\u5c06\\u65b0\\u7684\\u6392\\u5e8f\\u4fdd\\u5b58\\u5230 JSON \\u6587\\u4ef6\\n        if (file_put_contents(ORDER_FILE, json_encode($valid_order_items, JSON_PRETTY_PRINT)) !== false) {\\n            echo json_encode([&#039;success&#039; =&gt; true, &#039;message&#039; =&gt; &#039;\\u6392\\u5e8f\\u5df2\\u6210\\u529f\\u4fdd\\u5b58\\u3002&#039;]);\\n        } else {\\n            echo json_encode([&#039;success&#039; =&gt; false, &#039;message&#039; =&gt; &#039;\\u65e0\\u6cd5\\u5199\\u5165\\u6392\\u5e8f\\u6587\\u4ef6\\u3002\\u8bf7\\u68c0\\u67e5\\u6587\\u4ef6\\u6743\\u9650\\u3002&#039;]);\\n        }\\n    } else {\\n        echo json_encode([&#039;success&#039; =&gt; false, &#039;message&#039; =&gt; &#039;\\u7f3a\\u5c11\\u6392\\u5e8f\\u6570\\u636e\\u3002&#039;]);\\n    }\\n} else {\\n    echo json_encode([&#039;success&#039; =&gt; false, &#039;message&#039; =&gt; &#039;\\u53ea\\u5141\\u8bb8 POST \\u8bf7\\u6c42\\u3002&#039;]);\\n}\\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;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;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<h1 class=\"wp-block-heading\">\u4ecb\u7ecd<\/h1>\n\n\n\n<p>\u8fd9\u4e2a PHP \u6587\u4ef6\u662f\u4e00\u4e2a<strong>\u5c0f\u578b\u9879\u76ee\u7ba1\u7406\u540e\u53f0<\/strong>\uff0c\u4e3b\u8981\u529f\u80fd\u662f\u8ba9\u7528\u6237\u5728\u7f51\u9875\u754c\u9762\u4e0a<strong>\u521b\u5efa\u3001\u7f16\u8f91\u3001\u4fdd\u5b58\u548c\u5220\u9664<\/strong>\u4ee3\u7801\u9879\u76ee\uff08\u5305\u542b HTML\u3001CSS\u3001JavaScript \u548c PHP \u6587\u4ef6\uff09\u3002\u5b83\u63d0\u4f9b\u4e86\u4ee3\u7801\u7f16\u8f91\u5668\u3001\u9879\u76ee\u5217\u8868\u3001\u65e5\u591c\u95f4\u6a21\u5f0f\u5207\u6362\u4ee5\u53ca\u5168\u9ad8\u7f16\u8f91\u7b49\u4fbf\u6377\u529f\u80fd\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\u9879\u76ee\u4ecb\u7ecd<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">1. \u7528\u6237\u8ba4\u8bc1\u4e0e\u5b89\u5168\u6027<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u767b\u5f55\u7cfb\u7edf<\/strong>: \u4f7f\u7528\u7b80\u5355\u7684\u5bc6\u7801\u9a8c\u8bc1 (<code>ADMIN_PASSWORD<\/code>) \u6765\u4fdd\u62a4\u540e\u53f0\u8bbf\u95ee\u3002\u672a\u767b\u5f55\u7528\u6237\u9700\u8981\u8f93\u5165\u5bc6\u7801\u624d\u80fd\u8fdb\u5165\u3002<\/li>\n\n\n\n<li><strong>\u9879\u76ee\u5220\u9664\u786e\u8ba4<\/strong>: \u5220\u9664\u9879\u76ee\u65f6\uff0c\u9700\u8981\u8f93\u5165\u7ba1\u7406\u5458\u5bc6\u7801\u8fdb\u884c\u4e8c\u6b21\u786e\u8ba4\uff0c\u9632\u6b62\u8bef\u64cd\u4f5c\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. \u9879\u76ee\u7ba1\u7406<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u9879\u76ee\u5217\u8868\u663e\u793a<\/strong>: \u5de6\u4fa7\u8fb9\u680f\u52a8\u6001\u5217\u51fa\u670d\u52a1\u5668\u4e0a\u6240\u6709\u5df2\u521b\u5efa\u7684\u9879\u76ee\u6587\u4ef6\u5939\u3002<\/li>\n\n\n\n<li><strong>\u65b0\u5efa\u9879\u76ee<\/strong>:\n<ul class=\"wp-block-list\">\n<li>\u901a\u8fc7\u201c\u65b0\u5efa\u9879\u76ee\u201d\u6309\u94ae\u53ef\u4ee5\u6e05\u7a7a\u5f53\u524d\u7f16\u8f91\u533a\uff0c\u65b9\u4fbf\u521b\u5efa\u65b0\u9879\u76ee\u3002<\/li>\n\n\n\n<li>\u521b\u5efa\u65b0\u9879\u76ee\u65f6\uff0c\u4f1a\u68c0\u67e5\u9879\u76ee\u540d\u79f0\u662f\u5426\u5df2\u5b58\u5728\uff0c\u907f\u514d\u91cd\u590d\u3002<\/li>\n\n\n\n<li>\u652f\u6301\u4e3a\u65b0\u9879\u76ee\u521b\u5efa <code>index.html<\/code>, <code>style.css<\/code>, <code>script.js<\/code>, <code>index.php<\/code> \u7b49\u6587\u4ef6\u3002\u5982\u679c\u76ee\u6807\u6587\u4ef6\u5df2\u5b58\u5728\u4e14\u975e\u7a7a\uff0c\u4f1a\u63d0\u793a\u51b2\u7a81\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u7f16\u8f91\u9879\u76ee<\/strong>:\n<ul class=\"wp-block-list\">\n<li>\u70b9\u51fb\u5de6\u4fa7\u9879\u76ee\u5217\u8868\u4e2d\u7684\u9879\u76ee\u540d\u79f0\u5373\u53ef\u52a0\u8f7d\u5176\u5bf9\u5e94\u7684 HTML\u3001CSS\u3001JS \u548c PHP \u5185\u5bb9\u5230\u7f16\u8f91\u5668\u4e2d\u8fdb\u884c\u4fee\u6539\u3002<\/li>\n\n\n\n<li>\u5141\u8bb8\u4fee\u6539\u9879\u76ee\u6587\u4ef6\u5939\u540d\u79f0\uff0c\u7cfb\u7edf\u4f1a\u81ea\u52a8\u91cd\u547d\u540d\u5bf9\u5e94\u7684\u6587\u4ef6\u5939\u3002<\/li>\n\n\n\n<li>\u4fee\u6539\u9879\u76ee\u65f6\uff0c\u5373\u4f7f\u6587\u4ef6\u5939\u540d\u79f0\u4e0d\u53d8\uff0c\u4e5f\u4e0d\u4f1a\u518d\u63d0\u793a\u201c\u9879\u76ee\u5df2\u5b58\u5728\u201d\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u4fdd\u5b58\u9879\u76ee<\/strong>:\n<ul class=\"wp-block-list\">\n<li>\u901a\u8fc7\u9875\u9762\u5e95\u90e8\u7684\u201c\u4fdd\u5b58\u9879\u76ee\u201d\u6309\u94ae\u5c06\u5f53\u524d\u7f16\u8f91\u5668\u4e2d\u7684\u4ee3\u7801\u4fdd\u5b58\u5230\u5bf9\u5e94\u7684\u6587\u4ef6\uff08<code>index.html<\/code>, <code>style.css<\/code>, <code>script.js<\/code>, <code>index.php<\/code>\uff09\u3002<\/li>\n\n\n\n<li>\u5982\u679c\u67d0\u4e2a\u8bed\u8a00\u7684\u7f16\u8f91\u5668\u5185\u5bb9\u4e3a\u7a7a\uff0c\u4f1a\u5220\u9664\u5bf9\u5e94\u6587\u4ef6\uff08\u5982\u679c\u5b58\u5728\uff09\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u5220\u9664\u9879\u76ee<\/strong>: \u63d0\u4f9b\u5220\u9664\u9879\u76ee\u7684\u529f\u80fd\uff0c\u4f1a\u9012\u5f52\u5220\u9664\u9879\u76ee\u6587\u4ef6\u5939\u53ca\u5176\u6240\u6709\u5185\u5bb9\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. \u4ee3\u7801\u7f16\u8f91\u529f\u80fd<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u591a\u6587\u4ef6\u7f16\u8f91<\/strong>: \u5c06 HTML\u3001CSS\u3001JavaScript \u548c PHP \u4ee3\u7801\u5206\u79bb\u5230\u4e0d\u540c\u7684\u9009\u9879\u5361\u4e2d\u8fdb\u884c\u7f16\u8f91\u3002<\/li>\n\n\n\n<li><strong>CodeMirror \u96c6\u6210<\/strong>: \u4f7f\u7528 CodeMirror \u4ee3\u7801\u7f16\u8f91\u5668\u5e93\uff0c\u63d0\u4f9b\u4e86\u4ee5\u4e0b\u9ad8\u7ea7\u7f16\u8f91\u4f53\u9a8c\uff1a\n<ul class=\"wp-block-list\">\n<li><strong>\u8bed\u6cd5\u9ad8\u4eae<\/strong>: \u6839\u636e\u6587\u4ef6\u7c7b\u578b\u5bf9\u4ee3\u7801\u8fdb\u884c\u9ad8\u4eae\u663e\u793a\u3002<\/li>\n\n\n\n<li><strong>\u884c\u53f7\u663e\u793a<\/strong>: \u663e\u793a\u4ee3\u7801\u884c\u53f7\uff0c\u65b9\u4fbf\u5b9a\u4f4d\u3002<\/li>\n\n\n\n<li><strong>\u4ee3\u7801\u6298\u53e0<\/strong>: \u652f\u6301\u4ee3\u7801\u5757\u7684\u6298\u53e0\u4e0e\u5c55\u5f00\u3002<\/li>\n\n\n\n<li><strong>Sublime Text \u5feb\u6377\u952e<\/strong>: \u9ed8\u8ba4\u542f\u7528 Sublime Text \u98ce\u683c\u7684\u5feb\u6377\u952e\u3002<\/li>\n\n\n\n<li><strong>\u6ce8\u91ca\/\u53d6\u6d88\u6ce8\u91ca<\/strong>: \u63d0\u4f9b\u6309\u94ae\u548c\u5feb\u6377\u952e (Ctrl-\/) \u6765\u5feb\u901f\u6ce8\u91ca\u6216\u53d6\u6d88\u6ce8\u91ca\u9009\u5b9a\u4ee3\u7801\u3002<\/li>\n\n\n\n<li><strong>\u81ea\u52a8\u6362\u884c<\/strong>: \u786e\u4fdd\u4ee3\u7801\u5728\u7a97\u53e3\u5185\u81ea\u52a8\u6362\u884c\uff0c\u63d0\u9ad8\u53ef\u8bfb\u6027\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u5168\u9ad8\u6a21\u5f0f<\/strong>:\n<ul class=\"wp-block-list\">\n<li>\u6bcf\u4e2a\u4ee3\u7801\u7f16\u8f91\u5668\u90fd\u6709\u4e00\u4e2a\u201c\u5168\u9ad8\u201d\u6309\u94ae\uff0c\u70b9\u51fb\u540e\u53ef\u4ee5\u5c06\u5f53\u524d\u7f16\u8f91\u5668\u6269\u5c55\u5230\u5168\u5c4f\uff0c\u65b9\u4fbf\u4e13\u6ce8\u4e8e\u5355\u4e2a\u6587\u4ef6\u7684\u7f16\u8f91\u3002<\/li>\n\n\n\n<li>\u5168\u9ad8\u6a21\u5f0f\u4e0b\uff0c\u4fa7\u8fb9\u680f\u4fdd\u6301\u53ef\u89c1\uff0c\u6ce8\u91ca\/\u53d6\u6d88\u6ce8\u91ca\u6309\u94ae\u4f4d\u7f6e\u4e0d\u53d8\u3002<\/li>\n\n\n\n<li>\u5168\u9ad8\u6a21\u5f0f\u4e0b\uff0c\u201c\u5168\u9ad8\u201d\u6309\u94ae\u4f1a\u53d8\u6210\u201c\u534a\u9ad8\u201d\uff0c\u70b9\u51fb\u53ef\u6062\u590d\u6b63\u5e38\u89c6\u56fe\u3002<\/li>\n\n\n\n<li><strong>\u201c\u4fdd\u5b58\u9879\u76ee\u201d\u6309\u94ae\u5728\u5168\u9ad8\u6a21\u5f0f\u4e0b\u59cb\u7ec8\u53ef\u89c1<\/strong>\uff0c\u65b9\u4fbf\u968f\u65f6\u4fdd\u5b58\u3002<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4. \u7528\u6237\u754c\u9762\u4e0e\u4f53\u9a8c<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u54cd\u5e94\u5f0f\u5e03\u5c40<\/strong>: \u57fa\u7840\u7684 Flexbox \u5e03\u5c40\u786e\u4fdd\u5185\u5bb9\u5728\u4e0d\u540c\u5c3a\u5bf8\u4e0b\u80fd\u5408\u7406\u6392\u5217\u3002<\/li>\n\n\n\n<li><strong>\u65e5\u591c\u95f4\u6a21\u5f0f<\/strong>: \u63d0\u4f9b\u201c\u5207\u6362\u65e5\u591c\u95f4\u6a21\u5f0f\u201d\u6309\u94ae\uff0c\u7528\u6237\u53ef\u4ee5\u9009\u62e9\u6697\u8272\u6216\u4eae\u8272\u4e3b\u9898\uff0c\u5e76\u4f1a\u8bb0\u4f4f\u7528\u6237\u7684\u9009\u62e9\u3002<\/li>\n\n\n\n<li><strong>\u64cd\u4f5c\u63d0\u793a<\/strong>: \u63d0\u4f9b\u6210\u529f\u548c\u9519\u8bef\u6d88\u606f\uff0c\u53ca\u65f6\u53cd\u9988\u7528\u6237\u64cd\u4f5c\u7ed3\u679c\u3002<\/li>\n\n\n\n<li><strong>\u89c6\u89c9\u4f18\u5316<\/strong>: \u201c\u4fdd\u5b58\u9879\u76ee\u201d\u6309\u94ae\u8fdb\u884c\u4e86\u6837\u5f0f\u4f18\u5316\uff0c\u5305\u62ec\u4f4d\u7f6e\u8c03\u6574\u3001\u84dd\u8272\u900f\u660e\u80cc\u666f\u548c\u6587\u5b57\u9634\u5f71\uff0c\u4f7f\u5176\u66f4\u7f8e\u89c2\u4e14\u4e0d\u4f1a\u906e\u6321\u4e0b\u65b9\u5185\u5bb9\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u603b\u7684\u6765\u8bf4\uff0c\u8fd9\u4e2a\u5de5\u5177\u4e3a\u5f00\u53d1\u8005\u63d0\u4f9b\u4e86\u4e00\u4e2a<strong>\u8f7b\u91cf\u7ea7\u4e14\u529f\u80fd\u5b8c\u5584\u7684\u5728\u7ebf\u4ee3\u7801\u7f16\u8f91\u73af\u5883<\/strong>\uff0c\u5c24\u5176\u9002\u7528\u4e8e\u9700\u8981\u5feb\u901f\u8fed\u4ee3\u548c\u7ba1\u7406\u591a\u4e2a\u5c0f\u578b\u9879\u76ee\u7684\u573a\u666f\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5927\u81f4\u4f7f\u7528\u6b65\u9aa4 \u540e\u53f0\u622a\u56fe \u5730\u5740 PHP\u4ee3\u7801\uff08V3.0,\u6700\u65b0\u7248\uff09 \u540e\u53f0 \u9879\u76ee\u5c55\u793a\u7684\u9875\u9762 PHP\u4ee3\u7801\uff08V2.0\uff09 P [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[56,91],"tags":[],"class_list":["post-3437","post","type-post","status-publish","format-standard","hentry","category-56","category-91"],"_links":{"self":[{"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/3437","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=3437"}],"version-history":[{"count":19,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/3437\/revisions"}],"predecessor-version":[{"id":3485,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=\/wp\/v2\/posts\/3437\/revisions\/3485"}],"wp:attachment":[{"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3437"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3437"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.kangyue.pro\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3437"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}