处理文件上传中友好提示;处理文件上传失败场景图标展示;解决图片上传loading问题;替换所有进度条颜色更醒目;
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
This commit is contained in:
parent
6140c625e4
commit
e7ec387735
2
components.d.ts
vendored
2
components.d.ts
vendored
@ -8,6 +8,8 @@ export {}
|
|||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
|
AsyncError: typeof import('./src/components/async-error/index.vue')['default']
|
||||||
|
AsyncLoading: typeof import('./src/components/async-loading/index.vue')['default']
|
||||||
AudioMessage: typeof import('./src/components/talk/message/AudioMessage.vue')['default']
|
AudioMessage: typeof import('./src/components/talk/message/AudioMessage.vue')['default']
|
||||||
Avatar: typeof import('./src/components/base/Avatar.vue')['default']
|
Avatar: typeof import('./src/components/base/Avatar.vue')['default']
|
||||||
AvatarCropper: typeof import('./src/components/base/AvatarCropper.vue')['default']
|
AvatarCropper: typeof import('./src/components/base/AvatarCropper.vue')['default']
|
||||||
|
79
src/components/async-error/index.vue
Normal file
79
src/components/async-error/index.vue
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
location.reload(true);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="loader">
|
||||||
|
<p class="heading">加载中</p>
|
||||||
|
<div class="loading">
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- 重启页面 -->
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.loader {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
color: black;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
width: 5em;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load {
|
||||||
|
width: 23px;
|
||||||
|
height: 3px;
|
||||||
|
background-color: limegreen;
|
||||||
|
animation: 1s move_5011 infinite;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(1) {
|
||||||
|
animation-delay: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(2) {
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(3) {
|
||||||
|
animation-delay: 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move_5011 {
|
||||||
|
0% {
|
||||||
|
width: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
width: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
width: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
width: 0.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
78
src/components/async-loading/index.vue
Normal file
78
src/components/async-loading/index.vue
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="loader">
|
||||||
|
<p class="heading">加载中</p>
|
||||||
|
<div class="loading">
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.loader {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
color: black;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
width: 5em;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load {
|
||||||
|
width: 23px;
|
||||||
|
height: 3px;
|
||||||
|
background-color: limegreen;
|
||||||
|
animation: 1s move_5011 infinite;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(1) {
|
||||||
|
animation-delay: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(2) {
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(3) {
|
||||||
|
animation-delay: 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move_5011 {
|
||||||
|
0% {
|
||||||
|
width: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
width: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
width: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
width: 0.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -55,7 +55,7 @@ const getFileTypeIMG = computed(() => {
|
|||||||
default:
|
default:
|
||||||
objT.finishedImg = filePaperOther
|
objT.finishedImg = filePaperOther
|
||||||
objT.blankImg = filePaperOtherBlank
|
objT.blankImg = filePaperOtherBlank
|
||||||
objT.progressColor = '#747474'
|
objT.progressColor = '#46299d'
|
||||||
}
|
}
|
||||||
return objT
|
return objT
|
||||||
})
|
})
|
||||||
@ -132,7 +132,7 @@ const downloadAndOpenFile = () => {
|
|||||||
:height="95"
|
:height="95"
|
||||||
:src="getFileTypeIMG.blankImg"
|
:src="getFileTypeIMG.blankImg"
|
||||||
></tm-image>
|
></tm-image>
|
||||||
<wd-circle
|
<wd-circle v-if="data.uploadStatus === 1"
|
||||||
customClass="circleProgress"
|
customClass="circleProgress"
|
||||||
:modelValue="data.uploadCurrent"
|
:modelValue="data.uploadCurrent"
|
||||||
layerColor="#E3E3E3"
|
layerColor="#E3E3E3"
|
||||||
@ -140,6 +140,9 @@ const downloadAndOpenFile = () => {
|
|||||||
:strokeWidth="3"
|
:strokeWidth="3"
|
||||||
:size="20"
|
:size="20"
|
||||||
></wd-circle>
|
></wd-circle>
|
||||||
|
<div class="upload-failed" v-if="data.uploadStatus === 3">
|
||||||
|
<tm-icon :font-size="20" name="tmicon-times" color="#fff"></tm-icon>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="divider mt-[28rpx]"></div>
|
<div class="divider mt-[28rpx]"></div>
|
||||||
@ -288,4 +291,20 @@ const downloadAndOpenFile = () => {
|
|||||||
width: 40rpx !important;
|
width: 40rpx !important;
|
||||||
height: 40rpx !important;
|
height: 40rpx !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.upload-failed {
|
||||||
|
position: absolute;
|
||||||
|
top: 120rpx;
|
||||||
|
right: 52rpx;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #ff4d4f;
|
||||||
|
background: #ff4d4f;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -12,40 +12,40 @@ const img = computed(() => {
|
|||||||
// console.log(props.extra);
|
// console.log(props.extra);
|
||||||
let info = {
|
let info = {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0
|
height: 0,
|
||||||
}
|
}
|
||||||
if (props.extra.url.includes('blob:http://')) {
|
if (props.extra.url.includes('blob:http://')) {
|
||||||
info = {
|
info = {
|
||||||
width: props.extra.width,
|
width: props.extra.width,
|
||||||
height: props.extra.height
|
height: props.extra.height,
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
info = getImageInfo(props.extra.url)
|
info = getImageInfo(props.extra.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.width == 0 || info.height == 0) {
|
if (info.width == 0 || info.height == 0) {
|
||||||
return {
|
return {
|
||||||
width: 450,
|
width: 450,
|
||||||
height: 298
|
height: 298,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(info.width<300){
|
if (info.width < 300) {
|
||||||
return {
|
return {
|
||||||
width: 300,
|
width: 300,
|
||||||
height: info.height / (info.width / 300)
|
height: info.height / (info.width / 300),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.width < 350) {
|
if (info.width < 350) {
|
||||||
return {
|
return {
|
||||||
width: info.width,
|
width: info.width,
|
||||||
height: info.height
|
height: info.height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: 350,
|
width: 350,
|
||||||
height: info.height / (info.width / 350)
|
height: info.height / (info.width / 350),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -54,13 +54,30 @@ const img = computed(() => {
|
|||||||
class="im-message-image"
|
class="im-message-image"
|
||||||
:class="{
|
:class="{
|
||||||
left: data.float === 'left',
|
left: data.float === 'left',
|
||||||
right: data.float === 'right'
|
right: data.float === 'right',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
<tm-image preview :width="img.width" :height="img.height" :src="extra.url" model="aspectFill"/>
|
<div class="relative">
|
||||||
<wd-circle custom-class="circleProgress" v-if="props.data.uploadCurrent && props.data.uploadCurrent<100" v-model="props.data.uploadCurrent" color="#ffffff" layer-color="#E3E3E3"></wd-circle>
|
<tm-image
|
||||||
</div>
|
preview
|
||||||
|
:width="img.width"
|
||||||
|
:height="img.height"
|
||||||
|
:src="extra.url"
|
||||||
|
model="aspectFill"
|
||||||
|
/>
|
||||||
|
<wd-circle
|
||||||
|
custom-class="circleProgress"
|
||||||
|
v-if="data.uploadStatus === 1"
|
||||||
|
v-model="props.data.uploadCurrent"
|
||||||
|
color="#46299d"
|
||||||
|
layer-color="#E3E3E3"
|
||||||
|
></wd-circle>
|
||||||
|
<div class="upload-failed" v-if="data.uploadStatus === 3">
|
||||||
|
<tm-icon :font-size="20" name="tmicon-times" color="#fff"></tm-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@ -79,12 +96,12 @@ const img = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.right {
|
&.right {
|
||||||
background-color: #46299D;
|
background-color: #46299d;
|
||||||
border-radius: 16rpx 0 16rpx 16rpx;
|
border-radius: 16rpx 0 16rpx 16rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.image-container {
|
.image-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.circleProgress {
|
.circleProgress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -94,4 +111,18 @@ const img = computed(() => {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.upload-failed {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #ff4d4f;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, nextTick, getCurrentInstance, computed, onMounted } from 'vue'
|
import { ref, nextTick, getCurrentInstance, computed, onMounted } from 'vue'
|
||||||
import { getImageInfo } from '@/utils/functions'
|
import { getImageInfo } from '@/utils/functions'
|
||||||
import playCircle from "@/static/image/chatList/playCircle@2x.png";
|
import playCircle from '@/static/image/chatList/playCircle@2x.png'
|
||||||
import { useStatus } from "@/store/status";
|
import { useStatus } from '@/store/status'
|
||||||
|
|
||||||
const { statusBarHeight } = useStatus()
|
const { statusBarHeight } = useStatus()
|
||||||
const instance = getCurrentInstance()
|
const instance = getCurrentInstance()
|
||||||
@ -20,12 +20,12 @@ const open = ref(false)
|
|||||||
const img = computed(() => {
|
const img = computed(() => {
|
||||||
let info = {
|
let info = {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0
|
height: 0,
|
||||||
}
|
}
|
||||||
if (props.extra.url.includes('blob:http://')) {
|
if (props.extra.url.includes('blob:http://')) {
|
||||||
info = {
|
info = {
|
||||||
width: props.extra.width,
|
width: props.extra.width,
|
||||||
height: props.extra.height
|
height: props.extra.height,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info = getImageInfo(props.extra.url)
|
info = getImageInfo(props.extra.url)
|
||||||
@ -34,26 +34,26 @@ const img = computed(() => {
|
|||||||
if (info.width == 0 || info.height == 0) {
|
if (info.width == 0 || info.height == 0) {
|
||||||
return {
|
return {
|
||||||
width: 450,
|
width: 450,
|
||||||
height: 298
|
height: 298,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info.width < 300) {
|
if (info.width < 300) {
|
||||||
return {
|
return {
|
||||||
width: 300,
|
width: 300,
|
||||||
height: info.height / (info.width / 300)
|
height: info.height / (info.width / 300),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.width < 350) {
|
if (info.width < 350) {
|
||||||
return {
|
return {
|
||||||
width: info.width,
|
width: info.width,
|
||||||
height: info.height
|
height: info.height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: 350,
|
width: 350,
|
||||||
height: info.height / (info.width / 350)
|
height: info.height / (info.width / 350),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -67,14 +67,14 @@ const fullscreenchange = (e) => {
|
|||||||
|
|
||||||
/* 视频播放 获取第一帧 */
|
/* 视频播放 获取第一帧 */
|
||||||
const canplay = (e) => {
|
const canplay = (e) => {
|
||||||
console.log('Video can play:', e);
|
console.log('Video can play:', e)
|
||||||
|
|
||||||
if (e.target) {
|
if (e.target) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
e.target.pause();
|
e.target.pause()
|
||||||
}, 200);
|
}, 200)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
async function onPlay() {
|
async function onPlay() {
|
||||||
open.value = true
|
open.value = true
|
||||||
@ -92,41 +92,73 @@ async function onPlay() {
|
|||||||
}, 200)
|
}, 200)
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
videoRef.value = uni.createVideoContext(props.data.msg_id);
|
videoRef.value = uni.createVideoContext(props.data.msg_id)
|
||||||
videoRef.value.play()
|
videoRef.value.play()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
videoRef.value.pause()
|
videoRef.value.pause()
|
||||||
}, 200);
|
}, 200)
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<section class="im-message-video" :class="{ left: data.float === 'left' }" @click="onPlay">
|
<section
|
||||||
<div class="coverVideo" :style="{
|
class="im-message-video"
|
||||||
width: img.width + 'rpx',
|
:class="{ left: data.float === 'left' }"
|
||||||
height: img.height + 'rpx'
|
@click="onPlay"
|
||||||
}" v-if="props.extra.url.includes('blob:http://')">
|
>
|
||||||
<video :id="data.msg_id" :autoplay="false" disablepictureinpicture muted :src="props.extra.url" width="100%"
|
<div
|
||||||
height="100%" playsinline preload="auto" controls="false" x5-playsinline
|
class="coverVideo"
|
||||||
webkit-playsinline style="object-fit: cover; pointer-events: none;">
|
:style="{
|
||||||
</video>
|
width: img.width + 'rpx',
|
||||||
|
height: img.height + 'rpx',
|
||||||
|
}"
|
||||||
|
v-if="props.extra.url.includes('blob:http://')"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
:id="data.msg_id"
|
||||||
|
:autoplay="false"
|
||||||
|
disablepictureinpicture
|
||||||
|
muted
|
||||||
|
:src="props.extra.url"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
playsinline
|
||||||
|
preload="auto"
|
||||||
|
controls="false"
|
||||||
|
x5-playsinline
|
||||||
|
webkit-playsinline
|
||||||
|
style="object-fit: cover; pointer-events: none;"
|
||||||
|
></video>
|
||||||
</div>
|
</div>
|
||||||
<wd-img v-else :width="`${img.width}rpx`" :height="`${img.height}rpx`" :src="data.extra.cover" />
|
<wd-img
|
||||||
<div v-if="data.uploadStatus === 2 || !data.uploadStatus" class="btn-video" :style="{
|
v-else
|
||||||
width: img.width + 'rpx',
|
:width="`${img.width}rpx`"
|
||||||
height: img.height + 'rpx'
|
:height="`${img.height}rpx`"
|
||||||
}">
|
:src="data.extra.cover"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="data.uploadStatus === 2 || !data.uploadStatus"
|
||||||
|
class="btn-video"
|
||||||
|
:style="{
|
||||||
|
width: img.width + 'rpx',
|
||||||
|
height: img.height + 'rpx',
|
||||||
|
}"
|
||||||
|
>
|
||||||
<tm-image :src="playCircle" :width="80" :height="80" />
|
<tm-image :src="playCircle" :width="80" :height="80" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="btn-video" :style="{
|
<div
|
||||||
width: img.width + 'rpx',
|
v-else
|
||||||
height: img.height + 'rpx'
|
class="btn-video"
|
||||||
}" >
|
:style="{
|
||||||
|
width: img.width + 'rpx',
|
||||||
|
height: img.height + 'rpx',
|
||||||
|
}"
|
||||||
|
>
|
||||||
<wd-circle
|
<wd-circle
|
||||||
|
v-if="data.uploadStatus === 1"
|
||||||
v-model="props.data.uploadCurrent"
|
v-model="props.data.uploadCurrent"
|
||||||
customClass="circleProgress"
|
customClass="circleProgress"
|
||||||
layerColor="#E3E3E3"
|
color="#46299d"
|
||||||
color="#FFFFFF"
|
layer-color="#E3E3E3"
|
||||||
:strokeWidth="6"
|
:strokeWidth="6"
|
||||||
:size="40"
|
:size="40"
|
||||||
></wd-circle>
|
></wd-circle>
|
||||||
@ -140,6 +172,9 @@ onMounted(() => {
|
|||||||
:width="70"
|
:width="70"
|
||||||
:percent="props.data.uploadCurrent">
|
:percent="props.data.uploadCurrent">
|
||||||
</tm-progress> -->
|
</tm-progress> -->
|
||||||
|
<div class="upload-failed" v-if="data.uploadStatus === 3">
|
||||||
|
<tm-icon :font-size="20" name="tmicon-times" color="#fff"></tm-icon>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -162,7 +197,7 @@ onMounted(() => {
|
|||||||
.im-message-video {
|
.im-message-video {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 20rpx 18rpx;
|
padding: 20rpx 18rpx;
|
||||||
background: #46299D;
|
background: #46299d;
|
||||||
min-width: 30rpx;
|
min-width: 30rpx;
|
||||||
min-height: 30rpx;
|
min-height: 30rpx;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@ -220,7 +255,6 @@ onMounted(() => {
|
|||||||
:deep(.uni-video-bar) {
|
:deep(.uni-video-bar) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.circleProgress {
|
.circleProgress {
|
||||||
width: 80rpx !important;
|
width: 80rpx !important;
|
||||||
@ -245,4 +279,19 @@ onMounted(() => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.upload-failed {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #ff4d4f;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -10,6 +10,8 @@ import tmui from '@/uni_modules/tmui'
|
|||||||
import { config } from '@/config/tmui/index.js'
|
import { config } from '@/config/tmui/index.js'
|
||||||
import 'dayjs/locale/zh-cn'
|
import 'dayjs/locale/zh-cn'
|
||||||
import xLoaderror from '@/components/x-loaderror/index.vue'
|
import xLoaderror from '@/components/x-loaderror/index.vue'
|
||||||
|
import asyncLoading from '@/components/async-loading/index.vue'
|
||||||
|
import asyncError from '@/components/async-error/index.vue'
|
||||||
import { vLoading } from '@/components/x-loading/index.js'
|
import { vLoading } from '@/components/x-loading/index.js'
|
||||||
import messagePopup from '@/components/x-message/useMessagePopup'
|
import messagePopup from '@/components/x-message/useMessagePopup'
|
||||||
import pageAnimation from '@/components/page-animation/index.vue'
|
import pageAnimation from '@/components/page-animation/index.vue'
|
||||||
@ -29,6 +31,8 @@ export function createApp() {
|
|||||||
app.mixin(pageAnimation)
|
app.mixin(pageAnimation)
|
||||||
app.component('customNavbar', customNavbar)
|
app.component('customNavbar', customNavbar)
|
||||||
app.component('x-loaderror', xLoaderror)
|
app.component('x-loaderror', xLoaderror)
|
||||||
|
app.component('AsyncLoading', asyncLoading)
|
||||||
|
app.component('AsyncError', asyncError)
|
||||||
app.directive('no-space', {
|
app.directive('no-space', {
|
||||||
mounted(el) {
|
mounted(el) {
|
||||||
el.addEventListener('input', (e) => {
|
el.addEventListener('input', (e) => {
|
||||||
|
@ -181,12 +181,13 @@ const photoActionsSelect = (index) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
||||||
console.log(file, 'file')
|
console.log('开始上传文件:', file.name)
|
||||||
|
uploadsStore.updateUploadStatus(true)
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
if (type === 'image') {
|
if (type === 'image') {
|
||||||
let image = new Image()
|
let image = new Image()
|
||||||
image.src = URL.createObjectURL(file)
|
image.src = URL.createObjectURL(file)
|
||||||
image.onload = () => {
|
image.onload = async () => {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append('file', file)
|
form.append('file', file)
|
||||||
form.append('source', 'fonchain-chat')
|
form.append('source', 'fonchain-chat')
|
||||||
@ -220,44 +221,62 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtualList.value.unshift(newItem)
|
virtualList.value.unshift(newItem)
|
||||||
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
|
|
||||||
({ status, data, msg }) => {
|
try {
|
||||||
if (status == 0) {
|
const result = await uploadImg(form, (e) => onProgressFn(e, randomId))
|
||||||
// 更新上传状态为成功
|
console.log('上传完成,结果:', result)
|
||||||
const index = virtualList.value.findIndex(
|
|
||||||
(item) => item.file_num === randomId,
|
if (result.status === 0) {
|
||||||
)
|
// 更新上传状态为成功
|
||||||
if (index !== -1) {
|
const index = virtualList.value.findIndex(
|
||||||
virtualList.value[index].uploadStatus = 2
|
(item) => item.file_num === randomId,
|
||||||
virtualList.value[index].uploadCurrent = 100
|
)
|
||||||
}
|
if (index !== -1) {
|
||||||
resolve({
|
virtualList.value[index].uploadStatus = 2
|
||||||
type: 'image',
|
virtualList.value[index].uploadCurrent = 100
|
||||||
url: data.ori_url,
|
|
||||||
size: file.size,
|
|
||||||
width: image.width,
|
|
||||||
height: image.height,
|
|
||||||
file_num: randomId,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 更新上传状态为失败
|
|
||||||
const index = virtualList.value.findIndex(
|
|
||||||
(item) => item.file_num === randomId,
|
|
||||||
)
|
|
||||||
if (index !== -1) {
|
|
||||||
virtualList.value[index].uploadStatus = 3
|
|
||||||
}
|
|
||||||
resolve('')
|
|
||||||
message.error(msg)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
)
|
// 确保返回数据
|
||||||
|
resolve({
|
||||||
|
type: 'image',
|
||||||
|
url: result.data.ori_url,
|
||||||
|
size: file.size,
|
||||||
|
width: image.width,
|
||||||
|
height: image.height,
|
||||||
|
file_num: randomId,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error(result.msg)
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('上传出错:', error)
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error('上传失败')
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uni.getVideoInfo({
|
uni.getVideoInfo({
|
||||||
src: fileUrl,
|
src: fileUrl,
|
||||||
success: (resp) => {
|
success: async (resp) => {
|
||||||
console.log(resp)
|
console.log('视频信息:', resp)
|
||||||
|
const form = new FormData()
|
||||||
form.append('file', file)
|
form.append('file', file)
|
||||||
form.append('source', 'fonchain-chat')
|
form.append('source', 'fonchain-chat')
|
||||||
form.append('type', 'video')
|
form.append('type', 'video')
|
||||||
@ -287,45 +306,65 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
talk_type: dialogueStore.talk.talk_type,
|
talk_type: dialogueStore.talk.talk_type,
|
||||||
user_id: userStore.uid,
|
user_id: userStore.uid,
|
||||||
uploadCurrent: 0,
|
uploadCurrent: 0,
|
||||||
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
uploadStatus: 1,
|
||||||
}
|
}
|
||||||
virtualList.value.unshift(newItem)
|
virtualList.value.unshift(newItem)
|
||||||
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
|
|
||||||
({ status, data, msg }) => {
|
try {
|
||||||
if (status == 0) {
|
const result = await uploadImg(form, (e) => onProgressFn(e, randomId))
|
||||||
// 更新上传状态为成功
|
console.log('视频上传完成,结果:', result)
|
||||||
const index = virtualList.value.findIndex(
|
|
||||||
(item) => item.file_num === randomId,
|
if (result.status === 0) {
|
||||||
)
|
// 更新上传状态为成功
|
||||||
if (index !== -1) {
|
const index = virtualList.value.findIndex(
|
||||||
virtualList.value[index].uploadStatus = 2
|
(item) => item.file_num === randomId,
|
||||||
virtualList.value[index].uploadCurrent = 100
|
)
|
||||||
}
|
if (index !== -1) {
|
||||||
console.log(data)
|
virtualList.value[index].uploadStatus = 2
|
||||||
resolve({
|
virtualList.value[index].uploadCurrent = 100
|
||||||
type: 'video',
|
|
||||||
url: data.ori_url,
|
|
||||||
cover: data.cover_url,
|
|
||||||
duration: parseInt(resp.duration),
|
|
||||||
size: file.size,
|
|
||||||
file_num: randomId,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 更新上传状态为失败
|
|
||||||
const index = virtualList.value.findIndex(
|
|
||||||
(item) => item.file_num === randomId,
|
|
||||||
)
|
|
||||||
if (index !== -1) {
|
|
||||||
virtualList.value[index].uploadStatus = 3
|
|
||||||
}
|
|
||||||
resolve('')
|
|
||||||
message.error(msg)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
)
|
resolve({
|
||||||
|
type: 'video',
|
||||||
|
url: result.data.ori_url,
|
||||||
|
cover: result.data.cover_url,
|
||||||
|
duration: parseInt(resp.duration),
|
||||||
|
size: file.size,
|
||||||
|
file_num: randomId,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error(result.msg)
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('视频上传出错:', error)
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error('上传失败')
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('获取视频信息失败:', error)
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
message.error('获取视频信息失败')
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const form = new FormData()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -508,6 +547,7 @@ const chooseFile = () => {
|
|||||||
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
||||||
}
|
}
|
||||||
virtualList.value.unshift(newItem)
|
virtualList.value.unshift(newItem)
|
||||||
|
uploadsStore.updateUploadStatus(true)
|
||||||
uploadsStore.initUploadFile(
|
uploadsStore.initUploadFile(
|
||||||
res.tempFiles[0],
|
res.tempFiles[0],
|
||||||
props.talkParams,
|
props.talkParams,
|
||||||
@ -523,6 +563,7 @@ const chooseFile = () => {
|
|||||||
virtualList.value[index].uploadCurrent = 100
|
virtualList.value[index].uploadCurrent = 100
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
// 更新上传状态为失败
|
// 更新上传状态为失败
|
||||||
const index = virtualList.value.findIndex(
|
const index = virtualList.value.findIndex(
|
||||||
(item) => item.file_num === randomId,
|
(item) => item.file_num === randomId,
|
||||||
|
@ -216,6 +216,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<div class="footBox" id="footBoxArea">
|
<div class="footBox" id="footBoxArea">
|
||||||
|
<span
|
||||||
|
class="flex items-center justify-center text-[24rpx] text-[#999999]"
|
||||||
|
style="background-color: #e5e5e5; padding: 12rpx 24rpx;"
|
||||||
|
v-if="uploadsParams.isUploading"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
'正在发送中,剩余' +
|
||||||
|
uploadsParams.uploadingNum +
|
||||||
|
'个...请不要离开哦~'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
<div v-if="!dialogueStore.isOpenMultiSelect">
|
<div v-if="!dialogueStore.isOpenMultiSelect">
|
||||||
<div
|
<div
|
||||||
class="pt-[16rpx] ml-[32rpx] mr-[32rpx] flex items-start justify-between"
|
class="pt-[16rpx] ml-[32rpx] mr-[32rpx] flex items-start justify-between"
|
||||||
@ -540,6 +551,7 @@ const settingsStore = useSettingsStore()
|
|||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
const editorDraftStore = useEditorDraftStore()
|
const editorDraftStore = useEditorDraftStore()
|
||||||
|
const uploadsStore = useUploadsStore()
|
||||||
const editor = ref()
|
const editor = ref()
|
||||||
const zpagingRef = ref()
|
const zpagingRef = ref()
|
||||||
useZPaging(zpagingRef)
|
useZPaging(zpagingRef)
|
||||||
@ -559,6 +571,11 @@ const talkParams = reactive({
|
|||||||
unReadNum: computed(() => dialogueStore.unreadNum),
|
unReadNum: computed(() => dialogueStore.unreadNum),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const uploadsParams = reactive({
|
||||||
|
isUploading: computed(() => uploadsStore.isUploading),
|
||||||
|
uploadingNum: computed(() => uploadsStore.uploadingNum),
|
||||||
|
})
|
||||||
|
|
||||||
const state = ref({
|
const state = ref({
|
||||||
isOpenEmojiPanel: false,
|
isOpenEmojiPanel: false,
|
||||||
isOpenFilePanel: false,
|
isOpenFilePanel: false,
|
||||||
@ -662,14 +679,17 @@ const onSendMessage = (data = {}, callBack) => {
|
|||||||
ServePublishMessage(message)
|
ServePublishMessage(message)
|
||||||
.then(({ code, message }) => {
|
.then(({ code, message }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
if (callBack) {
|
if (callBack) {
|
||||||
callBack(true)
|
callBack(true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
message.warning(message)
|
message.warning(message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
message.warning('网络繁忙,请稍后重试!')
|
message.warning('网络繁忙,请稍后重试!')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -696,8 +716,11 @@ const onSendMessageClick = () => {
|
|||||||
|
|
||||||
switch (data.msgType) {
|
switch (data.msgType) {
|
||||||
case 1: // 文字消息
|
case 1: // 文字消息
|
||||||
|
if (data.items[0].content.trim() === '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (data.items[0].content.length > 1024) {
|
if (data.items[0].content.length > 1024) {
|
||||||
return message.info('发送内容超长,请分条发送')
|
return message.warning('发送内容超长,请分条发送')
|
||||||
}
|
}
|
||||||
onSendTextEvent({
|
onSendTextEvent({
|
||||||
data,
|
data,
|
||||||
@ -1646,6 +1669,9 @@ onUnmounted(() => {
|
|||||||
if (state.value.showMentionSelectTimer) {
|
if (state.value.showMentionSelectTimer) {
|
||||||
clearTimeout(state.value.showMentionSelectTimer)
|
clearTimeout(state.value.showMentionSelectTimer)
|
||||||
}
|
}
|
||||||
|
if (uploadsStore.isUploading) {
|
||||||
|
uploadsStore.clearUpload()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 修改防抖函数的实现
|
// 修改防抖函数的实现
|
||||||
|
@ -33,7 +33,9 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
state: () => {
|
state: () => {
|
||||||
return {
|
return {
|
||||||
isShow: false,
|
isShow: false,
|
||||||
items: []
|
items: [],
|
||||||
|
isUploading: false,//当前是否正在上传
|
||||||
|
uploadingNum: 0//当前正在上传数量
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
@ -74,7 +76,11 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
|
|
||||||
this.triggerUpload(upload_id,msgId)
|
this.triggerUpload(upload_id,msgId)
|
||||||
this.isShow = true
|
this.isShow = true
|
||||||
|
} else {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
}
|
}
|
||||||
|
}).catch(()=> {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -128,6 +134,7 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
this.triggerUpload(uploadId, msgId)
|
this.triggerUpload(uploadId, msgId)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
item.status = 3
|
item.status = 3
|
||||||
// 更新虚拟列表中的状态为失败
|
// 更新虚拟列表中的状态为失败
|
||||||
const { virtualList } = useDialogueListStore()
|
const { virtualList } = useDialogueListStore()
|
||||||
@ -138,6 +145,7 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
item.status = 3
|
item.status = 3
|
||||||
// 更新虚拟列表中的状态为失败
|
// 更新虚拟列表中的状态为失败
|
||||||
const { virtualList } = useDialogueListStore()
|
const { virtualList } = useDialogueListStore()
|
||||||
@ -155,7 +163,38 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
receiver_id: item.receiver_id,
|
receiver_id: item.receiver_id,
|
||||||
talk_type: item.talk_type,
|
talk_type: item.talk_type,
|
||||||
file_num: file_num
|
file_num: file_num
|
||||||
|
}).then((res) => {
|
||||||
|
console.log(res, 'res')
|
||||||
|
if(res.code == 200){
|
||||||
|
this.updateUploadStatus(false)
|
||||||
|
}else{
|
||||||
|
this.updateUploadStatus(false)
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
//更新资源上传状态
|
||||||
|
updateUploadStatus(isUploading: boolean){
|
||||||
|
if(isUploading){
|
||||||
|
this.uploadingNum++
|
||||||
|
this.isUploading = true
|
||||||
|
}else{
|
||||||
|
this.uploadingNum--
|
||||||
|
if(this.uploadingNum < 0){
|
||||||
|
this.uploadingNum = 0
|
||||||
|
}
|
||||||
|
if(this.uploadingNum === 0){
|
||||||
|
this.isUploading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 清除上传
|
||||||
|
clearUpload(){
|
||||||
|
this.isUploading = false
|
||||||
|
this.uploadingNum = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user