221 lines
5.7 KiB
Vue
221 lines
5.7 KiB
Vue
|
|
<template>
|
||
|
|
<!-- 自定义底部弹窗选择器 -->
|
||
|
|
<view class="picker-model" v-if="showPicker">
|
||
|
|
<view class="picker-content">
|
||
|
|
<view class="picker-item" @click="takePhoto">
|
||
|
|
<text>拍照</text>
|
||
|
|
</view>
|
||
|
|
<view class="picker-item" @click="choosePhoto">
|
||
|
|
<text>选择照片</text>
|
||
|
|
</view>
|
||
|
|
<view class="picker-item" @click="takeVideo">
|
||
|
|
<text>拍摄视频</text>
|
||
|
|
</view>
|
||
|
|
<view class="picker-item" @click="chooseVideoFromAlbum">
|
||
|
|
<text>选择视频</text>
|
||
|
|
</view>
|
||
|
|
<view class="picker-item" @click="closePicker">
|
||
|
|
<text>取消</text>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup>
|
||
|
|
import { ref, watch } from "vue";
|
||
|
|
import {compressImageUni} from '@/utils/common.js'
|
||
|
|
import { minioUpload } from '@/api/polling.js'
|
||
|
|
|
||
|
|
let showPicker = ref(false);
|
||
|
|
const openPicker = () => {
|
||
|
|
showPicker.value = true;
|
||
|
|
}
|
||
|
|
const closePicker = () => {
|
||
|
|
showPicker.value = false;
|
||
|
|
emit("closeMedia")
|
||
|
|
}
|
||
|
|
|
||
|
|
const takePhoto = () => {
|
||
|
|
captureMedia("image", "camera");
|
||
|
|
}
|
||
|
|
|
||
|
|
const choosePhoto = () => {
|
||
|
|
captureMedia("image", "album");
|
||
|
|
}
|
||
|
|
|
||
|
|
const takeVideo = () => {
|
||
|
|
captureMedia("video", "camera");
|
||
|
|
}
|
||
|
|
|
||
|
|
const chooseVideoFromAlbum = () => {
|
||
|
|
captureMedia("video", "album");
|
||
|
|
}
|
||
|
|
|
||
|
|
const captureMedia = async (type, source) => {
|
||
|
|
showPicker.value = false;
|
||
|
|
try {
|
||
|
|
if (type === "image") {
|
||
|
|
const res = await uni.chooseImage({
|
||
|
|
count: 1,
|
||
|
|
sourceType: [source],
|
||
|
|
});
|
||
|
|
processMedia(res.tempFilePaths, "image", source);
|
||
|
|
} else {
|
||
|
|
const res = await uni.chooseVideo({
|
||
|
|
sourceType: [source],
|
||
|
|
// sourceType: ['album', 'camera'], // 来源:相册和相机
|
||
|
|
maxDuration: 60, // 最大时长(秒)
|
||
|
|
camera: 'back', // 使用后置摄像头
|
||
|
|
compressed: true, // 压缩视频
|
||
|
|
});
|
||
|
|
processMedia([res.tempFilePath], "video", source);
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
emit("closeMedia")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 调用父组件的方法
|
||
|
|
const emit = defineEmits(['getMediaArr','closeMedia']);
|
||
|
|
|
||
|
|
// 执行压缩并上传
|
||
|
|
const processMedia = async(files, type, source) => {
|
||
|
|
let returnArr = [];
|
||
|
|
let res = files.map(async file=>{
|
||
|
|
return new Promise(async(resolve, reject) => {
|
||
|
|
try {
|
||
|
|
const info = {
|
||
|
|
path: file,
|
||
|
|
type: type,
|
||
|
|
source: source,
|
||
|
|
timestamp: Date.now(),
|
||
|
|
}
|
||
|
|
// #ifdef APP-PLUS
|
||
|
|
// 进行压缩图片
|
||
|
|
if(type=="image"){
|
||
|
|
info.path = await compressImageUni(file);
|
||
|
|
}
|
||
|
|
// #endif
|
||
|
|
|
||
|
|
// 保存选择记录
|
||
|
|
let data = await saveSelectionRecord(info);
|
||
|
|
returnArr.push({
|
||
|
|
fileName:data.fileName,
|
||
|
|
fileType:type
|
||
|
|
})
|
||
|
|
resolve(returnArr)
|
||
|
|
} catch (error) {
|
||
|
|
reject(error)
|
||
|
|
}
|
||
|
|
});
|
||
|
|
})
|
||
|
|
|
||
|
|
await Promise.all(res);
|
||
|
|
// console.log("returnArr=>",returnArr)
|
||
|
|
|
||
|
|
showPicker.value = false;
|
||
|
|
emit('getMediaArr',returnArr);
|
||
|
|
|
||
|
|
// 根据来源做不同处理
|
||
|
|
// if (source === "camera") {
|
||
|
|
// handleCameraMedia(info);
|
||
|
|
// } else {
|
||
|
|
// handleAlbumMedia(info);
|
||
|
|
// }
|
||
|
|
}
|
||
|
|
|
||
|
|
// 保存到云
|
||
|
|
const saveSelectionRecord = (info) => {
|
||
|
|
return new Promise(async (resolve, reject) => {
|
||
|
|
try {
|
||
|
|
// 执行上传
|
||
|
|
let param = {
|
||
|
|
filePath: info.path,
|
||
|
|
name: 'file',
|
||
|
|
formData: {
|
||
|
|
directory:'polling'
|
||
|
|
},
|
||
|
|
}
|
||
|
|
let res = await minioUpload(param);
|
||
|
|
resolve(res.data);
|
||
|
|
} catch (error) {
|
||
|
|
resolve(error);
|
||
|
|
}
|
||
|
|
// 保存到本地存储
|
||
|
|
// const records = uni.getStorageSync("mediaRecords") || [];
|
||
|
|
// records.unshift(info);
|
||
|
|
// uni.setStorageSync("mediaRecords", records.slice(0, 10)); // 只保留最近10条
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
const handleCameraMedia = (info) => {
|
||
|
|
// 从相机拍摄的媒体文件处理
|
||
|
|
if (info.type === "image") {
|
||
|
|
// 相机拍摄的照片可能有地理位置信息
|
||
|
|
extractImageMetadata(info.path);
|
||
|
|
} else {
|
||
|
|
// 相机拍摄的视频
|
||
|
|
uni.showToast({
|
||
|
|
title: "已保存拍摄的视频",
|
||
|
|
icon: "success",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const handleAlbumMedia = (info) => {
|
||
|
|
// 从相册选择的媒体文件处理
|
||
|
|
console.log("从相册选择:", info);
|
||
|
|
}
|
||
|
|
|
||
|
|
const extractImageMetadata = (filePath) => {
|
||
|
|
// 获取图片元数据(部分平台支持)
|
||
|
|
uni.getImageInfo({
|
||
|
|
src: filePath,
|
||
|
|
success: (res) => {
|
||
|
|
console.log("图片元数据:", res);
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 暴露方法给父组件
|
||
|
|
defineExpose({
|
||
|
|
openPicker
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style lang="scss" scoped>
|
||
|
|
.picker-model{
|
||
|
|
position: fixed;
|
||
|
|
top: 0;
|
||
|
|
right: 0;
|
||
|
|
bottom: 0;
|
||
|
|
left: 0;
|
||
|
|
background: rgba(0, 0, 0, 0.4);
|
||
|
|
z-index: 9999;
|
||
|
|
.picker-content{
|
||
|
|
width:100%;
|
||
|
|
position: absolute;
|
||
|
|
bottom:0;
|
||
|
|
left:0;
|
||
|
|
background-color: #fff;
|
||
|
|
border-radius: 10rpx 10rpx 0 0;
|
||
|
|
.picker-item{
|
||
|
|
border-bottom:1px solid #E7E7E7;
|
||
|
|
text-align: center;
|
||
|
|
height:90rpx;
|
||
|
|
line-height: 90rpx;
|
||
|
|
// #ifdef APP-PLUS
|
||
|
|
height:120rpx;
|
||
|
|
line-height: 120rpx;
|
||
|
|
// #endif
|
||
|
|
&:last-child{
|
||
|
|
border-bottom: none;
|
||
|
|
}
|
||
|
|
text{
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
</style>
|