mrr.sj.front/components/upload/media-upload.nvue

264 lines
5.6 KiB
Plaintext
Raw Normal View History

2026-03-24 11:45:13 +08:00
<template>
<view class="upload-section">
<!-- 上传类型选择 -->
<view class="upload-header">
<text class="section-title">上传照片/视频</text>
<text class="upload-tip">(最多可上传9张图片或1个视频)</text>
</view>
<!-- 媒体列表 -->
<view class="media-list">
<view
v-for="(item, index) in mediaList"
:key="index"
class="media-item"
>
<!-- 图片预览 -->
<image
v-if="item.type === 'image'"
:src="item.url"
class="media-preview"
mode="aspectFill"
></image>
<!-- 视频预览 -->
<video
v-if="item.type === 'video'"
:src="item.url"
class="media-preview"
:poster="item.poster"
></video>
<!-- 删除按钮 -->
<view class="delete-btn" @click="deleteMedia(index)">
<text class="delete-icon">×</text>
</view>
</view>
<!-- 上传按钮 -->
<view
v-if="showUploadBtn"
class="upload-btn"
@click="showActionSheet"
>
<text class="plus-icon">+</text>
<text class="upload-text">上传照片/视频</text>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'media-upload',
data() {
return {
mediaList: [],
maxCount: 9, // 最大图片数量
maxVideo: 1, // 最大视频数量
}
},
computed: {
showUploadBtn() {
// 如果有视频,不显示上传按钮
if (this.mediaList.some(item => item.type === 'video')) {
return false
}
// 如果图片数量达到最大值,不显示上传按钮
if (this.mediaList.length >= this.maxCount) {
return false
}
return true
}
},
methods: {
showActionSheet() {
uni.showActionSheet({
itemList: ['拍摄', '从相册选择'],
success: (res) => {
if (res.tapIndex === 0) {
this.takePhoto()
} else {
this.chooseMedia()
}
}
})
},
// 拍摄照片或视频
takePhoto() {
uni.showActionSheet({
itemList: ['拍照', '录视频'],
success: (res) => {
if (res.tapIndex === 0) {
// 拍照
uni.chooseImage({
count: 1,
sourceType: ['camera'],
success: (res) => {
this.handleImageSuccess(res)
}
})
} else {
// 录视频
uni.chooseVideo({
sourceType: ['camera'],
maxDuration: 60,
camera: 'back',
success: (res) => {
this.handleVideoSuccess(res)
}
})
}
}
})
},
// 从相册选择
chooseMedia() {
uni.showActionSheet({
itemList: ['选择图片', '选择视频'],
success: (res) => {
if (res.tapIndex === 0) {
// 选择图片
uni.chooseImage({
count: this.maxCount - this.mediaList.length,
sourceType: ['album'],
success: (res) => {
this.handleImageSuccess(res)
}
})
} else {
// 选择视频
uni.chooseVideo({
sourceType: ['album'],
maxDuration: 60,
success: (res) => {
this.handleVideoSuccess(res)
}
})
}
}
})
},
// 处理图片选择结果
handleImageSuccess(res) {
const newImages = res.tempFilePaths.map(path => ({
type: 'image',
url: path
}))
this.mediaList = [...this.mediaList, ...newImages]
this.$emit('change', this.mediaList)
},
// 处理视频选择结果
handleVideoSuccess(res) {
this.mediaList = [{
type: 'video',
url: res.tempFilePath,
poster: res.thumbTempFilePath
}]
this.$emit('change', this.mediaList)
},
// 删除媒体文件
deleteMedia(index) {
uni.showModal({
title: '提示',
content: '确定要删除这个文件吗?',
success: (res) => {
if (res.confirm) {
this.mediaList.splice(index, 1)
this.$emit('change', this.mediaList)
}
}
})
}
}
}
</script>
<style>
.upload-section {
padding: 30rpx;
background-color: #ffffff;
}
.upload-header {
flex-direction: row;
align-items: center;
margin-bottom: 20rpx;
}
.section-title {
font-size: 28rpx;
color: #333;
font-weight: bold;
}
.upload-tip {
font-size: 24rpx;
color: #999;
margin-left: 20rpx;
}
.media-list {
flex-direction: row;
flex-wrap: wrap;
}
.media-item {
width: 220rpx;
height: 220rpx;
margin-right: 20rpx;
margin-bottom: 20rpx;
position: relative;
}
.media-preview {
width: 220rpx;
height: 220rpx;
border-radius: 12rpx;
background-color: #f5f6fa;
}
.delete-btn {
position: absolute;
right: -16rpx;
top: -16rpx;
width: 40rpx;
height: 40rpx;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
justify-content: center;
align-items: center;
}
.delete-icon {
color: #ffffff;
font-size: 32rpx;
line-height: 32rpx;
}
.upload-btn {
width: 220rpx;
height: 220rpx;
background-color: #f5f6fa;
border-radius: 12rpx;
justify-content: center;
align-items: center;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.plus-icon {
font-size: 48rpx;
color: #999;
margin-bottom: 10rpx;
}
.upload-text {
font-size: 24rpx;
color: #999;
}
</style>