ui: align desktop shell and file actions
This commit is contained in:
@@ -7,9 +7,9 @@
|
|||||||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%232563eb'/%3E%3Cpath d='M17 18h30v7H24v7h18v7H24v7h23v7H17z' fill='white'/%3E%3C/svg%3E">
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%232563eb'/%3E%3Cpath d='M17 18h30v7H24v7h18v7H24v7h23v7H17z' fill='white'/%3E%3C/svg%3E">
|
||||||
<style>
|
<style>
|
||||||
:root{font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#172033;background:#f5f7fb}
|
:root{font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#172033;background:#f5f7fb}
|
||||||
*{box-sizing:border-box}[hidden]{display:none!important}body{margin:0}.top{height:64px;background:#fff;border-bottom:1px solid #e5e9f2;display:flex;align-items:center;padding:0 22px;gap:18px;position:sticky;top:0;z-index:2}.brand{font-weight:750;font-size:20px}.path{color:#718096;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.spacer{flex:1}
|
*{box-sizing:border-box}[hidden]{display:none!important}body{margin:0}.top{height:64px;background:#fff;border-bottom:1px solid #e5e9f2;display:flex;align-items:center;padding:0 max(18px,calc((100vw - 1600px)/2 + 18px));gap:18px;position:sticky;top:0;z-index:2}.brand{font-weight:750;font-size:20px}.path{color:#718096;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.spacer{flex:1}
|
||||||
button,input{font:inherit}button{border:0;border-radius:9px;padding:9px 13px;cursor:pointer;background:#2563eb;color:#fff}button.ghost{background:#eef2f7;color:#334155}button.danger{background:#dc2626}
|
button,input{font:inherit}button{border:0;border-radius:9px;padding:9px 13px;cursor:pointer;background:#2563eb;color:#fff}button.ghost{background:#eef2f7;color:#334155}button.danger{background:#dc2626}
|
||||||
main{max-width:1180px;margin:26px auto;padding:0 18px}.toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}.toolgroup{display:flex;align-items:center;gap:6px}.toolbar .searchbox{min-width:220px;flex:1;display:flex;align-items:center;gap:8px;padding:0 12px;border:1px solid var(--border);border-radius:10px;background:var(--surface);transition:border-color .15s,box-shadow .15s}.toolbar .searchbox:focus-within{border-color:var(--primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 12%,transparent)}.toolbar .searchbox .ui-icon{width:16px;height:16px;color:var(--muted)}.toolbar .searchbox input{min-width:0;flex:1;padding:10px 0;border:0;outline:0;background:transparent;color:var(--text)}.toolbar .divider{width:1px;height:26px;background:var(--border);margin:0 2px}.toolbar .primary-action{box-shadow:0 2px 6px rgba(37,99,235,.18)}.toolbar .iconbtn{flex:0 0 auto}
|
main{max-width:1600px;margin:26px auto;padding:0 18px}.toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}.toolgroup{display:flex;align-items:center;gap:6px}.toolbar .searchbox{min-width:220px;flex:1;display:flex;align-items:center;gap:8px;padding:0 12px;border:1px solid var(--border);border-radius:10px;background:var(--surface);transition:border-color .15s,box-shadow .15s}.toolbar .searchbox:focus-within{border-color:var(--primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 12%,transparent)}.toolbar .searchbox .ui-icon{width:16px;height:16px;color:var(--muted)}.toolbar .searchbox input{min-width:0;flex:1;padding:10px 0;border:0;outline:0;background:transparent;color:var(--text)}.toolbar .divider{width:1px;height:26px;background:var(--border);margin:0 2px}.toolbar .primary-action{box-shadow:0 2px 6px rgba(37,99,235,.18)}.toolbar .iconbtn{flex:0 0 auto}
|
||||||
.card{background:#fff;border:1px solid #e4e8f0;border-radius:14px;overflow:hidden;box-shadow:0 4px 18px rgba(20,30,50,.04)}
|
.card{background:#fff;border:1px solid #e4e8f0;border-radius:14px;overflow:hidden;box-shadow:0 4px 18px rgba(20,30,50,.04)}
|
||||||
table{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:0}.check-col{width:54px}.size-col{width:110px}.time-col{width:170px}.perm-col{width:82px}.action-col{width:54px}th,td{text-align:left;padding:12px 15px;border-bottom:1px solid #edf0f5}th{font-size:12px;color:#7b8798;background:#fafbfc;font-weight:650}tr:last-child td{border-bottom:0}.name{display:flex;align-items:center;gap:10px;min-width:0}.name a{color:#172033;text-decoration:none;font-weight:550;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sorthead{display:inline-flex;align-items:center;gap:5px;padding:3px 5px;margin:-3px -5px;background:transparent;color:inherit;font-size:inherit;font-weight:inherit}.sorthead:hover{background:var(--surface);color:var(--text)}.sorthead span{font-size:10px;color:var(--primary);min-width:8px}.meta{color:#8792a5;font-size:13px}.actions{display:flex;gap:7px;justify-content:flex-end;opacity:.55;transition:opacity .15s}.file-row:hover .actions,.file-row.selected .actions{opacity:1}.file-row{transition:background .12s}.file-row:hover{background:var(--surface2)}.file-row.selected{background:color-mix(in srgb,var(--primary) 7%,var(--surface))}.file-row.drop-target{background:color-mix(in srgb,var(--primary) 12%,var(--surface));box-shadow:inset 0 0 0 2px var(--primary)}.tile.drop-target{border-color:var(--primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 16%,transparent)}.side-item.drop-target{background:color-mix(in srgb,var(--primary) 12%,var(--surface2));color:var(--primary)}.dragging{opacity:.45}.gallery-nav{position:absolute;top:50%;transform:translateY(-50%);width:42px;height:42px;border-radius:50%;background:rgba(255,255,255,.12);color:#fff;border:1px solid rgba(255,255,255,.22);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center}.gallery-nav .ui-icon{width:22px;height:22px}.gallery-prev{left:16px}.gallery-next{right:16px}.gallery-stage-touch{touch-action:pan-y;user-select:none}.gallery-count{position:absolute;left:50%;bottom:14px;transform:translateX(-50%);padding:5px 9px;border-radius:99px;background:rgba(0,0,0,.48);color:#fff;font-size:12px}.preview-stage.media-stage{position:relative}.preview-stage video:focus{outline:2px solid var(--primary);outline-offset:2px}.media-hint{position:absolute;left:18px;top:14px;color:#aab5c5;font-size:12px;pointer-events:none}.file-row:focus-within{box-shadow:inset 2px 0 0 var(--primary)}.tile:focus-visible,.file-row:focus-within{outline:2px solid color-mix(in srgb,var(--primary) 65%,transparent);outline-offset:-2px}.file-row .file-kind{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border-radius:8px;background:var(--surface2);color:var(--muted);flex:0 0 auto}.file-row .name>span:last-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-row .action-col{width:54px}.file-row .actions{min-width:38px}.file-row .file-kind .ui-icon{width:18px;height:18px}.file-row .size-cell,.file-row .time-cell{white-space:nowrap;color:var(--muted);font-size:12px}.file-row .perm-cell{white-space:nowrap}.perm-dot{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--border);margin-right:5px}.perm-dot.read{background:var(--muted)}.perm-dot.write{background:var(--primary)}.perm-dot.delete{background:var(--danger)}.empty{padding:45px;text-align:center;color:#8a94a6}
|
table{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:0}.check-col{width:54px}.size-col{width:110px}.time-col{width:170px}.perm-col{width:82px}.action-col{width:54px}th,td{text-align:left;padding:12px 15px;border-bottom:1px solid #edf0f5}th{font-size:12px;color:#7b8798;background:#fafbfc;font-weight:650}tr:last-child td{border-bottom:0}.name{display:flex;align-items:center;gap:10px;min-width:0}.name a{color:#172033;text-decoration:none;font-weight:550;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sorthead{display:inline-flex;align-items:center;gap:5px;padding:3px 5px;margin:-3px -5px;background:transparent;color:inherit;font-size:inherit;font-weight:inherit}.sorthead:hover{background:var(--surface);color:var(--text)}.sorthead span{font-size:10px;color:var(--primary);min-width:8px}.meta{color:#8792a5;font-size:13px}.actions{display:flex;gap:7px;justify-content:flex-end;opacity:.55;transition:opacity .15s}.file-row:hover .actions,.file-row.selected .actions{opacity:1}.file-row{transition:background .12s}.file-row:hover{background:var(--surface2)}.file-row.selected{background:color-mix(in srgb,var(--primary) 7%,var(--surface))}.file-row.drop-target{background:color-mix(in srgb,var(--primary) 12%,var(--surface));box-shadow:inset 0 0 0 2px var(--primary)}.tile.drop-target{border-color:var(--primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 16%,transparent)}.side-item.drop-target{background:color-mix(in srgb,var(--primary) 12%,var(--surface2));color:var(--primary)}.dragging{opacity:.45}.gallery-nav{position:absolute;top:50%;transform:translateY(-50%);width:42px;height:42px;border-radius:50%;background:rgba(255,255,255,.12);color:#fff;border:1px solid rgba(255,255,255,.22);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center}.gallery-nav .ui-icon{width:22px;height:22px}.gallery-prev{left:16px}.gallery-next{right:16px}.gallery-stage-touch{touch-action:pan-y;user-select:none}.gallery-count{position:absolute;left:50%;bottom:14px;transform:translateX(-50%);padding:5px 9px;border-radius:99px;background:rgba(0,0,0,.48);color:#fff;font-size:12px}.preview-stage.media-stage{position:relative}.preview-stage video:focus{outline:2px solid var(--primary);outline-offset:2px}.media-hint{position:absolute;left:18px;top:14px;color:#aab5c5;font-size:12px;pointer-events:none}.file-row:focus-within{box-shadow:inset 2px 0 0 var(--primary)}.tile:focus-visible,.file-row:focus-within{outline:2px solid color-mix(in srgb,var(--primary) 65%,transparent);outline-offset:-2px}.file-row .file-kind{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border-radius:8px;background:var(--surface2);color:var(--muted);flex:0 0 auto}.file-row .name>span:last-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-row .action-col{width:54px}.file-row .actions{min-width:38px}.file-row .file-kind .ui-icon{width:18px;height:18px}.file-row .size-cell,.file-row .time-cell{white-space:nowrap;color:var(--muted);font-size:12px}.file-row .perm-cell{white-space:nowrap}.perm-dot{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--border);margin-right:5px}.perm-dot.read{background:var(--muted)}.perm-dot.write{background:var(--primary)}.perm-dot.delete{background:var(--danger)}.empty{padding:45px;text-align:center;color:#8a94a6}
|
||||||
.modal{position:fixed;inset:0;background:rgba(15,23,42,.5);display:none;align-items:center;justify-content:center;padding:18px;z-index:4;backdrop-filter:blur(4px)}.modal.show{display:flex}.dialog{width:min(480px,100%);max-height:calc(100vh - 36px);overflow:auto;background:var(--surface);border:1px solid var(--border);border-radius:18px;padding:22px;box-shadow:0 24px 80px rgba(0,0,0,.18)}.dialog.preview-dialog{width:min(1000px,100%);padding:0;overflow:hidden}.dialog h2{margin-top:0}.field{display:grid;gap:7px;margin:13px 0}.field input{padding:10px 11px;border:1px solid #d7ddea;border-radius:9px}.row{display:flex;gap:9px;justify-content:flex-end;margin-top:18px}.preview-head{display:flex;align-items:center;gap:12px;padding:14px 16px;border-bottom:1px solid var(--border)}.preview-title{font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:auto}.preview-stage{position:relative;min-height:180px;max-height:calc(100vh - 150px);overflow:auto;background:#0b0f14;padding:24px;display:flex;align-items:center;justify-content:center}.preview-stage img{max-width:100%;max-height:70vh;object-fit:contain}.preview-stage video{width:min(920px,100%);max-height:70vh;border-radius:10px}.preview-stage audio{width:min(720px,100%)}.preview-stage iframe{width:100%;height:70vh;border:0;background:#fff}.preview-text{width:min(920px,100%);max-height:70vh;overflow:auto;text-align:left;white-space:pre-wrap;background:#111821;color:#dce5f2;padding:18px;border-radius:10px;font:13px/1.6 ui-monospace,SFMono-Regular,monospace}.preview-empty{color:#aab5c5;text-align:center}.preview-foot{padding:12px 16px;border-top:1px solid var(--border);display:flex;justify-content:flex-end;gap:8px}.editor-wrap{width:min(1000px,100%);height:70vh;display:grid;grid-template-columns:auto minmax(0,1fr);background:#111821;border:1px solid #273243;border-radius:10px;overflow:hidden}.editor-lines{margin:0;padding:16px 12px;text-align:right;user-select:none;color:#617086;background:#0d131b;border-right:1px solid #273243;font:13px/1.6 ui-monospace,SFMono-Regular,monospace;overflow:hidden}.editor-input{width:100%;height:100%;resize:none;border:0;outline:0;padding:16px;background:#111821;color:#dce5f2;font:13px/1.6 ui-monospace,SFMono-Regular,monospace;tab-size:2}.editor-status{display:flex;align-items:center;gap:8px;margin-right:auto}.editor-dirty{color:var(--primary);font-weight:600}.media-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.media-toolbar label{font-size:12px;color:var(--muted)}.media-toolbar select{padding:7px 9px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text)}
|
.modal{position:fixed;inset:0;background:rgba(15,23,42,.5);display:none;align-items:center;justify-content:center;padding:18px;z-index:4;backdrop-filter:blur(4px)}.modal.show{display:flex}.dialog{width:min(480px,100%);max-height:calc(100vh - 36px);overflow:auto;background:var(--surface);border:1px solid var(--border);border-radius:18px;padding:22px;box-shadow:0 24px 80px rgba(0,0,0,.18)}.dialog.preview-dialog{width:min(1000px,100%);padding:0;overflow:hidden}.dialog h2{margin-top:0}.field{display:grid;gap:7px;margin:13px 0}.field input{padding:10px 11px;border:1px solid #d7ddea;border-radius:9px}.row{display:flex;gap:9px;justify-content:flex-end;margin-top:18px}.preview-head{display:flex;align-items:center;gap:12px;padding:14px 16px;border-bottom:1px solid var(--border)}.preview-title{font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:auto}.preview-stage{position:relative;min-height:180px;max-height:calc(100vh - 150px);overflow:auto;background:#0b0f14;padding:24px;display:flex;align-items:center;justify-content:center}.preview-stage img{max-width:100%;max-height:70vh;object-fit:contain}.preview-stage video{width:min(920px,100%);max-height:70vh;border-radius:10px}.preview-stage audio{width:min(720px,100%)}.preview-stage iframe{width:100%;height:70vh;border:0;background:#fff}.preview-text{width:min(920px,100%);max-height:70vh;overflow:auto;text-align:left;white-space:pre-wrap;background:#111821;color:#dce5f2;padding:18px;border-radius:10px;font:13px/1.6 ui-monospace,SFMono-Regular,monospace}.preview-empty{color:#aab5c5;text-align:center}.preview-foot{padding:12px 16px;border-top:1px solid var(--border);display:flex;justify-content:flex-end;gap:8px}.editor-wrap{width:min(1000px,100%);height:70vh;display:grid;grid-template-columns:auto minmax(0,1fr);background:#111821;border:1px solid #273243;border-radius:10px;overflow:hidden}.editor-lines{margin:0;padding:16px 12px;text-align:right;user-select:none;color:#617086;background:#0d131b;border-right:1px solid #273243;font:13px/1.6 ui-monospace,SFMono-Regular,monospace;overflow:hidden}.editor-input{width:100%;height:100%;resize:none;border:0;outline:0;padding:16px;background:#111821;color:#dce5f2;font:13px/1.6 ui-monospace,SFMono-Regular,monospace;tab-size:2}.editor-status{display:flex;align-items:center;gap:8px;margin-right:auto}.editor-dirty{color:var(--primary);font-weight:600}.media-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.media-toolbar label{font-size:12px;color:var(--muted)}.media-toolbar select{padding:7px 9px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text)}
|
||||||
@@ -65,7 +65,7 @@ button.ghost{background:var(--surface2);color:var(--text)}.meta,.path{color:var(
|
|||||||
<div class="searchbox"><svg class="ui-icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="m16 16 5 5"/></svg><input id="search" placeholder="搜索文件名,回车执行"></div>
|
<div class="searchbox"><svg class="ui-icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="m16 16 5 5"/></svg><input id="search" placeholder="搜索文件名,回车执行"></div>
|
||||||
<div class="toolgroup"><button id="usersBtn" class="ghost" onclick="showUsers()" hidden>用户管理</button><button class="ghost" id="pwdBtn" onclick="changePassword()" hidden>修改密码</button><button class="iconbtn" id="themeBtn" onclick="toggleTheme()" title="主题"><span id="themeIcon"></span></button><span class="view-switch"><button class="iconbtn viewbtn active" id="listBtn" onclick="setView('list')" title="列表"><span id="listIcon"></span></button><button class="iconbtn viewbtn" id="gridBtn" onclick="setView('grid')" title="网格"><span id="gridIcon"></span></button></span></div>
|
<div class="toolgroup"><button id="usersBtn" class="ghost" onclick="showUsers()" hidden>用户管理</button><button class="ghost" id="pwdBtn" onclick="changePassword()" hidden>修改密码</button><button class="iconbtn" id="themeBtn" onclick="toggleTheme()" title="主题"><span id="themeIcon"></span></button><span class="view-switch"><button class="iconbtn viewbtn active" id="listBtn" onclick="setView('list')" title="列表"><span id="listIcon"></span></button><button class="iconbtn viewbtn" id="gridBtn" onclick="setView('grid')" title="网格"><span id="gridIcon"></span></button></span></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="bulk" class="bulk"><span id="selectedCount" class="count"></span><button class="ghost" onclick="bulkMove()">移动</button><button class="ghost" onclick="bulkCopy()">复制</button><button class="ghost" onclick="bulkDownload()">下载 ZIP</button><button class="danger" onclick="bulkDelete()">删除</button><button class="ghost" onclick="clearSelection()">取消选择</button></div><div class="card" id="fileCard"><table><thead><tr><th class="check-col"><input id="selectAll" class="selectbox" type="checkbox" onchange="toggleAll(this.checked)" title="全选"></th><th class="name-col"><button class="sorthead" onclick="sortBy('name')" title="按名称排序">名称 <span id="sort-name"></span></button></th><th class="size-col"><button class="sorthead" onclick="sortBy('size')" title="按大小排序">大小 <span id="sort-size"></span></button></th><th class="time-col"><button class="sorthead" onclick="sortBy('modified')" title="按修改时间排序">修改时间 <span id="sort-modified"></span></button></th><th class="perm-col">权限</th><th class="action-col"></th></tr></thead><tbody id="files"></tbody></table><div id="grid" class="grid" hidden></div></div></section></div>
|
<div id="bulk" class="bulk"><span id="selectedCount" class="count"></span><button class="ghost" onclick="bulkMove()">移动</button><button class="ghost" onclick="bulkCopy()">复制</button><button class="ghost" onclick="bulkDownload()">下载 ZIP</button><button class="danger" onclick="bulkDelete()">删除</button><button class="ghost" onclick="clearSelection()">取消选择</button></div><div class="card" id="fileCard"><table><thead><tr><th class="check-col"><input id="selectAll" class="selectbox" type="checkbox" onchange="toggleAll(this.checked)" title="全选"></th><th class="name-col"><button class="sorthead" onclick="sortBy('name')" title="按名称排序">名称 <span id="sort-name"></span></button></th><th class="size-col"><button class="sorthead" onclick="sortBy('size')" title="按大小排序">大小 <span id="sort-size"></span></button></th><th class="time-col"><button class="sorthead" onclick="sortBy('modified')" title="按修改时间排序">修改时间 <span id="sort-modified"></span></button></th><th class="perm-col">权限</th><th class="action-col">操作</th></tr></thead><tbody id="files"></tbody></table><div id="grid" class="grid" hidden></div></div></section></div>
|
||||||
</main><div id="context" class="context"></div><div id="toastHost" class="toast-host"></div>
|
</main><div id="context" class="context"></div><div id="toastHost" class="toast-host"></div>
|
||||||
<div class="modal" id="modal"><div class="dialog" id="dialog"></div></div>
|
<div class="modal" id="modal"><div class="dialog" id="dialog"></div></div>
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
Reference in New Issue
Block a user