场景拍摄功能详解
概述
场景拍摄是美业小程序的核心功能,通过结构化的5场景流水线,帮助用户完成专业的探店视频创作。
功能架构
1. 场景拍摄列表页 (task-detail/index.vue)
页面职责
- 展示5个场景的横向列表
- 显示每个场景的完成状态(视频、照片)
- 提供拍摄、预览、回顾等操作入口
- 选择生成模式并提交任务
关键组件
vue
<!-- 场景拍摄列表页核心结构 -->
<template>
<view class="task-detail-page">
<!-- 1. 导航栏 -->
<view class="custom-nav">...</view>
<!-- 2. 流水线信息卡片 -->
<view class="pipeline-info-card">...</view>
<!-- 3. 场景横向滚动列表 -->
<scroll-view class="scenes-scroll">
<view v-for="scene in scenes" class="scene-compact-card">
<!-- 场景缩略卡片 -->
</view>
</scroll-view>
<!-- 4. 展开的场景详情 -->
<view v-if="expandedScene >= 0" class="scene-detail-expanded">
<!-- 素材状态 -->
<!-- 回顾本场景入口 -->
<!-- 拍摄指引 -->
<!-- 操作按钮 -->
</view>
<!-- 5. 素材完成度 -->
<view class="assets-overview-section">...</view>
<!-- 6. 生成模式选择 -->
<view class="generation-modes">...</view>
<!-- 7. 场景回顾弹窗 -->
<scene-review-popup
:visible="showSceneReviewPopup"
:scenes="pipelineInfo.scenes"
:scene-index="reviewSceneIndex"
@close="handleSceneReviewClose"
@retake="handleSceneRetake"
@script-update="handleScriptUpdate"
/>
</view>
</template>2. 场景回顾弹窗 (scene-review-popup.vue)
功能特性
核心能力:
- ✅ 全屏视频预览(支持播放控制)
- ✅ 显示口播文案
- ✅ 编辑口播文案(调用
script-edit-modal) - ✅ 左右切换场景(智能跳过未拍摄场景)
- ✅ 重拍功能(跳转到拍摄页面)
- ✅ 完成/关闭操作
交互流程:
用户点击"回顾本场景"
↓
打开全屏弹窗
├─ 播放已拍摄视频
├─ 显示口播文案
├─ 点击"编辑" → 弹出文案编辑器
│ ├─ 修改文案
│ ├─ 保存 → 更新场景数据
│ └─ 关闭编辑器
├─ 点击左右箭头 → 切换场景
│ └─ 自动跳过未拍摄场景
├─ 点击"重拍" → 跳转拍摄页面
│ └─ 自动开启提词器
└─ 点击"完成" → 关闭弹窗组件接口
Props:
typescript
interface Props {
visible: boolean; // 控制显示
scenes: Array<Scene>; // 所有场景数据
sceneIndex: number; // 当前场景索引
segmentManager: Object; // 分段管理器
pipelineType: string; // 流水线类型
}Events:
typescript
interface Events {
close: () => void; // 关闭弹窗
retake: (sceneIndex: number) => void; // 重拍场景
'script-update': (data: { // 更新口播文案
sceneIndex: number;
script: string;
}) => void;
}3. 口播文案编辑弹窗 (script-edit-modal.vue)
功能特性
- 字数限制: 500字上限,实时显示剩余字数
- 输入验证: 保存前检查是否为空
- 防误操作: 不允许点击背景关闭
- 场景信息: 显示场景序号和标题
组件结构
vue
<template>
<view v-if="visible" class="script-edit-modal">
<!-- 头部 -->
<view class="modal-header">
<text>编辑口播文案</text>
<view @click="handleClose">✕</view>
</view>
<!-- 场景信息 -->
<view class="scene-info">
<view class="scene-badge">第{{ sceneIndex + 1 }}段</view>
<text>{{ sceneTitle }}</text>
</view>
<!-- 编辑区域 -->
<textarea
v-model="localScript"
placeholder="请输入口播文案..."
:maxlength="500"
/>
<text class="char-counter">{{ charCount }} / 500</text>
<!-- 操作按钮 -->
<view class="modal-actions">
<view @click="handleClose">取消</view>
<view @click="handleSave">保存</view>
</view>
</view>
</template>优化历史
2026-01-03 场景回顾入口优化
优化前
- 分散的"预览"和"继续拍"两个独立按钮
- 只能预览视频,无法编辑文案
- 重拍需要返回列表页操作
- 场景切换不便
优化后
- 统一入口: 合并为"回顾本场景"单一入口
- 功能集成: 预览、编辑、重拍集中在一个弹窗
- 智能切换: 自动跳过未拍摄场景
- 即时编辑: 弹窗内直接修改口播文案
技术细节
新增方法:
javascript
// 打开场景回顾弹窗
const openSceneReview = (sceneIndex) => {
reviewSceneIndex.value = sceneIndex;
showSceneReviewPopup.value = true;
};
// 处理场景重拍
const handleSceneRetake = (sceneIndex) => {
showSceneReviewPopup.value = false;
uni.navigateTo({
url: `/pages/beauty-camera/index?pipelineType=${pipelineType.value}&sceneIndex=${sceneIndex}&showTeleprompter=1`
});
};
// 处理口播文案更新
const handleScriptUpdate = (data) => {
const { sceneIndex, script } = data;
pipelineInfo.value.scenes[sceneIndex].narration = script;
console.log('[TaskDetail] Script updated for scene', sceneIndex);
};模板改造:
vue
<!-- 旧版:两个独立按钮 -->
<view class="preview-btn" @click="previewSceneVideo(index)">预览</view>
<view class="photo-btn" @click="captureScenePhoto(index)">继续拍</view>
<!-- 新版:统一入口 -->
<view class="review-scene-entry" @click="openSceneReview(index)">
<view class="review-icon">👁️</view>
<view class="review-content">
<text class="review-title">回顾本场景</text>
<text class="review-desc">预览视频、编辑文案、重拍</text>
</view>
<text class="review-arrow">›</text>
</view>状态管理
场景完成状态
使用 SegmentManager 管理场景素材:
javascript
// 检查场景是否完成
const isSceneComplete = (idx) => {
if (!segmentManager.value) return false;
const detail = segmentManager.value.getSceneCompletionDetail(idx);
return detail.isComplete;
};
// 获取场景视频状态
const getSceneVideoStatus = (sceneIndex) => {
if (!segmentManager.value) return false;
const segment = segmentManager.value.getSegment(sceneIndex);
return !!segment;
};
// 获取场景照片状态
const getScenePhotoStatus = (sceneIndex) => {
if (!segmentManager.value) return { count: 0, isComplete: false };
const photos = segmentManager.value.getScenePhotos(sceneIndex);
return {
count: photos.length,
isComplete: photos.length >= 2,
hasPhotos: photos.length > 0
};
};整体进度计算
javascript
const overallProgress = computed(() => {
if (!segmentManager.value) return {
videoCount: 0,
photoCount: 0,
completedScenes: 0,
totalScenes: 5
};
return segmentManager.value.getOverallProgress();
});样式设计
设计原则
- 深色主题: 符合短视频创作调性
- 紫色主色: 与品牌色保持一致
- 圆角设计: 柔和、现代的视觉风格
- 触摸反馈: 所有可点击元素都有 scale 缩放效果
关键样式
scss
// 回顾入口卡片
.review-scene-entry {
display: flex;
align-items: center;
gap: 16rpx;
padding: 24rpx;
background: linear-gradient(135deg, rgba(124, 58, 237, 0.15), rgba(59, 130, 246, 0.1));
border: 1rpx solid rgba(124, 58, 237, 0.3);
border-radius: 20rpx;
transition: all 0.2s ease;
&:active {
background: linear-gradient(135deg, rgba(124, 58, 237, 0.25), rgba(59, 130, 246, 0.15));
transform: scale(0.98);
}
}
// 场景卡片(已完成)
.scene-compact-card {
&.completed {
background: rgba(167, 139, 250, 0.08);
border-color: rgba(167, 139, 250, 0.3);
}
&.active {
background: rgba(167, 139, 250, 0.15);
border-color: #A78BFA;
box-shadow: 0 0 16rpx rgba(167, 139, 250, 0.3);
}
}性能优化
代码瘦身(2026-01-03)
- 删除 21 个未使用函数
- 删除 40+ 个未使用样式类
- 文件从 4687 行精简到 3797 行
- 代码减少 19%
渲染优化
- 使用
v-if延迟渲染未展开场景 - 横向滚动列表使用
scroll-into-view自动定位 - 图片懒加载
测试要点
功能测试
- [ ] 场景列表展示正确
- [ ] 横向滚动流畅
- [ ] 场景展开/收起动画
- [ ] 视频/照片状态显示准确
- [ ] "回顾本场景"入口显示条件正确
- [ ] 场景回顾弹窗打开/关闭
- [ ] 视频预览播放
- [ ] 口播文案编辑保存
- [ ] 场景左右切换(跳过未拍摄)
- [ ] 重拍跳转到拍摄页面
边界测试
- [ ] 无素材时的状态显示
- [ ] 第一个/最后一个场景的切换按钮状态
- [ ] 口播文案为空时的保存提示
- [ ] 口播文案超过 500 字的截断
兼容性测试
- [ ] 微信开发者工具
- [ ] iOS 真机
- [ ] Android 真机
- [ ] 不同屏幕尺寸
常见问题
Q: 点击"回顾本场景"无法打开弹窗?
原因: 组件未正确注册
解决方案:
- 确认
src/pages/task-detail/index.json中已注册组件:
json
{
"usingComponents": {
"scene-review-popup": "/components/scene-review-popup",
"script-edit-modal": "/components/script-edit-modal"
}
}- 重新编译小程序
Q: 编辑口播文案后不生效?
原因: 文案更新没有同步到场景数据
解决方案: 检查 handleScriptUpdate 方法是否正确更新了 pipelineInfo.value.scenes 数组。
Q: 场景切换时卡顿?
原因: 视频组件渲染耗时
优化方案:
- 使用
v-if而非v-show控制弹窗显示 - 视频组件添加
poster属性预加载封面 - 减少不必要的数据绑定