Files
workspace/code/file-preview/.trae/documents/g3-file-preview-plan.md
T
2026-04-28 17:29:53 +08:00

386 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# G3File 预览区域布局修改计划
## 一、需求分析
根据用户需求,需要对 g3-file-container 进行以下修改:
1. **布局调整**:改为左右两栏布局
- **左侧区域**:保持现有完整结构(header + main + footer)
- **右侧区域**:新增预览区域(toolbar 10% + 预览内容区 90%)
2. **预览区域 Toolbar**:
- 文件总数(仅统计已上传文件)
- 当前预览文件名
- 顺序导航按钮(上一个/下一个)
3. **预览规则**:
- 只有 `status === 'uploaded'` 的文件才可预览
- 预览总数只计算已上传文件
4. **预览功能**:暂时不实现实际预览功能,只显示测试内容
## 二、布局结构
### 2.1 原布局
```
┌─────────────────────────────────────┐
│ Header │
├─────────────────────────────────────┤
│ Main │
│ (文件列表) │
├─────────────────────────────────────┤
│ Footer │
└─────────────────────────────────────┘
```
### 2.2 新布局
```
┌─────────────────────────────────────────────────────────────────┐
│ 左侧区域 │ 右侧预览区域 │
│ ┌─────────────────────────────────────┐ │ ┌───────────┐ │
│ │ Header │ │ │ Toolbar │ │
│ ├─────────────────────────────────────┤ │ │(10%高度) │ │
│ │ Main │ ├───────────────┤ │
│ │ (文件列表) │ │ │ │
│ ├─────────────────────────────────────┤ │ 预览内容区 │ │
│ │ Footer │ │ (90%高度) │ │
│ └─────────────────────────────────────┘ │ │ │
│ └─────────────┘ │
└───────────────────────────────────────────────────────────────┘
```
### 2.3 Toolbar 内容
```
┌─────────────────────────────────────────────────────────┐
│ [上一个] 第 1/5 个文件 当前: filename.pdf [下一个] │
└─────────────────────────────────────────────────────────┘
```
## 三、修改方案
### 3.1 修改文件
| 文件 | 修改内容 |
|------|----------|
| `g3-file/index.css` | 添加左右布局和预览区域样式 |
| `g3-file/index.js` | 修改布局结构、添加预览区域逻辑 |
### 3.2 JS 修改要点
1. **渲染方法 (`render`)**:修改 HTML 结构为左右布局
2. **状态管理**:
- `currentPreviewIndex`: 当前预览文件索引
3. **预览操作方法**:
- `getPreviewableFiles()`: 获取已上传文件列表
- `previewFile(file)`: 预览指定文件
- `previewNext()`: 预览下一个文件
- `previewPrev()`: 预览上一个文件
- `updatePreviewArea()`: 更新预览区域 UI
4. **事件绑定**:绑定预览区域按钮事件
### 3.3 CSS 修改要点
1. **整体容器**:改为横向 flex 布局
2. **左侧区域**:保持原有结构,设置宽度比例(如 50%)
3. **右侧区域**:
- 设置宽度比例(如 50%)
- 纵向 flex 布局
- toolbar 占 10% 高度
- 预览内容区占 90% 高度
4. **Toolbar 样式**:按钮、进度显示等
## 四、实施步骤
### 步骤 1:修改 CSS 样式
```css
/* 整体布局 - 横向排列 */
.g3-file-container {
height: 100%;
display: flex;
background: #ffffff;
overflow: hidden;
}
/* 左侧区域 */
.g3-file-left-panel {
flex: 1;
display: flex;
flex-direction: column;
border-right: 1px solid #eef0f2;
}
/* 右侧预览区域 */
.g3-file-right-panel {
flex: 1;
display: flex;
flex-direction: column;
background: #fafbfc;
}
/* 预览 Toolbar */
.g3-preview-toolbar {
height: 10%;
min-height: 48px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
background: #fff;
border-bottom: 1px solid #eef0f2;
}
/* 预览内容区域 */
.g3-preview-content {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
overflow: auto;
}
/* 预览空状态 */
.g3-preview-empty {
text-align: center;
color: #999;
font-size: 14px;
}
/* 预览文件信息 */
.g3-preview-file-info {
text-align: center;
}
/* 预览按钮 */
.g3-preview-btn {
padding: 6px 12px;
border: 1px solid #d9d9d9;
background: #fff;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.g3-preview-btn:hover:not(:disabled) {
border-color: #165dff;
color: #165dff;
}
.g3-preview-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* 预览状态文字 */
.g3-preview-status {
font-size: 13px;
color: #666;
}
```
### 步骤 2:修改 JS 渲染方法
修改 `render()` 方法的 HTML 结构:
```javascript
render: function () {
const html = `
<div class="g3-file-container">
<!-- 左侧区域 -->
<div class="g3-file-left-panel">
<div class="header">...</div>
<div class="main" style="display: none;">main</div>
<div class="empty-tip">...</div>
<div class="footer">...</div>
</div>
<!-- 右侧预览区域 -->
<div class="g3-file-right-panel">
<div class="g3-preview-toolbar">
<button class="g3-preview-btn preview-prev" disabled>上一个</button>
<div class="g3-preview-status">
<span class="preview-counter">第 0/0 个文件</span>
<span class="preview-filename" style="margin-left: 12px;"></span>
</div>
<button class="g3-preview-btn preview-next" disabled>下一个</button>
</div>
<div class="g3-preview-content">
<div class="g3-preview-empty">请选择一个已上传的文件进行预览</div>
</div>
</div>
<input type="file" class="file-input" style="display: none;" multiple />
<div class="g3-global-menu"></div>
</div>
`;
this.$container.html(html);
// 缓存 DOM 元素
this.$leftPanel = this.$container.find(".g3-file-left-panel");
this.$rightPanel = this.$container.find(".g3-file-right-panel");
this.$fileList = this.$leftPanel.find(".main");
this.$emptyTip = this.$leftPanel.find(".empty-tip");
this.$checkAll = this.$leftPanel.find(".check-all-checkbox");
this.$btnDownload = this.$leftPanel.find(".download-all");
this.$btnDelete = this.$leftPanel.find(".delete-all");
this.$btnUpload = this.$leftPanel.find(".upload");
this.$btnSelect = this.$leftPanel.find(".select");
this.$fileInput = this.$container.find(".file-input");
this.$pendingCount = this.$leftPanel.find(".pending-number");
// 预览区域元素
this.$previewToolbar = this.$container.find(".g3-preview-toolbar");
this.$previewContent = this.$container.find(".g3-preview-content");
this.$btnPreviewPrev = this.$container.find(".preview-prev");
this.$btnPreviewNext = this.$container.find(".preview-next");
this.$previewCounter = this.$container.find(".preview-counter");
this.$previewFilename = this.$container.find(".preview-filename");
return this;
}
```
### 步骤 3:添加预览相关状态和方法
```javascript
// 构造函数中添加
this.currentPreviewIndex = -1;
// 获取可预览文件(已上传文件)
getPreviewableFiles: function () {
return this.files.filter(file => file.status === 'uploaded');
},
// 预览指定文件
previewFile: function (file) {
const previewableFiles = this.getPreviewableFiles();
const index = previewableFiles.findIndex(f => f._id === file._id);
if (index !== -1) {
this.currentPreviewIndex = index;
this.updatePreviewArea();
}
},
// 预览下一个
previewNext: function () {
const previewableFiles = this.getPreviewableFiles();
if (previewableFiles.length === 0) return;
if (this.currentPreviewIndex < previewableFiles.length - 1) {
this.currentPreviewIndex++;
this.updatePreviewArea();
}
},
// 预览上一个
previewPrev: function () {
if (this.currentPreviewIndex > 0) {
this.currentPreviewIndex--;
this.updatePreviewArea();
}
},
// 更新预览区域
updatePreviewArea: function () {
const previewableFiles = this.getPreviewableFiles();
const total = previewableFiles.length;
// 更新计数器
if (this.currentPreviewIndex >= 0 && this.currentPreviewIndex < total) {
this.$previewCounter.text(`第 ${this.currentPreviewIndex + 1}/${total} 个文件`);
this.$previewFilename.text(`当前: ${previewableFiles[this.currentPreviewIndex].name}`);
} else {
this.$previewCounter.text(`第 0/${total} 个文件`);
this.$previewFilename.text('');
}
// 更新按钮状态
this.$btnPreviewPrev.prop('disabled', this.currentPreviewIndex <= 0);
this.$btnPreviewNext.prop('disabled',
this.currentPreviewIndex >= total - 1 || total === 0);
// 更新预览内容
if (this.currentPreviewIndex >= 0 && this.currentPreviewIndex < total) {
const file = previewableFiles[this.currentPreviewIndex];
this.$previewContent.html(`
<div class="g3-preview-file-info">
<h3>${file.name}</h3>
<p>大小: ${this.formatFileSize(file.size)}</p>
<p>上传时间: ${this.formatDate(file.uploadDate)}</p>
<p>状态: 已上传</p>
<p>URL: ${file.url || '-'}</p>
</div>
`);
} else {
this.$previewContent.html('<div class="g3-preview-empty">请选择一个已上传的文件进行预览</div>');
}
}
```
### 步骤 4:绑定预览事件
```javascript
bindEvents: function () {
var self = this;
// ... 原有事件绑定 ...
// 预览下一个按钮
this.$btnPreviewNext.off("click").on("click", function () {
self.previewNext();
});
// 预览上一个按钮
this.$btnPreviewPrev.off("click").on("click", function () {
self.previewPrev();
});
// 点击文件项预览(只对已上传文件生效)
this.$fileList
.off("click", ".g3-file-item")
.on("click", ".g3-file-item", function (e) {
if ($(e.target).closest(".g3-file-action, .g3-file-checkbox, .g3-file-delete-btn").length) {
return;
}
var id = $(this).data("id");
var file = self.files.find(f => f._id === id);
if (!file) return;
// 只有已上传文件才能预览
if (file.status === 'uploaded') {
self.previewFile(file);
}
if (typeof self.options.onPreview === "function") {
self.options.onPreview([file]);
}
});
}
```
### 步骤 5:更新文件操作后的预览状态
在 `internalDelete()`、`updateFileStatus()` 等方法中调用 `updatePreviewArea()`
## 五、注意事项
1. **预览计数**:只统计 `status === 'uploaded'` 的文件
2. **预览权限**:只有已上传文件才能预览
3. **边界处理**:
- 没有可预览文件时,工具栏按钮禁用
- 处于第一个文件时,上一个按钮禁用
- 处于最后一个文件时,下一个按钮禁用
4. **预览内容**:暂时显示测试内容(文件名、大小、日期等信息)
## 六、测试验证
1. 上传文件后,预览区域显示可预览文件数量
2. 点击已上传文件,预览区域显示文件信息
3. 上下按钮正确切换预览文件
4. 删除文件后,预览区域正确更新
5. 未上传文件点击不触发预览