{"id":4484,"date":"2026-01-16T17:05:57","date_gmt":"2026-01-16T16:05:57","guid":{"rendered":"https:\/\/chinesische-sprachschule-stuttgart.de\/?page_id=4484"},"modified":"2026-01-22T08:47:55","modified_gmt":"2026-01-22T07:47:55","slug":"filegallery","status":"publish","type":"page","link":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/filegallery\/","title":{"rendered":"\u6587 \u4ef6 \u4e0b \u8f7d"},"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: #f8f9fa;\r\n            --border: #e9ecef;\r\n            --text-main: #333;\r\n            --text-sub: #666;\r\n            --shadow: 0 4px 12px rgba(0,0,0,0.08);\r\n        }\r\n\r\n        \/* \u521d\u59cb\u5168\u90e8\u9690\u85cf\uff0c\u9632\u6b62\u95ea\u70c1 *\/\r\n        #gallery-lock, #gallery-app { display: none; }\r\n\r\n        \/* \u9a8c\u8bc1\u9501\u5c4f\u5c42 *\/\r\n        #gallery-lock {\r\n            position: fixed;\r\n            top: 0; left: 0; width: 100%; height: 100%;\r\n            background: #fff;\r\n            z-index: 999999;\r\n            display: none; \/* JS\u63a7\u5236\u5207\u6362\u4e3a flex *\/\r\n            align-items: center;\r\n            justify-content: center;\r\n            backface-visibility: hidden;\r\n            transform: translateZ(0);\r\n        }\r\n\r\n        .lock-box {\r\n            max-width: 360px; width: 85%;\r\n            padding: 40px 25px;\r\n            border-radius: 16px;\r\n            text-align: center;\r\n            background: #fff;\r\n            box-shadow: 0 15px 35px rgba(0,0,0,0.1);\r\n        }\r\n\r\n        .lock-input {\r\n            padding: 14px; border: 1px solid var(--border); border-radius: 8px;\r\n            width: 100%; margin-bottom: 20px; text-align: center; font-size: 16px;\r\n        }\r\n\r\n        .lock-btn {\r\n            padding: 12px 40px; background: var(--primary); color: #fff;\r\n            border: none; border-radius: 8px; cursor: pointer; font-weight: bold; width: 100%;\r\n        }\r\n\r\n        \/* \u4e3b\u5bb9\u5668 *\/\r\n        .stu-box { max-width: 1240px; margin: 20px auto; font-family: -apple-system, system-ui, sans-serif; color: var(--text-main); }\r\n        .stu-head { display: flex; gap: 10px; margin-bottom: 20px; background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.03); align-items: center; flex-wrap: wrap; }\r\n        .stu-sel, .stu-search, .stu-sort { padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px; font-size: 14px; height: 42px; box-sizing: border-box; background-color: #fff; }\r\n        \r\n        .base-btn { height: 42px; padding: 0 18px; border: 1px solid var(--border); background: var(--bg-light); cursor: pointer; font-size: 14px; border-radius: 6px; transition: 0.2s; white-space: nowrap; }\r\n        .view-btn-group { display: flex; border-radius: 6px; overflow: hidden; border: 1px solid var(--border); height: 42px; }\r\n        .view-btn { padding: 0 15px; background: var(--bg-light); border: none; border-right: 1px solid var(--border); cursor: pointer; font-size: 14px; color: var(--text-sub); }\r\n        .view-btn.active { background: var(--primary); color: #fff; }\r\n        \r\n        .tool-bar { display: flex; justify-content: space-between; align-items: center; background: #fff; border-radius: 10px; padding: 15px; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.03); flex-wrap: wrap; gap: 15px; }\r\n        .tool-left { display: flex; align-items: center; gap: 15px; flex-wrap: wrap; }\r\n        .chk-wrap { display: flex; align-items: center; font-size: 14px; cursor: pointer; font-weight: 500; white-space: nowrap; }\r\n        .chk-wrap input { margin-right: 8px; transform: scale(1.3); }\r\n        .act-btn { padding: 9px 20px; border: none; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: bold; transition: 0.2s; white-space: nowrap; }\r\n        .act-btn.disabled { background: var(--border); color: #999; cursor: not-allowed; }\r\n        .act-btn.active { background: var(--primary); color: #fff; box-shadow: 0 2px 8px rgba(0,115,170,0.2); }\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.75); z-index: 9999; 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-note { font-size: 14px; color: var(--text-sub); padding: 12px 20px; background: #fff9e6; border-bottom: 1px dotted #ffecb3; line-height: 1.5; }\r\n        .modal-note a.yt-link { color: var(--yt-red); font-weight: bold; text-decoration: underline; }\r\n        .modal-body { flex: 1; background: #000; }\r\n        .modal-iframe { width: 100%; height: 100%; border: none; }\r\n\r\n        .stu-container { display: grid; gap: 20px; }\r\n        \r\n        \/* \u54cd\u5e94\u5f0f\u7f51\u683c\u9501\u5b9a *\/\r\n        @media (min-width: 1025px) { .view-grid { grid-template-columns: repeat(4, 1fr) !important; } }\r\n        @media (max-width: 1024px) and (min-width: 768px) { .view-grid { grid-template-columns: repeat(3, 1fr) !important; } }\r\n        @media (max-width: 767px) { .view-grid { grid-template-columns: repeat(2, 1fr) !important; gap: 10px; } }\r\n\r\n        .file-card { background: #fff; border-radius: 12px; overflow: hidden; position: relative; border: 1px solid var(--border); display: flex; flex-direction: column; transition: border-color 0.2s, box-shadow 0.2s; }\r\n        .file-card:hover { transform: none !important; box-shadow: var(--shadow); border-color: var(--primary); }\r\n        \r\n        .file-checkbox { position: absolute; top: 12px; left: 12px; z-index: 10; width: 22px; height: 22px; cursor: pointer; }\r\n        .fc-thumb-box { width: 100%; height: 160px; background: #f4f6f8; position: relative; cursor: pointer; overflow: hidden; display: flex; align-items: center; justify-content: center; }\r\n        \r\n        .fc-img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease; }\r\n        .file-card:hover .fc-img { transform: scale(1.05); }\r\n        \r\n        .fc-format-icon { width: 64px; height: 64px; fill: #cbd5e1; z-index: 1; transition: 0.3s; }\r\n        .file-card:hover .fc-format-icon { transform: scale(1.1); fill: var(--primary); }\r\n        \r\n        .fc-play-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.15); display: flex; align-items: center; justify-content: center; z-index: 2; }\r\n        .fc-play-btn { width: 56px; height: 56px; background: rgba(255,255,255,0.9); border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 15px rgba(0,0,0,0.3); }\r\n        .fc-play-btn svg { width: 28px; height: 28px; fill: var(--yt-red); margin-left: 4px; }\r\n\r\n        .view-grid .fc-icon-sm { display: none !important; }\r\n        \r\n        .fc-body { padding: 15px; flex: 1; display: flex; flex-direction: column; overflow: hidden; }\r\n        .fc-head { font-weight: bold; font-size: 14px; line-height: 1.4; margin-bottom: 8px; color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }\r\n        .fc-note-line { font-size: 12px; color: var(--text-sub); margin-bottom: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }\r\n        \r\n        .fc-meta { font-size: 11px; color: #999; margin-top: auto; display: flex; justify-content: space-between; border-top: 1px solid #f5f5f5; padding-top: 10px; align-items: center; }\r\n        .fc-actions { display: flex; gap: 8px; margin-top: 15px; }\r\n\r\n        \/* \u6309\u94ae\u5dee\u5f02\u5316\u989c\u8272 *\/\r\n        .btn-act { flex: 1; padding: 9px 0; border-radius: 6px; font-size: 12px; font-weight: 600; text-align: center; text-decoration: none; border: 1px solid var(--border); transition: all 0.25s ease; cursor: pointer; }\r\n        .btn-play-yt { background: #fff0f0; color: var(--yt-red); border-color: #ffdada; }\r\n        .btn-play-yt:hover { background: var(--yt-red); color: #fff; border-color: var(--yt-red); box-shadow: 0 4px 8px rgba(255,0,0,0.25); }\r\n        .btn-play-music { background: #f5f3ff; color: var(--music-purple); border-color: #ddd6fe; }\r\n        .btn-play-music:hover { background: var(--music-purple); color: #fff; border-color: var(--music-purple); box-shadow: 0 4px 8px rgba(108,92,231,0.25); }\r\n        .btn-view { background: #f0fff4; color: var(--view-green); border-color: #c6f6d5; }\r\n        .btn-view:hover { background: var(--view-green); color: #fff; border-color: var(--view-green); box-shadow: 0 4px 8px rgba(46,204,113,0.25); }\r\n        .btn-download { background: #f1f5f9; color: var(--dl-grey); border-color: #e2e8f0; }\r\n        .btn-download:hover { background: var(--dl-grey); color: #fff; border-color: var(--dl-grey); box-shadow: 0 4px 8px rgba(99,110,114,0.25); }\r\n\r\n        \/* \u5217\u8868\u6a21\u5f0f\u79fb\u52a8\u7aef\u5782\u76f4\u6309\u94ae *\/\r\n        .view-list { grid-template-columns: 1fr; }\r\n        .view-list .file-card { display: grid; grid-template-columns: 50px 50px minmax(200px, 3.5fr) minmax(150px, 2fr) 120px 180px; align-items: center; padding: 12px 15px; border: none; border-bottom: 1px solid var(--border); border-radius: 0; background: #fff; }\r\n        .view-list .fc-thumb-box { display: none; }\r\n        .view-list .file-checkbox { position: static; }\r\n        .view-list .fc-icon-sm { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; margin: auto; border-radius: 8px; background: #f1f5f9; }\r\n        .view-list .fc-body { display: contents; }\r\n        .view-list .fc-head, .view-list .fc-note-line { margin: 0; padding-right: 20px; }\r\n        .view-list .fc-meta { border: none; padding: 0; justify-content: flex-start; gap: 20px; margin: 0; }\r\n        .view-list .fc-actions { margin: 0; justify-content: flex-end; }\r\n\r\n        @media (max-width: 900px) {\r\n            .view-list .file-card { grid-template-columns: 45px 45px 1fr 120px; gap: 8px; padding: 12px 10px; }\r\n            .view-list .fc-actions { flex-direction: column; gap: 5px; }\r\n            .view-list .btn-act { padding: 6px 0; width: 100%; font-size: 11px; }\r\n            .view-list .fc-note-line, .view-list .fc-meta { display: none; }\r\n            .stu-head { flex-direction: column; align-items: stretch; }\r\n            .tool-right { width: 100%; justify-content: space-between !important; }\r\n        }\r\n        \r\n        .beta-sig { text-align:right; font-size:10px; color:#ccc; margin-top:35px; font-family:monospace; opacity:0.6; }\r\n    <\/style>\r\n\r\n    <div id=\"gallery-lock\">\r\n        <div class=\"lock-box\">\r\n            <h3 style=\"margin-top:0; color:var(--primary)\">\u7cfb\u7edf\u8bbf\u95ee\u9a8c\u8bc1<\/h3>\r\n            <input type=\"password\" id=\"g-pass\" class=\"lock-input\" placeholder=\"\u8f93\u5165\u8bbf\u95ee\u5bc6\u7801\" onkeyup=\"if(event.key==='Enter') window.unlockGallery()\">\r\n            <button onclick=\"window.unlockGallery()\" class=\"lock-btn\">\u786e\u8ba4\u89e3\u9501<\/button>\r\n            <div id=\"g-err\" style=\"margin-top:15px; color:var(--yt-red); font-size:13px;\"><\/div>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div id=\"gallery-app\">\r\n        <div class=\"stu-box\">\r\n            <div id=\"preview-modal\" class=\"modal-overlay\" onclick=\"closePreview(event)\">\r\n                <div class=\"modal-content\" onclick=\"event.stopPropagation()\">\r\n                    <div class=\"modal-header\">\r\n                        <span id=\"modal-title\" class=\"modal-title\">\u9884\u89c8<\/span>\r\n                        <span style=\"cursor:pointer;font-size:36px;line-height:1\" onclick=\"closePreview()\">&times;<\/span>\r\n                    <\/div>\r\n                    <div id=\"modal-note\" class=\"modal-note\" style=\"display:none;\"><\/div>\r\n                    <div class=\"modal-body\"><iframe id=\"modal-iframe\" class=\"modal-iframe\" src=\"\" allow=\"autoplay; fullscreen\" allowfullscreen><\/iframe><\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <div class=\"stu-head\">\r\n                <select id=\"s-folder\" class=\"stu-sel\" onchange=\"loadFiles()\"><option>\u8f7d\u5165\u76ee\u5f55...<\/option><\/select>\r\n                <input id=\"s-search\" class=\"stu-search\" placeholder=\"\u641c\u7d22\u5173\u952e\u8bcd...\" oninput=\"renderFiles()\">\r\n                <select id=\"s-sort\" class=\"stu-sort\" onchange=\"sortFiles()\">\r\n                    <option value=\"new\">\u6700\u65b0\u4f18\u5148<\/option>\r\n                    <option value=\"old\">\u6700\u65e9\u4f18\u5148<\/option>\r\n                    <option value=\"name\">\u540d\u79f0 A-Z<\/option>\r\n                <\/select>\r\n                <button class=\"base-btn\" onclick=\"loadFiles()\">\u5237\u65b0\u5361\u7247<\/button>\r\n                <div class=\"view-btn-group\">\r\n                    <button class=\"view-btn active\" id=\"btn-grid\" onclick=\"setView('grid')\">\u5361\u7247<\/button>\r\n                    <button class=\"view-btn\" id=\"btn-list\" onclick=\"setView('list')\">\u5217\u8868<\/button>\r\n                <\/div>\r\n            <\/div>\r\n            \r\n            <div class=\"tool-bar\">\r\n                <div class=\"tool-left\">\r\n                    <label class=\"chk-wrap\"><input type=\"checkbox\" id=\"g-chk-all\" onchange=\"toggleSelectAll(this)\"> \u5168\u9009<\/label>\r\n                    <button id=\"g-btn-dl\" class=\"act-btn disabled\" onclick=\"downloadSelected()\" disabled>\u4e0b\u8f7d\u9009\u4e2d (0)<\/button>\r\n                <\/div>\r\n                <div class=\"tool-right\" style=\"display:flex; align-items:center;\">\r\n                    <select id=\"g-limit\" class=\"stu-sort\" style=\"height:34px; font-size:12px; margin-right:10px;\" onchange=\"changeLimit(this.value)\"><option value=\"20\">20\/\u9875<\/option><option value=\"50\">50\/\u9875<\/option><option value=\"100\">100\/\u9875<\/option><option value=\"9999\">\u5168\u90e8<\/option><\/select>\r\n                    <span id=\"g-pg-info\" style=\"font-size:12px; color:#999; margin-right: 15px;\">0\/0<\/span>\r\n                    <button class=\"base-btn\" style=\"height:34px; padding:0 12px\" onclick=\"turnPage(-1)\">\u2190<\/button>\r\n                    <button class=\"base-btn\" style=\"height:34px; padding:0 12px; margin-left:5px;\" onclick=\"turnPage(1)\">\u2192<\/button>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <div id=\"stu-content\" class=\"stu-container view-grid\"><\/div>\r\n            <div class=\"beta-sig\">ICHN Driver Hub v2.7.5 - Zero Flash Auth<\/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_gallery_auth\", CACHE_KEY = \"drive_folders_cache_v2\";\r\n        let allFiles = [], currentView = 'grid', currentPage = 1, itemsPerPage = 20;\r\n\r\n        const ytPath = \"M10 15l5.19-3L10 9v6zm11.56-7.83c.13.47.22 1.1.28 1.9.07.8.1 1.49.1 2.09L22 12c0 2.19-.16 3.8-.44 4.83-.25.9-.96 1.61-1.86 1.86C18.67 19 12 19 12 19s-6.67 0-7.7-.31c-.9-.25-1.61-.96-1.86-1.86C2.16 15.8 2 14.19 2 12c0-2.19.16-3.8.44-4.83.25-.9.96-1.61 1.86-1.86C5.33 5 12 5 12 5s6.67 0 7.7.31c.9.25 1.61.96 1.86 1.86z\";\r\n\r\n        \/\/ --- \u6838\u5fc3\u903b\u8f91\uff1a\u7acb\u5373\u6267\u884c\u72b6\u6001\u68c0\u67e5\uff0c\u9632\u6b62\u95ea\u70c1 ---\r\n        window.checkLock = function() {\r\n            const lockEl = document.getElementById('gallery-lock');\r\n            const appEl = document.getElementById('gallery-app');\r\n            if(localStorage.getItem(LOCK_KEY) === PWD) { \r\n                if(lockEl) lockEl.style.display = 'none';\r\n                if(appEl) appEl.style.display = 'block';\r\n                initApp(); \r\n            } else { \r\n                if(lockEl) lockEl.style.display = 'flex';\r\n                if(appEl) appEl.style.display = 'none';\r\n            }\r\n        }\r\n        \r\n        \/\/ \u77ac\u95f4\u6267\u884c\u4e00\u6b21\r\n        window.checkLock();\r\n\r\n        window.unlockGallery = function() {\r\n            let val = document.getElementById('g-pass').value;\r\n            if(val === PWD) { localStorage.setItem(LOCK_KEY, PWD); window.checkLock(); }\r\n            else { document.getElementById('g-err').innerText = \"\u9a8c\u8bc1\u5931\u8d25\uff1a\u5bc6\u7801\u9519\u8bef\"; }\r\n        }\r\n\r\n        function initApp() {\r\n            let cached = localStorage.getItem(CACHE_KEY);\r\n            if(cached) { try { renderFolderSelect(JSON.parse(cached)); } catch(e) {} }\r\n            fetch(GAS_URL + `?secret=${GAS_KEY}`).then(r=>r.json()).then(d=>{\r\n                if(Array.isArray(d)) { localStorage.setItem(CACHE_KEY, JSON.stringify(d)); renderFolderSelect(d); }\r\n            });\r\n        }\r\n        function renderFolderSelect(data) {\r\n            let s = document.getElementById('s-folder'), html = '<option value=\"\">-- \u9009\u62e9\u76ee\u5f55 --<\/option>';\r\n            data.forEach(x => { html += `<option value=\"${x.id}\" ${x.isDefault?'selected':''}>${x.name}<\/option>`; });\r\n            s.innerHTML = html; if (s.value) loadFiles();\r\n        }\r\n        window.loadFiles = function() {\r\n            let fid = document.getElementById('s-folder').value; if(!fid) return;\r\n            document.getElementById('stu-content').innerHTML = '<div style=\"grid-column: 1\/-1; text-align:center; padding:100px; color:#999; font-size:14px\">\u6b63\u5728\u83b7\u53d6\u4e91\u7aef\u5217\u8868...<\/div>';\r\n            fetch(GAS_URL + `?secret=${GAS_KEY}&folderId=${fid}`).then(r=>r.json()).then(res=>{\r\n                if(res.files) { allFiles = res.files; currentPage = 1; sortFiles(); }\r\n            });\r\n        }\r\n        window.setView = function(mode) {\r\n            currentView = mode; document.getElementById('btn-grid').classList.toggle('active', mode==='grid');\r\n            document.getElementById('btn-list').classList.toggle('active', mode==='list');\r\n            document.getElementById('stu-content').className = 'stu-container view-' + mode;\r\n        }\r\n        window.closePreview = function() { document.getElementById('preview-modal').style.display = 'none'; document.getElementById('modal-iframe').src = ''; }\r\n        window.openPreview = function(url, name, note, ytUrl) {\r\n            document.getElementById('modal-title').innerText = name;\r\n            let noteEl = document.getElementById('modal-note'), content = note || \"\";\r\n            if(ytUrl) content += (content ? \" | \" : \"\") + `<a href=\"${ytUrl}\" target=\"_blank\" class=\"yt-link\">\u5728 YouTube \u539f\u7ad9\u89c2\u770b<\/a>`;\r\n            if(content) { noteEl.innerHTML = content; noteEl.style.display = 'block'; } else { noteEl.style.display = 'none'; }\r\n            document.getElementById('modal-iframe').src = url; document.getElementById('preview-modal').style.display = 'flex';\r\n        }\r\n\r\n        window.getSafeIcon = function(mime) {\r\n            let d = \"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z\"; \r\n            if(mime.includes('audio') || mime.includes('music')) d = \"M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z\";\r\n            else if(mime.includes('image')) d = \"M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z\";\r\n            else if(mime.includes('video')) d = \"M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4h-4z\";\r\n            return `<svg viewBox=\"0 0 24 24\" style=\"width:100%;height:100%\"><path d=\"${d}\"\/><\/svg>`;\r\n        }\r\n\r\n        window.renderFiles = function() {\r\n            let txt = document.getElementById('s-search').value.toLowerCase(), filtered = txt ? allFiles.filter(f => f.name.toLowerCase().includes(txt) || (f.description && f.description.toLowerCase().includes(txt))) : allFiles;\r\n            if(!filtered.length) { document.getElementById('stu-content').innerHTML = '<div style=\"grid-column:1\/-1; text-align:center; padding:100px; color:#999\">\u65e0\u5339\u914d\u8d44\u6e90<\/div>'; return; }\r\n            let total = Math.ceil(filtered.length \/ itemsPerPage);\r\n            document.getElementById('g-pg-info').innerText = `${currentPage} \/ ${total} \u9875`;\r\n            let displayData = filtered.slice((currentPage-1)*itemsPerPage, currentPage*itemsPerPage);\r\n\r\n            document.getElementById('stu-content').innerHTML = displayData.map(f => {\r\n                let desc = f.description || \"\", lines = desc.split(\/[\\n\\r]+\/);\r\n                let ytUrlLine = lines.find(l => l.includes(\"YT_LINK:\"));\r\n                let ytUrl = ytUrlLine ? ytUrlLine.split(\"YT_LINK:\")[1].trim() : \"\";\r\n                let ytMatch = ytUrl !== \"\";\r\n                let remark = lines.filter(l => l.trim() && !l.includes(\"YT_LINK:\") && !l.startsWith('\u73ed\u7ea7:') && !l.startsWith('\u8001\u5e08:')).join(' ').trim();\r\n                \r\n                let playUrl = f.previewUrl; \r\n                if(ytMatch) { \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                \r\n                let safeRemark = remark.replace(\/'\/g, \"\\\\'\").replace(\/\"\/g, \"&quot;\"), safeName = f.name.replace(\/'\/g, \"\\\\'\").replace(\/\"\/g, \"&quot;\");\r\n                let thumbUrl = `https:\/\/drive.google.com\/thumbnail?id=${f.id}&sz=w800`;\r\n                \r\n                let btnLabel = \"\u9884\u89c8\", btnClass = \"btn-preview\", iconColor = 'var(--primary)';\r\n                if (ytMatch) { btnLabel = \"\u64ad\u653e\"; btnClass = \"btn-play-yt\"; iconColor = 'var(--yt-red)'; }\r\n                else if (f.mimeType.includes('audio') || f.mimeType.includes('music')) { btnLabel = \"\u64ad\u653e\"; btnClass = \"btn-play-music\"; iconColor = 'var(--music-purple)'; }\r\n                else if (f.mimeType.includes('image')) { btnLabel = \"\u67e5\u770b\"; btnClass = \"btn-view\"; iconColor = 'var(--view-green)'; }\r\n\r\n                return `\r\n                <div class=\"file-card\">\r\n                    <input type=\"checkbox\" class=\"file-checkbox\" data-dl=\"${f.downloadUrl}\" onclick=\"event.stopPropagation(); updateGalleryBatchBtn();\">\r\n                    <div class=\"fc-thumb-box\" onclick=\"openPreview('${playUrl}', '${safeName}', '${safeRemark}', '${ytUrl}')\">\r\n                        ${(f.mimeType.includes('image') || ytMatch) \r\n                            ? `<img decoding=\"async\" src=\"${thumbUrl}\" class=\"fc-img\" loading=\"lazy\" onerror=\"this.style.opacity='0'\">` \r\n                            : `<div class=\"fc-format-icon\" style=\"fill:${iconColor}\">${getSafeIcon(f.mimeType)}<\/div>`}\r\n                        ${ytMatch ? `<div class=\"fc-play-overlay\"><div class=\"fc-play-btn\"><svg viewBox=\"0 0 24 24\"><path d=\"M8 5v14l11-7z\"\/><\/svg><\/div><\/div>` : ''}\r\n                    <\/div>\r\n                    <div class=\"fc-icon-sm\" style=\"fill:${iconColor}\">${ytMatch ? `<svg viewBox=\"0 0 24 24\" style=\"width:18px;height:18px\"><path d=\"${ytPath}\"\/><\/svg>` : getSafeIcon(f.mimeType)}<\/div>\r\n                    <div class=\"fc-body\">\r\n                        <div class=\"fc-head\" title=\"${f.name}\">${f.name}<\/div>\r\n                        <div class=\"fc-note-line\" title=\"${remark || '\u65e0\u5907\u6ce8'}\">${remark || \"\u65e0\u5907\u6ce8\"}<\/div>\r\n                        <div class=\"fc-meta\">\r\n                            <span>${f.date.split(' ')[0]}<\/span>\r\n                            <span style=\"display:flex; align-items:center; color:var(--yt-red)\">\r\n                                ${ytMatch ? `<svg style=\"width:14px;height:14px;fill:var(--yt-red);margin-right:4px;\" viewBox=\"0 0 24 24\"><path d=\"${ytPath}\"\/><\/svg><b style=\"font-size:11px\">YouTube<\/b>` : `<span style=\"color:#999\">${f.size} MB<\/span>`}\r\n                            <\/span>\r\n                        <\/div>\r\n                        <div class=\"fc-actions\">\r\n                            <button onclick=\"openPreview('${playUrl}', '${safeName}', '${safeRemark}', '${ytUrl}')\" class=\"btn-act ${btnClass}\">${btnLabel}<\/button>\r\n                            ${ytMatch ? `<a href=\"${ytUrl}\" target=\"_blank\" class=\"btn-act btn-play-yt\">\u89c2\u770b\u94fe\u63a5<\/a>` : `<a href=\"${f.downloadUrl}\" target=\"_blank\" class=\"btn-act btn-download\">\u4e0b\u8f7d\u6587\u4ef6<\/a>`}\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>`;\r\n            }).join('');\r\n        }\r\n        window.sortFiles = function() {\r\n            let t = document.getElementById('s-sort').value;\r\n            if(t === 'new') allFiles.sort((a,b) => b.date.localeCompare(a.date));\r\n            else if(t === 'old') allFiles.sort((a,b) => a.date.localeCompare(b.date));\r\n            else allFiles.sort((a,b) => a.name.localeCompare(b.name));\r\n            renderFiles();\r\n        }\r\n        window.changeLimit = (v) => { itemsPerPage = parseInt(v); currentPage = 1; renderFiles(); }\r\n        window.turnPage = (d) => { let total = Math.ceil(allFiles.length \/ itemsPerPage); if(currentPage+d >=1 && currentPage+d <= total) { currentPage += d; renderFiles(); } }\r\n        window.updateGalleryBatchBtn = function() {\r\n            let count = document.querySelectorAll('.file-checkbox:checked').length, btn = document.getElementById('g-btn-dl');\r\n            btn.innerText = `\u4e0b\u8f7d\u9009\u4e2d (${count})`; btn.disabled = count === 0; btn.classList.toggle('active', count > 0); btn.classList.toggle('disabled', count === 0);\r\n        }\r\n        window.toggleSelectAll = (el) => { document.querySelectorAll('.file-checkbox').forEach(c => c.checked = el.checked); updateGalleryBatchBtn(); }\r\n        window.downloadSelected = () => { \r\n            let chks = document.querySelectorAll('.file-checkbox:checked');\r\n            if(confirm(`\u786e\u8ba4\u4e0b\u8f7d\u9009\u4e2d\u7684 ${chks.length} \u4e2a\u8d44\u6e90\uff1f`)) chks.forEach((c, i) => setTimeout(() => window.open(c.getAttribute('data-dl'), '_blank'), i * 1500)); \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-4484","page","type-page","status-publish","hentry"],"acf":[],"jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":4754,"url":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/filemanager\/","url_meta":{"origin":4484,"position":0},"title":"\u6587 \u4ef6 \u7ba1 \u7406","author":"admin","date":"2026\u5e741\u670822\u65e5","format":false,"excerpt":"","rel":"","context":"\u00c4hnlicher Beitrag","block_context":{"text":"\u00c4hnlicher Beitrag","link":""},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4476,"url":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/fileupload\/","url_meta":{"origin":4484,"position":1},"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":903,"url":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/school-rules\/","url_meta":{"origin":4484,"position":2},"title":"Hausordnung","author":"admin","date":"2025\u5e744\u67084\u65e5","format":false,"excerpt":"\u5b89\u5168 \u6211\u4eec\u5171\u540c\u627f\u62c5\u7ef4\u62a4\u6821\u56ed\u5b89\u5168\u7684\u8d23\u4efb\uff0c\u6240\u6709\u5e08\u751f\u53ca\u53c2\u4e0e\u5b66\u6821\u6d3b\u52a8\u7684\u4eba\u5458\u90fd\u5e94\u79c9\u6301\u8c28\u614e\u3001\u8d1f\u8d23\u7684\u6001\u5ea6\uff0c\u9075\u5b88\u4ee5\u4e0b\u2026","rel":"","context":"\u00c4hnlicher Beitrag","block_context":{"text":"\u00c4hnlicher Beitrag","link":""},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_shortlink":"https:\/\/wp.me\/PgAON2-1ak","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\/4484","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=4484"}],"version-history":[{"count":4,"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/pages\/4484\/revisions"}],"predecessor-version":[{"id":4756,"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/pages\/4484\/revisions\/4756"}],"wp:attachment":[{"href":"https:\/\/chinesische-sprachschule-stuttgart.de\/de_de\/wp-json\/wp\/v2\/media?parent=4484"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}