赞
踩
- <template>
- <div class="upload_container">
- <div class="igmBox">
- <div class="img_box" v-for="(item, index) in data" :key="item.url">
- <img :src="getFileUrl(item)" @click="handleclicksc(index)">
- <div class="delete_btn"> <van-icon name="cross" class="" @click="afterDelete(index)" /> </div>
- </div>
- </div>
-
- <van-uploader v-bind="uploadParameter" :after-read="afterRead" :before-read="beforeRead" @oversize="onOversize"
- upload-icon="plus" :preview-full-image="false" v-show="isUploadShow" ref="uploadRef">
- <template #default>
- <div></div>
- </template>
- </van-uploader>
-
- <div class="uploadBox">
- <div @click="$refs.uploadRef.chooseFile()" class="chooseFile"><i
- class="iconfont icon-zengjia"></i><span>图片/视频</span></div>
- <div v-longpress="handleAudio" class="chooseFile" @touchend="touchendBtn"><i
- class="iconfont icon-zengjia"></i><span>语音输入</span></div>
- <!-- 语音音阶动画 -->
- <div class="prompt-layer prompt-layer-1" v-if="isLongPress">
- <div class="prompt-loader">
- <div class="em" v-for="(item, index) in 15" :key="index"></div>
- </div>
- <!-- <div class="p">{{ '剩余:' + count + 's' }}</div> -->
- <div class="span">松手结束录音</div>
- </div>
- </div>
-
- <PreviewImgOrVideo :previewShow="previewShow" @close="$event => previewShow = $event" :data="preViewData"
- v-if="previewShow">
- </PreviewImgOrVideo>
- </div>
- </template>
- <script>
- import { mapGetters } from "vuex";
- import videoIcon from '../images/video_icon.png';
- import audioIcon from '../images/audio_icon.png';
- import { getNewFileUrl } from "@/utils/download";
- import { filesExperts } from '@/api/appyjzj/newIndex';
- import PreviewImgOrVideo from './previewImgOrVideo.vue';
- export default {
- directives: {
- longpress: {
- bind: function (el, binding) {
-
- // 定义长按时间阈值
- let pressTimer = null
- let longPressActive = false
-
- // 创建计时器(这会在长按后启动)
- let start = (e) => {
- if (e.type === 'click' && e.button !== 0) {
- return
- }
- if (pressTimer === null) {
- pressTimer = setTimeout(() => {
- handler()
- }, 500)
- }
- }
-
- // 取消计时器(长按结束时会运行)
- let cancel = (e) => {
- if (pressTimer !== null) {
- clearTimeout(pressTimer)
- pressTimer = null
- }
- }
-
- // 长按要运行的函数
- const handler = (e) => {
- binding.value(e)
- }
-
- // 添加事件监听器
- el.addEventListener("mousedown", start)
- el.addEventListener("touchstart", start)
-
- // 取消计时器
- el.addEventListener("click", cancel)
- el.addEventListener("mouseout", cancel)
- el.addEventListener("touchend", cancel)
- el.addEventListener("touchcancel", cancel)
- }
- }
-
- },
- components: {
- PreviewImgOrVideo
- },
- props: {
- data: {
- type: Array,
- default: () => []
- },
- uploadParameter: {
- type: Object,
- default: () => { }
- }
- },
- model: {
- prop: 'data',
- event: 'change'
- },
- data() {
- return {
- previewShow: false,
- preViewData: {},
- loading: false,
- mediaRecorder: null,
- isLongPress: false,
- recordedBlob: false
- };
- },
- computed: {
- ...mapGetters(["userInfo"]),
- isUploadShow() {
- return this.uploadParameter['max-count'] && this.uploadParameter['max-count'] > this.data.length
- }
- },
- methods: {
- getNewFileUrl,
- isVideo(filename) {
- const videoExtensions = ['mp4', 'mov', 'avi', 'mkv', 'MOV'];
- const extension = filename.split('.').pop();
- return videoExtensions.includes(extension);
- },
- isAudio(filename) {
- const audioExtensions = ['mp3', 'wav', 'wma', 'ogg', 'aac', 'flac'];
- const extension = filename.split('.').pop();
- return audioExtensions.includes(extension);
- },
- getFileUrl(file) {
- if (this.isVideo(file.name)) {
- return videoIcon;
- } else if (this.isAudio(file.name)) {
- return audioIcon;
- } else {
- return this.getNewFileUrl(file.url);
- }
- },
- // 上传附件
- async afterRead(file) {
- this.loading = true
- file.status = "uploading";
- file.message = "上传中...";
- const formData = new FormData();
- formData.append("singleFile", file.file);
- try {
- const { data, code } = await filesExperts(formData);
- if (code === 2000) {
- this.data.push({
- name: data.fileName,
- uid: data.id,
- url: data.location
- });
- file.status = "done";
- file.message = "上传成功";
- console.log('this.from', this.formData)
- }
- } catch (err) {
- console.log('err', err)
- file.status = "failed";
- file.message = "上传失败";
- } finally {
- this.loading = false
- }
- },
- beforeRead(file) {
- if (this.loading) return false
- if (!file.type.startsWith('image/') && !file.type.startsWith('video/')) {
- this.$toast('请上传图片或视频文件');
- return false;
- }
- return true;
- },
- //手动点击删除,修改包含所有信息的文件列表,通过watch根据该列表动态修改图片文件列表
- afterDelete(index) {
- this.data.splice(index, 1)
- },
- onOversize(file) {
- this.$toast('超过大小');
- },
- //取消掉组件自带的点击预览功能,自己添加(系统自带预览点击视频时会先视频的播放图片)
- handleclicksc(index) {
- let file = this.data[index]
- const name = file.name;
- const fileExtension = name.split(".").pop().toLowerCase();
-
- const isImage = ["jpg", "jpeg", "png", "gif", "bmp"].includes(fileExtension);
- const isVideo = ["mp4", "mov", "avi", "mkv", 'MOV'].includes(fileExtension);
- if (isVideo) {
- this.preViewData = {
- url: getNewFileUrl(file.url),
- urlType: 'video'
- }
- }
- if (isImage) {
- this.preViewData = {
- url: getNewFileUrl(file.url),
- urlType: 'image'
- }
- }
- this.previewShow = true
- },
- async handleAudio() {
- this.isLongPress = true // 开始长按
- // 开始录音
- if (this.isLongPress) {
- console.log('navigator', navigator)
- console.log('navigator.mediaDevices', navigator.mediaDevices)
- navigator.mediaDevices.getUserMedia({ audio: true })
- .then(stream => {
- this.mediaRecorder = new MediaRecorder(stream);
-
- this.mediaRecorder.addEventListener('dataavailable', event => {
- console.log('event', event.data)
- this.recordedBlob = event.data;
- });
-
- this.mediaRecorder.start();
- })
- .catch(error => {
- // 用户拒绝访问麦克风
- });
- }
-
-
- },
- async touchendBtn() {
- this.isLongPress = false // 结束长按
- this.mediaRecorder.stop();
- this.mediaRecorder.addEventListener('stop', async () => {
- // dataavailable 会在这里被触发
- try {
- const formData = new FormData();
- formData.append("singleFile", this.recordedBlob, `${this.userInfo.profile.name}的录音.mp3`);
- const { data, code } = await filesExperts(formData);
- if (code === 2000) {
- this.data.push({
- name: data.fileName,
- uid: data.id,
- url: data.location
- });
- }
- } catch (err) {
- console.log('err', err)
- } finally {
- this.loading = false
- this.mediaRecorder = null;
-
- }
- })
-
- }
- }
- }
- </script>
- <style scoped lang="scss">
- .upload_container {
- margin-top: 7px;
-
- .igmBox {
- display: grid;
- grid-template-columns: repeat(auto-fill, 80px);
- grid-gap: 10px;
- }
-
- width: 100%;
-
- }
-
- .img_box {
- width: 80px;
- height: 80px;
- position: relative;
-
- img {
- width: 100%;
- height: 100%;
- }
-
- .delete_btn {
- position: absolute;
- top: 0;
- right: 0;
- width: 14px;
- height: 14px;
- background-color: rgba(0, 0, 0, 0.7);
- border-radius: 0 0 0 12px;
-
- .van-icon-cross {
- position: absolute;
- top: -2px;
- right: -2px;
- color: #fff;
- font-size: 16px;
- -webkit-transform: scale(0.5);
- transform: scale(0.5);
- }
- }
- }
-
- .uploadBox {
- position: relative;
- all: unset;
- display: flex;
- justify-content: flex-end;
-
- .chooseFile {
- margin-left: 16px;
-
- i {
- margin-right: 4px;
- font-size: 16px;
- color: #1890FF;
- }
-
- span {
- font-size: 13px;
- font-family: PingFangSC-Regular, PingFang SC;
- color: #1890FF;
- }
- }
-
- /* 提示小弹窗 */
- .prompt-layer {
- border-radius: 8px;
- background: #f6f6f6;
- padding: 8px 16px;
- box-sizing: border-box;
- position: absolute;
- left: 50%;
- top: 50%;
- z-index: 999;
- transform: translate(-50%, -50%);
- // box-shadow: 5px rgba(0, 0, 0, .5);
- }
-
- // .prompt-layer::after {
- // content: '';
- // display: block;
- // border: 6px solid rgba(0, 0, 0, 0);
- // border-top-color: rgba(255, 211, 0, 1);
- // position: absolute;
- // bottom: -10px;
- // left: 50%;
- // transform: translateX(-50%);
- // }
-
- .prompt-layer-1 {
- font-size: 12px;
- width: 128px;
- text-align: center;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- }
-
- .prompt-layer-1 .p {
- color: #000000;
- }
-
- .prompt-layer-1 .span {
- color: rgba(0, 0, 0, .6);
- }
- }
-
- /* 语音音阶------------- */
- .prompt-loader {
- width: 96px;
- height: 20px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 6px;
- }
-
- .prompt-loader .em {
- display: block;
- background: #333333;
- width: 1px;
- height: 10%;
- margin-right: 2.5px;
- float: left;
- }
-
- .prompt-loader .em:last-child {
- margin-right: 0px;
- }
-
- .prompt-loader .em:nth-child(1) {
- animation: load 2.5s 1.4s infinite linear;
- }
-
- .prompt-loader .em:nth-child(2) {
- animation: load 2.5s 1.2s infinite linear;
- }
-
- .prompt-loader .em:nth-child(3) {
- animation: load 2.5s 1s infinite linear;
- }
-
- .prompt-loader .em:nth-child(4) {
- animation: load 2.5s 0.8s infinite linear;
- }
-
- .prompt-loader .em:nth-child(5) {
- animation: load 2.5s 0.6s infinite linear;
- }
-
- .prompt-loader .em:nth-child(6) {
- animation: load 2.5s 0.4s infinite linear;
- }
-
- .prompt-loader .em:nth-child(7) {
- animation: load 2.5s 0.2s infinite linear;
- }
-
- .prompt-loader .em:nth-child(8) {
- animation: load 2.5s 0s infinite linear;
- }
-
- .prompt-loader .em:nth-child(9) {
- animation: load 2.5s 0.2s infinite linear;
- }
-
- .prompt-loader .em:nth-child(10) {
- animation: load 2.5s 0.4s infinite linear;
- }
-
- .prompt-loader .em:nth-child(11) {
- animation: load 2.5s 0.6s infinite linear;
- }
-
- .prompt-loader .em:nth-child(12) {
- animation: load 2.5s 0.8s infinite linear;
- }
-
- .prompt-loader .em:nth-child(13) {
- animation: load 2.5s 1s infinite linear;
- }
-
- .prompt-loader .em:nth-child(14) {
- animation: load 2.5s 1.2s infinite linear;
- }
-
- .prompt-loader .em:nth-child(15) {
- animation: load 2.5s 1.4s infinite linear;
- }
-
- @keyframes load {
- 0% {
- height: 10%;
- }
-
- 50% {
- height: 100%;
- }
-
- 100% {
- height: 10%;
- }
- }
-
- /* 语音音阶-------------------- */
- .prompt-layer-2 {
- top: -40px;
- }
-
- .prompt-layer-2 .text {
- color: rgba(0, 0, 0, 1);
- font-size: 12px;
- }
-
- /deep/.van-uploader {
- width: 100%;
-
- .van-uploader__wrapper,
- .van-uploader__input-wrapper {
- width: 100%;
- }
- }
- </style>

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。