

<script>
import ActivityService from "@/app/service/activityService.js";
const ActivityServices = new ActivityService();
import CryptoJS from 'crypto-js';
import { Base64 } from 'js-base64';
let uid = 0
export default {
props: {
showInfo:{
type:Object,
default:{
from:'release',
loadingText:true,
maxNum:true,
showPreview:true,
}
},
userId: {
type: String,
required: true
},
initFileList: {
type: Array,
default: []
},
fileType: {
type: Number,
default: 0
},
activityId: String,
recordingParams: Object,
cameraParams: Object,
ossConfig: {
region: "yourRegion",
accessKeyId: "yourAccessKeyId",
accessKeySecret: "yourAccessKeySecret",
stsToken: "yourSecurityToken",
bucket: "examplebucket",
authorizationV4: true
}
},
computed: {
activity_info() {
return this.$store.getters['activity/activity_info']
},
},
watch: {
initFileList: {
immediate: true,
handler(newVal) {
if (newVal) {
console.log(this.activityId,"活动ID")
console.log(newVal)
this.fileList = [...newVal].filter(item=>item.url).map(item=>{
item.preview = item.url;
return item;
})
}else{
console.log(newVal)
}
}
}
},
data() {
return {
fileList: [],
uploading: false,
progress: 0,
previewUrl: '',
currentFile: null,
files:null,
}
},
methods: {
async handleUpload() {
if (this.uploading) return
try {
const files = await this.chooseMedia()
this.files =files;
console.log(files,"files")
if (!files.length) return
const validFiles = this.validateFiles(files)
this.fileList = [...this.fileList, ...validFiles]
for (const file of validFiles) {
await this.uploadFile(file)
}
uni.showToast({ title: '全部上传完成' })
} catch (error) {
} finally {
this.uploading = false
}
},
chooseMedia() {
return new Promise((resolve, reject) => {
wx.requirePrivacyAuthorize({
success: () => {
uni.chooseMedia({
count: 4 - this.fileList.length,
mediaType: ['image', 'video'],
sourceType: ['album', 'camera'],
maxDuration: 30,
success: res => resolve(res.tempFiles),
fail: reject
})
},
fail: () => {
wx.showToast({
title: '需同意隐私协议才能使用该功能',
icon: 'none'
});
}
})
})
},
validateFiles(files) {
return files.map(file => {
const isVideo = file.fileType === 'video'
const maxSize = isVideo ? 10 * 1024 * 1024 : 2 * 1024 * 1024
if (file.size > maxSize) {
throw new Error(`${isVideo ? '视频' : '图片'}大小不能超过${isVideo ? 10 : 2}MB`)
}
return {
uid: uid++,
type: file.fileType,
name: file.tempFilePath.split('/').pop(),
size: file.size,
preview: file.tempFilePath,
progress: 0,
status: 'pending'
}
})
},
readFileContent(tempFilePath) {
return new Promise((resolve, reject) => {
uni.getFileSystemManager().readFile({
filePath: tempFilePath,
success: res => resolve(res.data),
fail: err => reject(new Error('文件读取失败'))
});
});
},
async uploadFile(file) {
try {
file.status = 'uploading';
const ossConfig = await ActivityServices.getAliyunConfig({
user_id: this.userId,
file_name: file.name,
file_type: file.type === 'video' ? 1 : 0
});
const ossUrl = await this.uploadToOSS(file,
ossConfig.data.data
);
file.progress = 100;
file.status = 'success';
file.url = ossUrl;
} catch (error) {
file.status = 'error';
throw error;
}
},
formatEndpoint(endpoint) {
if (endpoint.startsWith('http://')) return endpoint;
if (endpoint.startsWith('https://')) return endpoint;
return `https://${endpoint}`;
},
getMimeType(fileType) {
const types = {
image: 'image/jpeg',
video: 'video/mp4'
};
return types[fileType] || 'application/octet-stream';
},
getUTCDate() {
const expiration = new Date();
expiration.setUTCHours(expiration.getUTCHours() + 1);
return expiration.toISOString().split('.')[0] + 'Z';
},
async uploadToOSS(file,config) {
try {
const policy = {
expiration: this.getUTCDate(config.expiration),
conditions: [
['content-length-range', 0, 104857600],
['eq', '$bucket', config.bucket],
['starts-with', '$key', `${this.userId}/`]
]
};
const policyBase64 = Base64.encode(JSON.stringify(policy));
const signature = CryptoJS.HmacSHA1(policyBase64, config.access_key_secret)
.toString(CryptoJS.enc.Base64);
const fileName = `${this.userId}/${Date.now()}_${file.name}`;
const formData = {
key: fileName,
OSSAccessKeyId: config.access_key_id,
policy: policyBase64,
signature: signature,
'x-oss-security-token': config.security_token
};
console.log(formData,"formData")
const endpoint = config.endpoint
.replace('https//', '')
.replace(/^(http:\/\/|https:\/\/)/, '')
const uploadRes = await uni.uploadFile({
url: `https://${config.bucket}.${endpoint}`,
filePath: file.preview,
name: 'file',
formData: formData
});
if (uploadRes.statusCode === 204) {
this.uploadResult = "上传成功";
console.log("imgUrl:" ,`https://${config.bucket}.${endpoint}/${fileName}`)
const uploadImgUrl = `https://${config.bucket}.${endpoint}/${fileName}`;
this.uploadComplete(uploadImgUrl, file)
} else {
console.log(uploadRes.data,"上传失败")
this.uploadResult = `上传失败: ${uploadRes.data}`;
}
} catch (err) {
console.error("上传失败33:", err);
this.uploadResult = "上传失败";
}
},
uploadComplete(fileUrl, file){
const param = {
user_id:this.userId,
video_url:fileUrl,
type:file.type === 'video' ? 1 : 0,
privacy:0,
sence:0
}
if(this.activity_info.activity_id){
param.activity_id=this.activity_info.activity_id
}
ActivityServices.uploadData(param).then(res=>{
console.log(res,"complete")
if (res.data.code === 0 && res.data.data && res.data.data.video_url) {
this.fileList = this.fileList.map(item => {
const newItem = {...item}
if (item.uid === file.uid) {
newItem.url = res.data.data.video_url
}
return newItem
})
this.$emit('fileListChange', this.fileList)
}
})
},
removeFile(index) {
if (this.uploading) return
this.fileList.splice(index, 1)
this.$emit('fileListChange', this.fileList)
},
formatSize(bytes) {
const units = ['B', 'KB', 'MB', 'GB']
let size = bytes
let unitIndex = 0
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024
unitIndex++
}
return `${size.toFixed(1)}${units[unitIndex]}`
},
async notifyBackend(ossUrl) {
const params = {
userId: this.userId,
videoUrl: ossUrl,
type: this.activityId ? 1 : 0,
activity_id: this.activityId
}
if (this.fileType === 1) {
params.recordingParams = this.validateRecordingParams()
params.cameraIntrinsicParameters = this.validateCameraParams()
}
await ActivityServices.uploadData(params)
},
validateRecordingParams() {
const requiredFields = [
'recordType', 'sceneType', 'quality',
'players', 'startTime', 'endTime'
]
requiredFields.forEach(field => {
if (!this.recordingParams?.[field]) {
throw new Error(`缺少必要录制参数: ${field}`)
}
})
return {
...this.recordingParams,
startTime: new Date(this.recordingParams.startTime).getTime(),
endTime: new Date(this.recordingParams.endTime).getTime()
}
},
validateCameraParams() {
const requiredFields = [
'focalLength', 'principalPoint', 'sensorSize',
'distortionCoefficients', 'deviceModel'
]
requiredFields.forEach(field => {
if (!this.cameraParams?.[field]) {
throw new Error(`缺少必要相机参数: ${field}`)
}
})
return this.cameraParams
}
}
}
</script>
上传文件的接口域名是写在upload域名中
请求获取数据的接口域名才是写在request域名中
上传文件,需要配置到uploadfile域名里