{"id":4754,"date":"2026-01-22T08:47:35","date_gmt":"2026-01-22T07:47:35","guid":{"rendered":"https:\/\/chinesische-sprachschule-stuttgart.de\/?page_id=4754"},"modified":"2026-02-12T16:06:31","modified_gmt":"2026-02-12T15:06:31","slug":"filemanager","status":"publish","type":"page","link":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/filemanager\/","title":{"rendered":"\u6587 \u4ef6 \u7ba1 \u7406"},"content":{"rendered":"    <style>\r\n        :root {\r\n            --primary: #0073aa;\r\n            --yt-red: #ff0000;\r\n            --music-purple: #6c5ce7;\r\n            --view-green: #2ecc71;\r\n            --dl-grey: #636e72;\r\n            --bg-light: #f8fafc;\r\n            --border: #e2e8f0;\r\n            --text-main: #1e293b;\r\n            --text-sub: #64748b;\r\n        }\r\n\r\n        \/* \u96f6\u95ea\u70c1\u9a8c\u8bc1\u63a7\u5236 *\/\r\n        #manager-wrapper { opacity: 0; transition: opacity 0.2s; }\r\n        #manager-lock, #manager-app { display: none; }\r\n        \r\n        #manager-lock {\r\n            position: fixed; top: 0; left: 0; width: 100%; height: 100%;\r\n            background: #fff; z-index: 999999; display: none; align-items: center; justify-content: center;\r\n        }\r\n        .lock-box { max-width: 360px; width: 90%; padding: 40px 30px; border-radius: 20px; text-align: center; background: #fff; box-shadow: 0 20px 50px rgba(0,0,0,0.08); border: 1px solid var(--border); box-sizing: border-box; }\r\n        .lock-input { box-sizing: border-box; padding: 14px; border: 2px solid var(--border); border-radius: 10px; width: 100%; margin-bottom: 20px; text-align: center; font-size: 18px; outline: none; transition: border-color 0.2s; }\r\n        .lock-input:focus { border-color: var(--primary); }\r\n        .lock-btn { box-sizing: border-box; padding: 14px; background: var(--primary); color: #fff; border: none; border-radius: 10px; cursor: pointer; font-weight: bold; width: 100%; font-size: 16px; }\r\n\r\n        \/* \u4e3b\u5bb9\u5668 *\/\r\n        .adm-box { max-width: 1240px; margin: 30px auto; font-family: -apple-system, system-ui, sans-serif; background: #fff; padding: 30px; border-radius: 16px; border: 1px solid var(--border); box-shadow: 0 4px 20px rgba(0,0,0,0.04); box-sizing: border-box; }\r\n        .adm-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; padding-bottom: 20px; border-bottom: 1px solid var(--border); flex-wrap: wrap; gap: 15px; }\r\n        \r\n        \/* \u5b58\u50a8\u914d\u989d\u533a *\/\r\n        .quota-box { background: var(--bg-light); padding: 18px; border-radius: 12px; margin-bottom: 25px; border: 1px solid var(--border); box-sizing: border-box; }\r\n        .quota-bar { height: 10px; background: #e2e8f0; margin-top: 12px; border-radius: 6px; overflow: hidden; }\r\n        .quota-fill { height: 100%; background: var(--primary); width: 0%; transition: width 1s ease; }\r\n\r\n        \/* \u7f51\u683c\u5e03\u5c40 *\/\r\n        .adm-grid { display: grid; grid-template-columns: 340px 1fr; gap: 30px; }\r\n        .f-list-wrap, .file-area { min-width: 0; box-sizing: border-box; }\r\n\r\n        @media (max-width: 960px) { \r\n            .adm-grid { grid-template-columns: 1fr; gap: 20px; } \r\n            .adm-box { padding: 15px; margin: 15px auto; }\r\n        }\r\n\r\n        \/* \u4fa7\u8fb9\u680f\uff1a\u6587\u4ef6\u5939\u7ba1\u7406 *\/\r\n        .f-list-card { border: 1px solid var(--border); border-radius: 12px; padding: 15px; background: #fff; box-sizing: border-box; }\r\n        .f-bulk-tools { display: flex; justify-content: space-between; align-items: center; background: #fff8e5; padding: 10px; border-radius: 8px; margin-bottom: 12px; border: 1px solid #ffeeba; font-size: 12px; }\r\n        \r\n        .f-item { padding: 12px; cursor: pointer; border-radius: 8px; margin-bottom: 6px; display: flex; align-items: center; gap: 10px; transition: all 0.2s; font-size: 13px; border: 1px solid transparent; flex-wrap: wrap; box-sizing: border-box; }\r\n        .f-item:hover { background: var(--bg-light); border-color: var(--border); }\r\n        .f-item.active { background: #eff6ff; color: var(--primary); font-weight: bold; border-color: #bfdbfe; }\r\n        .f-item input[type=\"checkbox\"] { transform: scale(1.1); cursor: pointer; flex-shrink: 0; }\r\n        .f-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\r\n        .f-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }\r\n\r\n        \/* \u9876\u90e8\u64cd\u4f5c\u6761 *\/\r\n        .tool-bar { display: flex; justify-content: space-between; align-items: center; background: var(--bg-light); border-radius: 12px; padding: 12px 18px; margin-bottom: 20px; border: 1px solid var(--border); flex-wrap: wrap; gap: 15px; box-sizing: border-box; }\r\n        .chk-wrap { display: flex; align-items: center; font-size: 14px; cursor: pointer; color: var(--text-main); font-weight: 500; white-space: nowrap; border-right: 2px solid #e2e8f0; padding-right: 15px; }\r\n        .chk-wrap input { margin-right: 8px; transform: scale(1.3); cursor: pointer; }\r\n        .tb-actions { display: flex; gap: 10px; flex-wrap: wrap; }\r\n        .tool-right { display: flex; align-items: center; gap: 12px; white-space: nowrap; }\r\n\r\n        \/* \u8868\u683c\u533a\u57df *\/\r\n        .file-tbl-wrap { width: 100%; border: 1px solid var(--border); border-radius: 12px; overflow-x: auto; -webkit-overflow-scrolling: touch; box-sizing: border-box; }\r\n        .file-tbl { width: 100%; border-collapse: collapse; font-size: 13px; table-layout: fixed; min-width: 550px; }\r\n        .file-tbl th { background: #f8fafc; padding: 14px 10px; font-weight: 600; text-align: left; border-bottom: 1px solid var(--border); color: var(--text-sub); }\r\n        .file-tbl td { padding: 12px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; }\r\n        \r\n        .col-chk { width: 35px; text-align: center; }\r\n        .col-name { white-space: normal; word-break: break-word; line-height: 1.5; }\r\n        .col-act { width: 200px; text-align: right; }\r\n        .col-act .btn-link { margin-left: 10px; }\r\n        \r\n        \/* \u9884\u89c8\u5f39\u7a97 *\/\r\n        .modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 999999; justify-content: center; align-items: center; backdrop-filter: blur(4px); }\r\n        .modal-content { background: #fff; width: 95%; max-width: 960px; height: 85%; border-radius: 12px; display: flex; flex-direction: column; overflow: hidden; }\r\n        .modal-header { padding: 15px 20px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }\r\n        .modal-title { font-weight: bold; font-size: 18px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 75%; }\r\n        .modal-body { flex: 1; background: #000; }\r\n        .modal-iframe { width: 100%; height: 100%; border: none; }\r\n\r\n        \/* \u6309\u94ae\u4e0e\u72b6\u6001\u6807\u7b7e *\/\r\n        .btn { border: none; cursor: pointer; padding: 8px 14px; border-radius: 8px; font-size: 12px; font-weight: 700; transition: all 0.2s; display: inline-flex; align-items: center; justify-content: center; gap: 6px; box-sizing: border-box; }\r\n        .btn-blue { background: var(--primary); color: white; }\r\n        .btn-red { background: #fff1f2; color: var(--yt-red); border: 1px solid #fecdd3; }\r\n        .btn-red:not(.disabled):hover { background: var(--yt-red); color: white; }\r\n        .btn-grey { background: #f1f5f9; color: var(--text-main); border: 1px solid #e2e8f0; }\r\n        \r\n        .btn-link { background: none; color: var(--primary); text-decoration: underline; padding: 0; cursor: pointer; font-weight: 600; border: none; font-size: 12px; }\r\n        .btn-link.red { color: var(--yt-red); }\r\n        .btn-link.sub { color: var(--text-sub); text-decoration: none; }\r\n        \r\n        \/* \u6279\u91cf\u6309\u94ae\u6fc0\u6d3b\u6001 (\u4fee\u590d\u70b9\u51fb\u5931\u6548) *\/\r\n        .act-active-del { background: var(--yt-red) !important; color: white !important; box-shadow: 0 4px 12px rgba(255,0,0,0.15); border-color: transparent; }\r\n        .act-active-dl { background: var(--primary) !important; color: white !important; box-shadow: 0 4px 12px rgba(0,115,170,0.15); border-color: transparent; }\r\n        .disabled { opacity: 0.3; cursor: not-allowed !important; pointer-events: none; }\r\n\r\n        .default-badge { background: var(--primary); color: white; padding: 3px 8px; border-radius: 6px; font-size: 11px; font-weight: normal; }\r\n        .set-default-btn { font-size: 11px; color: var(--primary); border: 1px solid var(--primary); padding: 2px 6px; border-radius: 6px; background: transparent; transition: 0.2s; cursor: pointer; }\r\n        .set-default-btn:hover { background: var(--primary); color: white; }\r\n\r\n        .sys-sig { text-align: right; font-size: 10px; color: #cbd5e1; margin-top: 30px; font-family: monospace; user-select: none; }\r\n\r\n        \/* ================= \u79fb\u52a8\u7aef\u6781\u9650\u54cd\u5e94\u5f0f\u4f18\u5316 ================= *\/\r\n        @media (max-width: 600px) {\r\n            .f-actions { flex-basis: 100%; justify-content: flex-end; padding-top: 10px; margin-top: 4px; border-top: 1px dashed var(--border); }\r\n            \r\n            .tool-bar { flex-direction: column; align-items: stretch; gap: 12px; padding: 15px; }\r\n            .chk-wrap { border-bottom: 1px dashed var(--border); padding-bottom: 12px; justify-content: space-between; border-right: none; }\r\n            .chk-wrap::after { content: \"\u9009\u4e2d\u4e0b\u65b9\u6587\u4ef6\u8fdb\u884c\u64cd\u4f5c\"; font-size: 12px; color: var(--text-sub); font-weight: normal; }\r\n            .tb-actions { width: 100%; display: flex; gap: 10px; }\r\n            .tb-actions .btn { flex: 1; }\r\n            .tool-right { justify-content: space-between; background: #fff; padding: 8px 12px; border-radius: 8px; border: 1px solid var(--border); width: 100%; box-sizing: border-box; }\r\n\r\n            .file-tbl-wrap { border: none; background: transparent; overflow: visible; }\r\n            .file-tbl { min-width: 100%; display: block; }\r\n            .file-tbl thead { display: none; }\r\n            .file-tbl tbody { display: block; width: 100%; }\r\n            .file-tbl tr { display: flex; flex-wrap: wrap; align-items: center; border: 1px solid var(--border); border-radius: 10px; margin-bottom: 12px; padding: 15px; background: #fff; box-sizing: border-box; box-shadow: 0 2px 8px rgba(0,0,0,0.02); }\r\n            .file-tbl td { padding: 0; border: none; }\r\n            .file-tbl td.col-chk { width: 35px; display: flex; align-items: center; }\r\n            .file-tbl td.col-name { width: calc(100% - 35px); font-weight: 600; line-height: 1.4; word-break: break-all; }\r\n            .file-tbl td.col-act { width: 100%; margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--border); display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 12px; text-align: right; }\r\n            .file-tbl td.col-act .btn-link { display: inline-block; margin: 0; font-size: 13px; }\r\n        }\r\n    <\/style>\r\n\r\n    <div id=\"manager-wrapper\">\r\n        <div id=\"manager-lock\">\r\n            <div class=\"lock-box\">\r\n                <h3 style=\"margin-top:0; color:var(--primary)\">\u65af\u56fe\u52a0\u7279\u5b66\u6821\u7ba1\u7406\u9a8c\u8bc1<\/h3>\r\n                <input type=\"password\" id=\"m-pass\" class=\"lock-input\" placeholder=\"\u8bf7\u8f93\u5165\u7ba1\u7406\u5bc6\u7801\" onkeyup=\"if(event.key==='Enter') window.unlockManager()\">\r\n                <button onclick=\"window.unlockManager()\" class=\"lock-btn\">\u767b\u5f55\u7ba1\u7406\u540e\u53f0<\/button>\r\n                <div id=\"m-err\" style=\"margin-top:15px; color:var(--yt-red); font-size:13px; font-weight:bold;\"><\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <div id=\"m-preview-modal\" class=\"modal-overlay\" onclick=\"window.closePreview()\">\r\n            <div class=\"modal-content\" onclick=\"event.stopPropagation()\">\r\n                <div class=\"modal-header\">\r\n                    <span id=\"m-modal-title\" class=\"modal-title\">\u8d44\u6e90\u9884\u89c8<\/span>\r\n                    <span style=\"cursor:pointer;font-size:32px;line-height:1;color:#666;\" onclick=\"window.closePreview()\">&times;<\/span>\r\n                <\/div>\r\n                <div class=\"modal-body\">\r\n                    <iframe id=\"m-modal-iframe\" class=\"modal-iframe\" src=\"\" allow=\"autoplay; fullscreen\" allowfullscreen><\/iframe>\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <div id=\"manager-app\">\r\n            <div class=\"adm-box\">\r\n                <div class=\"adm-header\">\r\n                    <h3 style=\"margin:0\">ICHN \u7f51\u76d8\u8d44\u6e90\u5de5\u4f5c\u53f0<\/h3>\r\n                    <div style=\"display:flex; gap:10px; flex-wrap:wrap;\">\r\n                        <button onclick=\"window.fixPerms()\" class=\"btn btn-blue\" style=\"background:#27ae60;\">\ud83d\udee0\ufe0f \u4e00\u952e\u6743\u9650\u516c\u5f00<\/button>\r\n                        <button onclick=\"window.initManager()\" class=\"btn btn-grey\">\ud83d\udd04 \u4e91\u7aef\u540c\u6b65<\/button>\r\n                        <button onclick=\"window.logoutManager()\" class=\"btn btn-link red\" style=\"margin-left:10px;\">\u5b89\u5168\u9000\u51fa<\/button>\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <div class=\"quota-box\">\r\n                    <div style=\"display:flex; justify-content:space-between; font-size:13px;\">\r\n                        <span style=\"font-weight:600; color:var(--text-sub);\">Google Drive \u4e91\u7aef\u5b58\u50a8\u914d\u989d<\/span>\r\n                        <span id=\"q-txt\">\u6b63\u5728\u8fde\u63a5...<\/span>\r\n                    <\/div>\r\n                    <div class=\"quota-bar\"><div id=\"q-fill\" class=\"quota-fill\"><\/div><\/div>\r\n                <\/div>\r\n\r\n                <div style=\"margin-bottom: 25px; display:flex; gap:10px; flex-wrap:wrap;\">\r\n                    <input id=\"new-f\" placeholder=\"\u521b\u5efa\u65b0\u76ee\u5f55\u540d\u79f0...\" style=\"padding:12px; border:1px solid var(--border); flex:1; min-width:200px; border-radius:8px; outline:none; font-size:14px; box-sizing: border-box;\">\r\n                    <button onclick=\"window.createF()\" class=\"btn btn-blue\" style=\"padding:0 20px;\">+ \u65b0\u5efa\u6587\u4ef6\u5939<\/button>\r\n                <\/div>\r\n\r\n                <div class=\"adm-grid\">\r\n                    <div class=\"f-list-wrap\">\r\n                        <div class=\"f-list-card\">\r\n                            <div style=\"display:flex; justify-content:space-between; align-items:center; margin-bottom:15px; padding:0 5px;\">\r\n                                <span style=\"font-weight:700; color:var(--text-main);\">\u73b0\u6709\u76ee\u5f55<\/span>\r\n                                <label style=\"font-size:11px; cursor:pointer;\"><input type=\"checkbox\" id=\"f-chk-all\" onchange=\"window.toggleAllFolders(this)\"> \u5168\u9009<\/label>\r\n                            <\/div>\r\n                            \r\n                            <div id=\"bulk-bar-folder\" class=\"f-bulk-tools\" style=\"display:none;\">\r\n                                <span>\u5df2\u9009 <b id=\"sel-cnt-folder\">0<\/b> \u4e2a<\/span>\r\n                                <button onclick=\"window.batchDelFolders()\" class=\"btn-link red\" style=\"font-weight:bold;\">\u6279\u91cf\u5220\u9664<\/button>\r\n                            <\/div>\r\n\r\n                            <div id=\"folder-container\"><\/div>\r\n                        <\/div>\r\n                    <\/div>\r\n\r\n                    <div class=\"file-area\">\r\n                        <div id=\"file-header\" style=\"margin-bottom:15px; font-weight:700; color:var(--primary); font-size:16px;\">\u8bf7\u70b9\u51fb\u5de6\u4fa7\u76ee\u5f55\u8fdb\u884c\u64cd\u4f5c<\/div>\r\n                        \r\n                        <div class=\"tool-bar\">\r\n                            <label class=\"chk-wrap\"><input type=\"checkbox\" id=\"m-chk-all\" onchange=\"window.toggleAllFiles(this)\"> \u5168\u9009\u5217\u8868<\/label>\r\n                            \r\n                            <div class=\"tb-actions\">\r\n                                <button id=\"m-btn-del\" class=\"btn btn-red disabled\" onclick=\"window.batchDelFiles()\" disabled=\"true\">\u5220\u9664 (0)<\/button>\r\n                                <button id=\"m-btn-dl\" class=\"btn btn-blue disabled\" onclick=\"window.batchDlFiles()\" disabled=\"true\">\u4e0b\u8f7d (0)<\/button>\r\n                            <\/div>\r\n                            \r\n                            <div class=\"tool-right\">\r\n                                <select id=\"m-limit\" style=\"height:32px; font-size:12px; border-radius:6px; border:1px solid var(--border); outline:none; cursor:pointer;\" onchange=\"window.changeLimit(this.value)\">\r\n                                    <option value=\"20\">20\/\u9875<\/option><option value=\"50\">50\/\u9875<\/option><option value=\"9999\">\u5168\u90e8<\/option>\r\n                                <\/select>\r\n                                <span id=\"m-pg-info\" style=\"font-size:12px; color:var(--text-sub); font-weight:bold;\">0 \/ 0<\/span>\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n                        <div class=\"file-tbl-wrap\">\r\n                            <div id=\"file-container\"><\/div>\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>\r\n                <div class=\"sys-sig\">ICHN Manager v1.0.5 (Admin) | CSS Stuttgart<\/div>\r\n            <\/div>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <script>\r\n    (function(){\r\n        const GAS_URL = 'https:\/\/script.google.com\/macros\/s\/AKfycbxjZP3wtM8jnjS4HQIugIdp1BPG8j8TXXzGpDdBGlcJmBN5MNjCXZNYjmLrxKGeRp1t\/exec'; const GAS_KEY = 'YourSuperSecretKey2026_ChangeMe'; const ICHN_VER = 'v1.0.5';        const PWD = \"mh2026\", LOCK_KEY = \"drive_manager_auth_v5\";\r\n        let currentFiles = [], currentFolderId = '', currentPage = 1, itemsPerPage = 20;\r\n\r\n        window.checkLock = function() {\r\n            const wrap = document.getElementById('manager-wrapper'), lockEl = document.getElementById('manager-lock'), appEl = document.getElementById('manager-app');\r\n            if(localStorage.getItem(LOCK_KEY) === PWD) { \r\n                lockEl.style.display = 'none'; appEl.style.display = 'block'; wrap.style.opacity = '1';\r\n                window.initManager();\r\n            } else { \r\n                lockEl.style.display = 'flex'; appEl.style.display = 'none'; wrap.style.opacity = '1';\r\n            }\r\n        };\r\n        setTimeout(window.checkLock, 0);\r\n\r\n        window.unlockManager = function() {\r\n            if(document.getElementById('m-pass').value === PWD) {\r\n                localStorage.setItem(LOCK_KEY, PWD); window.checkLock();\r\n            } else { document.getElementById('m-err').innerText = \"\u63d0\u793a\uff1a\u8bbf\u95ee\u5bc6\u7801\u9519\u8bef\"; }\r\n        };\r\n\r\n        window.logoutManager = function() { localStorage.removeItem(LOCK_KEY); location.reload(); };\r\n        window.initManager = function() { window.checkQuota(); window.loadFolders(); };\r\n\r\n        window.loadFolders = function() {\r\n            const container = document.getElementById('folder-container');\r\n            container.innerHTML = '<div style=\"padding:15px; color:#999; font-size:12px;\">\ud83d\udd04 \u4e91\u7aef\u540c\u6b65\u4e2d...<\/div>';\r\n            window.apiRead({action: 'list_folders'}, (d) => {\r\n                const folders = Array.isArray(d) ? d : (d.folders || []);\r\n                if(!folders.length) { container.innerHTML = \"\u65e0\u53ef\u7528\u76ee\u5f55\"; return; }\r\n                container.innerHTML = folders.map(f => {\r\n                    let defaultAction = f.isDefault ? `<span class=\"default-badge\">\u9ed8\u8ba4<\/span>` : `<button class=\"set-default-btn\" onclick=\"window.setDef('${f.id}', event)\">\u8bbe\u4e3a\u9ed8\u8ba4<\/button>`;\r\n                    return `\r\n                    <div class=\"f-item\" data-id=\"${f.id}\" onclick=\"window.loadFiles('${f.id}', '${f.name.replace(\/'\/g, \"\\\\'\")}', this)\">\r\n                        <input type=\"checkbox\" class=\"f-chk\" value=\"${f.id}\" onclick=\"event.stopPropagation()\" onchange=\"window.chkFolders()\">\r\n                        <span class=\"f-name\" title=\"${f.name}\">${f.name}<\/span>\r\n                        <div class=\"f-actions\">\r\n                            ${defaultAction}\r\n                            <button class=\"btn-link sub\" onclick=\"window.renFolder('${f.id}', '${f.name.replace(\/'\/g, \"\\\\'\")}', event)\">\u6539\u540d<\/button>\r\n                        <\/div>\r\n                    <\/div>`;\r\n                }).join('');\r\n            });\r\n        };\r\n\r\n        window.loadFiles = function(fid, fname, el) {\r\n            currentFolderId = fid; currentPage = 1;\r\n            document.querySelectorAll('.f-item').forEach(e=>e.classList.remove('active'));\r\n            if(el) el.classList.add('active');\r\n            document.getElementById('file-header').innerText = `\u7ba1\u7406\uff1a${fname}`;\r\n            document.getElementById('file-container').innerHTML = '<div style=\"padding:50px; text-align:center; color:#999;\">\u6b63\u5728\u8f7d\u5165\u6587\u4ef6...<\/div>';\r\n            window.apiRead({action: 'list_files', folderId: fid}, (res) => {\r\n                currentFiles = res.files || res || []; window.renderFiles();\r\n            });\r\n        };\r\n\r\n        window.openPreview = function(url, name) {\r\n            document.getElementById('m-modal-title').innerText = name;\r\n            document.getElementById('m-modal-iframe').src = url;\r\n            document.getElementById('m-preview-modal').style.display = 'flex';\r\n        };\r\n        window.closePreview = function() {\r\n            document.getElementById('m-preview-modal').style.display = 'none';\r\n            document.getElementById('m-modal-iframe').src = '';\r\n        };\r\n\r\n        window.renderFiles = function() {\r\n            const container = document.getElementById('file-container');\r\n            if(!currentFiles.length) { container.innerHTML = '<div style=\"padding:40px; text-align:center; color:#999;\">\u8be5\u76ee\u5f55\u4e0b\u6682\u65e0\u6587\u4ef6<\/div>'; return; }\r\n            let total = Math.ceil(currentFiles.length \/ itemsPerPage);\r\n            document.getElementById('m-pg-info').innerText = `${currentPage} \/ ${total}`;\r\n            let displayData = currentFiles.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);\r\n            \r\n            let h = `<table class=\"file-tbl\"><thead><tr><th class=\"col-chk\"><\/th><th class=\"col-name\">\u6587\u4ef6\u540d\u79f0 \/ \u8d44\u6e90\u5907\u6ce8<\/th><th class=\"col-act\">\u64cd\u4f5c\u9762\u677f<\/th><\/tr><\/thead><tbody>`;\r\n            displayData.forEach(f => {\r\n                let isYT = f.description && f.description.indexOf(\"YT_LINK:\") !== -1;\r\n                let playUrl = f.previewUrl;\r\n                if(isYT) {\r\n                    let ytUrl = f.description.split(\"YT_LINK:\")[1].split(\/[\\n\\r]\/)[0].trim();\r\n                    let vid = ytUrl.match(\/(?:v=|be\\\/|embed\\\/)([^#&?]*)\/);\r\n                    if(vid && vid[1]) playUrl = `https:\/\/www.youtube.com\/embed\/${vid[1]}?autoplay=1`;\r\n                }\r\n                let safeName = f.name.replace(\/'\/g, \"\\\\'\").replace(\/\"\/g, \"&quot;\");\r\n\r\n                h += `<tr>\r\n                    <td class=\"col-chk\"><input type=\"checkbox\" class=\"file-chk\" value=\"${f.id}\" data-dl=\"${f.downloadUrl}\" onchange=\"window.updateManagerBatchBtn()\"><\/td>\r\n                    <td class=\"col-name\" title=\"${f.name}\">${f.name}<\/td>\r\n                    <td class=\"col-act\">\r\n                        <button class=\"btn-link\" style=\"color:var(--view-green);\" onclick=\"window.openPreview('${playUrl}','${safeName}')\">\u67e5\u770b<\/button>\r\n                        <button class=\"btn-link\" onclick=\"window.renFile('${f.id}','${safeName}')\">\u6539\u540d<\/button>\r\n                        <button class=\"btn-link red\" onclick=\"window.delSingle('${f.id}')\">\u5220\u9664<\/button>\r\n                        <a href=\"${f.downloadUrl}\" target=\"_blank\" class=\"btn-link sub\">\u4e0b\u8f7d<\/a>\r\n                    <\/td>\r\n                <\/tr>`;\r\n            });\r\n            container.innerHTML = h + `<\/tbody><\/table>`;\r\n            \r\n            \/\/ \u6bcf\u6b21\u6e32\u67d3\u6587\u4ef6\u5217\u8868\u540e\uff0c\u91cd\u7f6e\u6279\u91cf\u6309\u94ae\u72b6\u6001\r\n            document.getElementById('m-chk-all').checked = false;\r\n            window.updateManagerBatchBtn();\r\n        };\r\n\r\n        \/\/ --- \u4fee\u590d\u540e\u7684\u5f3a\u5236\u72b6\u6001\u8986\u76d6\u903b\u8f91 ---\r\n        window.updateManagerBatchBtn = function() {\r\n            let chks = document.querySelectorAll('.file-chk:checked');\r\n            let n = chks.length;\r\n            let btnDel = document.getElementById('m-btn-del');\r\n            let btnDl = document.getElementById('m-btn-dl');\r\n            \r\n            btnDel.innerText = `\u5220\u9664\u9009\u4e2d (${n})`; \r\n            btnDl.innerText = `\u4e0b\u8f7d\u9009\u4e2d (${n})`;\r\n            \r\n            if (n > 0) {\r\n                \/\/ \u6709\u9009\u4e2d\u9879\uff1a\u5f3a\u5236\u8d4b\u4e88\u6d3b\u52a8Class\uff0c\u5e76\u79fb\u9664disabled\u5c5e\u6027\r\n                btnDel.className = 'btn btn-red act-active-del';\r\n                btnDel.disabled = false;\r\n                \r\n                btnDl.className = 'btn btn-blue act-active-dl';\r\n                btnDl.disabled = false;\r\n            } else {\r\n                \/\/ \u65e0\u9009\u4e2d\u9879\uff1a\u5f3a\u5236\u8d4b\u4e88\u7070\u8272\u7981\u7528Class\uff0c\u5e76\u9644\u52a0disabled\u5c5e\u6027\r\n                btnDel.className = 'btn btn-red disabled';\r\n                btnDel.disabled = true;\r\n                \r\n                btnDl.className = 'btn btn-blue disabled';\r\n                btnDl.disabled = true;\r\n            }\r\n        };\r\n\r\n        window.toggleAllFiles = (el) => { document.querySelectorAll('.file-chk').forEach(c => c.checked = el.checked); window.updateManagerBatchBtn(); };\r\n        window.toggleAllFolders = (el) => { document.querySelectorAll('.f-chk').forEach(c => c.checked = el.checked); window.chkFolders(); };\r\n        window.chkFolders = () => {\r\n            let n = document.querySelectorAll('.f-chk:checked').length;\r\n            document.getElementById('sel-cnt-folder').innerText = n;\r\n            document.getElementById('bulk-bar-folder').style.display = n > 0 ? 'flex' : 'none';\r\n        };\r\n\r\n        window.renFolder = (id, old, e) => {\r\n            e.stopPropagation(); let n = prompt(\"\u91cd\u547d\u540d\u6587\u4ef6\u5939\u540d\u79f0\uff1a\", old);\r\n            if(n && n !== old) window.apiAction({action:'rename_item', type:'folder', id:id, newName:n}, window.loadFolders);\r\n        };\r\n        window.renFile = (id, old) => {\r\n            let n = prompt(\"\u91cd\u547d\u540d\u6587\u4ef6\u540d\u79f0\uff1a\", old);\r\n            if(n && n !== old) window.apiAction({action:'rename_item', type:'file', id:id, newName:n}, () => window.loadFiles(currentFolderId, \"\u6b63\u5728\u5237\u65b0\"));\r\n        };\r\n        window.batchDelFolders = () => {\r\n            let ids = Array.from(document.querySelectorAll('.f-chk:checked')).map(c=>c.value);\r\n            if(ids.length && confirm(`\u8b66\u544a\uff1a\u786e\u5b9a\u5220\u9664\u9009\u4e2d\u7684 ${ids.length} \u4e2a\u6587\u4ef6\u5939\u53ca\u5176\u5185\u90e8\u6240\u6709\u5185\u5bb9\uff1f`)) window.apiAction({action:'delete_folder', folderId:ids.join(',')}, window.loadFolders);\r\n        };\r\n        window.batchDelFiles = () => {\r\n            let ids = Array.from(document.querySelectorAll('.file-chk:checked')).map(c=>c.value);\r\n            if(ids.length && confirm(`\u786e\u5b9a\u5220\u9664\u9009\u4e2d\u7684 ${ids.length} \u4e2a\u9879\u76ee\uff1f`)) window.apiAction({action:'delete_file', fileId:ids.join(',')}, () => window.loadFiles(currentFolderId, \"\u6b63\u5728\u5237\u65b0\"));\r\n        };\r\n        window.batchDlFiles = () => {\r\n            let chks = document.querySelectorAll('.file-chk:checked');\r\n            if(chks.length && confirm(`\u786e\u5b9a\u6279\u91cf\u5f00\u542f\u4e0b\u8f7d\u4efb\u52a1\uff1f`)) chks.forEach((c, i) => setTimeout(() => window.open(c.getAttribute('data-dl'), '_blank'), i * 1200));\r\n        };\r\n\r\n        window.setDef = (id, e) => { e.stopPropagation(); if(confirm(\"\u786e\u8ba4\u4e3a\u5168\u6821\u8d44\u6e90\u9ed8\u8ba4\u76ee\u5f55\uff1f\")) window.apiAction({action:'set_default', targetId:id}, window.loadFolders); };\r\n        window.createF = () => { let n = document.getElementById('new-f').value; if(n) window.apiAction({action:'create_folder', folderName:n}, ()=>{ document.getElementById('new-f').value=''; window.loadFolders(); }); };\r\n        window.delSingle = (id) => { if(confirm(\"\u786e\u5b9a\u5f7b\u5e95\u5220\u9664\u6b64\u8d44\u6e90\uff1f\")) window.apiAction({action:'delete_file', fileId:id}, ()=>window.loadFiles(currentFolderId, \"\u6b63\u5728\u5237\u65b0\")); };\r\n        window.changeLimit = (v) => { itemsPerPage = parseInt(v); currentPage = 1; window.renderFiles(); };\r\n        window.fixPerms = () => { if(confirm(\"\u786e\u5b9a\u4fee\u590d\u5e76\u516c\u5f00\u6240\u6709\u8d44\u6e90\u8bbf\u95ee\u6743\u9650\uff1f\")) window.apiAction({action:'fix_permissions'}, ()=>alert(\"\u6743\u9650\u4fee\u590d\u6307\u4ee4\u5df2\u53d1\u9001\")); };\r\n\r\n        window.apiRead = async (p, sc) => {\r\n            const q = new URLSearchParams({ secret: GAS_KEY, ...p }).toString();\r\n            try { const r = await fetch(`${GAS_URL}?${q}`, { method: 'GET' }); const res = await r.json(); sc(res); } catch (e) { console.error(e); }\r\n        };\r\n        window.apiAction = async (d, sc) => {\r\n            document.body.style.cursor='wait';\r\n            const p = new URLSearchParams({ secret: GAS_KEY, ...d });\r\n            try {\r\n                const r = await fetch(GAS_URL, { method: 'POST', body: p.toString(), headers: { 'Content-Type': 'application\/x-www-form-urlencoded' } });\r\n                const res = await r.json(); if(res.status==='success' || res.count !== undefined) sc(res); else alert(\"\u64cd\u4f5c\u5f02\u5e38: \" + (res.message || \"\u540e\u7aef\u672a\u54cd\u5e94\"));\r\n            } catch (e) { alert(\"\u7f51\u7edc\u5f02\u5e38\"); } finally { document.body.style.cursor='default'; }\r\n        };\r\n        window.checkQuota = () => {\r\n            window.apiRead({action: 'get_quota'}, (d) => {\r\n                const used = d.used !== undefined ? d.used : (d.data ? d.data.used : 0);\r\n                const limit = d.limit !== undefined ? d.limit : (d.data ? d.data.limit : 15e9);\r\n                let pct = ((used \/ limit) * 100).toFixed(1);\r\n                document.getElementById('q-txt').innerText = `${(used\/1e9).toFixed(2)}GB \/ ${(limit\/1e9).toFixed(0)}GB (${pct}%)`;\r\n                document.getElementById('q-fill').style.width = pct + '%';\r\n            });\r\n        };\r\n    })();\r\n    <\/script>\r\n    \n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_EventAllDay":false,"_EventTimezone":"","_EventStartDate":"","_EventEndDate":"","_EventStartDateUTC":"","_EventEndDateUTC":"","_EventShowMap":false,"_EventShowMapLink":false,"_EventURL":"","_EventCost":"","_EventCostDescription":"","_EventCurrencySymbol":"","_EventCurrencyCode":"","_EventCurrencyPosition":"","_EventDateTimeSeparator":"","_EventTimeRangeSeparator":"","_EventOrganizerID":[],"_EventVenueID":[],"_OrganizerEmail":"","_OrganizerPhone":"","_OrganizerWebsite":"","_VenueAddress":"","_VenueCity":"","_VenueCountry":"","_VenueProvince":"","_VenueState":"","_VenueZip":"","_VenuePhone":"","_VenueURL":"","_VenueStateProvince":"","_VenueLat":"","_VenueLng":"","_VenueShowMap":false,"_VenueShowMapLink":false,"_themeisle_gutenberg_block_has_review":false,"footnotes":""},"class_list":["post-4754","page","type-page","status-publish","hentry"],"acf":[],"jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":4476,"url":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/fileupload\/","url_meta":{"origin":4754,"position":0},"title":"\u6587 \u4ef6 \u4e0a \u4f20","author":"admin","date":"2026\u5e741\u670816\u65e5","format":false,"excerpt":"","rel":"","context":"\u00c4hnlicher Beitrag","block_context":{"text":"\u00c4hnlicher Beitrag","link":""},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4484,"url":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/filegallery\/","url_meta":{"origin":4754,"position":1},"title":"\u6587 \u4ef6 \u4e0b \u8f7d","author":"admin","date":"2026\u5e741\u670816\u65e5","format":false,"excerpt":"","rel":"","context":"\u00c4hnlicher Beitrag","block_context":{"text":"\u00c4hnlicher Beitrag","link":""},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":650,"url":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/school-manage-page\/","url_meta":{"origin":4754,"position":2},"title":"Schulleitung","author":"admin","date":"2025\u5e743\u670813\u65e5","format":false,"excerpt":"\u9886\u5bfc\u56e2\u961f \u6211\u6821\u9886\u5bfc\u56e2\u961f\u7531\u591a\u4f4d\u8d44\u6df1\u6559\u80b2\u4e13\u5bb6\u7ec4\u6210\uff0c\u5206\u522b\u8d1f\u8d23\u5b66\u6821\u603b\u4f53\u7ba1\u7406\u3001\u6559\u52a1\u5de5\u4f5c\u3001\u884c\u653f\u4e8b\u52a1\u3001\u6587\u5316\u6d3b\u52a8\u548c\u8bfe\u2026","rel":"","context":"\u00c4hnlicher Beitrag","block_context":{"text":"\u00c4hnlicher Beitrag","link":""},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chinesische-sprachschule-stuttgart.de\/media\/2025\/03\/teamSchulleitung-scaled.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chinesische-sprachschule-stuttgart.de\/media\/2025\/03\/teamSchulleitung-scaled.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/chinesische-sprachschule-stuttgart.de\/media\/2025\/03\/teamSchulleitung-scaled.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/chinesische-sprachschule-stuttgart.de\/media\/2025\/03\/teamSchulleitung-scaled.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/chinesische-sprachschule-stuttgart.de\/media\/2025\/03\/teamSchulleitung-scaled.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/chinesische-sprachschule-stuttgart.de\/media\/2025\/03\/teamSchulleitung-scaled.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]}],"jetpack_shortlink":"https:\/\/wp.me\/PgAON2-1eG","rttpg_featured_image_url":null,"rttpg_author":{"display_name":"admin","author_link":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/author\/admin\/"},"rttpg_comment":0,"rttpg_category":null,"rttpg_excerpt":null,"_links":{"self":[{"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/pages\/4754","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/comments?post=4754"}],"version-history":[{"count":1,"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/pages\/4754\/revisions"}],"predecessor-version":[{"id":4755,"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/pages\/4754\/revisions\/4755"}],"wp:attachment":[{"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/media?parent=4754"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}