feat: 文件管理器 + Windows兼容 + SVG主题适配 (v0.6.0)
新增: - services/web_panel/routes/files.py — 全功能文件管理后端API (11个端点) - pages/files.html + files.js — 文件管理前端 (浏览/编辑/上传/删除/右键菜单) - 插件Picker API: window.open+postMessage唤出文件选择器 - 符号链接目录双层面包屑 (逻辑路径+物理路径) - 文件系统全访问+跨平台 (Linux/Windows/macOS) - permission_rules.yaml新增4个filemanager.*权限 修复: - SVG fill=currentColor 日夜模式自适应 - 特殊目录容错 (/dev/fd损坏符号链接/proc) - 面包屑每层级独立可点击+可编辑路径跳转 - ..行返回上级+data-is-dir补全 - rmlint→lstat回退 损坏符号链接不炸页面 文档: - 插件开发指南新增第八章(文件管理器集成) - 开发踩坑记录新增4条(特殊目录/双面包屑/SVG颜色/Windows) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<!-- File Manager Page -->
|
||||
<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>
|
||||
Reference in New Issue
Block a user