视频上传按钮修复
This commit is contained in:
parent
0e9bca8d97
commit
79ee295c18
|
|
@ -19,9 +19,13 @@
|
|||
mode="aspectFill"
|
||||
@click="handlePreview(index)"
|
||||
/>
|
||||
<view v-if="deletable" class="delete-icon" @click.stop="handleDelete(index)">
|
||||
×
|
||||
</view>
|
||||
<image
|
||||
v-if="deletable"
|
||||
class="delete-icon"
|
||||
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6ab3fc63-3bad-403d-bbfc-9609a93c048a.png"
|
||||
mode="aspectFit"
|
||||
@click.stop="handleDelete(index)"
|
||||
></image>
|
||||
</view>
|
||||
<!-- 上传按钮 -->
|
||||
<view class="preview-item">
|
||||
|
|
@ -41,27 +45,34 @@
|
|||
|
||||
<!-- 视频预览区域 -->
|
||||
<view class="preview-container" :style="'width:'+width" v-if="accept == 'video/*'">
|
||||
<view
|
||||
class="preview-item"
|
||||
v-if="oneFile"
|
||||
>
|
||||
<!-- <video
|
||||
:src="oneFile"
|
||||
class="preview-image"
|
||||
@click="handlePreview(index)"
|
||||
/> -->
|
||||
<image class="preview-image" :src="oneFile + '?x-oss-process=video/snapshot,t_0,f_jpg'" mode="aspectFill"></image>
|
||||
<view v-if="deletable" class="delete-icon" @click.stop="handleDelete()">
|
||||
×
|
||||
<block v-if="showPreview">
|
||||
<view
|
||||
v-for="(file, index) in videoList"
|
||||
:key="file || index"
|
||||
class="preview-item"
|
||||
>
|
||||
<!-- <video
|
||||
:src="file"
|
||||
class="preview-image"
|
||||
@click="handlePreview(index)"
|
||||
/> -->
|
||||
<image class="preview-image" :src="getVideoPoster(file)" mode="aspectFill"></image>
|
||||
<image
|
||||
v-if="deletable"
|
||||
class="delete-icon"
|
||||
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6ab3fc63-3bad-403d-bbfc-9609a93c048a.png"
|
||||
mode="aspectFit"
|
||||
@click.stop="handleDelete(index)"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="preview-item">
|
||||
<!-- 上传按钮 -->
|
||||
<view
|
||||
class="upload-btn"
|
||||
@click="handleUpload"
|
||||
:style="btnStyle"
|
||||
v-if="!oneFile"
|
||||
v-if="videoCount < maxCount"
|
||||
>
|
||||
<slot name="button">
|
||||
<text class="plus-icon">+</text>
|
||||
|
|
@ -161,6 +172,7 @@ export default {
|
|||
return {
|
||||
fileList: [],
|
||||
oneFile: '',
|
||||
videoList: [],
|
||||
loading: false,
|
||||
dragIndex: -1,
|
||||
isDragging: false,
|
||||
|
|
@ -168,6 +180,12 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
videoCount() {
|
||||
return this.showPreview ? this.videoList.length : 0
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
|
|
@ -179,6 +197,7 @@ export default {
|
|||
immediate: true,
|
||||
handler(newVal) {
|
||||
this.oneFile = newVal
|
||||
this.videoList = newVal ? [newVal] : []
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -284,12 +303,15 @@ export default {
|
|||
await this.uploadFile(file);
|
||||
}
|
||||
} else if (this.accept === 'video/*') {
|
||||
const res = await uni.chooseVideo({
|
||||
sourceType: [sourceType],
|
||||
compressed: true,
|
||||
maxDuration: 60
|
||||
});
|
||||
await this.uploadFile(res);
|
||||
const count = this.maxCount - this.videoCount;
|
||||
if (count <= 0) {
|
||||
uni.showToast({ title: `最多上传${this.maxCount}个文件`, icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const files = await this.chooseVideoFiles(sourceType, count);
|
||||
for (const file of files) {
|
||||
await this.uploadFile(file);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('选择文件失败:', error);
|
||||
|
|
@ -305,7 +327,7 @@ export default {
|
|||
})
|
||||
return Promise.reject(new Error('文件大小超出限制'))
|
||||
}
|
||||
let date = new Date().getTime()
|
||||
let date = `${new Date().getTime()}_${Math.floor(Math.random() * 100000)}`
|
||||
const fileExt = this.getFileExt(file)
|
||||
|
||||
let artisan = this.type==1 ? 'yh' : this.type==2 ? 'syr' : this.type==3 ? 'sj' : '';
|
||||
|
|
@ -327,8 +349,12 @@ export default {
|
|||
}else if(this.accept == 'video/*') {
|
||||
const newFile = fileUrl
|
||||
this.oneFile = fileUrl
|
||||
this.$emit('input', this.oneFile)
|
||||
this.$emit('change', this.oneFile)
|
||||
if (this.showPreview) {
|
||||
this.videoList = this.videoList.concat([newFile]).slice(0, this.maxCount)
|
||||
}
|
||||
const emitValue = this.maxCount > 1 && this.showPreview ? this.videoList : this.oneFile
|
||||
this.$emit('input', emitValue)
|
||||
this.$emit('change', emitValue)
|
||||
this.$emit('success', newFile)
|
||||
return newFile
|
||||
}
|
||||
|
|
@ -369,6 +395,44 @@ export default {
|
|||
return dir ? `${dir}/${name}` : name
|
||||
},
|
||||
|
||||
getVideoPoster(url) {
|
||||
if (!url) return ''
|
||||
if (String(url).indexOf('x-oss-process=') > -1) return url
|
||||
const connector = String(url).indexOf('?') > -1 ? '&' : '?'
|
||||
return `${url}${connector}x-oss-process=video/snapshot,t_2000,f_jpg,m_fast`
|
||||
},
|
||||
|
||||
chooseVideoFiles(sourceType, count) {
|
||||
if (uni.chooseMedia) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.chooseMedia({
|
||||
count,
|
||||
mediaType: ['video'],
|
||||
sourceType: [sourceType],
|
||||
maxDuration: 60,
|
||||
success: (res) => {
|
||||
const files = (res.tempFiles || []).map((item) => ({
|
||||
...item,
|
||||
tempFilePath: item.tempFilePath || item.path,
|
||||
path: item.tempFilePath || item.path,
|
||||
}));
|
||||
resolve(files);
|
||||
},
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.chooseVideo({
|
||||
sourceType: [sourceType],
|
||||
compressed: true,
|
||||
maxDuration: 60,
|
||||
success: (res) => resolve([res]),
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 上传到OSS
|
||||
uploadToOss(file, ossConfig, name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -512,11 +576,14 @@ export default {
|
|||
this.$emit('change', this.fileList)
|
||||
this.$emit('delete', deletedFile, index)
|
||||
}else if(this.accept == 'video/*') {
|
||||
const deletedFile = this.oneFile
|
||||
this.oneFile = ''
|
||||
this.$emit('input', this.oneFile)
|
||||
this.$emit('change', this.oneFile)
|
||||
this.$emit('delete', deletedFile)
|
||||
const deleteIndex = index === undefined ? 0 : index
|
||||
const deletedFile = this.videoList[deleteIndex]
|
||||
this.videoList.splice(deleteIndex, 1)
|
||||
this.oneFile = this.videoList[0] || ''
|
||||
const emitValue = this.maxCount > 1 ? this.videoList : this.oneFile
|
||||
this.$emit('input', emitValue)
|
||||
this.$emit('change', emitValue)
|
||||
this.$emit('delete', deletedFile, deleteIndex)
|
||||
}
|
||||
|
||||
// }
|
||||
|
|
@ -539,8 +606,11 @@ export default {
|
|||
|
||||
.preview-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
justify-items: center;
|
||||
grid-template-columns: repeat(3, 200rpx);
|
||||
column-gap: 18rpx;
|
||||
row-gap: 20rpx;
|
||||
justify-content: flex-start;
|
||||
justify-items: stretch;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
|
@ -579,7 +649,6 @@ export default {
|
|||
position: relative;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.image-preview-item.dragging {
|
||||
|
|
@ -597,15 +666,8 @@ export default {
|
|||
position: absolute;
|
||||
top: -10rpx;
|
||||
right: -10rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #ff4d4f;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
z-index: 1;
|
||||
width: 42rpx;
|
||||
height: 42rpx;
|
||||
z-index: 5;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,23 @@
|
|||
<view>
|
||||
<view v-if="maxCount > 1" class="video-list">
|
||||
<view v-for="(item, index) in currentList" :key="index" class="video-wrapper">
|
||||
<video :src="item" class="preview-video" controls />
|
||||
<view class="delete-btn" @click="deleteVideo(index)">
|
||||
<text class="delete-icon">×</text>
|
||||
<image :src="getVideoPoster(item)" class="preview-video" mode="aspectFill" @click="previewVideo(item)" />
|
||||
<view class="play-mask" @click="previewVideo(item)">
|
||||
<view class="play-circle">
|
||||
<view class="play-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
<image
|
||||
class="delete-btn"
|
||||
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6ab3fc63-3bad-403d-bbfc-9609a93c048a.png"
|
||||
mode="aspectFit"
|
||||
@click="deleteVideo(index)"
|
||||
></image>
|
||||
</view>
|
||||
<ali-oss-uploader v-if="currentList.length < maxCount" :key="currentList.length"
|
||||
<ali-oss-uploader v-if="currentList.length < maxCount"
|
||||
:max-count="maxCount - currentList.length"
|
||||
:max-size="maxSize" accept="video/*" :userId="uploadUserId" :type="ossType" :kind="2" width="200rpx"
|
||||
:show-preview="false"
|
||||
@input="onMultiInput" @change="onChange" />
|
||||
</view>
|
||||
<view v-else>
|
||||
|
|
@ -17,9 +26,25 @@
|
|||
:userId="uploadUserId" :type="ossType" :kind="2" width="100%" :file-string="currentValue" @input="onInput"
|
||||
@change="onChange" @success="onInput" @delete="deleteSingleVideo" />
|
||||
<view v-else class="video-wrapper">
|
||||
<video :src="currentValue" class="preview-video" controls />
|
||||
<view class="delete-btn" @click="deleteSingleVideo">
|
||||
<text class="delete-icon">×</text>
|
||||
<image :src="getVideoPoster(currentValue)" class="preview-video" mode="aspectFill" @click="previewVideo(currentValue)" />
|
||||
<view class="play-mask" @click="previewVideo(currentValue)">
|
||||
<view class="play-circle">
|
||||
<view class="play-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
<image
|
||||
class="delete-btn"
|
||||
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6ab3fc63-3bad-403d-bbfc-9609a93c048a.png"
|
||||
mode="aspectFit"
|
||||
@click="deleteSingleVideo"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showPlayer" class="player-mask" @click="closePlayer">
|
||||
<view class="player-box" @click.stop>
|
||||
<video :src="playingVideo" class="player-video" controls autoplay show-fullscreen-btn />
|
||||
<view class="player-close" @click="closePlayer">
|
||||
<text class="player-close-text">×</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -41,7 +66,9 @@ export default {
|
|||
data: function () {
|
||||
return {
|
||||
currentValue: '',
|
||||
currentList: []
|
||||
currentList: [],
|
||||
showPlayer: false,
|
||||
playingVideo: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -80,13 +107,33 @@ export default {
|
|||
},
|
||||
onMultiInput: function (val) {
|
||||
var arr = Array.isArray(val) ? val : [val];
|
||||
var list = this.currentList.concat(arr).slice(0, this.maxCount);
|
||||
var existing = this.currentList.filter(function (item) {
|
||||
return arr.indexOf(item) === -1;
|
||||
});
|
||||
var list = existing.concat(arr).filter(function (item, index, self) {
|
||||
return item && self.indexOf(item) === index;
|
||||
}).slice(0, this.maxCount);
|
||||
this.currentList = list;
|
||||
this.$emit('input', list);
|
||||
},
|
||||
onChange: function (val) {
|
||||
this.$emit('change', val);
|
||||
},
|
||||
getVideoPoster: function (url) {
|
||||
if (!url) return '';
|
||||
if (String(url).indexOf('x-oss-process=') > -1) return url;
|
||||
var connector = String(url).indexOf('?') > -1 ? '&' : '?';
|
||||
return url + connector + 'x-oss-process=video/snapshot,t_2000,f_jpg,m_fast';
|
||||
},
|
||||
previewVideo: function (url) {
|
||||
if (!url) return;
|
||||
this.playingVideo = url;
|
||||
this.showPlayer = true;
|
||||
},
|
||||
closePlayer: function () {
|
||||
this.showPlayer = false;
|
||||
this.playingVideo = '';
|
||||
},
|
||||
deleteSingleVideo: function () {
|
||||
this.currentValue = '';
|
||||
this.$emit('input', '');
|
||||
|
|
@ -110,32 +157,100 @@ export default {
|
|||
position: relative;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.preview-video {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 8rpx;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.play-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
border-radius: 8rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.play-circle {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(0, 0, 0, 0.55);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.play-icon {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 14rpx solid transparent;
|
||||
border-bottom: 14rpx solid transparent;
|
||||
border-left: 22rpx solid #ffffff;
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
position: absolute;
|
||||
top: -10rpx;
|
||||
right: -10rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #ff4d4f;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
z-index: 1;
|
||||
width: 42rpx;
|
||||
height: 42rpx;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
.player-mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.82);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.player-box {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.player-video {
|
||||
width: 100%;
|
||||
height: 420rpx;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.player-close {
|
||||
position: absolute;
|
||||
right: -12rpx;
|
||||
top: -58rpx;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255, 255, 255, 0.22);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.player-close-text {
|
||||
color: #ffffff;
|
||||
font-size: 32rpx;
|
||||
font-size: 42rpx;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -12,18 +12,9 @@
|
|||
<!-- 表单区域 -->
|
||||
<view class="form-container">
|
||||
<!-- 服务分类(仅显示不可编辑) -->
|
||||
<view class="form-item" v-if="firstClassName">
|
||||
<text class="form-label">服务分类</text>
|
||||
<view class="form-right">
|
||||
<text class="form-value">{{ firstClassName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 服务子类(仅显示不可编辑) -->
|
||||
<view class="form-item" v-if="secondClassName">
|
||||
<text class="form-label">服务子类</text>
|
||||
<view class="form-right">
|
||||
<text class="form-value">{{ secondClassName }}</text>
|
||||
</view>
|
||||
<view class="form-item service-class-item" v-if="serviceClassName">
|
||||
<text class="form-label">服务分类:</text>
|
||||
<text class="form-value service-class-value">{{ serviceClassName }}</text>
|
||||
</view>
|
||||
<!-- 动态表单区域 -->
|
||||
<dynamic-form :fields="formFields" v-model="formData" :upload-user-id="formData.publish_user_id"
|
||||
|
|
@ -209,6 +200,9 @@ export default {
|
|||
return group.type === 'video';
|
||||
});
|
||||
},
|
||||
serviceClassName() {
|
||||
return [this.firstClassName, this.secondClassName].filter(Boolean).join('/');
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 字段类型映射:接口类型 -> dynamic-form类型
|
||||
|
|
@ -1171,6 +1165,18 @@ export default {
|
|||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.service-class-item {
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.service-class-value {
|
||||
flex: 1;
|
||||
margin-right: 0;
|
||||
line-height: 40rpx;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
|
|
|
|||
|
|
@ -120,13 +120,13 @@ const request = async (options, isUpdate) => {
|
|||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
// baseURL = "http://116.63.163.121:93"; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
baseURL = "http://116.63.163.121:96"; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
baseURL = "http://116.63.163.121:93"; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
// baseURL = "http://116.63.163.121:96"; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
// baseURL = "https://app.mrrweb.com.cn";
|
||||
} else {
|
||||
baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
// baseURL = "http://116.63.163.121:93"; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
baseURL = "http://116.63.163.121:96"; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
baseURL = "http://116.63.163.121:93"; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
// baseURL = "http://116.63.163.121:96"; // 发布到生产环境时,此处代码会被摇树移除掉。
|
||||
// baseURL = "https://app.mrrweb.com.cn";
|
||||
|
||||
console.log("生产环境");
|
||||
|
|
|
|||
Loading…
Reference in New Issue