# 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 = `
...
...
第 0/0 个文件
请选择一个已上传的文件进行预览
`; 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(`

${file.name}

大小: ${this.formatFileSize(file.size)}

上传时间: ${this.formatDate(file.uploadDate)}

状态: 已上传

URL: ${file.url || '-'}

`); } else { this.$previewContent.html('
请选择一个已上传的文件进行预览
'); } } ``` ### 步骤 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. 未上传文件点击不触发预览