fix
@ -2,17 +2,78 @@
|
|||||||
import { fileFormatSize } from '@/utils/strings'
|
import { fileFormatSize } from '@/utils/strings'
|
||||||
import { download, getFileNameSuffix } from '@/utils/functions'
|
import { download, getFileNameSuffix } from '@/utils/functions'
|
||||||
import { ITalkRecordExtraFile, ITalkRecord } from '@/types/chat'
|
import { ITalkRecordExtraFile, ITalkRecord } from '@/types/chat'
|
||||||
|
import filePaperPDF from '@/static/image/chat/file-paper-pdf.png'
|
||||||
|
import filePaperPPT from '@/static/image/chat/file-paper-ppt.png'
|
||||||
|
import filePaperWord from '@/static/image/chat/file-paper-word.png'
|
||||||
|
import filePaperExcel from '@/static/image/chat/file-paper-excel.png'
|
||||||
|
import filePaperOther from '@/static/image/chat/file-paper-other.png'
|
||||||
|
import filePaperPDFBlank from '@/static/image/chat/file-paper-pdf-blank.png'
|
||||||
|
import filePaperPPTBlank from '@/static/image/chat/file-paper-ppt-blank.png'
|
||||||
|
import filePaperWordBlank from '@/static/image/chat/file-paper-word-blank.png'
|
||||||
|
import filePaperExcelBlank from '@/static/image/chat/file-paper-excel-blank.png'
|
||||||
|
import filePaperOtherBlank from '@/static/image/chat/file-paper-other-blank.png'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
extra: ITalkRecordExtraFile
|
extra: ITalkRecordExtraFile
|
||||||
data: ITalkRecord
|
data: ITalkRecord
|
||||||
maxWidth?: Boolean
|
maxWidth?: Boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const getFileTypeIMG = (fileName: string) => {
|
||||||
|
const suffix = fileName.split('.').pop()?.toLowerCase() || ''
|
||||||
|
let objT = {
|
||||||
|
finishedImg: '',
|
||||||
|
blankImg: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (suffix) {
|
||||||
|
case 'pdf':
|
||||||
|
objT.finishedImg = filePaperPDF
|
||||||
|
objT.blankImg = filePaperPDFBlank
|
||||||
|
break;
|
||||||
|
case 'doc':
|
||||||
|
case 'docx':
|
||||||
|
objT.finishedImg = filePaperWord
|
||||||
|
objT.blankImg = filePaperWordBlank
|
||||||
|
break;
|
||||||
|
case 'xls':
|
||||||
|
case 'xlsx':
|
||||||
|
objT.finishedImg = filePaperExcel
|
||||||
|
objT.blankImg = filePaperExcelBlank
|
||||||
|
break;
|
||||||
|
case 'ppt':
|
||||||
|
case 'pptx':
|
||||||
|
objT.finishedImg = filePaperPPT
|
||||||
|
objT.blankImg = filePaperPPTBlank
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
objT.finishedImg = filePaperOther
|
||||||
|
objT.blankImg = filePaperOtherBlank
|
||||||
|
}
|
||||||
|
return objT
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="file-message">
|
<section class="file-message" :class="{ left: data.float === 'left' }">
|
||||||
<div class="main">
|
<div class="flex justify-between">
|
||||||
|
<div class="w-[228rpx] text-[32rpx] text-[#1A1A1A] h-[88rpx] leading-[44rpx] textEllipsis">
|
||||||
|
{{ extra.name }}
|
||||||
|
</div>
|
||||||
|
<div v-if="data.uploadStatus === 2 || !data.uploadStatus" class="w-[95rpx]">
|
||||||
|
<tm-image :width="95" :height="95" :src="getFileTypeIMG(extra.name).finishedImg"></tm-image>
|
||||||
|
</div>
|
||||||
|
<div v-if="data.uploadStatus === 1 || data.uploadStatus === 3" class="w-[95rpx]">
|
||||||
|
<tm-image :width="95" :height="95" :src="getFileTypeIMG(extra.name).blankImg"></tm-image>
|
||||||
|
<tm-progress class="circleProgress" linear="right" model="circle" bgColor="#E3E3E3" color="#DE4E4E" :height="3" :width="40"
|
||||||
|
:percent="data.uploadCurrent"></tm-progress>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="divider mt-[28rpx]"></div>
|
||||||
|
<div class="text-[24rpx] text-[#747474] mt-[10rpx]">{{ fileFormatSize(extra.size) }}</div>
|
||||||
|
<!-- <div class="main">
|
||||||
<div class="ext">{{ getFileNameSuffix(extra.name) }}</div>
|
<div class="ext">{{ getFileNameSuffix(extra.name) }}</div>
|
||||||
<div class="file-box">
|
<div class="file-box">
|
||||||
<p class="info">
|
<p class="info">
|
||||||
@ -25,17 +86,23 @@ defineProps<{
|
|||||||
<div class="footer">
|
<div class="footer">
|
||||||
<a @click="download(data.msg_id)">下载</a>
|
<a @click="download(data.msg_id)">下载</a>
|
||||||
<a>在线预览</a>
|
<a>在线预览</a>
|
||||||
</div>
|
</div> -->
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.file-message {
|
.file-message {
|
||||||
width: 250px;
|
width: 486rpx;
|
||||||
min-height: 85px;
|
min-height: 220rpx;
|
||||||
padding: 10px;
|
padding: 28rpx 30rpx 22rpx 30rpx;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border: 1px solid var(--im-message-border-color);
|
background-color: #fff;
|
||||||
|
border-radius: 16rpx 0 16rpx 16rpx;
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 0 16rpx 16rpx 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
height: 45px;
|
height: 45px;
|
||||||
@ -115,4 +182,25 @@ defineProps<{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.textEllipsis {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
background-color: #E7E7E7;
|
||||||
|
height: 1rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circleProgress {
|
||||||
|
position: absolute;
|
||||||
|
top: 120rpx;
|
||||||
|
right: 52rpx;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -54,6 +54,11 @@ const img = (src: string, width = 200) => {
|
|||||||
:class="{ left: data.float === 'left' }"
|
:class="{ left: data.float === 'left' }"
|
||||||
>
|
>
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
|
<!-- <image
|
||||||
|
:src="extra.url"
|
||||||
|
mode="scaleToFill"
|
||||||
|
:width="img(extra.url,350).width" :height="img(extra.url,350).height"
|
||||||
|
/> -->
|
||||||
<tm-image preview :width="img(extra.url,350).width" :height="img(extra.url,350).height" :src="extra.url" />
|
<tm-image preview :width="img(extra.url,350).width" :height="img(extra.url,350).height" :src="extra.url" />
|
||||||
<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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,11 +18,15 @@ const videoContext = ref()
|
|||||||
const open = ref(false)
|
const open = ref(false)
|
||||||
|
|
||||||
const img = (src: string, width = 200) => {
|
const img = (src: string, width = 200) => {
|
||||||
// console.log(props);
|
|
||||||
|
|
||||||
const info: any = getImageInfo(src)
|
const info: any = getImageInfo(src)
|
||||||
|
|
||||||
if (info.width == 0 || info.height == 0) {
|
if (info.width == 0 || info.height == 0) {
|
||||||
|
if (props.extra.width) {
|
||||||
|
return {
|
||||||
|
width: props.extra.width,
|
||||||
|
height: props.extra.height
|
||||||
|
}
|
||||||
|
}
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +46,7 @@ const img = (src: string, width = 200) => {
|
|||||||
const fullscreenchange = (e) => {
|
const fullscreenchange = (e) => {
|
||||||
if(!e.detail.fullScreen){
|
if(!e.detail.fullScreen){
|
||||||
videoContext.value.stop()
|
videoContext.value.stop()
|
||||||
|
videoContext.value.seek(0)
|
||||||
open.value = false
|
open.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,11 +60,24 @@ async function onPlay() {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<section class="im-message-video" :class="{ left: data.float === 'left' }" @click="onPlay">
|
<section class="im-message-video" :class="{ left: data.float === 'left' }" @click="onPlay">
|
||||||
<tm-image :src="extra.cover" :width="img(extra.cover, 350).width" :height="img(extra.cover, 350).height" />
|
<wd-img :width="`${img(data.extra.cover, 350).width}rpx`" :height="`${img(data.extra.cover, 350).height}rpx`" :src="data.extra.cover" />
|
||||||
|
<div v-if="data.uploadStatus === 2 || !data.uploadStatus" class="btn-video" :style="{
|
||||||
<div class="btn-video">
|
width: img(data.extra.cover, 350).width + 'rpx',
|
||||||
|
height: img(data.extra.cover, 350).height + 'rpx'
|
||||||
|
}" >
|
||||||
<tm-image :src="playCircle" :width="80" :height="80" />
|
<tm-image :src="playCircle" :width="80" :height="80" />
|
||||||
</div>
|
</div>
|
||||||
|
<tm-progress
|
||||||
|
v-if="props.data.uploadCurrent"
|
||||||
|
class="circleProgress"
|
||||||
|
linear="right"
|
||||||
|
model="circle"
|
||||||
|
bgColor="#E3E3E3"
|
||||||
|
color="#FFFFFF"
|
||||||
|
:height="8"
|
||||||
|
:width="70"
|
||||||
|
:percent="props.data.uploadCurrent">
|
||||||
|
</tm-progress>
|
||||||
<div v-show="open">
|
<div v-show="open">
|
||||||
<video ref="videoRef" :src="props.extra.url" controls @fullscreenchange="fullscreenchange"
|
<video ref="videoRef" :src="props.extra.url" controls @fullscreenchange="fullscreenchange"
|
||||||
:id="props.extra.url">
|
:id="props.extra.url">
|
||||||
@ -84,19 +102,12 @@ async function onPlay() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-video {
|
.btn-video {
|
||||||
width: 30px;
|
|
||||||
height: 20px;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: calc(50% - 15px);
|
|
||||||
top: calc(50% - 10px);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #ffffff;
|
display: flex;
|
||||||
}
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
&:hover {
|
background: rgba(0, 0, 0, 0.2);
|
||||||
.btn-video {
|
|
||||||
color: #03a9f4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,4 +126,12 @@ async function onPlay() {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.circleProgress {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -3,6 +3,7 @@ import { ServeTalkRecords } from '@/api/chat'
|
|||||||
import { useDialogueStore, useDialogueListStore } from '@/store'
|
import { useDialogueStore, useDialogueListStore } from '@/store'
|
||||||
import { formatTalkRecord } from '@/utils/talk'
|
import { formatTalkRecord } from '@/utils/talk'
|
||||||
import { addClass, removeClass } from '@/utils/dom'
|
import { addClass, removeClass } from '@/utils/dom'
|
||||||
|
import lodash from 'lodash'
|
||||||
|
|
||||||
export const useTalkRecord = (uid) => {
|
export const useTalkRecord = (uid) => {
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
@ -10,9 +11,9 @@ export const useTalkRecord = (uid) => {
|
|||||||
const records = computed(() => {
|
const records = computed(() => {
|
||||||
const dialogueList = getDialogueList(dialogueStore.index_name)
|
const dialogueList = getDialogueList(dialogueStore.index_name)
|
||||||
if(dialogueList){
|
if(dialogueList){
|
||||||
return dialogueList.records.toReversed()
|
return lodash.cloneDeep(dialogueList.records).reverse()
|
||||||
}
|
}
|
||||||
return dialogueStore.records.toReversed()
|
return lodash.cloneDeep(dialogueStore.records)?.reverse()
|
||||||
} )
|
} )
|
||||||
|
|
||||||
const location = reactive({
|
const location = reactive({
|
||||||
@ -96,12 +97,12 @@ export const useTalkRecord = (uid) => {
|
|||||||
return (location.msgid = '')
|
return (location.msgid = '')
|
||||||
}
|
}
|
||||||
const items = (data.items || []).map((item) => formatTalkRecord(uid, item))
|
const items = (data.items || []).map((item) => formatTalkRecord(uid, item))
|
||||||
|
|
||||||
if (request.cursor == 0) {
|
if (request.cursor == 0) {
|
||||||
// 判断是否是初次加载
|
// 判断是否是初次加载
|
||||||
dialogueStore.clearDialogueRecord()
|
dialogueStore.clearDialogueRecord()
|
||||||
}
|
}
|
||||||
const reverseItems = items.toReversed()
|
|
||||||
|
const reverseItems = lodash.cloneDeep(items).reverse()
|
||||||
dialogueStore.unshiftDialogueRecord(reverseItems)
|
dialogueStore.unshiftDialogueRecord(reverseItems)
|
||||||
addDialogueRecord(params.direction=='down'?reverseItems:items,params.direction=='down'?'add':'unshift')
|
addDialogueRecord(params.direction=='down'?reverseItems:items,params.direction=='down'?'add':'unshift')
|
||||||
zpagingComplete(dialogueStore.index_name)
|
zpagingComplete(dialogueStore.index_name)
|
||||||
|
@ -31,6 +31,8 @@ import photoGraph from '@/static/image/chatList/photoGraph.png'
|
|||||||
import folder from '@/static/image/chatList/folder.png'
|
import folder from '@/static/image/chatList/folder.png'
|
||||||
import { uploadImg } from '@/api/chat'
|
import { uploadImg } from '@/api/chat'
|
||||||
import { uniqueId } from '@/utils'
|
import { uniqueId } from '@/utils'
|
||||||
|
import { getFileFromUrl } from '@/utils'
|
||||||
|
import { getVideoImage } from '@/utils/common'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
sendUserInfo: {
|
sendUserInfo: {
|
||||||
@ -40,28 +42,31 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const dialogueListStore = useDialogueListStore()
|
const { addDialogueRecord, virtualList, updateUploadProgress } = useDialogueListStore()
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const emit = defineEmits(['selectImg','updateUploadProgress'])
|
const emit = defineEmits(['selectImg'])
|
||||||
|
|
||||||
const onProgressFn = (progress, file,id) => {
|
const onProgressFn = (progress, file, id) => {
|
||||||
emit('updateUploadProgress', id, progress.loaded / progress.total * 100)
|
console.log(progress.loaded / progress.total * 100, 'progress');
|
||||||
|
|
||||||
|
updateUploadProgress(id, progress.loaded / progress.total * 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUploadImage = (file) => {
|
const onUploadImageVideo = async (file, type = 'image') => {
|
||||||
return new Promise((resolve) => {
|
console.log(file, 'file');
|
||||||
let image = new Image()
|
return new Promise(async (resolve) => {
|
||||||
image.src = URL.createObjectURL(file)
|
if (type === 'image') {
|
||||||
image.onload = () => {
|
let image = new Image()
|
||||||
const form = new FormData()
|
image.src = URL.createObjectURL(file)
|
||||||
form.append('file', file)
|
image.onload = () => {
|
||||||
form.append("source", "fonchain-chat");
|
const form = new FormData()
|
||||||
form.append("urlParam", `width=${image.width}&height=${image.height}`);
|
form.append('file', file)
|
||||||
let randomId = uniqueId()
|
form.append("source", "fonchain-chat");
|
||||||
dialogueListStore.addDialogueRecord([
|
form.append("urlParam", `width=${image.width}&height=${image.height}`);
|
||||||
{
|
let randomId = uniqueId()
|
||||||
|
let newItem = {
|
||||||
avatar: userStore.avatar,
|
avatar: userStore.avatar,
|
||||||
created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
extra: {
|
extra: {
|
||||||
@ -83,66 +88,162 @@ const onUploadImage = (file) => {
|
|||||||
sequence: -1,
|
sequence: -1,
|
||||||
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 上传失败
|
||||||
}
|
}
|
||||||
], 'add')
|
|
||||||
|
|
||||||
|
virtualList.value.unshift(newItem)
|
||||||
|
uploadImg(form, (e, file) => onProgressFn(e, file, randomId)).then(({ status, data, msg }) => {
|
||||||
|
if (status == 0) {
|
||||||
|
resolve({
|
||||||
|
type: 'image',
|
||||||
|
url: data.ori_url,
|
||||||
|
size: file.size,
|
||||||
|
width: image.width,
|
||||||
|
height: image.height
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resolve('')
|
||||||
|
message.error(msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let resp = await getVideoImage(file)
|
||||||
|
const form = new FormData()
|
||||||
|
form.append('file', file)
|
||||||
|
form.append("source", "fonchain-chat");
|
||||||
|
form.append("type", "video");
|
||||||
|
form.append("urlParam", `width=${resp.width}&height=${resp.height}`);
|
||||||
|
let randomId = uniqueId()
|
||||||
|
let newItem = {
|
||||||
|
avatar: userStore.avatar,
|
||||||
|
created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
extra: {
|
||||||
|
duration: parseInt(resp.duration),
|
||||||
|
height: resp.height,
|
||||||
|
name: "",
|
||||||
|
url: '',
|
||||||
|
cover: resp.url,
|
||||||
|
width: resp.width
|
||||||
|
},
|
||||||
|
float: "right",
|
||||||
|
isCheck: false,
|
||||||
|
is_mark: 0,
|
||||||
|
is_read: 0,
|
||||||
|
is_revoke: 0,
|
||||||
|
msg_id: randomId,
|
||||||
|
msg_type: 5,
|
||||||
|
nickname: userStore.nickname,
|
||||||
|
receiver_id: dialogueStore.talk.receiver_id,
|
||||||
|
sequence: -1,
|
||||||
|
talk_type: dialogueStore.talk.talk_type,
|
||||||
|
user_id: userStore.uid,
|
||||||
|
uploadCurrent: 0,
|
||||||
|
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
||||||
|
}
|
||||||
|
virtualList.value.unshift(newItem)
|
||||||
uploadImg(form, (e, file) => onProgressFn(e, file, randomId)).then(({ status, data, msg }) => {
|
uploadImg(form, (e, file) => onProgressFn(e, file, randomId)).then(({ status, data, msg }) => {
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
// message.success('上传成功')
|
console.log(data);
|
||||||
resolve({
|
resolve({
|
||||||
|
type: 'video',
|
||||||
url: data.ori_url,
|
url: data.ori_url,
|
||||||
size: file.size,
|
cover: data.cover_url,
|
||||||
width: image.width,
|
duration: parseInt(resp.duration),
|
||||||
height: image.height
|
size: file.size
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
resolve('')
|
// resolve('')
|
||||||
message.error(msg)
|
// message.error(msg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const base64ToFile = (base64) => {
|
||||||
|
// base64转file
|
||||||
|
const [header, base64String] = base64.split(";base64,");
|
||||||
|
const imageType = header.split(":")[1];
|
||||||
|
const byteCharacters = atob(base64String);
|
||||||
|
const byteArray = new Uint8Array(
|
||||||
|
Array.from(byteCharacters, (char) => char.charCodeAt(0))
|
||||||
|
);
|
||||||
|
return new File(
|
||||||
|
[new Blob([byteArray], { type: imageType })],
|
||||||
|
"example.png",
|
||||||
|
{ type: imageType }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const choosePhoto = () => {
|
const choosePhoto = () => {
|
||||||
uni.chooseImage({
|
window.plus?.gallery.pick((res) => {
|
||||||
sourceType: ['album'],
|
console.log(res);
|
||||||
success: async (res) => {
|
res.files.forEach(async (filePath) => {
|
||||||
console.log(res.tempFiles);
|
const suffix = filePath.split('.').pop()?.toLowerCase() || ''
|
||||||
res.tempFiles.forEach(async item => {
|
if (['jpg', 'png'].includes(suffix)) {
|
||||||
if (item.type.indexOf('image/') === 0) {
|
console.log("进入图片")
|
||||||
console.log("进入图片")
|
window.plus?.io?.resolveLocalFileSystemURL(filePath, async (entry) => {
|
||||||
let data = await onUploadImage(item)
|
entry.file((file) => {
|
||||||
// return false;
|
const fileReader = new plus.io.FileReader();
|
||||||
emit('selectImg', data)
|
fileReader.readAsDataURL(file);
|
||||||
// if (src) {
|
fileReader.onloadend = async (e) => {
|
||||||
// quill.insertEmbed(index, 'image', src)
|
const base64Url = e.target.result;
|
||||||
// quill.setSelection(index + 1)
|
const fileObj = base64ToFile(base64Url);
|
||||||
// }
|
let data = await onUploadImageVideo(fileObj, 'image')
|
||||||
// return
|
emit('selectImg', data)
|
||||||
}
|
};
|
||||||
|
})
|
||||||
if (item.type.indexOf('video/') === 0) {
|
},
|
||||||
console.log("进入视频")
|
(err) => {
|
||||||
let fn = emitCall('video_event', item, () => { })
|
console.log(err);
|
||||||
emit('editor-event', fn)
|
}
|
||||||
}
|
)
|
||||||
})
|
}
|
||||||
|
if (['mp4', 'flv'].includes(suffix)) {
|
||||||
},
|
console.log(filePath,"进入视频")
|
||||||
fail: (err) => {
|
window.plus?.io?.resolveLocalFileSystemURL(filePath, async (entry) => {
|
||||||
console.log(err);
|
entry.file((file) => {
|
||||||
|
console.log(file,'file');
|
||||||
message.error(err)
|
const fileReader = new plus.io.FileReader();
|
||||||
|
fileReader.readAsDataURL(file);
|
||||||
|
fileReader.onloadend = async (e) => {
|
||||||
|
const base64Url = e.target.result;
|
||||||
|
const fileObj = base64ToFile(base64Url);
|
||||||
|
let data = await onUploadImageVideo(fileObj, 'video')
|
||||||
|
emit('selectImg', data)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, (err) => {
|
||||||
|
console.log(err);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filter: 'none',
|
||||||
|
maximum: 9,
|
||||||
|
multiple: true,
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
const takePhoto = () => {
|
const takePhoto = () => {
|
||||||
|
|
||||||
}
|
}
|
||||||
const chooseFile = () => {
|
const chooseFile = () => {
|
||||||
|
window.plus?.io.requestFileSystem(
|
||||||
|
3,
|
||||||
|
(res) => {
|
||||||
|
console.log(res);
|
||||||
|
}, (err) => {
|
||||||
|
console.log(err);
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ import { ServePublishMessage } from '@/api/chat'
|
|||||||
|
|
||||||
Quill.register('formats/emoji', EmojiBlot)
|
Quill.register('formats/emoji', EmojiBlot)
|
||||||
|
|
||||||
const { getDialogueList,updateZpagingRef } = useDialogueListStore()
|
const { getDialogueList,updateZpagingRef,virtualList } = useDialogueListStore()
|
||||||
const talkStore = useTalkStore()
|
const talkStore = useTalkStore()
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
@ -197,8 +197,6 @@ const state = ref({
|
|||||||
isOpenFilePanel: false
|
isOpenFilePanel: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const virtualList = ref([])
|
|
||||||
|
|
||||||
const handleEmojiPanel = () => {
|
const handleEmojiPanel = () => {
|
||||||
state.value.isOpenFilePanel = false;
|
state.value.isOpenFilePanel = false;
|
||||||
state.value.isOpenEmojiPanel = !state.value.isOpenEmojiPanel
|
state.value.isOpenEmojiPanel = !state.value.isOpenEmojiPanel
|
||||||
@ -208,7 +206,7 @@ const handleFilePanel = () => {
|
|||||||
state.value.isOpenFilePanel = !state.value.isOpenFilePanel
|
state.value.isOpenFilePanel = !state.value.isOpenFilePanel
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSendMessage = (data = {}, callBack) => {
|
const onSendMessage = (data = {}) => {
|
||||||
let message = {
|
let message = {
|
||||||
...data,
|
...data,
|
||||||
receiver: {
|
receiver: {
|
||||||
@ -220,7 +218,7 @@ const onSendMessage = (data = {}, callBack) => {
|
|||||||
ServePublishMessage(message)
|
ServePublishMessage(message)
|
||||||
.then(({ code, message }) => {
|
.then(({ code, message }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
callBack(true)
|
// callBack(true)
|
||||||
} else {
|
} else {
|
||||||
message.warning(message)
|
message.warning(message)
|
||||||
}
|
}
|
||||||
@ -262,14 +260,7 @@ const onSendTextEvent = lodash.throttle((value) => {
|
|||||||
mentions: data.mentionUids
|
mentions: data.mentionUids
|
||||||
}
|
}
|
||||||
|
|
||||||
onSendMessage(message, (ok) => {
|
onSendMessage(message)
|
||||||
if (!ok) return
|
|
||||||
|
|
||||||
let el = document.getElementById('talk-session-list')
|
|
||||||
el?.scrollTo({ top: 0, behavior: 'smooth' })
|
|
||||||
|
|
||||||
callBack(true)
|
|
||||||
})
|
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
// 编辑器输入事件
|
// 编辑器输入事件
|
||||||
@ -287,8 +278,8 @@ const onInputEvent = ({ data }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 发送表情消息
|
// 发送表情消息
|
||||||
const onSendEmoticonEvent = ({ data, callBack }) => {
|
const onSendEmoticonEvent = ({ data }) => {
|
||||||
onSendMessage({ type: 'emoticon', emoticon_id: data }, callBack)
|
onSendMessage({ type: 'emoticon', emoticon_id: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册事件
|
// 注册事件
|
||||||
@ -392,7 +383,7 @@ const editorOption = {
|
|||||||
bindings: {
|
bindings: {
|
||||||
enter: {
|
enter: {
|
||||||
key: 13,
|
key: 13,
|
||||||
handler: onSendMessage
|
handler: onSendMessageClick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -435,7 +426,7 @@ const editorOption = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSelectImg = (data) => {
|
const handleSelectImg = (data) => {
|
||||||
onSendMessage({ type: 'image', ...data })
|
onSendMessage({ ...data })
|
||||||
}
|
}
|
||||||
|
|
||||||
const virtualListChange = (vList) => {
|
const virtualListChange = (vList) => {
|
||||||
@ -461,7 +452,7 @@ const initData = async() => {
|
|||||||
no_limit: dialogueList?1:0,
|
no_limit: dialogueList?1:0,
|
||||||
}
|
}
|
||||||
await onLoad({ ...objT })
|
await onLoad({ ...objT })
|
||||||
// zpagingRef.value?.complete(records.value)
|
zpagingRef.value?.complete(records.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async() => {
|
onMounted(async() => {
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref,watch,computed } from 'vue';
|
import { ref,watch,computed } from 'vue';
|
||||||
|
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||||
import { useChatList } from "@/store/chatList/index.js";
|
import { useChatList } from "@/store/chatList/index.js";
|
||||||
import {useAuth} from "@/store/auth";
|
import {useAuth} from "@/store/auth";
|
||||||
import { useTalkStore,useUserStore } from '@/store'
|
import { useTalkStore,useUserStore } from '@/store'
|
||||||
@ -61,6 +62,9 @@ watch(() => talkStore, (newValue, oldValue) => {
|
|||||||
|
|
||||||
},{deep:true,immediate:true})
|
},{deep:true,immediate:true})
|
||||||
|
|
||||||
|
onShow(()=>{
|
||||||
|
talkStore.loadTalkList()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
uni-page-body,page{
|
uni-page-body,page{
|
||||||
|
BIN
src/static/image/chat/file-paper-excel-blank.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/static/image/chat/file-paper-excel.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
src/static/image/chat/file-paper-other-blank.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/static/image/chat/file-paper-other.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
src/static/image/chat/file-paper-pdf-blank.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/static/image/chat/file-paper-pdf.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
src/static/image/chat/file-paper-ppt-blank.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/static/image/chat/file-paper-ppt.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/static/image/chat/file-paper-word-blank.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/static/image/chat/file-paper-word.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
@ -4,7 +4,7 @@ import {uniStorage} from "@/utils/uniStorage.js"
|
|||||||
import {ref} from 'vue'
|
import {ref} from 'vue'
|
||||||
export const useAuth = createGlobalState(() => {
|
export const useAuth = createGlobalState(() => {
|
||||||
// const token = useStorage('token', '', uniStorage)
|
// const token = useStorage('token', '', uniStorage)
|
||||||
const token = ref('30119d9978a6f3321fb4779c0040e997df4dd0dd0cf6b71119657617d2249ed783f940b0050d5be7e758740ea467afdf3eeb4d28fb5ea234af60ebe51fb218ff6a0563074f3084b41c1bc8dc0733d06bfbb433a8d5a1d13eb6227adbf50a5da566a4cacdbf91899e563f10864fe2acfe62e0966fbd28506c80ffdda3f2f2f1cdf47228c1222630dd71bf9086f3fd73b23ac4fa18032fd834babe4ba7c7c210a329e9767e3e70b35f7745f2c84fda47c1c0ee95bdc6bf946fbef5927b397b37f7614b53736e13edef3e504c70124204b44913e3def0c87bf860be2788bf0360c3')
|
const token = ref('30119d9978a6f3321fb4779c0040e997df4dd0dd0cf6b71119657617d2249ed783f940b0050d5be7e758740ea467afdf3eeb4d28fb5ea234af60ebe51fb218ff6a0563074f3084b41c1bc8dc0733d06bfbb433a8d5a1d13eb6227adbf50a5da566a4cacdbf91899e563f10864fe2acfe8edb3a186766d1fb247c2e3c6bb3c014a610243d87b0460c692d5bea2442fe553a9cf98e29ff7be27c364ab2047c67957e28df8f7cdd90366fd8f94967d5f8e037fab5f9e3c3a342f4830875841d5a4361ab087bd4205321e6ad9db918811786bd9e1be7df913383eef6f47f436073ca')
|
||||||
const refreshToken = useStorage('refreshToken', '', uniStorage)
|
const refreshToken = useStorage('refreshToken', '', uniStorage)
|
||||||
const userInfo = useStorage('userInfo', {}, uniStorage)
|
const userInfo = useStorage('userInfo', {}, uniStorage)
|
||||||
const leaderList = useStorage('leaderList', [], uniStorage)
|
const leaderList = useStorage('leaderList', [], uniStorage)
|
||||||
|
@ -9,6 +9,7 @@ import {uniStorage} from "@/utils/uniStorage.js"
|
|||||||
export const useDialogueListStore = createGlobalState(() => {
|
export const useDialogueListStore = createGlobalState(() => {
|
||||||
const dialogueList = useStorage('dialogueList', [], uniStorage)
|
const dialogueList = useStorage('dialogueList', [], uniStorage)
|
||||||
const zpagingRef = ref()
|
const zpagingRef = ref()
|
||||||
|
const virtualList = ref([])
|
||||||
|
|
||||||
const getDialogueList=(indexName)=>{
|
const getDialogueList=(indexName)=>{
|
||||||
return dialogueList.value.find(item=>item.index_name===indexName)
|
return dialogueList.value.find(item=>item.index_name===indexName)
|
||||||
@ -61,9 +62,7 @@ export const useDialogueListStore = createGlobalState(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updateUploadProgress=(id,progress)=>{
|
const updateUploadProgress=(id,progress)=>{
|
||||||
const dialogue = lodash.cloneDeep(useDialogueStore())
|
const record = virtualList.value.find(item=>item.msg_id===id)
|
||||||
const item = getDialogueList(dialogue.index_name)
|
|
||||||
const record = item.records.find(item=>item.msg_id===id)
|
|
||||||
if(record){
|
if(record){
|
||||||
record.uploadCurrent = progress
|
record.uploadCurrent = progress
|
||||||
}
|
}
|
||||||
@ -75,13 +74,13 @@ export const useDialogueListStore = createGlobalState(() => {
|
|||||||
|
|
||||||
const zpagingComplete=(index_name)=>{
|
const zpagingComplete=(index_name)=>{
|
||||||
const item = getDialogueList(index_name)
|
const item = getDialogueList(index_name)
|
||||||
zpagingRef.value?.complete(item.records.toReversed())
|
zpagingRef.value?.complete(lodash.cloneDeep(item.records).reverse())
|
||||||
}
|
}
|
||||||
|
|
||||||
const addChatRecord = (indexName,item)=>{
|
const addChatRecord = (indexName,item)=>{
|
||||||
const dialogue = lodash.cloneDeep(useDialogueStore())
|
const dialogue = lodash.cloneDeep(useDialogueStore())
|
||||||
if (dialogue?.index_name === indexName) {
|
if (dialogue?.index_name === indexName) {
|
||||||
zpagingRef.value?.addChatRecordData(item.records)
|
zpagingRef.value?.addChatRecordData(item,false,false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,5 +94,6 @@ export const useDialogueListStore = createGlobalState(() => {
|
|||||||
updateZpagingRef,
|
updateZpagingRef,
|
||||||
zpagingComplete,
|
zpagingComplete,
|
||||||
addChatRecord,
|
addChatRecord,
|
||||||
|
virtualList
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import axios from 'axios';
|
||||||
// BD-09 转 GCJ-02
|
// BD-09 转 GCJ-02
|
||||||
export const bd09togcj02 = (bd_lon, bd_lat) => {
|
export const bd09togcj02 = (bd_lon, bd_lat) => {
|
||||||
const x_pi = (3.14159265358979324 * 3000.0) / 180.0;
|
const x_pi = (3.14159265358979324 * 3000.0) / 180.0;
|
||||||
@ -85,5 +86,93 @@ export const convertBd09ToWgs84 = (bd_lon, bd_lat) => {
|
|||||||
|
|
||||||
export const uniqueId = () => 'id-' + new Date().getTime().toString(36) + '-' + Math.random().toString(36).substr(2, 9);
|
export const uniqueId = () => 'id-' + new Date().getTime().toString(36) + '-' + Math.random().toString(36).substr(2, 9);
|
||||||
|
|
||||||
|
export const getFileType = (url) => {
|
||||||
|
// 从URL中提取文件扩展名
|
||||||
|
const ext = url.split('.').pop()?.toLowerCase()
|
||||||
|
|
||||||
|
// 图片类型
|
||||||
|
if(ext === 'jpg' || ext === 'jpeg') {
|
||||||
|
return 'image/jpeg'
|
||||||
|
}
|
||||||
|
if(ext === 'png') {
|
||||||
|
return 'image/png'
|
||||||
|
}
|
||||||
|
if(ext === 'gif') {
|
||||||
|
return 'image/gif'
|
||||||
|
}
|
||||||
|
if(ext === 'webp') {
|
||||||
|
return 'image/webp'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 视频类型
|
||||||
|
if(ext === 'mp4') {
|
||||||
|
return 'video/mp4'
|
||||||
|
}
|
||||||
|
if(ext === 'webm') {
|
||||||
|
return 'video/webm'
|
||||||
|
}
|
||||||
|
if(ext === 'avi') {
|
||||||
|
return 'video/x-msvideo'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 音频类型
|
||||||
|
if(ext === 'mp3') {
|
||||||
|
return 'audio/mpeg'
|
||||||
|
}
|
||||||
|
if(ext === 'wav') {
|
||||||
|
return 'audio/wav'
|
||||||
|
}
|
||||||
|
if(ext === 'ogg') {
|
||||||
|
return 'audio/ogg'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文档类型
|
||||||
|
if(ext === 'pdf') {
|
||||||
|
return 'application/pdf'
|
||||||
|
}
|
||||||
|
if(ext === 'doc' || ext === 'docx') {
|
||||||
|
return 'application/msword'
|
||||||
|
}
|
||||||
|
if(ext === 'xls' || ext === 'xlsx') {
|
||||||
|
return 'application/vnd.ms-excel'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回二进制流类型
|
||||||
|
return 'application/octet-stream'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getFileFromUrl = (url, fileName) => {
|
||||||
|
return new Promise(async(resolve, reject) => {
|
||||||
|
const osName = uni.getSystemInfoSync().osName;
|
||||||
|
if (osName === "android") {
|
||||||
|
var blob = null;
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", url);
|
||||||
|
xhr.setRequestHeader('Accept',getFileType(url));
|
||||||
|
xhr.responseType = "blob";
|
||||||
|
// 加载时处理
|
||||||
|
xhr.onload = () => {
|
||||||
|
// 获取返回结果
|
||||||
|
blob = xhr.response;
|
||||||
|
let file= new File([blob], fileName, { type: getFileType(url) });
|
||||||
|
// 返回结果
|
||||||
|
console.log(file);
|
||||||
|
|
||||||
|
resolve(file);
|
||||||
|
};
|
||||||
|
xhr.onerror = (e) => {
|
||||||
|
reject(e)
|
||||||
|
};
|
||||||
|
// 发送
|
||||||
|
xhr.send();
|
||||||
|
}else{
|
||||||
|
const response = await fetch(url);
|
||||||
|
const blob = await response.blob();
|
||||||
|
const file = new File([blob], fileName, { type: getFileType(url) });
|
||||||
|
resolve(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|