# Changelog — files.html + sync_v2.py 全面迭代

**日期**: 2026-05-30  
**Commit**: 14131f9  
**类型**: 安全加固 + 功能补全 + UX 全面改进  
**涉及文件**:
- `server/api/sync_v2.py` — 符号链接解析 + 新增 3 个端点
- `server/api/schemas.py` — 新增 FileDownload/FileRead/FileWrite schema
- `web/app/files.html` — 前端全面重写

## 后端变更 (sync_v2.py)

### P2-1/P3-2: 符号链接解析
- `ls -la` 解析逻辑新增 `is_link` 字段（检测 `l` 权限）
- 符号链接文件名 `name -> target` 分离为 `name` + `link_target`
- 响应新增 `is_link` 和 `link_target` 字段

### P2-7: 新增 `/api/sync/download` 端点
- 通过 SFTP 流式下载远程文件
- 使用 `StreamingResponse` + 64KB chunk 避免内存膨胀
- 审计日志记录

### P2-8: 新增 `/api/sync/read-file` + `/write-file` 端点
- `read-file`: `stat` 检查大小 → `cat` 读取内容，限制 1MB
- `write-file`: base64 编码内容避免 shell 注入，`echo | base64 -d | tee` 写入
- 两个端点均有审计日志

## 前端全面重写 (files.html)

### P1-1: 目录删除二次确认
- 目录删除：自定义模态框 + 要求输入目录名确认
- 文件删除：自定义确认模态框

### P2-2/P2-3: 事件委托
- 移除所有内联 `onclick="..."` 字符串拼接
- 改用 `data-action` + `data-path` + `data-name` 属性
- 统一事件委托 `fileListEl.addEventListener('click', ...)`
- 彻底消除 XSS 向量

### P2-4: 上传进度条
- `XMLHttpRequest.upload.onprogress` 实时进度
- 顶部进度条显示当前文件名 + 百分比 + 进度条动画

### P2-5: 文件大小可读化
- `formatSize()` 函数：字节 → B/KB/MB/GB
- 保留 1 位小数

### P2-6: 文件类型图标
- 30+ 文件扩展名映射
- `.py`→🐍 `.jpg`→🖼️ `.tar.gz`→📦 `.log`→📊 `.env`→🔒 等

### P2-7: 文件下载
- 每行 hover 显示 ⬇ 下载按钮
- 点击触发 SFTP 下载 → 浏览器保存文件

### P2-8: 文件预览/编辑
- 每行 hover 显示 👁 预览按钮
- 点击读取文件内容 → 模态框显示 + textarea 编辑 + 保存

### P2-9: 自定义模态框
- 完全替代原生 `prompt()` / `confirm()`
- Tailwind 样式：暗色主题 + backdrop blur + 圆角
- 支持：文本提示 / 输入框 / 多行编辑 / 危险操作红色样式

### P2-10: 批量操作
- 每行开头 checkbox + 表头全选
- 选中时底部出现批量操作栏（计数 + 批量删除 + 取消）

### P3-1: 文件搜索
- 面包屑右侧搜索框
- 前端实时过滤文件名

### P3-2: 符号链接显示
- 🔗 图标 + cyan 颜色
- hover 显示 `→ target` tooltip

### P3-3: 空目录状态
- 📂 大图标 + 提示文字 + 「上传文件」引导按钮

### P3-4: 服务器刷新
- 🔄 按钮在服务器下拉旁，点击重新加载列表

### P3-5: 操作 loading
- 上传期间顶部进度条持续显示
- 浏览期间文件列表显示 ⏳ 加载动画

## 验证结果

| 测试 | 结果 |
|------|------|
| 健康检查 | ✅ ok |
| 页面加载 | ✅ 0 errors |
| 浏览 /tmp | ✅ 文件列表+图标+大小正确 |
| 符号链接 mysql.sock | ✅ 🔗 图标 |
| 面包屑 | ✅ /tmp 路径 |
| 搜索框 | ✅ 存在 |
| 全选 checkbox | ✅ 存在 |
| 操作按钮 | ✅ 👁 ⬏ ✏ 🗑 |

## 是否需迁移/重启
- 需要重启后端服务（新增 3 个 API 端点）
