支付宝小程序拍照片/视频上传
·
用支付宝原生api写了个拍摄组件供参考,可拍图片和视频,预览图片和视频以及上传。
camera.acss
/* 照片拍摄组件样式 */
.photo-capture-container {
background: white;
margin: 20rpx;
padding: 30rpx;
border-radius: 16rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
/* 标题区域 */
.photo-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
}
.photo-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.photo-count {
font-size: 28rpx;
color: #666;
margin-left: 10rpx;
}
.sample-btn {
padding: 10rpx 20rpx;
background: #f0f0f0;
border-radius: 20rpx;
font-size: 24rpx;
color: #666;
}
.sample-btn:active {
background: #e0e0e0;
}
/* 照片网格 */
.photo-grid {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.photo-item {
position: relative;
width: 200rpx;
height: 200rpx;
border-radius: 12rpx;
overflow: hidden;
background: #f5f5f5;
}
.photo-image, .photo-video {
width: 100%;
height: 100%;
border-radius: 12rpx;
}
/* 视频播放图标 */
.video-play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60rpx;
height: 60rpx;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
backdrop-filter: blur(8rpx);
border: 4rpx solid rgba(255, 255, 255, 0.8);
}
.play-icon {
color: white;
font-size: 24rpx;
margin-left: 4rpx;
font-weight: bold;
}
/* 删除按钮 */
.photo-delete {
position: absolute;
top: 8rpx;
right: 8rpx;
width: 40rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.delete-icon {
color: white;
font-size: 28rpx;
font-weight: bold;
}
/* 只读模式隐藏删除按钮 */
.photo-item.readonly .photo-delete {
display: none;
}
/* 添加照片按钮 */
.add-photo-btn {
width: 200rpx;
height: 200rpx;
border: 2rpx dashed #ccc;
border-radius: 12rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #fafafa;
}
.add-photo-btn:active {
background: #f0f0f0;
}
.add-icon {
font-size: 60rpx;
color: #999;
margin-bottom: 10rpx;
}
.add-text {
font-size: 24rpx;
color: #999;
}
/* 提示信息 */
.photo-tips {
margin-top: 30rpx;
padding-top: 20rpx;
border-top: 2rpx solid #f0f0f0;
}
.photo-tips text {
display: block;
font-size: 24rpx;
color: #999;
line-height: 1.6;
margin-bottom: 8rpx;
}
.photo-tips text:last-child {
margin-bottom: 0;
}
/* 照片预览弹窗 */
.photo-viewer {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.9);
}
.viewer-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: transparent;
}
.viewer-content {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center; /* 居中对齐 */
justify-content: center; /* 垂直居中 */
background: transparent;
padding: 80rpx 20rpx 180rpx 20rpx; /* 为顶部关闭按钮和底部控制区域预留空间 */
}
.photo-swiper {
width: 100%;
height: 70vh;
display: flex;
align-items: center;
justify-content: center;
}
/* 预览图片样式 */
.viewer-image {
width: 90%; /* 限制宽度 */
max-width: 100%;
max-height: 70vh;
object-fit: contain;
border-radius: 8px;
}
/* 预览视频样式 */
.viewer-video {
width: 90%; /* 限制宽度 */
max-width: 100%;
max-height: 65vh; /* 减少视频高度,为进度条预留更多空间 */
background: transparent;
border-radius: 8px;
object-fit: contain;
}
.viewer-controls {
position: absolute;
bottom: 20rpx; /* 减少底部距离,避免过于靠近底部 */
left: 0;
right: 0;
padding: 30rpx 30rpx 40rpx 30rpx; /* 调整内边距,底部稍大一些 */
background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
border-radius: 20rpx 20rpx 0 0; /* 添加顶部圆角 */
}
.photo-counter {
text-align: center;
font-size: 28rpx; /* 稍微减小字体 */
color: white;
margin-bottom: 20rpx; /* 减少间距 */
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.5);
}
.viewer-buttons {
display: flex;
gap: 20rpx; /* 减少按钮间距 */
justify-content: center;
flex-wrap: wrap; /* 允许换行 */
}
.viewer-btn {
min-width: 100rpx; /* 减少最小宽度 */
padding: 20rpx 28rpx; /* 减少内边距 */
text-align: center;
font-size: 28rpx; /* 减小字体 */
font-weight: 500;
border-radius: 40rpx; /* 减少圆角 */
background: rgba(255, 255, 255, 0.9);
color: #333;
border: 2rpx solid rgba(255, 255, 255, 0.3);
backdrop-filter: blur(10rpx);
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.3);
}
.viewer-btn:active {
background: rgba(255, 255, 255, 0.7);
transform: scale(0.95);
}
.viewer-btn.delete {
background: rgba(255, 71, 87, 0.9);
color: white;
border: 2rpx solid rgba(255, 71, 87, 0.3);
}
.viewer-btn.delete:active {
background: rgba(255, 55, 66, 0.7);
transform: scale(0.95);
}
/* 关闭按钮 */
.viewer-close {
position: absolute;
top: 60rpx;
right: 40rpx;
width: 80rpx;
height: 80rpx;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
z-index: 1001;
backdrop-filter: blur(10rpx);
border: 2rpx solid rgba(255, 255, 255, 0.3);
}
.viewer-close:active {
background: rgba(0, 0, 0, 0.8);
transform: scale(0.9);
}
.close-icon {
color: white;
font-size: 48rpx;
font-weight: bold;
line-height: 1;
}
/* 样例图片查看器 */
.sample-viewer {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.9);
}
.sample-viewer .viewer-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: transparent;
}
.sample-viewer-title {
position: absolute;
top: 60rpx;
left: 40rpx;
z-index: 1001;
}
.sample-viewer-title .viewer-title {
color: white;
font-size: 32rpx;
font-weight: bold;
}
.sample-viewer .viewer-content {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: transparent;
padding: 80rpx 20rpx 180rpx 20rpx;
}
.sample-swiper {
width: 100%;
height: 70vh;
display: flex;
align-items: center;
justify-content: center;
}
.sample-viewer .viewer-image {
width: 90%;
max-width: 100%;
max-height: 100%;
border-radius: 8rpx;
}
.sample-viewer .viewer-controls {
position: absolute;
bottom: 40rpx;
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
gap: 20rpx;
}
.sample-viewer .photo-counter {
color: white;
font-size: 28rpx;
background: rgba(0, 0, 0, 0.5);
padding: 10rpx 20rpx;
border-radius: 20rpx;
}
.sample-viewer .viewer-buttons {
display: flex;
gap: 20rpx;
}
.sample-viewer .viewer-btn {
padding: 20rpx 40rpx;
background: rgba(255, 255, 255, 0.2);
color: white;
border-radius: 40rpx;
font-size: 28rpx;
backdrop-filter: blur(10rpx);
border: 1rpx solid rgba(255, 255, 255, 0.3);
}
.sample-viewer .viewer-btn:active {
background: rgba(255, 255, 255, 0.3);
transform: scale(0.95);
}
camera.axml
<!-- 照片拍摄组件 -->
<view>
<!-- 标题区域 -->
<view class="photo-header">
<text>请拍摄完整清晰照片</text>
<text a:if="{{mode === 'add' || mode === 'edit'}}" class="photo-count">({{photoList.length}}/{{maxCount}})</text>
<view class="sample-btn" onTap="onViewSample">
<text>查看样例</text>
</view>
</view>
<!-- 照片网格 -->
<view class="photo-grid">
<!-- 只读模式:显示已提交的图片 -->
<block a:if="{{mode === 'readonly'}}">
<view a:for="{{photoList}}" a:key="index" class="photo-item readonly">
<image
a:if="{{item.imgType === 'image' || !item.imgType}}"
src="{{item.url || item.imgUrl || item}}"
class="photo-image"
mode="aspectFill"
onTap="onPreviewPhoto"
data-index="{{index}}"
/>
<video
a:if="{{item.imgType === 'video'}}"
src="{{item.url || item.imgUrl || item}}"
class="photo-video"
poster="{{item.poster || item.thumbUrl}}"
controls="{{false}}"
onTap="onPreviewPhoto"
data-index="{{index}}"
/>
<view a:if="{{item.imgType === 'video'}}" class="video-play-icon">
<text class="play-icon">▶</text>
</view>
</view>
</block>
<!-- 编辑模式:可以删除和添加照片 -->
<block a:else>
<view a:for="{{photoList}}" a:key="index" class="photo-item editable">
<image
a:if="{{item.imgType === 'image' || !item.imgType}}"
src="{{item.url || item.imgUrl || item}}"
class="photo-image"
mode="aspectFill"
onTap="onPreviewPhoto"
data-index="{{index}}"
/>
<video
a:if="{{item.imgType === 'video'}}"
src="{{item.url || item.imgUrl || item}}"
class="photo-video"
poster="{{item.poster || item.thumbUrl}}"
controls="{{false}}"
onTap="onPreviewPhoto"
data-index="{{index}}"
/>
<view a:if="{{item.imgType === 'video'}}" class="video-play-icon">
<text class="play-icon">▶</text>
</view>
<view class="photo-delete" onTap="onDeletePhoto" data-index="{{index}}">
<text class="delete-icon">×</text>
</view>
</view>
</block>
<!-- 添加照片按钮 - 只在添加/编辑模式显示 -->
<view a:if="{{(mode === 'add' || mode === 'edit') && photoList.length < maxCount}}" class="add-photo-btn" onTap="onAddPhoto">
<text class="add-icon">+</text>
<text class="add-text">拍摄</text>
</view>
</view>
<!-- 提示信息 -->
<!-- <view class="photo-tips">
<text a:if="{{mode === 'readonly'}}">• 以上为已提交的照片内容</text>
<text a:if="{{mode === 'readonly'}}">• 点击照片可查看大图</text>
<text a:if="{{mode === 'add' || mode === 'edit'}}">• 请拍摄清晰的照片或视频,确保广告牌内容可见</text>
<text a:if="{{mode === 'add' || mode === 'edit'}}">• 建议拍摄角度正面,距离适中</text>
<text a:if="{{mode === 'add' || mode === 'edit'}}">• 最多可拍摄{{maxCount}}张照片或视频</text>
<text a:if="{{mode === 'add' || mode === 'edit'}}">• 建议在指定位置100米范围内拍摄</text>
</view> -->
</view>
<!-- 照片预览弹窗 -->
<view a:if="{{showPhotoViewer}}" class="photo-viewer">
<view class="viewer-overlay" onTap="onCloseViewer"></view>
<!-- 关闭按钮 -->
<view class="viewer-close" onTap="onCloseViewer">
<text class="close-icon">×</text>
</view>
<view class="viewer-content">
<swiper
class="photo-swiper"
current="{{currentPhotoIndex}}"
bindchange="onPhotoSwiperChange"
circular="{{true}}"
indicator-dots="{{false}}"
>
<swiper-item a:for="{{photoList}}" a:key="index">
<image
a:if="{{item.imgType === 'image' || !item.imgType}}"
src="{{item.url || item.imgUrl || item}}"
class="viewer-image"
mode="aspectFit"
onTap="onCloseViewer"
/>
<video
a:if="{{item.imgType === 'video'}}"
src="{{item.url || item.imgUrl || item}}"
class="viewer-video"
poster="{{item.poster || item.thumbUrl}}"
controls="{{true}}"
autoplay="{{false}}"
loop="{{false}}"
/>
</swiper-item>
</swiper>
<view class="viewer-controls">
<view class="photo-counter">{{currentPhotoIndex + 1}}/{{photoList.length}}</view>
<view class="viewer-buttons">
<view class="viewer-btn" onTap="onPrevPhoto">上一张</view>
<view class="viewer-btn" onTap="onNextPhoto">下一张</view>
<view a:if="{{mode === 'add' || mode === 'edit'}}" class="viewer-btn delete" onTap="onDeleteCurrentPhoto">删除</view>
</view>
</view>
</view>
</view>
<!-- 样例图片查看器 -->
<view a:if="{{showSampleViewer}}" class="sample-viewer">
<view class="viewer-overlay" onTap="onCloseSampleViewer"></view>
<!-- 关闭按钮 -->
<view class="viewer-close" onTap="onCloseSampleViewer">
<text class="close-icon">×</text>
</view>
<!-- 标题 -->
<view class="sample-viewer-title">
<text class="viewer-title">拍摄样例</text>
</view>
<view class="viewer-content">
<swiper
class="sample-swiper"
current="{{currentSampleIndex}}"
bindchange="onSampleSwiperChange"
circular="{{true}}"
indicator-dots="{{false}}"
>
<swiper-item a:for="{{sampleImages}}" a:key="index">
<image
src="{{item}}"
class="viewer-image"
mode="aspectFit"
onTap="onCloseSampleViewer"
/>
</swiper-item>
</swiper>
<view class="viewer-controls">
<view class="photo-counter">{{currentSampleIndex + 1}}/{{sampleImages.length}}</view>
<view class="viewer-buttons">
<view class="viewer-btn" onTap="onPrevSampleImage">上一张</view>
<view class="viewer-btn" onTap="onNextSampleImage">下一张</view>
</view>
</view>
</view>
</view>
camera.js
Component({
/**
* 组件属性
*/
props: {
// 照片列表
photoList: {
type: Array,
value: []
},
// 模式:readonly(只读), add(添加), edit(编辑)
mode: {
type: String,
value: 'add'
},
// 标题
title: {
type: String,
value: '拍摄'
},
// 最大照片数量
maxCount: {
type: Number,
value: 5
},
// 样例图片列表
sampleImages: {
type: Array,
value: []
}
},
/**
* 组件数据
*/
data: {
showPhotoViewer: false, // 是否显示照片预览
currentPhotoIndex: 0, // 当前预览的照片索引
currentPhoto: null, // 当前预览的照片
showSampleViewer: false, // 是否显示样例查看器
currentSampleIndex: 0 // 当前查看的样例图片索引
},
/**
* 组件方法
*/
methods: {
/**
* 获取文件扩展名
*/
getFileExtension(filePath) {
if (!filePath) return '';
const lastDotIndex = filePath.lastIndexOf('.');
return lastDotIndex !== -1 ? filePath.substring(lastDotIndex + 1).toLowerCase() : '';
},
/**
* 添加照片
*/
onAddPhoto() {
if (this.props.mode === 'readonly') {
return;
}
if (this.props.photoList.length >= this.props.maxCount) {
my.showToast({
content: `最多只能拍摄${this.props.maxCount}张照片`,
type: 'fail'
});
return;
}
// 显示选择拍摄类型的弹窗
my.showActionSheet({
title: '选择拍摄类型',
items: ['拍摄照片', '拍摄视频'],
success: (res) => {
if (res.index === 0) {
// 拍摄照片
this.capturePhoto();
} else if (res.index === 1) {
// 拍摄视频
this.captureVideo();
}
}
});
},
/**
* 拍摄照片
*/
capturePhoto() {
my.chooseImage({
count: 1,
sourceType: ['camera'], // 只允许拍照
success: (res) => {
const tempFilePath = res.tempFilePaths[0];
// 上传文件
this.uploadFile(tempFilePath, 'image')
.then((uploadResult) => {
console.log('照片上传结果:', uploadResult);
console.log('当前照片列表:', this.props.photoList);
// 触发onChange回调,传递上传后的结果
const newPhotoList = [...this.props.photoList, uploadResult];
if (this.props.onChange) {
this.props.onChange({
photoList: newPhotoList,
action: 'add',
photo: uploadResult,
mediaType: 'image'
});
}
my.showToast({
content: '照片上传成功',
type: 'success'
});
})
.catch((error) => {
console.error('照片上传失败:', error);
my.showToast({
content: error.message || '照片上传失败',
type: 'fail'
});
});
},
fail: (error) => {
console.error('拍照失败:', error);
my.showToast({
content: '拍照失败,请重试',
type: 'fail'
});
}
});
},
/**
* 拍摄视频
*/
captureVideo() {
my.chooseVideo({
sourceType: ['album', 'camera'], // 只允许拍摄
maxDuration: 60, // 最长60秒
success: (res) => {
console.log('拍摄视频信息:', res);
const fs = my.getFileSystemManager();
const oldPath = res.tempFilePath;
const newPath = `${my.env.USER_DATA_PATH}/upload_${Date.now()}.mp4`;
// 把临时文件.video文件拷贝成一个 .mp4 文件
fs.copyFile({
srcPath: oldPath,
destPath: newPath,
success: () => {
// 上传文件
this.uploadFile(newPath, 'video')
.then((uploadResult) => {
my.hideLoading();
// 触发onChange回调,传递上传后的结果
const newPhotoList = [...this.props.photoList, uploadResult];
if (this.props.onChange) {
this.props.onChange({
photoList: newPhotoList,
action: 'add',
photo: uploadResult,
mediaType: 'video'
});
}
my.showToast({
content: '视频上传成功',
type: 'success'
});
})
.catch((error) => {
my.hideLoading();
console.error('视频上传失败:', error);
my.showToast({
content: error.message || '视频上传失败',
type: 'fail'
});
});
},
fail: (err) => {
console.error('拷贝文件失败', err);
}
});
},
fail: (error) => {
console.error('拍摄视频失败:', error);
my.showToast({
content: '视频拍摄失败,请重试',
type: 'fail'
});
}
});
},
/**
* 删除照片
*/
onDeletePhoto(e) {
if (this.props.mode === 'readonly') {
return;
}
const index = parseInt(e.target.dataset.index);
const photoToDelete = this.props.photoList[index];
my.confirm({
title: '确认删除',
content: '确定要删除这张照片吗?',
success: (result) => {
if (result.confirm) {
const newPhotoList = this.props.photoList.filter((_, i) => i !== index);
// 触发onChange回调
if (this.props.onChange) {
this.props.onChange({
photoList: newPhotoList,
action: 'delete',
photo: photoToDelete,
index: index
});
}
}
}
});
},
/**
* 预览照片
*/
onPreviewPhoto(e) {
const index = parseInt(e.target.dataset.index);
const photo = this.props.photoList[index];
this.setData({
showPhotoViewer: true,
currentPhotoIndex: index,
currentPhoto: photo
});
},
/**
* 关闭预览
*/
onCloseViewer() {
this.setData({
showPhotoViewer: false,
currentPhotoIndex: 0,
currentPhoto: null
});
},
/**
* 照片滑动事件
*/
onPhotoSwiperChange(e) {
const { current } = e.detail;
this.setData({
currentPhotoIndex: current,
currentPhoto: this.props.photoList[current]
});
},
/**
* 上一张照片
*/
onPrevPhoto() {
const newIndex = this.data.currentPhotoIndex > 0
? this.data.currentPhotoIndex - 1
: this.props.photoList.length - 1;
this.setData({
currentPhotoIndex: newIndex,
currentPhoto: this.props.photoList[newIndex]
});
},
/**
* 下一张照片
*/
onNextPhoto() {
const newIndex = this.data.currentPhotoIndex < this.props.photoList.length - 1
? this.data.currentPhotoIndex + 1
: 0;
this.setData({
currentPhotoIndex: newIndex,
currentPhoto: this.props.photoList[newIndex]
});
},
/**
* 删除当前预览的照片
*/
onDeleteCurrentPhoto() {
if (this.props.mode === 'readonly') {
return;
}
const index = this.data.currentPhotoIndex;
const photoToDelete = this.props.photoList[index];
my.confirm({
title: '确认删除',
content: '确定要删除这张照片吗?',
success: (result) => {
if (result.confirm) {
const newPhotoList = this.props.photoList.filter((_, i) => i !== index);
// 关闭预览
this.onCloseViewer();
// 触发onChange回调
this.props.onChange({
photoList: newPhotoList,
action: 'delete',
photo: photoToDelete,
index: index
})
}
}
});
},
/**
* 查看样例
*/
onViewSample() {
// if (this.props.mode === 'readonly') {
// return;
// }
// 触发查看样例事件
this.props.onChange({
sampleImages: this.props.sampleImages
});
},
/**
* 上传文件
*/
uploadFile(filePath, fileType) {
return new Promise((resolve, reject) => {
// 获取token
let token = '';
const tokenData = my.getStorageSync({ key: 'token' });
token = tokenData.data || '';
// 尝试从全局获取BASE_URL
let baseUrl = '';
try {
const app = getApp();
if (app && app.globalData && app.globalData.BASE_URL) {
baseUrl = app.globalData.BASE_URL;
} else {
// 可以尝试从本地存储或配置文件获取
const configData = my.getStorageSync({ key: 'config' });
if (configData.data && configData.data.baseUrl) {
baseUrl = configData.data.baseUrl;
}
}
} catch (e) {
console.error('获取全局BASE_URL失败:', e);
}
if (!baseUrl) {
console.error('BASE_URL为空,无法上传');
reject(new Error('服务器地址配置错误'));
return;
}
const uploadUrl = `${baseUrl}/common/upload`;
console.log('上传URL:', uploadUrl);
// 设置超时定时器
const timeoutId = setTimeout(() => {
console.error('上传超时');
reject(new Error('上传超时,请检查网络连接'));
}, 30000); // 30秒超时
my.uploadFile({
url: uploadUrl,
filePath: filePath, // 使用修正后的文件路径
name: 'file',
fileType: fileType,
header: {
'Authorization': token ? `Bearer ${token}` : '',
// 'Content-Type': 'multipart/form-data'
},
success: (res) => {
clearTimeout(timeoutId);
console.log('文件上传成功,原始响应:', res);
if (!res.data) {
console.error('上传响应数据为空');
reject(new Error('服务器响应异常'));
return;
}
try {
const responseData = JSON.parse(res.data);
console.log('解析后的响应数据:', responseData);
if (responseData.code === 200 && responseData.data) {
// 返回上传结果,包含文件URL和类型信息
const uploadResult = {
imgType: fileType === 'video' ? 'video' : 'image',
imgUrl: responseData.data, // 后端返回的URL字符串
remark: null,
filePath: filePath // 保留本地文件路径
};
console.log('构造的上传结果:', uploadResult);
resolve(uploadResult);
} else {
console.error('上传失败,服务器返回:', responseData);
reject(new Error(responseData.message || responseData.msg || '上传失败'));
}
} catch (parseError) {
console.error('解析上传响应失败:', parseError, '原始数据:', res.data);
reject(new Error('解析服务器响应失败'));
}
},
fail: (error) => {
clearTimeout(timeoutId);
console.error('文件上传失败:', error);
let errorMessage = '文件上传失败';
if (error.error) {
errorMessage += ': ' + error.error;
} else if (error.errorMessage) {
errorMessage += ': ' + error.errorMessage;
}
reject(new Error(errorMessage));
}
});
});
},
/**
* 查看样例图片
*/
onViewSample() {
if (!this.props.sampleImages || this.props.sampleImages.length === 0) {
my.showToast({
content: '暂无样例图片',
type: 'fail'
});
return;
}
this.setData({
showSampleViewer: true,
currentSampleIndex: 0
});
},
/**
* 关闭样例查看器
*/
onCloseSampleViewer() {
this.setData({
showSampleViewer: false
});
},
/**
* 样例图片滑动事件
*/
onSampleSwiperChange(e) {
const { current } = e.detail;
this.setData({
currentSampleIndex: current
});
},
/**
* 上一张样例图片
*/
onPrevSampleImage() {
const { currentSampleIndex } = this.data;
const sampleImages = this.props.sampleImages || [];
const newIndex = currentSampleIndex > 0 ? currentSampleIndex - 1 : sampleImages.length - 1;
this.setData({
currentSampleIndex: newIndex
});
},
/**
* 下一张样例图片
*/
onNextSampleImage() {
const { currentSampleIndex } = this.data;
const sampleImages = this.props.sampleImages || [];
const newIndex = currentSampleIndex < sampleImages.length - 1 ? currentSampleIndex + 1 : 0;
this.setData({
currentSampleIndex: newIndex
});
}
},
didMount() {
console.log(11, this.props.photoList)
}
});
注意:组件是AI写的,可能有些bug。
火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。
更多推荐
所有评论(0)