Files
SenSu/static/web_panel/pages/files.html
T
qinglong 9b997d8bda fix: 文件选择器改为页内iframe弹窗 + 乱码编码修复 + API路径修复
- pickPath()从window.open改为页内iframe模态弹窗(遮罩+关闭按钮)
- files.html添加meta charset+CSS link,独立模式自动加载files.js
- API路径统一通过_apiUrl()构建,适配主面板和iframe两种上下文
- 独立iframe模式注入body/container覆写样式(无topbar)
- 选择模式栏移至底部margin-top:auto紧凑排列
- MD3风格toggle开关(显示隐藏复选框)
- CSS版本号缓存破坏

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 21:51:42 +08:00

95 lines
4.6 KiB
HTML

<!-- File Manager Page -->
<meta charset="UTF-8">
<link rel="stylesheet" href="../css/style.css?v=0601">
<div class="fm-container">
<!-- Top bar: editable path + actions -->
<div class="fm-toolbar">
<div class="fm-path-bar">
<input class="fm-path-input" id="fm-path-input" type="text" spellcheck="false" title="输入路径后回车跳转">
<div class="fm-breadcrumb" id="fm-breadcrumb"></div>
</div>
<div class="fm-actions">
<label class="fm-toggle">
<input type="checkbox" id="fm-hidden" onchange="FilesModule.refresh()">
<span>显示隐藏</span>
</label>
<button class="btn btn-sm btn-outlined" onclick="FilesModule.createFile()">
<svg width="14" height="14" viewBox="0 0 24 24"><path fill="currentColor" d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm-1 2l5 5h-5V4zM8 14h8v2H8v-2zm0-4h8v2H8v-2z"/></svg>
新建文件
</button>
<button class="btn btn-sm btn-outlined" onclick="FilesModule.createDir()">
<svg width="14" height="14" viewBox="0 0 24 24"><path fill="currentColor" d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-2 4h-3v3h-2v-3h-3V8h3V5h2v3h3v2z"/></svg>
新建文件夹
</button>
<button class="btn btn-sm btn-tonal" onclick="document.getElementById('fm-upload-input').click()">
<svg width="14" height="14" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/></svg>
上传
</button>
<input type="file" id="fm-upload-input" multiple style="display:none" onchange="FilesModule.upload(this.files)">
</div>
</div>
<!-- File list -->
<div class="fm-list" id="fm-list">
<div style="text-align:center;color:var(--text-dim);padding:40px">加载中...</div>
</div>
<!-- Editor overlay -->
<div class="fm-editor-overlay" id="fm-editor" style="display:none">
<div class="fm-editor-header">
<span id="fm-editor-title">编辑文件</span>
<div>
<button class="btn btn-sm btn-tonal" onclick="FilesModule.saveFile()">💾 保存</button>
<button class="btn btn-sm btn-outlined" onclick="FilesModule.closeEditor()">✕ 关闭</button>
</div>
</div>
<textarea id="fm-editor-textarea" spellcheck="false"></textarea>
</div>
<!-- Delete confirm dialog -->
<div class="fm-dialog-overlay" id="fm-dialog" style="display:none">
<div class="fm-dialog">
<p id="fm-dialog-msg">确认删除?</p>
<div style="display:flex;gap:8px;justify-content:flex-end;margin-top:16px">
<button class="btn btn-sm btn-outlined" onclick="FilesModule.closeDialog()">取消</button>
<button class="btn btn-sm btn-danger" id="fm-dialog-confirm" onclick="FilesModule.confirmDelete()">删除</button>
</div>
</div>
</div>
<!-- Context menu -->
<div class="fm-context" id="fm-context" style="display:none">
<div class="fm-context-item" onclick="FilesModule.ctxDownload()">⬇ 下载</div>
<div class="fm-context-item" onclick="FilesModule.ctxRename()">✏ 重命名</div>
<div class="fm-context-item" onclick="FilesModule.ctxEdit()">📝 编辑</div>
<div class="fm-context-sep"></div>
<div class="fm-context-item danger" onclick="FilesModule.ctxDelete()">🗑 删除</div>
</div>
</div>
<script>
// Load files.js for standalone mode (iframe picker)
(function(){
// Reset body/container for iframe — no topbar, no sidebar
if(window.parent !== window){
var s=document.createElement('style');
s.textContent='html,body{height:100%;margin:0;overflow:hidden}.fm-container{height:100%;gap:8px}.fm-list{padding-bottom:0}';
document.head.appendChild(s);
}
var cssHref = document.querySelector('link[href*=\"style.css\"]')?.href || '';
// e.g. http://host:4200/SenSu/static/css/style.css → staticBase = .../SenSu/static
var staticBase = cssHref.replace(/\/css\/style\.css.*$/, '');
// apiBase = .../SenSu (strip /static)
var apiBase = cssHref.replace(/\/static\/css\/style\.css.*$/, '');
var script = document.createElement('script');
script.src = staticBase + '/pages/files.js?v=0602';
script.onload = function(){
if(window.FilesModule){
window.FilesModule._apiBase = apiBase;
if(window.FilesModule.init) window.FilesModule.init();
}
};
document.head.appendChild(script);
})();
</script>