diff --git a/components.d.ts b/components.d.ts index f93eeb3..7d10b9f 100644 --- a/components.d.ts +++ b/components.d.ts @@ -8,6 +8,8 @@ export {} /* prettier-ignore */ declare module 'vue' { 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'] Avatar: typeof import('./src/components/base/Avatar.vue')['default'] AvatarCropper: typeof import('./src/components/base/AvatarCropper.vue')['default'] diff --git a/src/App.vue b/src/App.vue index 646919e..8ce481d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,10 +1,11 @@ + + + + + diff --git a/src/components/async-loading/index.vue b/src/components/async-loading/index.vue new file mode 100644 index 0000000..5bb623b --- /dev/null +++ b/src/components/async-loading/index.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/src/components/talk/message/FileMessage.vue b/src/components/talk/message/FileMessage.vue index 6735c14..0d121c3 100644 --- a/src/components/talk/message/FileMessage.vue +++ b/src/components/talk/message/FileMessage.vue @@ -55,7 +55,7 @@ const getFileTypeIMG = computed(() => { default: objT.finishedImg = filePaperOther objT.blankImg = filePaperOtherBlank - objT.progressColor = '#747474' + objT.progressColor = '#46299d' } return objT }) @@ -132,7 +132,7 @@ const downloadAndOpenFile = () => { :height="95" :src="getFileTypeIMG.blankImg" > - { :strokeWidth="3" :size="20" > +
+ +
@@ -288,4 +291,20 @@ const downloadAndOpenFile = () => { width: 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%; +} diff --git a/src/components/talk/message/ImageMessage.vue b/src/components/talk/message/ImageMessage.vue index 8a84a27..9f6a226 100644 --- a/src/components/talk/message/ImageMessage.vue +++ b/src/components/talk/message/ImageMessage.vue @@ -12,40 +12,40 @@ const img = computed(() => { // console.log(props.extra); let info = { width: 0, - height: 0 + height: 0, } if (props.extra.url.includes('blob:http://')) { info = { width: props.extra.width, - height: props.extra.height + height: props.extra.height, } - }else { + } else { info = getImageInfo(props.extra.url) } if (info.width == 0 || info.height == 0) { return { width: 450, - height: 298 + height: 298, } } - if(info.width<300){ + if (info.width < 300) { return { width: 300, - height: info.height / (info.width / 300) + height: info.height / (info.width / 300), } } if (info.width < 350) { return { width: info.width, - height: info.height + height: info.height, } } return { width: 350, - height: info.height / (info.width / 350) + height: info.height / (info.width / 350), } }) @@ -54,13 +54,30 @@ const img = computed(() => { class="im-message-image" :class="{ left: data.float === 'left', - right: data.float === 'right' + right: data.float === 'right', }" > -
- - -
+
+
+ + +
+ +
+
+
diff --git a/src/components/talk/message/VideoMessage.vue b/src/components/talk/message/VideoMessage.vue index 38a0cd3..a11ffcf 100644 --- a/src/components/talk/message/VideoMessage.vue +++ b/src/components/talk/message/VideoMessage.vue @@ -1,8 +1,8 @@ diff --git a/src/event/talk.js b/src/event/talk.js index f2435b0..cc3b6f1 100644 --- a/src/event/talk.js +++ b/src/event/talk.js @@ -143,27 +143,32 @@ class Talk extends Base { !useTalkStore().items[useTalkStore().findTalkIndex(this.getIndexName())] ?.is_disturb ) { - if (typeof plus !== 'undefined') { - let OAWebView = plus.webview.all() - OAWebView.forEach((webview) => { - if (webview.id === 'webviewId1') { - webview.evalJS(`updateUnreadMsgNumAdd()`) - } - }) - } else { - document.addEventListener('plusready', () => { - let OAWebView = plus.webview.all() - OAWebView.forEach((webview) => { - if (webview.id === 'webviewId1') { - webview.evalJS(`updateUnreadMsgNumAdd()`) - } - }) - }) - } + this.updateUnreadMsgNumAdd() } } } + //更新未读数量+1 + updateUnreadMsgNumAdd() { + if (typeof plus !== 'undefined') { + let OAWebView = plus.webview.all() + OAWebView.forEach((webview) => { + if (webview.id === 'webviewId1') { + webview.evalJS(`updateUnreadMsgNumAdd()`) + } + }) + } else { + document.addEventListener('plusready', () => { + let OAWebView = plus.webview.all() + OAWebView.forEach((webview) => { + if (webview.id === 'webviewId1') { + webview.evalJS(`updateUnreadMsgNumAdd()`) + } + }) + }) + } + } + /** * 显示消息提示 * @returns @@ -206,7 +211,10 @@ class Talk extends Base { }).then(async ({ code, data }) => { if (code == 200) { let item = formatTalkItem(data) - item.unread_num = 1 + if (!item?.is_disturb) { + item.unread_num = 1 + this.updateUnreadMsgNumAdd() + } useTalkStore().addItem(item) await useTalkStore().loadTalkList() } diff --git a/src/hooks/useSessionMenu.js b/src/hooks/useSessionMenu.js index 1963d13..d7bff50 100644 --- a/src/hooks/useSessionMenu.js +++ b/src/hooks/useSessionMenu.js @@ -11,7 +11,12 @@ import { reactive, nextTick, computed, h, inject } from 'vue' // EditTwo, // IdCard // } from '@icon-park/vue-next' -import { ServeTopTalkList, ServeDeleteTalkList, ServeSetNotDisturb } from '@/api/chat' +import { + ServeTopTalkList, + ServeDeleteTalkList, + ServeSetNotDisturb, + ServeClearTalkUnreadNum, +} from '@/api/chat' import { useDialogueStore, useTalkStore, useDialogueListStore } from '@/store' import { ServeSecedeGroup } from '@/api/group' // import { ServeDeleteContact, ServeEditContactRemark } from '@/api/contact' @@ -23,7 +28,7 @@ export function useSessionMenu() { show: false, x: 0, y: 0, - item: {} + item: {}, }) const dialogueStore = useDialogueStore() @@ -118,10 +123,22 @@ export function useSessionMenu() { // 移除会话 const onRemoveTalk = (item) => { ServeDeleteTalkList({ - list_id: item.id + list_id: item.id, }).then(({ code }) => { if (code == 200) { onDeleteTalk(item.index_name) + console.error(item, 'item') + if (item.unread_num > 0) { + //同时已读 + ServeClearTalkUnreadNum( + { + talk_type: item.talk_type, + receiver_id: item.receiver_id, + }, + item.unread_num, + ).then(() => { + }) + } } }) } @@ -131,13 +148,13 @@ export function useSessionMenu() { ServeSetNotDisturb({ talk_type: item.talk_type, receiver_id: item.receiver_id, - is_disturb: item.is_disturb == 0 ? 1 : 0 + is_disturb: item.is_disturb == 0 ? 1 : 0, }).then(({ code, message }) => { if (code == 200) { message.success('设置成功!') talkStore.updateItem({ index_name: item.index_name, - is_disturb: item.is_disturb == 0 ? 1 : 0 + is_disturb: item.is_disturb == 0 ? 1 : 0, }) } else { message.error(message) @@ -153,12 +170,12 @@ export function useSessionMenu() { ServeTopTalkList({ list_id: item.id, - type: item.is_top == 0 ? 1 : 2 + type: item.is_top == 0 ? 1 : 2, }).then(({ code, message }) => { if (code == 200) { talkStore.updateItem({ index_name: item.index_name, - is_top: item.is_top == 0 ? 1 : 0 + is_top: item.is_top == 0 ? 1 : 0, }) } else { message.error(message) @@ -201,7 +218,7 @@ export function useSessionMenu() { negativeText: '取消', onPositiveClick: () => { ServeSecedeGroup({ - group_id: item.receiver_id + group_id: item.receiver_id, }).then(({ code, message }) => { if (code == 200) { message.success('已退出群聊') @@ -210,7 +227,7 @@ export function useSessionMenu() { message.error(message) } }) - } + }, }) } @@ -259,12 +276,18 @@ export function useSessionMenu() { disturb: onSetDisturb, signout_group: onSignOutGroup, delete_contact: onDeleteContact, - remark: onChangeRemark + remark: onChangeRemark, } dropdown.show = false evnets[key] && evnets[key](dropdown.item) } - return { dropdown, onCloseContextMenu, onContextMenuTalkHandle, onToTopTalk, onRemoveTalk } + return { + dropdown, + onCloseContextMenu, + onContextMenuTalkHandle, + onToTopTalk, + onRemoveTalk, + } } diff --git a/src/main.js b/src/main.js index a5d29b0..94ae8fe 100644 --- a/src/main.js +++ b/src/main.js @@ -10,6 +10,8 @@ import tmui from '@/uni_modules/tmui' import { config } from '@/config/tmui/index.js' import 'dayjs/locale/zh-cn' 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 messagePopup from '@/components/x-message/useMessagePopup' import pageAnimation from '@/components/page-animation/index.vue' @@ -29,6 +31,8 @@ export function createApp() { app.mixin(pageAnimation) app.component('customNavbar', customNavbar) app.component('x-loaderror', xLoaderror) + app.component('AsyncLoading', asyncLoading) + app.component('AsyncError', asyncError) app.directive('no-space', { mounted(el) { el.addEventListener('input', (e) => { diff --git a/src/pages/dialog/components/filePanel.vue b/src/pages/dialog/components/filePanel.vue index 27470ad..f2550c6 100644 --- a/src/pages/dialog/components/filePanel.vue +++ b/src/pages/dialog/components/filePanel.vue @@ -101,6 +101,11 @@ const photoActionsSelect = (index) => { success: async (res) => { console.log(res, 'res') res.tempFiles.forEach(async (file) => { + const fileSizeInMB = (file.size / (1024 * 1024)).toFixed(2) + if (fileSizeInMB > 100) { + plus.nativeUI.toast('图片大小不能超过100MB') + return + } let data = await onUploadImageVideo(file, 'image') emit('selectImg', data, data.file_num) }) @@ -121,6 +126,13 @@ const photoActionsSelect = (index) => { fileReader.onloadend = async (e) => { const base64Url = e.target.result const fileObj = base64ToFile(base64Url) + const fileSizeInMB = (fileObj.size / (1024 * 1024)).toFixed( + 2, + ) + if (fileSizeInMB > 100) { + plus.nativeUI.toast('图片大小不能超过100MB') + return + } let data = await onUploadImageVideo(fileObj, 'image') emit('selectImg', data, data.file_num) } @@ -152,6 +164,11 @@ const photoActionsSelect = (index) => { maxDuration: 60, success: async (res) => { console.log(res, 'res') + const fileSizeInMB = (res.tempFile.size / (1024 * 1024)).toFixed(2) + if (fileSizeInMB > 100) { + plus.nativeUI.toast('视频大小不能超过100MB') + return + } let data = await onUploadImageVideo( res.tempFile, 'video', @@ -164,12 +181,13 @@ const photoActionsSelect = (index) => { } const onUploadImageVideo = async (file, type = 'image', fileUrl) => { - console.log(file, 'file') + console.log('开始上传文件:', file.name) + uploadsStore.updateUploadStatus(true) return new Promise(async (resolve) => { if (type === 'image') { let image = new Image() image.src = URL.createObjectURL(file) - image.onload = () => { + image.onload = async () => { const form = new FormData() form.append('file', file) form.append('source', 'fonchain-chat') @@ -203,40 +221,62 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => { } virtualList.value.unshift(newItem) - uploadImg(form, (e) => onProgressFn(e, randomId)).then( - ({ status, data, msg }) => { - if (status == 0) { - // 更新上传状态为成功 - const index = virtualList.value.findIndex(item => item.file_num === randomId) - if (index !== -1) { - virtualList.value[index].uploadStatus = 2 - virtualList.value[index].uploadCurrent = 100 - } - resolve({ - type: 'image', - 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) + + try { + const result = await uploadImg(form, (e) => onProgressFn(e, randomId)) + console.log('上传完成,结果:', result) + + if (result.status === 0) { + // 更新上传状态为成功 + const index = virtualList.value.findIndex( + (item) => item.file_num === randomId, + ) + if (index !== -1) { + virtualList.value[index].uploadStatus = 2 + virtualList.value[index].uploadCurrent = 100 } - }, - ) + + // 确保返回数据 + 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 { uni.getVideoInfo({ src: fileUrl, - success: (resp) => { - console.log(resp) + success: async (resp) => { + console.log('视频信息:', resp) + const form = new FormData() form.append('file', file) form.append('source', 'fonchain-chat') form.append('type', 'video') @@ -266,41 +306,65 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => { talk_type: dialogueStore.talk.talk_type, user_id: userStore.uid, uploadCurrent: 0, - uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败 + uploadStatus: 1, } virtualList.value.unshift(newItem) - uploadImg(form, (e) => onProgressFn(e, randomId)).then( - ({ status, data, msg }) => { - if (status == 0) { - // 更新上传状态为成功 - const index = virtualList.value.findIndex(item => item.file_num === randomId) - if (index !== -1) { - virtualList.value[index].uploadStatus = 2 - virtualList.value[index].uploadCurrent = 100 - } - console.log(data) - resolve({ - 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) + + try { + const result = await uploadImg(form, (e) => onProgressFn(e, randomId)) + console.log('视频上传完成,结果:', result) + + if (result.status === 0) { + // 更新上传状态为成功 + const index = virtualList.value.findIndex( + (item) => item.file_num === randomId, + ) + if (index !== -1) { + virtualList.value[index].uploadStatus = 2 + virtualList.value[index].uploadCurrent = 100 } - }, - ) + + 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() } }) } @@ -451,6 +515,11 @@ const chooseFile = () => { count: 1, extension: [''], success: (res) => { + const fileSizeInMB = (res.tempFiles[0].size / (1024 * 1024)).toFixed(2) + if (fileSizeInMB > 100) { + plus.nativeUI.toast('文件大小不能超过100MB') + return + } let randomId = uniqueId() let newItem = { avatar: userStore.avatar, @@ -478,23 +547,34 @@ const chooseFile = () => { uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败 } virtualList.value.unshift(newItem) - uploadsStore.initUploadFile(res.tempFiles[0], props.talkParams, randomId, (status, data, msg) => { - if (status === 0) { - // 更新上传状态为成功 - const index = virtualList.value.findIndex(item => item.file_num === randomId) - if (index !== -1) { - virtualList.value[index].uploadStatus = 2 - virtualList.value[index].uploadCurrent = 100 + uploadsStore.updateUploadStatus(true) + uploadsStore.initUploadFile( + res.tempFiles[0], + props.talkParams, + randomId, + (status, data, msg) => { + if (status === 0) { + // 更新上传状态为成功 + const index = virtualList.value.findIndex( + (item) => item.file_num === randomId, + ) + if (index !== -1) { + virtualList.value[index].uploadStatus = 2 + virtualList.value[index].uploadCurrent = 100 + } + } else { + uploadsStore.updateUploadStatus(false) + // 更新上传状态为失败 + const index = virtualList.value.findIndex( + (item) => item.file_num === randomId, + ) + if (index !== -1) { + virtualList.value[index].uploadStatus = 3 + } + message.error(msg) } - } else { - // 更新上传状态为失败 - const index = virtualList.value.findIndex(item => item.file_num === randomId) - if (index !== -1) { - virtualList.value[index].uploadStatus = 3 - } - message.error(msg) - } - }) + }, + ) }, }) } diff --git a/src/pages/dialog/index.vue b/src/pages/dialog/index.vue index f26604a..f506d15 100644 --- a/src/pages/dialog/index.vue +++ b/src/pages/dialog/index.vue @@ -22,7 +22,12 @@ :hideBack="dialogueStore.isOpenMultiSelect" >