```json
{
"summary": "五项精确修改:①曲库名称点击即原地可编辑(contenteditable,blur 保存),与封面顶对齐;②导入按钮移至曲库名称与曲目数之间(紧凑胶囊样式);③封面右下角导入按钮移除,封面保留点击换封面;④排序+搜索重构为同一行——左侧搜索图标点击展开输入框实时过滤曲目,右侧排序下拉;⑤曲目操作弹窗仅保留置顶/删除/分享三项。",
"widget": {
"type": "full-html",
"html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, viewport-fit=cover\">\n <title>VintageSheet | 复古曲谱阅读器</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.c…\">\n <link href=\"https://fonts.googleapis.com/css2?family=Playfair+Display+SC:wght@400;7…\" rel=\"stylesheet\">\n <style>\n :root {\n --bg-dark: #2f2f2f;--bg-cream: #e9e7e0;--red-primary: #e33b0d;--red-deep: #b32a08;--red-accent: #f0481a;--red-darker: #8a1f06;\n --text-on-dark: #e5ded5;--text-on-dark-secondary: #b0a89e;--text-primary: #1a1214;--text-muted: #8b7670;\n }\n *{margin:0;padding:0;box-sizing:border-box}\n html,body{width:100%;height:100%;overflow:hidden;background:#1a1a1a;font-family:'Josefin Sans',sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent;user-select:none;-webkit-user-select:none}\n .app-root{width:100%;height:100dvh;height:100vh;display:flex;flex-direction:column;background:var(--bg-dark);position:relative;overflow:hidden}\n .nav-top{background:rgba(47,47,47,0.88);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);position:relative;z-index:30;box-shadow:0 4px 20px rgba(0,0,0,0.35),inset 0 1px 0 rgba(255,255,255,0.04);border-bottom:0.5px solid rgba(255,255,255,0.05)}\n .bottom-nav-container{background:rgba(47,47,47,0.85);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);position:relative;z-index:30;box-shadow:0 -4px 20px rgba(0,0,0,0.35),inset 0 -0.5px 0 rgba(255,255,255,0.03);border-top:0.5px solid rgba(255,255,255,0.05)}\n .staff-lines-bg{position:relative;background-color:var(--bg-cream)}\n .staff-lines-bg::before{content:'';position:absolute;inset:0;pointer-events:none;z-index:0;opacity:.22;background:repeating-linear-gradient(0deg,transparent 0px,transparent 3px,rgba(227,59,13,0.25) 3px,rgba(227,59,13,0.25) 3.5px,transparent 3.5px,transparent 9px,rgba(227,59,13,0.25) 9px,rgba(227,59,13,0.25) 9.5px,transparent 9.5px,transparent 15px,rgba(227,59,13,0.25) 15px,rgba(227,59,13,0.25) 15.5px,transparent 15.5px,transparent 21px,rgba(227,59,13,0.25) 21px,rgba(227,59,13,0.25) 21.5px,transparent 21.5px,transparent 27px,rgba(227,59,13,0.25) 27px,rgba(227,59,13,0.25) 27.5px,transparent 27.5px,transparent 55px)}\n .staff-lines-bg::after{content:'';position:absolute;inset:0;pointer-events:none;z-index:1;opacity:.06;background:radial-gradient(ellipse at 25% 30%,rgba(227,59,13,0.18) 0%,transparent 60%),radial-gradient(ellipse at 75% 70%,rgba(227,59,13,0.10) 0%,transparent 55%)}\n\n .vinyl-mini{width:100%;height:100%;border-radius:50%;position:relative;overflow:hidden;background:repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 2.8px,rgba(0,0,0,0.07) 2.8px,rgba(0,0,0,0.07) 3px),repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 5.6px,rgba(0,0,0,0.05) 5.6px,rgba(0,0,0,0.05) 5.9px),repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 9.5px,rgba(0,0,0,0.04) 9.5px,rgba(0,0,0,0.04) 9.8px),repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 14px,rgba(0,0,0,0.035) 14px,rgba(0,0,0,0.035) 14.4px),repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 21px,rgba(0,0,0,0.03) 21px,rgba(0,0,0,0.03) 21.5px),radial-gradient(circle at 50% 50%,#1a1a1a 0%,#1e1e1e 100%);box-shadow:inset 0 0 1px rgba(255,255,255,0.012),0 3px 12px rgba(0,0,0,0.32),0 0 0 1px rgba(60,28,15,0.35)}\n .vinyl-mini::before{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:34%;height:34%;border-radius:50%;background:radial-gradient(circle at 50% 50%,var(--red-primary) 0%,var(--red-deep) 55%,var(--red-darker) 88%,#3a1003 100%);z-index:3;box-shadow:inset 0 1px 0 rgba(255,255,255,0.12),inset 0 -1px 2px rgba(0,0,0,0.35),0 0 0 0.6px rgba(255,255,255,0.06)}\n .vinyl-mini::after{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:7px;height:7px;border-radius:50%;background:#0a0a0a;z-index:4;box-shadow:inset 0 0 1px rgba(255,255,255,0.03),0 0 0 1px rgba(0,0,0,0.3)}\n .vinyl-mini .vinyl-shine{position:absolute;inset:0;border-radius:50%;pointer-events:none;z-index:2;background:linear-gradient(135deg,rgba(255,255,255,0.05) 0%,transparent 30%,transparent 55%,rgba(255,255,255,0.02) 70%,transparent 100%)}\n\n .lib-card{aspect-ratio:1;border-radius:10px;overflow:hidden;cursor:pointer;position:relative;background:var(--bg-cream);box-shadow:0 6px 22px rgba(0,0,0,0.16),0 1px 3px rgba(0,0,0,0.08);transition:transform .2s ease,box-shadow .2s ease}\n .lib-card:active{transform:scale(.965);box-shadow:0 3px 10px rgba(0,0,0,0.18)}\n .lib-card.dragging{opacity:.45;z-index:25;transform:scale(1.04);box-shadow:0 16px 40px rgba(0,0,0,0.35)}\n .lib-card .card-cover{position:absolute;inset:0;overflow:hidden}\n .lib-card .card-cover img{width:100%;height:100%;object-fit:cover;display:block}\n .lib-card .card-cover .cover-placeholder{width:100%;height:100%;background:linear-gradient(160deg,#3a3532 0%,#2f2b28 50%,#1f1c1a 100%);display:flex;align-items:center;justify-content:center}\n .lib-card .vinyl-peek{position:absolute;right:-24%;top:5%;width:62%;aspect-ratio:1;z-index:2;pointer-events:none;transition:transform .4s cubic-bezier(.25,.46,.45,.94)}\n .lib-card:active .vinyl-peek{transform:translateX(-6%)}\n .lib-card .card-info{position:absolute;inset:auto 0 0 0;z-index:3;background:linear-gradient(to bottom,transparent 0%,rgba(20,17,15,0.55) 30%,rgba(16,13,11,0.88) 100%);padding:18px 10px 10px 10px;display:flex;flex-direction:column;border-top:0.5px solid rgba(227,59,13,0.22)}\n .lib-card .card-info .card-name{font-family:'Josefin Sans',sans-serif;font-size:11px;font-weight:600;letter-spacing:.05em;color:#f0e8e0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 1px 2px rgba(0,0,0,0.35)}\n .lib-card .card-info .card-count{font-size:9px;color:rgba(200,188,178,0.75);letter-spacing:.06em;margin-top:2px;text-shadow:0 1px 1px rgba(0,0,0,0.25)}\n .lib-card .del-btn{position:absolute;top:6px;right:6px;width:22px;height:22px;border-radius:50%;background:var(--red-primary);color:#fff;display:none;align-items:center;justify-content:center;font-size:9px;z-index:8;box-shadow:0 2px 6px rgba(227,59,13,0.45);cursor:pointer;transition:all .2s ease}\n .lib-card .del-btn.show-del{display:flex;animation:popIn .25s cubic-bezier(.34,1.56,.64,1)}\n @keyframes popIn{from{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}\n .lib-card .del-btn:active{transform:scale(.85)}\n .lib-card .drag-handle{position:absolute;top:6px;left:6px;z-index:8;color:rgba(255,255,255,0.75);font-size:13px;cursor:grab;letter-spacing:-2px;line-height:1;opacity:0;padding:2px 5px;border-radius:3px;transition:all .2s ease;pointer-events:none;text-shadow:0 1px 3px rgba(0,0,0,0.6)}\n .lib-card .drag-handle.show-handle{opacity:.85;pointer-events:auto}\n .lib-card .drag-handle:active{cursor:grabbing;background:rgba(255,255,255,0.10)}\n .lib-card .cover-overlay-card{position:absolute;inset:0;z-index:5;background:rgba(0,0,0,0.40);display:none;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease}\n .lib-card .cover-overlay-card.show-cover{display:flex;animation:fadeIn2 .2s ease}\n @keyframes fadeIn2{from{opacity:0}to{opacity:1}}\n .lib-card .cover-overlay-card i{color:#fff;font-size:20px;text-shadow:0 1px 3px rgba(0,0,0,0.5)}\n\n /* ===== 子曲谱视图 ===== */\n .sub-view{position:absolute;inset:0;z-index:20;background:var(--bg-cream);transition:transform .35s cubic-bezier(.25,.46,.45,.94);display:flex;flex-direction:column}\n .sub-view.hidden-sub{transform:translateX(105%);pointer-events:none}\n .sub-view.visible-sub{transform:translateX(0);pointer-events:auto}\n .sub-header{display:flex;align-items:flex-start;gap:14px;padding:12px 16px 10px 16px;flex-shrink:0}\n .sub-cover-wrap{width:85px;height:85px;border-radius:8px;flex-shrink:0;overflow:hidden;position:relative;box-shadow:0 4px 14px rgba(0,0,0,0.18);cursor:pointer}\n .sub-cover-wrap img{width:100%;height:100%;object-fit:cover;display:block}\n .sub-cover-wrap .vinyl-peek-sub{position:absolute;right:-24%;top:5%;width:62%;aspect-ratio:1;z-index:2;pointer-events:none}\n .sub-cover-wrap .cover-tap-hint{position:absolute;inset:0;z-index:3;background:rgba(0,0,0,0);display:flex;align-items:center;justify-content:center;transition:all .2s ease;pointer-events:none}\n .sub-cover-wrap:active .cover-tap-hint{background:rgba(0,0,0,0.25)}\n .sub-cover-wrap .cover-tap-hint i{color:#fff;font-size:16px;opacity:0;transition:opacity .2s ease}\n .sub-cover-wrap:active .cover-tap-hint i{opacity:1}\n .sub-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}\n .sub-info .lib-name{font-family:'Josefin Sans',sans-serif;font-size:15px;font-weight:600;letter-spacing:.05em;color:var(--text-primary);cursor:text;display:inline-block;outline:none;border-bottom:1px dashed transparent;transition:border-color .2s ease;padding:1px 2px;margin:-1px -2px;border-radius:3px}\n .sub-info .lib-name:focus{background:rgba(227,59,13,0.04);border-bottom-color:rgba(227,59,13,0.30)}\n .btn-import-inline{display:inline-flex;align-items:center;gap:4px;padding:5px 10px;border-radius:5px;border:1px solid rgba(227,59,13,0.30);background:rgba(227,59,13,0.05);color:var(--red-primary);font-size:10px;letter-spacing:.04em;cursor:pointer;transition:all .2s ease;align-self:flex-start}\n .btn-import-inline:active{background:rgba(227,59,13,0.14)}\n .sub-info .lib-meta{font-size:10px;color:var(--red-primary);letter-spacing:.05em;}\n\n /* 排序+搜索行 */\n .toolbar-row{display:flex;align-items:center;justify-content:space-between;padding:6px 16px 4px;flex-shrink:0;z-index:22;gap:10px}\n .search-inline-wrap{display:flex;align-items:center;gap:0;flex:1;max-width:180px}\n .btn-search-toggle{width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-muted);border:1px solid rgba(0,0,0,0.06);background:rgba(233,231,224,0.50);transition:all .2s ease;flex-shrink:0}\n .btn-search-toggle:active{background:rgba(227,59,13,0.08);color:var(--red-primary)}\n .search-input-inline{flex:1;min-width:0;height:30px;border-radius:16px;border:1px solid rgba(227,59,13,0.22);background:rgba(233,231,224,0.60);padding:0 10px;font-size:11px;font-family:'Josefin Sans',sans-serif;color:var(--text-primary);outline:none;transition:all .25s ease;display:none}\n .search-input-inline.show-input{display:block}\n .search-input-inline:focus{border-color:rgba(227,59,13,0.40)}\n .sort-dropdown-wrap{position:relative;flex-shrink:0}\n .sort-toggle{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:16px;font-size:11px;letter-spacing:.04em;color:var(--text-muted);background:rgba(233,231,224,0.55);border:1px solid rgba(0,0,0,0.06);cursor:pointer;transition:all .2s ease}\n .sort-toggle:active{background:rgba(227,59,13,0.06);color:var(--red-primary)}\n .sort-toggle i{font-size:10px}\n .sort-dropdown{position:absolute;top:100%;right:0;z-index:25;background:#f5f2ec;border-radius:8px;box-shadow:0 6px 22px rgba(0,0,0,0.14);min-width:140px;overflow:hidden;animation:slideUp2 .2s cubic-bezier(.34,1.56,.64,1);border:1px solid rgba(0,0,0,0.05);margin-top:4px}\n @keyframes slideUp2{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}\n .sort-dropdown .sort-opt{padding:10px 16px;font-size:11px;color:var(--text-primary);cursor:pointer;transition:all .15s ease;letter-spacing:.04em;display:flex;align-items:center;gap:8px}\n .sort-dropdown .sort-opt:active{background:rgba(227,59,13,0.06);color:var(--red-primary)}\n .sort-dropdown .sort-opt i{font-size:10px;width:16px;text-align:center}\n\n .sub-song-list{flex:1;overflow-y:auto;padding:4px 16px 12px 16px}\n .sub-song-list.no-scrollbar::-webkit-scrollbar{display:none}\n .sub-song-list.no-scrollbar{scrollbar-width:none;-ms-overflow-style:none}\n .song-row{display:flex;align-items:center;gap:10px;padding:12px 8px;border-bottom:1px solid rgba(227,59,13,0.10);cursor:pointer;transition:all .2s ease;position:relative}\n .song-row:active{background:rgba(227,59,13,0.04)}\n .song-row.hidden-row{display:none}\n .song-row .song-index{width:22px;text-align:right;font-size:10px;color:var(--text-muted);font-family:'Josefin Sans',sans-serif;flex-shrink:0}\n .song-row .song-body{flex:1;min-width:0}\n .song-row .song-title{font-size:16px;color:var(--text-primary);font-family:'Liu Jian Mao Cao','Ma Shan Zheng',cursive;line-height:1.3}\n .song-more-btn{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-muted);transition:all .2s ease;flex-shrink:0;font-size:14px;letter-spacing:-1px;font-weight:bold}\n .song-more-btn:active{background:rgba(227,59,13,0.08);color:var(--red-primary)}\n .song-action-popup{position:absolute;right:8px;top:100%;z-index:30;background:#f5f2ec;border-radius:8px;box-shadow:0 8px 28px rgba(0,0,0,0.18);min-width:150px;overflow:hidden;animation:slideUp3 .2s cubic-bezier(.34,1.56,.64,1);border:1px solid rgba(0,0,0,0.06)}\n @keyframes slideUp3{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}\n .song-action-popup .action-item{display:flex;align-items:center;gap:10px;padding:11px 16px;font-size:12px;color:var(--text-primary);cursor:pointer;transition:all .15s ease;letter-spacing:.04em}\n .song-action-popup .action-item:active{background:rgba(227,59,13,0.06);color:var(--red-primary)}\n .song-action-popup .action-item i{width:16px;text-align:center;font-size:12px}\n .song-action-popup .action-item.danger{color:var(--red-primary)}\n\n .stack-card-wrap{position:relative;height:170px;cursor:pointer}.stack-card-wrap:active{transform:scale(.97)}\n .stack-card-back{position:absolute;top:7px;left:12px;right:0;bottom:0;border-radius:8px;overflow:hidden;opacity:.30;filter:blur(2.5px);transform:rotate(1.5deg)}.stack-card-back img{width:100%;height:100%;object-fit:cover}\n .stack-card-front{position:absolute;top:0;left:0;right:12px;bottom:7px;border-radius:8px;overflow:hidden;box-shadow:0 6px 24px rgba(0,0,0,0.25),0 2px 6px rgba(0,0,0,0.15)}.stack-card-front img{width:100%;height:100%;object-fit:cover}\n .stack-label{position:absolute;bottom:8px;left:8px;z-index:3;background:rgba(15,10,8,0.80);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);color:#e5ded5;font-size:11px;padding:4px 10px;border-radius:3px;letter-spacing:.06em;font-family:'Josefin Sans',sans-serif}\n .rec-mini-card{flex-shrink:0;width:130px;border-radius:8px;overflow:hidden;cursor:pointer;transition:transform .2s ease;position:relative;background:rgba(233,231,224,0.65);border:1px solid rgba(255,255,255,0.40);box-shadow:0 3px 12px rgba(0,0,0,0.06)}.rec-mini-card:active{transform:scale(.95)}\n .rec-mini-card img{width:100%;height:80px;object-fit:cover;display:block}.rec-mini-card .rec-mini-label{padding:8px 10px;font-size:10px;letter-spacing:.04em;color:var(--text-primary);font-family:'Josefin Sans',sans-serif}\n\n .search-bar{background:rgba(233,231,224,0.68);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,0.42);border-radius:8px;display:flex;align-items:center;gap:8px;padding:10px 14px;cursor:pointer;transition:all .25s ease;box-shadow:inset 0 1px 0 rgba(255,255,255,0.40);flex:1}\n .search-bar i{color:var(--text-muted);font-size:13px}.search-bar span{color:var(--text-muted);font-size:12px;letter-spacing:.04em;flex:1}\n .search-bar.focused{border-color:rgba(227,59,13,0.30);box-shadow:inset 0 1px 0 rgba(255,255,255,0.40),0 0 0 2px rgba(227,59,13,0.08)}\n .search-history-dropdown{position:absolute;top:100%;left:0;right:0;z-index:60;background:#f0ede8;border-radius:8px;margin-top:4px;box-shadow:0 8px 28px rgba(0,0,0,0.18);overflow:hidden;transition:all .3s ease;max-height:260px;overflow-y:auto}\n .search-history-dropdown.no-scrollbar::-webkit-scrollbar{display:none}.search-history-dropdown.no-scrollbar{scrollbar-width:none;-ms-overflow-style:none}\n .search-history-dropdown.hidden-dropdown{max-height:0;opacity:0;pointer-events:none;margin-top:0}\n .history-item{padding:11px 16px;display:flex;align-items:center;gap:10px;cursor:pointer;transition:all .15s ease;border-bottom:1px solid rgba(0,0,0,0.04);font-size:12px;color:var(--text-primary)}.history-item:active{background:rgba(227,59,13,0.06)}.history-item i{color:var(--text-muted);font-size:10px}\n .clear-history-btn{display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;cursor:pointer;font-size:11px;color:var(--red-primary);letter-spacing:.05em;transition:all .15s ease;border-top:1px solid rgba(0,0,0,0.06)}.clear-history-btn:active{background:rgba(227,59,13,0.06)}.clear-history-btn i{font-size:10px}\n\n .btn-manage{width:34px;height:34px;border-radius:50%;border:1px solid rgba(227,59,13,0.28);background:transparent;color:var(--text-muted);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;flex-shrink:0}\n .btn-manage:active{background:rgba(227,59,13,0.10);color:var(--red-primary)}.btn-manage.active-manage{background:rgba(227,59,13,0.14);border-color:rgba(227,59,13,0.45);color:var(--red-accent)}.btn-manage i{font-size:14px}\n\n .drag-ghost{position:fixed;pointer-events:none;z-index:99;opacity:.85;transform:scale(1.05);box-shadow:0 14px 36px rgba(0,0,0,0.35);border-radius:10px;overflow:hidden;background:rgba(233,231,224,0.92);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(227,59,13,0.30)}\n\n .btn-back{width:32px;height:32px;border-radius:50%;border:1px solid rgba(255,255,255,0.40);background:rgba(233,231,224,0.55);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);color:var(--text-muted);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .25s ease;box-shadow:inset 0 1px 0 rgba(255,255,255,0.40)}.btn-back:active{background:rgba(227,59,13,0.10);color:var(--red-primary)}\n\n .nav-item{cursor:pointer;transition:all .3s ease;color:var(--text-on-dark-secondary);font-family:'Josefin Sans',sans-serif;font-weight:300;letter-spacing:.06em;font-size:12px;display:flex;align-items:center;gap:8px;padding:6px 14px;border-radius:20px;background:transparent;border:1px solid transparent}\n .nav-item.active{color:var(--red-accent);font-weight:400;background:rgba(227,59,13,0.10);border:1px solid rgba(255,255,255,0.10);box-shadow:inset 0 1px 0 rgba(255,255,255,0.06)}.nav-item i{font-size:14px}\n\n .btn-account{width:36px;height:36px;border-radius:50%;border:1px solid rgba(255,255,255,0.18);background:rgba(47,47,47,0.55);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);color:var(--text-on-dark-secondary);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .25s ease;position:relative;overflow:visible;box-shadow:inset 0 1px 0 rgba(255,255,255,0.08),0 2px 8px rgba(0,0,0,0.25)}\n .btn-account:active{background:rgba(227,59,13,0.20);color:var(--text-on-dark)}.btn-account .note-icon{position:relative;z-index:2;font-size:12px;color:var(--red-primary)}\n .btn-account::after{content:'';position:absolute;inset:-3px;border-radius:50%;border:1px dashed rgba(227,59,13,0.20);pointer-events:none;animation:gearRotate 12s linear infinite}@keyframes gearRotate{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}\n\n .sidebar-overlay{position:absolute;inset:0;z-index:45;background:rgba(0,0,0,0.40);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);transition:opacity .35s ease;pointer-events:auto}.sidebar-overlay.hidden-overlay{opacity:0;pointer-events:none}\n .sidebar-panel{position:absolute;top:0;right:0;bottom:0;width:75%;z-index:46;background:rgba(35,33,31,0.78);backdrop-filter:blur(22px);-webkit-backdrop-filter:blur(22px);box-shadow:-8px 0 35px rgba(0,0,0,0.50),inset -1px 0 0 rgba(255,255,255,0.06);border-left:0.5px solid rgba(255,255,255,0.08);transition:transform .35s cubic-bezier(.25,.46,.45,.94);display:flex;flex-direction:column;overflow-y:auto}\n .sidebar-panel.hidden-sidebar{transform:translateX(105%)}.sidebar-panel.visible-sidebar{transform:translateX(0)}\n .sidebar-section{border-bottom:0.5px solid rgba(255,255,255,0.05);padding:14px 18px}\n .sidebar-item{display:flex;align-items:center;gap:12px;cursor:pointer;transition:all .2s ease;color:var(--text-on-dark-secondary);font-size:13px;letter-spacing:.04em;border-radius:8px;padding:10px 10px;margin:2px -6px}.sidebar-item:active{color:var(--red-accent);background:rgba(255,255,255,0.04)}.sidebar-item i{width:20px;text-align:center;font-size:13px}\n .avatar-ring{border:2px solid rgba(255,255,255,0.20);box-shadow:0 0 20px rgba(227,59,13,0.15),inset 0 0 8px rgba(255,255,255,0.04)}\n\n .app-logo{width:32px;height:32px;position:relative;display:flex;align-items:center;justify-content:center}\n .app-logo .logo-diamond{width:20px;height:20px;border:1.2px solid var(--red-primary);transform:rotate(45deg);position:absolute;opacity:.85}\n .app-logo .logo-diamond-inner{width:10px;height:10px;border:0.8px solid rgba(227,59,13,0.45);transform:rotate(45deg);position:absolute}\n .app-logo .logo-staff{position:absolute;display:flex;flex-direction:column;gap:2.5px;align-items:center;z-index:1}.app-logo .logo-staff span{display:block;height:.6px;background:var(--red-primary);border-radius:1px}\n .app-logo .logo-dot{width:3px;height:3px;background:var(--red-accent);border-radius:50%;position:absolute;bottom:4px;z-index:2}\n .font-calligraphy{font-family:'Liu Jian Mao Cao','Ma Shan Zheng',cursive;font-weight:400}\n\n .btn-add-lib{display:flex;align-items:center;justify-content:center;gap:6px;padding:10px;border-radius:8px;border:1.5px dashed rgba(227,59,13,0.30);color:var(--red-primary);font-size:12px;letter-spacing:.05em;cursor:pointer;transition:all .2s ease;background:rgba(233,231,224,0.35)}.btn-add-lib:active{background:rgba(227,59,13,0.08);border-color:rgba(227,59,13,0.50)}\n\n .tab-panel{transition:opacity .4s ease,transform .4s ease}.tab-panel.hidden-panel{opacity:0;pointer-events:none;position:absolute;transform:translateY(6px)}.tab-panel.visible-panel{opacity:1;pointer-events:auto;position:relative;transform:translateY(0)}\n\n .no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{scrollbar-width:none;-ms-overflow-style:none}\n .sub-cover-placeholder{width:100%;height:100%;background:linear-gradient(160deg,#3a3532 0%,#2f2b28 50%,#1f1c1a 100%);display:flex;align-items:center;justify-content:center}\n </style>\n</head>\n<body>\n <div class=\"app-root\">\n <div class=\"w-full flex items-center justify-between px-6 shrink-0 relative z-30\" style=\"height:34px;background:#1f1e1c\"><span class=\"text-[11px] text-[#b0a89e] font-['Josefin_Sans'] tracking-wide\">15:00</span><div class=\"flex items-center gap-1.5\"><div class=\"w-3 h-3 rounded-full border border-[#5e5850] flex items-center justify-center\"><div class=\"w-[6px] h-[6px] rounded-full bg-[#8a8278]\"></div></div><span class=\"text-[10px] text-[#b0a89e]\">88%</span></div></div>\n <div class=\"w-full shrink-0 nav-top\"><div class=\"flex items-center justify-between px-5 py-2.5\"><div class=\"app-logo\" aria-label=\"曲谱应用\"><div class=\"logo-diamond\"></div><div class=\"logo-diamond-inner\"></div><div class=\"logo-staff\"><span style=\"width:11px;\"></span><span style=\"width:9px;\"></span><span style=\"width:11px;\"></span></div><div class=\"logo-dot\"></div></div><button class=\"btn-account\" aria-label=\"账号\" onclick=\"openSidebar()\"><i class=\"fa-solid fa-music note-icon\"></i></button></div></div>\n\n <div class=\"relative flex-1 overflow-hidden\" style=\"min-height:0;z-index:15\">\n <div id=\"tab-panel-0\" class=\"tab-panel visible-panel h-full w-full flex flex-col\" style=\"background:#e9e7e0\">\n <div class=\"relative px-5 pt-4 pb-1 z-10 shrink-0\"><div class=\"flex items-center gap-2 mb-0.5\"><div class=\"w-5 h-[1px] bg-[#e33b0d] opacity-35\"></div><span class=\"text-[9px] tracking-[0.15em] text-[#8b7670] font-['Josefin_Sans'] font-light uppercase\">Commendatio</span><div class=\"flex-1 h-[1px] bg-[#e33b0d] opacity-18\"></div></div></div>\n <div class=\"flex-1 overflow-y-auto no-scrollbar z-10 relative px-4 pb-2\">\n <div class=\"stack-card-wrap mb-4\" onclick=\"openSubCollection('古典精选','周杰伦')\"><div class=\"stack-card-back\"><img src=\"/assets/images/16-9/business-04.jpg\" alt=\"\" loading=\"lazy\"></div><div class=\"stack-card-front\"><img src=\"/assets/images/business/business-25.jpg\" alt=\"\" loading=\"lazy\"></div><span class=\"stack-label\">古典精选 · 经典永恒</span></div>\n <div class=\"flex items-center gap-2 mb-3\"><div class=\"w-4 h-[1px] bg-[#e33b0d] opacity-40\"></div><span class=\"text-[11px] tracking-[0.10em] text-[#5c4046] font-['Josefin_Sans'] font-semibold uppercase\">热门精选</span><div class=\"flex-1 h-[1px] bg-[#e33b0d] opacity-15\"></div></div>\n <div class=\"grid grid-cols-2 gap-3 mb-4\"><div class=\"rec-mini-card\" style=\"width:auto\" onclick=\"openSubCollection('肖邦夜曲','陈奕迅')\"><img src=\"/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg\" alt=\"\" loading=\"lazy\"><div class=\"rec-mini-label\">肖邦夜曲全集</div></div><div class=\"rec-mini-card\" style=\"width:auto\" onclick=\"openSubCollection('巴赫平均律','周杰伦')\"><img src=\"/assets/images/education/education-1.jpg\" alt=\"\" loading=\"lazy\"><div class=\"rec-mini-label\">巴赫平均律</div></div></div>\n <div class=\"flex items-center gap-2 mb-3\"><div class=\"w-4 h-[1px] bg-[#e33b0d] opacity-40\"></div><span class=\"text-[11px] tracking-[0.10em] text-[#5c4046] font-['Josefin_Sans'] font-semibold uppercase\">编辑推荐</span><div class=\"flex-1 h-[1px] bg-[#e33b0d] opacity-15\"></div></div>\n <div class=\"flex gap-3 overflow-x-auto no-scrollbar pb-2\"><div class=\"rec-mini-card\" onclick=\"openSubCollection('德彪西意象集','林俊杰')\"><img src=\"/assets/images/cases/porto2.jpg\" alt=\"\" loading=\"lazy\"><div class=\"rec-mini-label\">德彪西意象集</div></div><div class=\"rec-mini-card\" onclick=\"openSubCollection('拉赫玛尼诺夫','邓紫棋')\"><img src=\"/assets/images/16-9/business-03.jpg\" alt=\"\" loading=\"lazy\"><div class=\"rec-mini-label\">拉赫玛尼诺夫</div></div><div class=\"rec-mini-card\" onclick=\"openSubCollection('舒伯特艺术歌曲','五月天')\"><img src=\"/assets/images/fashion-lifestyle/fashion-lifestyle-4.jpg\" alt=\"\" loading=\"lazy\"><div class=\"rec-mini-label\">舒伯特艺术歌曲</div></div></div>\n </div>\n <div class=\"px-5 pb-2 relative z-10 shrink-0\"><div class=\"flex items-center gap-2\"><div class=\"flex-1 h-[1px] bg-[#e33b0d] opacity-12\"></div><div class=\"flex gap-1\"><div class=\"w-1 h-1 bg-[#e33b0d] opacity-35\"></div><div class=\"w-2 h-1 bg-[#e33b0d] opacity-25\"></div><div class=\"w-1 h-1 bg-[#e33b0d] opacity-35\"></div></div><div class=\"flex-1 h-[1px] bg-[#e33b0d] opacity-12\"></div></div></div>\n </div>\n\n <div id=\"tab-panel-1\" class=\"tab-panel hidden-panel h-full w-full flex flex-col\" style=\"background:#e9e7e0\">\n <div class=\"shrink-0 px-4 pt-3 pb-2 relative\" style=\"z-index:28\"><div class=\"relative flex items-center gap-2\" id=\"search-wrapper\"><div class=\"search-bar\" id=\"search-bar\" onclick=\"toggleSearchHistory()\"><i class=\"fa-solid fa-magnifying-glass\"></i><span id=\"search-placeholder\">搜索曲谱…</span></div><div class=\"search-history-dropdown no-scrollbar hidden-dropdown\" id=\"search-dropdown\"><div id=\"history-list\"><div class=\"history-item\" onclick=\"selectHistory('贝多芬月光奏鸣曲')\"><i class=\"fa-solid fa-clock-rotate-left\"></i><span>贝多芬月光奏鸣曲</span></div><div class=\"history-item\" onclick=\"selectHistory('莫扎特钢琴协奏曲')\"><i class=\"fa-solid fa-clock-rotate-left\"></i><span>莫扎特钢琴协奏曲</span></div><div class=\"history-item\" onclick=\"selectHistory('肖邦夜曲全集')\"><i class=\"fa-solid fa-clock-rotate-left\"></i><span>肖邦夜曲全集</span></div><div class=\"history-item\" onclick=\"selectHistory('巴赫平均律曲集')\"><i class=\"fa-solid fa-clock-rotate-left\"></i><span>巴赫平均律曲集</span></div></div><div class=\"clear-history-btn\" onclick=\"clearSearchHistory()\"><i class=\"fa-solid fa-trash-can\"></i><span>清除搜索历史</span></div></div><button class=\"btn-manage\" id=\"btn-manage\" onclick=\"toggleManageMode()\" aria-label=\"管理曲库\"><i class=\"fa-solid fa-pen-to-square\"></i></button></div></div>\n <div class=\"px-4 shrink-0 relative\" style=\"z-index:10\"><div class=\"h-[1px]\" style=\"background:linear-gradient(90deg,transparent,rgba(227,59,13,0.20),transparent)\"></div></div>\n <div class=\"flex-1 px-4 overflow-y-auto no-scrollbar relative pt-2 pb-1\" style=\"z-index:5\" id=\"lib-scroll-area\">\n <div class=\"grid grid-cols-2 gap-3\" id=\"lib-grid\">\n <div class=\"lib-card\" id=\"lib-mine\" data-lib=\"我的曲库\" data-locked=\"true\" onclick=\"handleLibClick('我的曲库','周杰伦')\"><div class=\"card-cover\"><img src=\"/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg\" alt=\"\" loading=\"lazy\"></div><div class=\"vinyl-peek\"><div class=\"vinyl-mini\"><div class=\"vinyl-shine\"></div></div></div><div class=\"card-info\"><div class=\"card-name\">我的曲库</div><div class=\"card-count\">7 首曲目</div></div></div>\n <div class=\"lib-card\" id=\"lib-1\" data-lib=\"古典奏鸣曲集\" data-locked=\"false\" data-cover=\"/assets/images/business/business-25.jpg\" onclick=\"handleLibClick('古典奏鸣曲集','周杰伦')\"><div class=\"drag-handle\">⠿</div><div class=\"del-btn\" id=\"del-1\" onclick=\"event.stopPropagation();deleteLib('lib-1')\"><i class=\"fa-solid fa-xmark\"></i></div><div class=\"cover-overlay-card\" id=\"cover-overlay-1\" onclick=\"event.stopPropagation();changeCover('1')\"><i class=\"fa-solid fa-camera\"></i></div><div class=\"card-cover\"><img src=\"/assets/images/business/business-25.jpg\" alt=\"\" loading=\"lazy\" id=\"cover-img-1\"></div><div class=\"vinyl-peek\"><div class=\"vinyl-mini\"><div class=\"vinyl-shine\"></div></div></div><div class=\"card-info\"><div class=\"card-name\">古典奏鸣曲集</div><div class=\"card-count\">12 首曲目</div></div></div>\n <div class=\"lib-card\" id=\"lib-2\" data-lib=\"浪漫钢琴选\" data-locked=\"false\" data-cover=\"/assets/images/fashion-lifestyle/fashion-lifestyle-4.jpg\" onclick=\"handleLibClick('浪漫钢琴选','陈奕迅')\"><div class=\"drag-handle\">⠿</div><div class=\"del-btn\" id=\"del-2\" onclick=\"event.stopPropagation();deleteLib('lib-2')\"><i class=\"fa-solid fa-xmark\"></i></div><div class=\"cover-overlay-card\" id=\"cover-overlay-2\" onclick=\"event.stopPropagation();changeCover('2')\"><i class=\"fa-solid fa-camera\"></i></div><div class=\"card-cover\"><img src=\"/assets/images/fashion-lifestyle/fashion-lifestyle-4.jpg\" alt=\"\" loading=\"lazy\" id=\"cover-img-2\"></div><div class=\"vinyl-peek\"><div class=\"vinyl-mini\"><div class=\"vinyl-shine\"></div></div></div><div class=\"card-info\"><div class=\"card-name\">浪漫钢琴选</div><div class=\"card-count\">8 首曲目</div></div></div>\n <div class=\"lib-card\" id=\"lib-3\" data-lib=\"交响乐珍藏\" data-locked=\"false\" data-cover=\"/assets/images/cases/porto2.jpg\" onclick=\"handleLibClick('交响乐珍藏','林俊杰')\"><div class=\"drag-handle\">⠿</div><div class=\"del-btn\" id=\"del-3\" onclick=\"event.stopPropagation();deleteLib('lib-3')\"><i class=\"fa-solid fa-xmark\"></i></div><div class=\"cover-overlay-card\" id=\"cover-overlay-3\" onclick=\"event.stopPropagation();changeCover('3')\"><i class=\"fa-solid fa-camera\"></i></div><div class=\"card-cover\"><img src=\"/assets/images/cases/porto2.jpg\" alt=\"\" loading=\"lazy\" id=\"cover-img-3\"></div><div class=\"vinyl-peek\"><div class=\"vinyl-mini\"><div class=\"vinyl-shine\"></div></div></div><div class=\"card-info\"><div class=\"card-name\">交响乐珍藏</div><div class=\"card-count\">15 首曲目</div></div></div>\n <div class=\"lib-card\" id=\"lib-4\" data-lib=\"巴洛克精选\" data-locked=\"false\" data-cover=\"/assets/images/16-9/business-03.jpg\" onclick=\"handleLibClick('巴洛克精选','邓紫棋')\"><div class=\"drag-handle\">⠿</div><div class=\"del-btn\" id=\"del-4\" onclick=\"event.stopPropagation();deleteLib('lib-4')\"><i class=\"fa-solid fa-xmark\"></i></div><div class=\"cover-overlay-card\" id=\"cover-overlay-4\" onclick=\"event.stopPropagation();changeCover('4')\"><i class=\"fa-solid fa-camera\"></i></div><div class=\"card-cover\"><img src=\"/assets/images/16-9/business-03.jpg\" alt=\"\" loading=\"lazy\" id=\"cover-img-4\"></div><div class=\"vinyl-peek\"><div class=\"vinyl-mini\"><div class=\"vinyl-shine\"></div></div></div><div class=\"card-info\"><div class=\"card-name\">巴洛克精选</div><div class=\"card-count\">5 首曲目</div></div></div>\n <div class=\"lib-card\" id=\"lib-5\" data-lib=\"现代作品集\" data-locked=\"false\" data-cover=\"/assets/images/education/education-1.jpg\" onclick=\"handleLibClick('现代作品集','五月天')\"><div class=\"drag-handle\">⠿</div><div class=\"del-btn\" id=\"del-5\" onclick=\"event.stopPropagation();deleteLib('lib-5')\"><i class=\"fa-solid fa-xmark\"></i></div><div class=\"cover-overlay-card\" id=\"cover-overlay-5\" onclick=\"event.stopPropagation();changeCover('5')\"><i class=\"fa-solid fa-camera\"></i></div><div class=\"card-cover\"><img src=\"/assets/images/education/education-1.jpg\" alt=\"\" loading=\"lazy\" id=\"cover-img-5\"></div><div class=\"vinyl-peek\"><div class=\"vinyl-mini\"><div class=\"vinyl-shine\"></div></div></div><div class=\"card-info\"><div class=\"card-name\">现代作品集</div><div class=\"card-count\">9 首曲目</div></div></div>\n </div>\n <div class=\"btn-add-lib mt-3 mb-2\" onclick=\"addNewLib()\"><i class=\"fa-solid fa-plus text-[11px]\"></i><span>新增曲库</span></div>\n </div>\n </div>\n\n <!-- ===== 子曲谱视图 ===== -->\n <div id=\"sub-collection-view\" class=\"sub-view hidden-sub\">\n <div class=\"flex items-center gap-2 px-4 pt-3 pb-1 z-10\"><button class=\"btn-back\" onclick=\"closeSubCollection()\" aria-label=\"返回\"><i class=\"fa-solid fa-arrow-left text-[11px]\"></i></button><div class=\"w-5 h-[1px] bg-[#e33b0d] opacity-35\"></div><span class=\"text-[9px] tracking-[0.12em] text-[#8b7670] font-['Josefin_Sans'] font-light uppercase\">shorthand of emotion</span><div class=\"flex-1 h-[1px] bg-[#e33b0d] opacity-18\"></div></div>\n <div class=\"sub-header\">\n <div class=\"sub-cover-wrap\" onclick=\"event.stopPropagation();changeSubCover()\">\n <img id=\"sub-cover-img\" src=\"/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg\" alt=\"\" loading=\"lazy\">\n <div class=\"vinyl-peek-sub\"><div class=\"vinyl-mini\"><div class=\"vinyl-shine\"></div></div></div>\n <div class=\"cover-tap-hint\"><i class=\"fa-solid fa-camera\"></i></div>\n </div>\n <div class=\"sub-info\">\n <div class=\"lib-name\" id=\"sub-lib-name\" contenteditable=\"true\" onfocus=\"this._prev=this.textContent\" onblur=\"saveLibName(this)\" onkeydown=\"if(event.key==='Enter'){this.blur();event.preventDefault()}\">我的曲库</div>\n <button class=\"btn-import-inline\" onclick=\"event.stopPropagation();alert('导入曲谱')\"><i class=\"fa-solid fa-plus text-[9px]\"></i> 导入曲谱</button>\n <div class=\"lib-meta\" id=\"sub-lib-meta\">共 5 首曲目</div>\n </div>\n </div>\n <div class=\"px-4\"><div class=\"h-[1px]\" style=\"background:linear-gradient(90deg,transparent,rgba(227,59,13,0.20),transparent)\"></div></div>\n <!-- 排序+搜索行 -->\n <div class=\"toolbar-row\">\n <div class=\"search-inline-wrap\">\n <button class=\"btn-search-toggle\" id=\"btn-search-toggle\" onclick=\"toggleInlineSearch()\"><i class=\"fa-solid fa-magnifying-glass\" style=\"font-size:11px\"></i></button>\n <input class=\"search-input-inline\" id=\"search-input-inline\" type=\"text\" placeholder=\"搜索曲目…\" oninput=\"filterSongRows()\">\n </div>\n <div class=\"sort-dropdown-wrap\">\n <div class=\"sort-toggle\" id=\"sort-toggle\" onclick=\"event.stopPropagation();toggleSortDropdown()\"><i class=\"fa-solid fa-arrow-down-wide-short\"></i><span id=\"sort-label\">排序方式</span><i class=\"fa-solid fa-chevron-down\" style=\"font-size:8px\"></i></div>\n </div>\n </div>\n <!-- 曲目列表 -->\n <div class=\"sub-song-list no-scrollbar\" id=\"sub-song-list\">\n <div class=\"song-row\" onclick=\"closeAllPopups()\"><span class=\"song-index\">I</span><div class=\"song-body\"><div class=\"song-title\">晴天</div></div><div class=\"song-more-btn\" onclick=\"event.stopPropagation();toggleSongPopup(event)\">···</div></div>\n <div class=\"song-row\" onclick=\"closeAllPopups()\"><span class=\"song-index\">II</span><div class=\"song-body\"><div class=\"song-title\">十年</div></div><div class=\"song-more-btn\" onclick=\"event.stopPropagation();toggleSongPopup(event)\">···</div></div>\n <div class=\"song-row\" onclick=\"closeAllPopups()\"><span class=\"song-index\">III</span><div class=\"song-body\"><div class=\"song-title\">修炼爱情</div></div><div class=\"song-more-btn\" onclick=\"event.stopPropagation();toggleSongPopup(event)\">···</div></div>\n <div class=\"song-row\" onclick=\"closeAllPopups()\"><span class=\"song-index\">IV</span><div class=\"song-body\"><div class=\"song-title\">光年之外</div></div><div class=\"song-more-btn\" onclick=\"event.stopPropagation();toggleSongPopup(event)\">···</div></div>\n <div class=\"song-row\" onclick=\"closeAllPopups()\"><span class=\"song-index\">V</span><div class=\"song-body\"><div class=\"song-title\">突然好想你</div></div><div class=\"song-more-btn\" onclick=\"event.stopPropagation();toggleSongPopup(event)\">···</div></div>\n </div>\n </div>\n </div>\n\n <div class=\"w-full shrink-0 bottom-nav-container\"><div class=\"flex items-center justify-center gap-20 relative\" style=\"height:42px\"><button class=\"nav-item active\" id=\"nav-home\" onclick=\"switchTab(0)\"><i class=\"fa-solid fa-house\"></i><span>首页</span></button><button class=\"nav-item\" id=\"nav-library\" onclick=\"switchTab(1)\"><i class=\"fa-solid fa-compact-disc\"></i><span>曲库</span></button></div></div>\n\n <div id=\"sidebar-overlay\" class=\"sidebar-overlay hidden-overlay\" onclick=\"closeSidebar()\"></div>\n <div id=\"sidebar-panel\" class=\"sidebar-panel hidden-sidebar\">\n <div class=\"sidebar-section flex flex-col items-center pt-6 pb-4 gap-3\"><div class=\"w-16 h-16 rounded-full avatar-ring flex items-center justify-center\" style=\"background:rgba(37,35,33,0.60)\"><i class=\"fa-solid fa-user-astronaut text-2xl\" style=\"color:var(--red-primary)\"></i></div><p class=\"text-[15px] font-['Josefin_Sans'] font-semibold tracking-wider\" style=\"color:var(--text-on-dark)\">Vintage Musician</p><span class=\"text-[10px] tracking-[0.1em] px-3 py-0.5 rounded-full\" style=\"background:rgba(227,59,13,0.14);color:var(--red-accent);border:1px solid rgba(227,59,13,0.22)\">PRO 会员</span></div>\n <div class=\"sidebar-section\"><div class=\"flex items-center justify-between mb-2\"><span class=\"text-[11px] tracking-wider\" style=\"color:var(--text-on-dark-secondary)\">云端存储</span><span class=\"text-[11px]\" style=\"color:var(--red-accent)\">2.1 / 5.0 GB</span></div><div class=\"w-full h-2 rounded-full\" style=\"background:rgba(0,0,0,0.35)\"><div class=\"h-full rounded-full\" style=\"width:42%;background:var(--red-primary)\"></div></div></div>\n <div class=\"sidebar-section\" style=\"border-bottom:none\"><div class=\"sidebar-item\"><i class=\"fa-solid fa-palette\"></i><span>外观设置</span><i class=\"fa-solid fa-chevron-right text-[9px] ml-auto opacity-30\"></i></div><div class=\"sidebar-item\"><i class=\"fa-solid fa-bell\"></i><span>通知偏好</span><i class=\"fa-solid fa-chevron-right text-[9px] ml-auto opacity-30\"></i></div><div class=\"sidebar-item\"><i class=\"fa-solid fa-cloud-arrow-up\"></i><span>数据同步</span><i class=\"fa-solid fa-chevron-right text-[9px] ml-auto opacity-30\"></i></div><div class=\"sidebar-item\"><i class=\"fa-solid fa-circle-info\"></i><span>关于应用</span><i class=\"fa-solid fa-chevron-right text-[9px] ml-auto opacity-30\"></i></div></div>\n <div class=\"sidebar-section\" style=\"border-bottom:none;margin-top:auto;padding-bottom:20px\"><div class=\"sidebar-item\" style=\"color:var(--red-primary)\"><i class=\"fa-solid fa-arrow-right-from-bracket\"></i><span>退出登录</span></div></div>\n </div>\n </div>\n\n <script>\n let manageMode = false;\n let dragCard = null, dragGhost = null;\n let dragStartX = 0, dragStartY = 0, dragOrigRect = null;\n\n function switchTab(i){const p=[document.getElementById('tab-panel-0'),document.getElementById('tab-panel-1')],n=[document.getElementById('nav-home'),document.getElementById('nav-library')];p.forEach((e,x)=>{if(x===i){e.classList.remove('hidden-panel');e.classList.add('visible-panel')}else{e.classList.remove('visible-panel');e.classList.add('hidden-panel')}});n.forEach((e,x)=>{if(e){if(x===i)e.classList.add('active');else e.classList.remove('active')}});closeSubCollection();exitManageMode();closeSearchHistory()}\n\n function openSubCollection(title,composer){if(manageMode)return;document.getElementById('sub-lib-name').textContent=title;hideInlineSearch();const sv=document.getElementById('sub-collection-view');sv.classList.remove('hidden-sub');sv.classList.add('visible-sub')}\n function closeSubCollection(){const sv=document.getElementById('sub-collection-view');sv.classList.remove('visible-sub');sv.classList.add('hidden-sub');closeAllPopups();closeSortDropdown();hideInlineSearch()}\n function handleLibClick(title,composer){if(manageMode)return;openSubCollection(title,composer)}\n\n function toggleManageMode(){manageMode=!manageMode;const btn=document.getElementById('btn-manage');if(manageMode){btn.classList.add('active-manage');document.querySelectorAll('.lib-card[data-locked=\"false\"] .del-btn').forEach(b=>b.classList.add('show-del'));document.querySelectorAll('.lib-card[data-locked=\"false\"] .drag-handle').forEach(b=>b.classList.add('show-handle'));document.querySelectorAll('.lib-card[data-locked=\"false\"] .cover-overlay-card').forEach(b=>b.classList.add('show-cover'))}else{exitManageMode()}}\n function exitManageMode(){manageMode=false;document.getElementById('btn-manage').classList.remove('active-manage');document.querySelectorAll('.del-btn').forEach(b=>b.classList.remove('show-del'));document.querySelectorAll('.drag-handle').forEach(b=>b.classList.remove('show-handle'));document.querySelectorAll('.cover-overlay-card').forEach(b=>b.classList.remove('show-cover'));cleanupDrag()}\n\n function deleteLib(id){const c=document.getElementById(id);if(c){c.style.transition='all .3s ease';c.style.opacity='0';c.style.transform='scale(0.8)';setTimeout(()=>c.remove(),300)}}\n function changeCover(libId){const url=prompt('请输入封面图片URL(留空恢复默认):');const img=document.getElementById('cover-img-'+libId);if(!img)return;if(url&&url.trim()){img.src=url.trim()}else{const def=document.getElementById('lib-'+libId)?.getAttribute('data-cover');img.src=def||''}}\n\n function addNewLib(){const name=prompt('请输入新曲库名称:');if(name&&name.trim()){const grid=document.getElementById('lib-grid');const newId='lib-'+Date.now();const div=document.createElement('div');div.className='lib-card';div.id=newId;div.setAttribute('data-lib',name.trim());div.setAttribute('data-locked','false');div.setAttribute('data-cover','');div.setAttribute('onclick',`handleLibClick('${name.trim().replace(/'/g,\"\\\\'\")}','自建曲库')`);div.innerHTML=`<div class=\"drag-handle\">⠿</div><div class=\"del-btn\" id=\"del-${newId}\" onclick=\"event.stopPropagation();deleteLib('${newId}')\"><i class=\"fa-solid fa-xmark\"></i></div><div class=\"cover-overlay-card\" id=\"cover-overlay-${newId}\" onclick=\"event.stopPropagation();changeCover('${newId}')\"><i class=\"fa-solid fa-camera\"></i></div><div class=\"card-cover\"><div class=\"cover-placeholder\"></div></div><div class=\"vinyl-peek\"><div class=\"vinyl-mini\"><div class=\"vinyl-shine\"></div></div></div><div class=\"card-info\"><div class=\"card-name\">${name.trim()}</div><div class=\"card-count\">0 首曲目</div></div>`;grid.appendChild(div);bindDragEvents(div);if(manageMode){div.querySelector('.del-btn').classList.add('show-del');div.querySelector('.drag-handle').classList.add('show-handle');div.querySelector('.cover-overlay-card').classList.add('show-cover')}}}\n\n function bindDragEvents(card){const h=card.querySelector('.drag-handle');if(!h)return;h.addEventListener('touchstart',onDragStart,{passive:false});h.addEventListener('mousedown',onDragStart)}\n function hideAllDelButtons(){document.querySelectorAll('.del-btn.show-del').forEach(b=>b.classList.remove('show-del'))}\n function restoreAllDelButtons(){if(!manageMode)return;document.querySelectorAll('.lib-card[data-locked=\"false\"] .del-btn').forEach(b=>b.classList.add('show-del'))}\n\n function onDragStart(e){if(!manageMode)return;e.preventDefault();const h=e.target.closest('.drag-handle');if(!h||!h.classList.contains('show-handle'))return;dragCard=h.closest('.lib-card');if(!dragCard||dragCard.getAttribute('data-locked')==='true'){dragCard=null;return};hideAllDelButtons();const t=e.touches?e.touches[0]:e;dragStartX=t.clientX;dragStartY=t.clientY;dragOrigRect=dragCard.getBoundingClientRect();dragGhost=dragCard.cloneNode(true);const gd=dragGhost.querySelector('.del-btn');if(gd)gd.classList.remove('show-del');const gh=dragGhost.querySelector('.drag-handle');if(gh)gh.classList.remove('show-handle');const gc=dragGhost.querySelector('.cover-overlay-card');if(gc)gc.classList.remove('show-cover');dragGhost.classList.add('drag-ghost');dragGhost.style.width=dragOrigRect.width+'px';dragGhost.style.height=dragOrigRect.height+'px';dragGhost.style.left=dragOrigRect.left+'px';dragGhost.style.top=dragOrigRect.top+'px';document.body.appendChild(dragGhost);dragCard.classList.add('dragging');document.addEventListener('touchmove',onDragMove,{passive:false});document.addEventListener('touchend',onDragEnd);document.addEventListener('mousemove',onDragMove);document.addEventListener('mouseup',onDragEnd)}\n function onDragMove(e){if(!dragCard||!dragGhost)return;e.preventDefault();const t=e.touches?e.touches[0]:e;dragGhost.style.left=(dragOrigRect.left+(t.clientX-dragStartX))+'px';dragGhost.style.top=(dragOrigRect.top+(t.clientY-dragStartY))+'px'}\n function onDragEnd(e){document.removeEventListener('touchmove',onDragMove);document.removeEventListener('touchend',onDragEnd);document.removeEventListener('mousemove',onDragMove);document.removeEventListener('mouseup',onDragEnd);if(!dragCard||!dragGhost){cleanupDrag();return};const gr=dragGhost.getBoundingClientRect();const gcx=gr.left+gr.width/2,gcy=gr.top+gr.height/2;const grid=document.getElementById('lib-grid');const cards=Array.from(grid.querySelectorAll('.lib-card')).filter(c=>c!==dragCard);let target=null,min=Infinity;cards.forEach(c=>{const r=c.getBoundingClientRect();const d=Math.hypot(gcx-(r.left+r.width/2),gcy-(r.top+r.height/2));if(d<min){min=d;target=c}});if(target&&min<130){const all=Array.from(grid.children);const iD=all.indexOf(dragCard),iT=all.indexOf(target);if(iD<iT)grid.insertBefore(dragCard,target.nextSibling);else grid.insertBefore(dragCard,target)};cleanupDrag()}\n function cleanupDrag(){restoreAllDelButtons();if(dragCard)dragCard.classList.remove('dragging');if(dragGhost){dragGhost.remove();dragGhost=null};dragCard=null;dragOrigRect=null}\n\n function toggleSearchHistory(){if(manageMode)return;const dd=document.getElementById('search-dropdown'),sb=document.getElementById('search-bar');if(dd.classList.contains('hidden-dropdown')){dd.classList.remove('hidden-dropdown');sb.classList.add('focused')}else{closeSearchHistory()}}\n function closeSearchHistory(){document.getElementById('search-dropdown').classList.add('hidden-dropdown');document.getElementById('search-bar').classList.remove('focused')}\n function selectHistory(t){document.getElementById('search-placeholder').textContent=t;closeSearchHistory()}\n function clearSearchHistory(){document.getElementById('history-list').innerHTML='';closeSearchHistory()}\n\n function changeSubCover(){const url=prompt('请输入封面图片URL(留空恢复默认):');const img=document.getElementById('sub-cover-img');if(!img)return;if(url&&url.trim()){img.src=url.trim()}else{img.src='/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg'}}\n\n function saveLibName(el){const v=el.textContent.trim();if(!v){el.textContent=el._prev||'未命名曲库'}el.scrollLeft=0}\n\n function toggleSortDropdown(){const existing=document.querySelector('.sort-dropdown');if(existing){existing.remove();return}closeAllPopups();const wrap=document.querySelector('.sort-dropdown-wrap');const dd=document.createElement('div');dd.className='sort-dropdown';dd.innerHTML=`<div class=\"sort-opt\" onclick=\"applySort('按名称排序')\"><i class=\"fa-solid fa-arrow-up-a-z\"></i>按名称排序</div><div class=\"sort-opt\" onclick=\"applySort('按时间排序')\"><i class=\"fa-regular fa-clock\"></i>按时间排序</div><div class=\"sort-opt\" onclick=\"applySort('按热度排序')\"><i class=\"fa-solid fa-fire\"></i>按热度排序</div>`;wrap.appendChild(dd);setTimeout(()=>document.addEventListener('click',function f(e){if(!e.target.closest('.sort-dropdown-wrap')){dd.remove();document.removeEventListener('click',f)}},{once:false}),10)}\n function closeSortDropdown(){const d=document.querySelector('.sort-dropdown');if(d)d.remove()}\n function applySort(label){document.getElementById('sort-label').textContent=label;closeSortDropdown()}\n\n function toggleInlineSearch(){const inp=document.getElementById('search-input-inline');const btn=document.getElementById('btn-search-toggle');if(inp.classList.contains('show-input')){hideInlineSearch()}else{inp.classList.add('show-input');inp.focus();btn.style.background='rgba(227,59,13,0.10)';btn.style.color='var(--red-primary)'}}\n function hideInlineSearch(){const inp=document.getElementById('search-input-inline');const btn=document.getElementById('btn-search-toggle');inp.classList.remove('show-input');inp.value='';btn.style.background='';btn.style.color='';filterSongRows()}\n function filterSongRows(){const q=document.getElementById('search-input-inline').value.trim().toLowerCase();document.querySelectorAll('#sub-song-list .song-row').forEach(r=>{const title=r.querySelector('.song-title')?.textContent.toLowerCase()||'';if(!q||title.includes(q)){r.classList.remove('hidden-row')}else{r.classList.add('hidden-row')}})}\n\n function toggleSongPopup(e){const btn=e.target.closest('.song-more-btn');if(!btn)return;const ex=document.querySelector('.song-action-popup');if(ex&&ex.parentElement===btn.parentElement){ex.remove();return};closeAllPopups();closeSortDropdown();const popup=document.createElement('div');popup.className='song-action-popup';popup.innerHTML=`<div class=\"action-item\" onclick=\"event.stopPropagation();closeAllPopups();\"><i class=\"fa-solid fa-thumbtack\"></i><span>置顶</span></div><div class=\"action-item danger\" onclick=\"event.stopPropagation();closeAllPopups();\"><i class=\"fa-regular fa-trash-can\"></i><span>删除</span></div><div class=\"action-item\" onclick=\"event.stopPropagation();closeAllPopups();\"><i class=\"fa-solid fa-share-nodes\"></i><span>分享</span></div>`;btn.parentElement.appendChild(popup);setTimeout(()=>document.addEventListener('click',closeAllPopupsOnce,{once:true}),10)}\n function closeAllPopups(){document.querySelectorAll('.song-action-popup').forEach(p=>p.remove())}\n function closeAllPopupsOnce(){closeAllPopups()}\n\n function openSidebar(){document.getElementById('sidebar-overlay').classList.remove('hidden-overlay');document.getElementById('sidebar-panel').classList.remove('hidden-sidebar');document.getElementById('sidebar-panel').classList.add('visible-sidebar')}\n function closeSidebar(){document.getElementById('sidebar-overlay').classList.add('hidden-overlay');document.getElementById('sidebar-panel').classList.remove('visible-sidebar');document.getElementById('sidebar-panel').classList.add('hidden-sidebar')}\n\n document.addEventListener('DOMContentLoaded',()=>{document.querySelectorAll('.lib-card[data-locked=\"false\"]').forEach(bindDragEvents);document.getElementById('tab-panel-1').addEventListener('click',function(e){if(!e.target.closest('#search-wrapper'))closeSearchHistory()})});\n </script>\n</body>\n</html>"
},
"next": [
"置顶功能联动列表更新",
"搜索结果为空时显示提示",
"排序功能串联实际重排",
"搜索框支持键盘输入优化",
"装饰艺术细节深化"
],
"breakpoint": "xs"
}
```
推理
现在我们分析一下用户的新需求:
1. **修改曲库名称就在页面上修改不用弹窗**:把 `lib-name` 改成 `contenteditable` 或者点击后原地变为可编辑状态(input 内联编辑),不需要 prompt 弹窗了。
2. **曲库名称与图片顶对齐**:目前 `.sub-header` 使用 `align-items: center`,需要改为 `align-items: flex-start`。
3. **导入按钮不要设置在封面上,放在曲库名称和"共多少曲目"之间**:把 `btn-import-corner` 从封面右下角移除,改为放在曲库名称下方、曲目数上方(即在 `lib-name` 和 `lib-meta` 之间),作为一个小按钮。或者放在 `lib-name` 同一行右侧?用户说"放在曲库名称和共多少曲目之间,注意间距合理"。我来理解一下——目前 sub-info 里是:lib-name 在上,lib-meta(共 x 首)在下。导入按钮放在它们之间,即 lib-name 下方、lib-meta 上方。
4. **排序功能放在右侧**:目前排序下拉在左侧(`.sort-dropdown-wrap` 是 left:16px),需要改为右侧对齐。
5. **新增搜索按钮,用于搜索曲库内曲目**:在排序旁边或附近新增一个搜索按钮,可以在曲目列表内搜索。可能需要一个搜索 input 或者点击后弹出搜索框。
另外,这个排序下拉和搜索按钮应该放在同一行——排序在右边,搜索按钮也在排序附近。可以让它们在同一行:左边放搜索按钮,右边放排序下拉,或者都放在右侧。
等等,用户说"排序功能放在右侧,新增搜索按钮,用于搜索曲库内曲目"。可以理解为:排序和搜索放在同一行,排序在右侧,搜索按钮在排序旁边。
让我把这些修改逐一实现:
1. `renameLib()` 不再使用 prompt,而是点击后将 `lib-name` 变成可编辑的 input(或者直接用 contenteditable)。其实用 contenteditable 最简单:设置 `contenteditable="true"`,点击后自动获得焦点,blur 时保存。
2. `.sub-header` 的 `align-items: center` → `align-items: flex-start`。
3. 新建 `btn-import-inline` 放在 `lib-name` 和 `lib-meta` 之间,移除 `.btn-import-corner`。
4. 排序下拉容器改为右侧对齐,搜索按钮新增在排序旁边。
5. 新增曲目搜索功能:在排序旁边加一个搜索图标按钮,点击弹出搜索输入框或直接在原地展开。
现在需要获取一些资产图片——不过当前设计使用的是已有的 assets 图片,不需要额外获取。但我可以先调用 get_assets 看看有没有合适的搜索相关图片,实际上不需要——我用 Font Awesome 的搜索图标即可。
好,开始修改。注意:曲谱详情页的子曲谱视图是在 `#sub-collection-view` 中。现在我需要在这个视图中添加搜索功能。
关于搜索按钮——可以用一个简单的搜索图标,点击后在曲目列表上方出现一个搜索输入框(或者覆盖在列表上方)。为了简洁,可以在排序那一行加入搜索图标按钮,点击后展开一个 inline 搜索框。
让我重新设计排序+搜索行:左侧搜索按钮+搜索输入框(默认隐藏),右侧排序下拉。或者更简单——搜索图标按钮点击后在原地展开输入框。
实际上更实用的做法:在排序旁边放一个搜索图标,点击后在曲目列表顶部出现一个搜索输入框(带取消按钮),可以实时过滤曲目。
不过为了简单,我先做一个点击搜索图标后出现一个小的搜索输入框在排序那一行。
等等——用户说"新增搜索按钮,用于搜索曲库内曲目"。那就是在子曲谱视图内搜索。我来在排序下拉旁边加一个搜索按钮,点击后展开一个搜索框。
好,现在开始编码。
还需要注意:`contenteditable` 的 lib-name 在失去焦点时保存新的名称。还有导入按钮的样式。
另外,关于封面点击换封面——目前 `sub-cover-wrap` 上有点击事件 `changeSubCover()`,这个保留。
现在还要考虑:用户之前说曲谱卡片不需要"作者"信息,我已经移除了。现在曲谱详情行只有曲名(song-title),没有 artist 了。
现在关于封面右下角的导入按钮——用户说不要放封面上,我要把它从 `.btn-import-corner` 移除,改为放在 sub-info 中 lib-name 和 lib-meta 之间。
好,现在开始写修改后的代码。改动点:
1. HTML 中 sub-header 部分:移除 `.btn-import-corner`(保留封面点击换封面功能),添加导入按钮到 sub-info 中。
2. CSS 中:添加 `.sub-header` align-items: flex-start,添加新导入按钮样式,搜索相关样式。
3. JS 中:renameLib 改为 contenteditable 方式,添加搜索功能。
关于搜索功能——我将添加一个简单的客户端过滤:点击搜索按钮后弹出搜索输入,实时过滤曲目列表中的行。
现在这个代码已经非常长了。我需要压缩一些样式。但根据要求要保持完整 HTML。让我尽量保持代码整洁。
有一件事需要注意——之前的 `.btn-import-corner` 样式要移除或保留但不在 HTML 中使用。
好,开始修改。
我还需要处理排序下拉的位置——从左侧移到右侧。目前 `.sort-dropdown-wrap` 中的 `.sort-dropdown` 是 `left:16px`,需要改为 `right:0` 或 `right:16px`。
此外,搜索按钮和排序放在同一行——我可以在 `.sort-dropdown-wrap` 中使用 flex 布局,左边搜索区右边排序区。
关于曲目搜索,我将实现简单的文本过滤:在曲目列表上方出现搜索框,输入文字后隐藏不匹配的行。
实际上更简洁的做法是:将搜索框放在排序同一行,点击搜索图标后展开输入框。
让我重新设计 sort-dropdown-wrap 为一行:
- 左侧:搜索图标按钮 + 搜索输入框(默认隐藏)
- 右侧:排序下拉按钮
这样整体布局更好。
另外注意:由于整个页面是 position:relative 的,搜索下拉和排序下拉的 z-index 需要足够高。
好,开始编写最终代码。由于代码量很大,我会尽量保持与之前版本的一致性,只做上述修改。
关于 `contenteditable`:点击 lib-name 后可以直接编辑。需要处理的是:如果用户清空了名称,要恢复默认值;按 Enter 键时 blur。我会在 JS 中添加相关事件处理。
现在开始输出。
1. **修改曲库名称就在页面上修改不用弹窗**:把 `lib-name` 改成 `contenteditable` 或者点击后原地变为可编辑状态(input 内联编辑),不需要 prompt 弹窗了。
2. **曲库名称与图片顶对齐**:目前 `.sub-header` 使用 `align-items: center`,需要改为 `align-items: flex-start`。
3. **导入按钮不要设置在封面上,放在曲库名称和"共多少曲目"之间**:把 `btn-import-corner` 从封面右下角移除,改为放在曲库名称下方、曲目数上方(即在 `lib-name` 和 `lib-meta` 之间),作为一个小按钮。或者放在 `lib-name` 同一行右侧?用户说"放在曲库名称和共多少曲目之间,注意间距合理"。我来理解一下——目前 sub-info 里是:lib-name 在上,lib-meta(共 x 首)在下。导入按钮放在它们之间,即 lib-name 下方、lib-meta 上方。
4. **排序功能放在右侧**:目前排序下拉在左侧(`.sort-dropdown-wrap` 是 left:16px),需要改为右侧对齐。
5. **新增搜索按钮,用于搜索曲库内曲目**:在排序旁边或附近新增一个搜索按钮,可以在曲目列表内搜索。可能需要一个搜索 input 或者点击后弹出搜索框。
另外,这个排序下拉和搜索按钮应该放在同一行——排序在右边,搜索按钮也在排序附近。可以让它们在同一行:左边放搜索按钮,右边放排序下拉,或者都放在右侧。
等等,用户说"排序功能放在右侧,新增搜索按钮,用于搜索曲库内曲目"。可以理解为:排序和搜索放在同一行,排序在右侧,搜索按钮在排序旁边。
让我把这些修改逐一实现:
1. `renameLib()` 不再使用 prompt,而是点击后将 `lib-name` 变成可编辑的 input(或者直接用 contenteditable)。其实用 contenteditable 最简单:设置 `contenteditable="true"`,点击后自动获得焦点,blur 时保存。
2. `.sub-header` 的 `align-items: center` → `align-items: flex-start`。
3. 新建 `btn-import-inline` 放在 `lib-name` 和 `lib-meta` 之间,移除 `.btn-import-corner`。
4. 排序下拉容器改为右侧对齐,搜索按钮新增在排序旁边。
5. 新增曲目搜索功能:在排序旁边加一个搜索图标按钮,点击弹出搜索输入框或直接在原地展开。
现在需要获取一些资产图片——不过当前设计使用的是已有的 assets 图片,不需要额外获取。但我可以先调用 get_assets 看看有没有合适的搜索相关图片,实际上不需要——我用 Font Awesome 的搜索图标即可。
好,开始修改。注意:曲谱详情页的子曲谱视图是在 `#sub-collection-view` 中。现在我需要在这个视图中添加搜索功能。
关于搜索按钮——可以用一个简单的搜索图标,点击后在曲目列表上方出现一个搜索输入框(或者覆盖在列表上方)。为了简洁,可以在排序那一行加入搜索图标按钮,点击后展开一个 inline 搜索框。
让我重新设计排序+搜索行:左侧搜索按钮+搜索输入框(默认隐藏),右侧排序下拉。或者更简单——搜索图标按钮点击后在原地展开输入框。
实际上更实用的做法:在排序旁边放一个搜索图标,点击后在曲目列表顶部出现一个搜索输入框(带取消按钮),可以实时过滤曲目。
不过为了简单,我先做一个点击搜索图标后出现一个小的搜索输入框在排序那一行。
等等——用户说"新增搜索按钮,用于搜索曲库内曲目"。那就是在子曲谱视图内搜索。我来在排序下拉旁边加一个搜索按钮,点击后展开一个搜索框。
好,现在开始编码。
还需要注意:`contenteditable` 的 lib-name 在失去焦点时保存新的名称。还有导入按钮的样式。
另外,关于封面点击换封面——目前 `sub-cover-wrap` 上有点击事件 `changeSubCover()`,这个保留。
现在还要考虑:用户之前说曲谱卡片不需要"作者"信息,我已经移除了。现在曲谱详情行只有曲名(song-title),没有 artist 了。
现在关于封面右下角的导入按钮——用户说不要放封面上,我要把它从 `.btn-import-corner` 移除,改为放在 sub-info 中 lib-name 和 lib-meta 之间。
好,现在开始写修改后的代码。改动点:
1. HTML 中 sub-header 部分:移除 `.btn-import-corner`(保留封面点击换封面功能),添加导入按钮到 sub-info 中。
2. CSS 中:添加 `.sub-header` align-items: flex-start,添加新导入按钮样式,搜索相关样式。
3. JS 中:renameLib 改为 contenteditable 方式,添加搜索功能。
关于搜索功能——我将添加一个简单的客户端过滤:点击搜索按钮后弹出搜索输入,实时过滤曲目列表中的行。
现在这个代码已经非常长了。我需要压缩一些样式。但根据要求要保持完整 HTML。让我尽量保持代码整洁。
有一件事需要注意——之前的 `.btn-import-corner` 样式要移除或保留但不在 HTML 中使用。
好,开始修改。
我还需要处理排序下拉的位置——从左侧移到右侧。目前 `.sort-dropdown-wrap` 中的 `.sort-dropdown` 是 `left:16px`,需要改为 `right:0` 或 `right:16px`。
此外,搜索按钮和排序放在同一行——我可以在 `.sort-dropdown-wrap` 中使用 flex 布局,左边搜索区右边排序区。
关于曲目搜索,我将实现简单的文本过滤:在曲目列表上方出现搜索框,输入文字后隐藏不匹配的行。
实际上更简洁的做法是:将搜索框放在排序同一行,点击搜索图标后展开输入框。
让我重新设计 sort-dropdown-wrap 为一行:
- 左侧:搜索图标按钮 + 搜索输入框(默认隐藏)
- 右侧:排序下拉按钮
这样整体布局更好。
另外注意:由于整个页面是 position:relative 的,搜索下拉和排序下拉的 z-index 需要足够高。
好,开始编写最终代码。由于代码量很大,我会尽量保持与之前版本的一致性,只做上述修改。
关于 `contenteditable`:点击 lib-name 后可以直接编辑。需要处理的是:如果用户清空了名称,要恢复默认值;按 Enter 键时 blur。我会在 JS 中添加相关事件处理。
现在开始输出。
角色
assistant
content
total_tokens
496278
summary
五项精确修改:①曲库名称点击即原地可编辑(contenteditable,blur 保存),与封面顶对齐;②导入按钮移至曲库名称与曲目数之间(紧凑胶囊样式);③封面右下角导入按钮移除,封面保留点击换封面;④排序+搜索重构为同一行——左侧搜索图标点击展开输入框实时过滤曲目,右侧排序下拉;⑤曲目操作弹窗仅保留置顶/删除/分享三项。
uiParsing
关闭