178 lines
4.3 KiB
Markdown
178 lines
4.3 KiB
Markdown
# Spec: 第一步 - 内容预览功能
|
||
|
||
## ADDED Requirements
|
||
|
||
### 预览图展示
|
||
- **Requirement**: 实现左侧预览图的横排展示布局,支持点击放大功能
|
||
- **Scenario**: 用户可以看到内容审核中选定项目的预览图,点击缩略图弹出全屏预览对话框,支持缩放操作
|
||
|
||
### 3D模型展示
|
||
- **Requirement**: 实现右侧3D模型的横排展示,集成现有的ModelViewer组件
|
||
- **Scenario**: 用户可以看到对应的3D模型预览,模型支持旋转、缩放等交互操作,使用demo/model.glb作为示例
|
||
|
||
### 拆件按钮功能
|
||
- **Requirement**: 添加拆件按钮,点击后进入第二步拆件结果展示
|
||
- **Scenario**: 用户在预览完图片和模型后,点击拆件按钮触发拆件流程,系统显示加载状态并进入下一步
|
||
|
||
### 响应式布局
|
||
- **Requirement**: 实现桌面端横排布局,平板端和移动端垂直堆叠布局
|
||
- **Scenario**: 在不同屏幕尺寸下,预览图和模型能够合理适配屏幕空间,保证可读性和交互性
|
||
|
||
## 技术实现细节
|
||
|
||
### 布局结构
|
||
```html
|
||
<div class="preview-step-content">
|
||
<div class="preview-layout">
|
||
<div class="preview-images">
|
||
<img
|
||
:src="previewImageUrl"
|
||
class="preview-thumbnail"
|
||
@click="openImagePreview"
|
||
alt="预览图"
|
||
/>
|
||
</div>
|
||
<div class="model-viewer-container">
|
||
<ModelViewer
|
||
:model-url="modelUrl"
|
||
:show-controls="true"
|
||
style="height: 400px; width: 100%;"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div class="step-actions">
|
||
<el-button
|
||
type="primary"
|
||
size="large"
|
||
@click="startDisassembly"
|
||
:loading="disassemblyLoading"
|
||
>
|
||
{{ t('disassembly.actions.startDisassembly') }}
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
### 图片预览对话框
|
||
```javascript
|
||
const openImagePreview = () => {
|
||
previewImageVisible.value = true
|
||
}
|
||
|
||
// 使用现有的预览对话框组件
|
||
// 通过currentImage和imageScale进行控制
|
||
```
|
||
|
||
### 样式实现
|
||
```css
|
||
.preview-layout {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 24px;
|
||
margin-bottom: 32px;
|
||
}
|
||
|
||
.preview-images {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
background: #f8fafc;
|
||
border-radius: 8px;
|
||
padding: 16px;
|
||
}
|
||
|
||
.preview-thumbnail {
|
||
max-width: 100%;
|
||
max-height: 400px;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
transition: transform 200ms ease;
|
||
}
|
||
|
||
.preview-thumbnail:hover {
|
||
transform: scale(1.02);
|
||
}
|
||
|
||
/* 平板端适配 */
|
||
@media (max-width: 1024px) {
|
||
.preview-layout {
|
||
grid-template-columns: 1fr;
|
||
gap: 16px;
|
||
}
|
||
}
|
||
|
||
/* 移动端适配 */
|
||
@media (max-width: 768px) {
|
||
.preview-layout {
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
.preview-images,
|
||
.model-viewer-container {
|
||
padding: 12px;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 数据流设计
|
||
|
||
### 初始数据加载
|
||
```javascript
|
||
const loadPreviewData = async () => {
|
||
try {
|
||
// 从路由参数获取内容ID
|
||
const contentId = route.params.id
|
||
|
||
// 加载预览图和模型数据
|
||
previewImageUrl.value = `/api/content/${contentId}/preview`
|
||
modelUrl.value = `/api/content/${contentId}/model`
|
||
|
||
// 如果没有对应内容,使用demo资源
|
||
if (!previewImageUrl.value) {
|
||
previewImageUrl.value = '/src/assets/demo/suoluetu.png'
|
||
}
|
||
if (!modelUrl.value) {
|
||
modelUrl.value = '/src/assets/demo/model.glb'
|
||
}
|
||
|
||
} catch (error) {
|
||
ElMessage.error(t('common.loadFailed'))
|
||
}
|
||
}
|
||
```
|
||
|
||
### 拆件流程启动
|
||
```javascript
|
||
const startDisassembly = async () => {
|
||
try {
|
||
disassemblyLoading.value = true
|
||
|
||
// 调用拆件API(用户后续实现)
|
||
// await callDisassemblyAPI(contentId)
|
||
|
||
// 模拟加载时间
|
||
await new Promise(resolve => setTimeout(resolve, 2000))
|
||
|
||
// 更新步骤状态
|
||
updateStepStatus(1, 'completed')
|
||
updateStepStatus(2, 'current')
|
||
workflowState.currentStep = 2
|
||
|
||
// 清空第二步可能存在的数据
|
||
overrideDownstreamSteps(2)
|
||
|
||
} catch (error) {
|
||
ElMessage.error(t('disassembly.errors.disassemblyFailed'))
|
||
} finally {
|
||
disassemblyLoading.value = false
|
||
}
|
||
}
|
||
```
|
||
|
||
## 验证标准
|
||
- 预览图能够正确加载和显示
|
||
- 点击预览图能够弹出放大对话框
|
||
- 3D模型能够正确渲染和交互
|
||
- 拆件按钮能够正常触发流程
|
||
- 响应式布局在各种设备上正常工作
|
||
- 加载状态和错误处理完善 |