处理未读消息数量显示、删除回话自动已读、显示样式等问题
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:
wangyifeng 2025-03-28 16:13:45 +08:00
parent e904dae8a0
commit f17250f236
5 changed files with 139 additions and 57 deletions

View File

@ -11,7 +11,12 @@ import { reactive, nextTick, computed, h, inject } from 'vue'
// EditTwo, // EditTwo,
// IdCard // IdCard
// } from '@icon-park/vue-next' // } 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 { useDialogueStore, useTalkStore, useDialogueListStore } from '@/store'
import { ServeSecedeGroup } from '@/api/group' import { ServeSecedeGroup } from '@/api/group'
// import { ServeDeleteContact, ServeEditContactRemark } from '@/api/contact' // import { ServeDeleteContact, ServeEditContactRemark } from '@/api/contact'
@ -23,7 +28,7 @@ export function useSessionMenu() {
show: false, show: false,
x: 0, x: 0,
y: 0, y: 0,
item: {} item: {},
}) })
const dialogueStore = useDialogueStore() const dialogueStore = useDialogueStore()
@ -118,10 +123,22 @@ export function useSessionMenu() {
// 移除会话 // 移除会话
const onRemoveTalk = (item) => { const onRemoveTalk = (item) => {
ServeDeleteTalkList({ ServeDeleteTalkList({
list_id: item.id list_id: item.id,
}).then(({ code }) => { }).then(({ code }) => {
if (code == 200) { if (code == 200) {
onDeleteTalk(item.index_name) 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({ ServeSetNotDisturb({
talk_type: item.talk_type, talk_type: item.talk_type,
receiver_id: item.receiver_id, receiver_id: item.receiver_id,
is_disturb: item.is_disturb == 0 ? 1 : 0 is_disturb: item.is_disturb == 0 ? 1 : 0,
}).then(({ code, message }) => { }).then(({ code, message }) => {
if (code == 200) { if (code == 200) {
message.success('设置成功!') message.success('设置成功!')
talkStore.updateItem({ talkStore.updateItem({
index_name: item.index_name, index_name: item.index_name,
is_disturb: item.is_disturb == 0 ? 1 : 0 is_disturb: item.is_disturb == 0 ? 1 : 0,
}) })
} else { } else {
message.error(message) message.error(message)
@ -153,12 +170,12 @@ export function useSessionMenu() {
ServeTopTalkList({ ServeTopTalkList({
list_id: item.id, list_id: item.id,
type: item.is_top == 0 ? 1 : 2 type: item.is_top == 0 ? 1 : 2,
}).then(({ code, message }) => { }).then(({ code, message }) => {
if (code == 200) { if (code == 200) {
talkStore.updateItem({ talkStore.updateItem({
index_name: item.index_name, index_name: item.index_name,
is_top: item.is_top == 0 ? 1 : 0 is_top: item.is_top == 0 ? 1 : 0,
}) })
} else { } else {
message.error(message) message.error(message)
@ -201,7 +218,7 @@ export function useSessionMenu() {
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
ServeSecedeGroup({ ServeSecedeGroup({
group_id: item.receiver_id group_id: item.receiver_id,
}).then(({ code, message }) => { }).then(({ code, message }) => {
if (code == 200) { if (code == 200) {
message.success('已退出群聊') message.success('已退出群聊')
@ -210,7 +227,7 @@ export function useSessionMenu() {
message.error(message) message.error(message)
} }
}) })
} },
}) })
} }
@ -259,12 +276,18 @@ export function useSessionMenu() {
disturb: onSetDisturb, disturb: onSetDisturb,
signout_group: onSignOutGroup, signout_group: onSignOutGroup,
delete_contact: onDeleteContact, delete_contact: onDeleteContact,
remark: onChangeRemark remark: onChangeRemark,
} }
dropdown.show = false dropdown.show = false
evnets[key] && evnets[key](dropdown.item) evnets[key] && evnets[key](dropdown.item)
} }
return { dropdown, onCloseContextMenu, onContextMenuTalkHandle, onToTopTalk, onRemoveTalk } return {
dropdown,
onCloseContextMenu,
onContextMenuTalkHandle,
onToTopTalk,
onRemoveTalk,
}
} }

View File

@ -101,6 +101,11 @@ const photoActionsSelect = (index) => {
success: async (res) => { success: async (res) => {
console.log(res, 'res') console.log(res, 'res')
res.tempFiles.forEach(async (file) => { 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') let data = await onUploadImageVideo(file, 'image')
emit('selectImg', data, data.file_num) emit('selectImg', data, data.file_num)
}) })
@ -121,6 +126,13 @@ const photoActionsSelect = (index) => {
fileReader.onloadend = async (e) => { fileReader.onloadend = async (e) => {
const base64Url = e.target.result const base64Url = e.target.result
const fileObj = base64ToFile(base64Url) 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') let data = await onUploadImageVideo(fileObj, 'image')
emit('selectImg', data, data.file_num) emit('selectImg', data, data.file_num)
} }
@ -152,6 +164,11 @@ const photoActionsSelect = (index) => {
maxDuration: 60, maxDuration: 60,
success: async (res) => { success: async (res) => {
console.log(res, '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( let data = await onUploadImageVideo(
res.tempFile, res.tempFile,
'video', 'video',
@ -207,7 +224,9 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
({ status, data, msg }) => { ({ status, data, msg }) => {
if (status == 0) { if (status == 0) {
// //
const index = virtualList.value.findIndex(item => item.file_num === randomId) const index = virtualList.value.findIndex(
(item) => item.file_num === randomId,
)
if (index !== -1) { if (index !== -1) {
virtualList.value[index].uploadStatus = 2 virtualList.value[index].uploadStatus = 2
virtualList.value[index].uploadCurrent = 100 virtualList.value[index].uploadCurrent = 100
@ -222,7 +241,9 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
}) })
} else { } else {
// //
const index = virtualList.value.findIndex(item => item.file_num === randomId) const index = virtualList.value.findIndex(
(item) => item.file_num === randomId,
)
if (index !== -1) { if (index !== -1) {
virtualList.value[index].uploadStatus = 3 virtualList.value[index].uploadStatus = 3
} }
@ -273,7 +294,9 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
({ status, data, msg }) => { ({ status, data, msg }) => {
if (status == 0) { if (status == 0) {
// //
const index = virtualList.value.findIndex(item => item.file_num === randomId) const index = virtualList.value.findIndex(
(item) => item.file_num === randomId,
)
if (index !== -1) { if (index !== -1) {
virtualList.value[index].uploadStatus = 2 virtualList.value[index].uploadStatus = 2
virtualList.value[index].uploadCurrent = 100 virtualList.value[index].uploadCurrent = 100
@ -289,7 +312,9 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
}) })
} else { } else {
// //
const index = virtualList.value.findIndex(item => item.file_num === randomId) const index = virtualList.value.findIndex(
(item) => item.file_num === randomId,
)
if (index !== -1) { if (index !== -1) {
virtualList.value[index].uploadStatus = 3 virtualList.value[index].uploadStatus = 3
} }
@ -451,6 +476,11 @@ const chooseFile = () => {
count: 1, count: 1,
extension: [''], extension: [''],
success: (res) => { success: (res) => {
const fileSizeInMB = (res.tempFiles[0].size / (1024 * 1024)).toFixed(2)
if (fileSizeInMB > 100) {
plus.nativeUI.toast('文件大小不能超过100MB')
return
}
let randomId = uniqueId() let randomId = uniqueId()
let newItem = { let newItem = {
avatar: userStore.avatar, avatar: userStore.avatar,
@ -478,23 +508,32 @@ const chooseFile = () => {
uploadStatus: 1, // 1 2 3 uploadStatus: 1, // 1 2 3
} }
virtualList.value.unshift(newItem) virtualList.value.unshift(newItem)
uploadsStore.initUploadFile(res.tempFiles[0], props.talkParams, randomId, (status, data, msg) => { uploadsStore.initUploadFile(
if (status === 0) { res.tempFiles[0],
// props.talkParams,
const index = virtualList.value.findIndex(item => item.file_num === randomId) randomId,
if (index !== -1) { (status, data, msg) => {
virtualList.value[index].uploadStatus = 2 if (status === 0) {
virtualList.value[index].uploadCurrent = 100 //
const index = virtualList.value.findIndex(
(item) => item.file_num === randomId,
)
if (index !== -1) {
virtualList.value[index].uploadStatus = 2
virtualList.value[index].uploadCurrent = 100
}
} else {
//
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)
}
})
}, },
}) })
} }

View File

@ -22,7 +22,12 @@
:hideBack="dialogueStore.isOpenMultiSelect" :hideBack="dialogueStore.isOpenMultiSelect"
> >
<template #left v-if="dialogueStore.isOpenMultiSelect"> <template #left v-if="dialogueStore.isOpenMultiSelect">
<text class="ml-[36rpx]" @click="dialogueStore.isOpenMultiSelect = false">取消</text> <text
class="ml-[36rpx]"
@click="dialogueStore.isOpenMultiSelect = false"
>
取消
</text>
</template> </template>
<template <template
#subTitle #subTitle
@ -215,13 +220,17 @@
<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"
> >
<div class="flex-1 quillBox"> <div class="flex-1 quillBox" style="">
<QuillEditor <QuillEditor
ref="editor" ref="editor"
id="editor" id="editor"
:options="editorOption" :options="editorOption"
@editorChange="onEditorChange" @editorChange="onEditorChange"
style="width: 100%; flex: 1; height: 100%; border: none;" style="
width: 100%;
flex: 1;
height: 100%;
"
@click="onEditorClick" @click="onEditorClick"
/> />
<!-- <tm-input type=textarea autoHeight focusColor="#F9F9F9" color="#F9F9F9" :inputPadding="[12]" <!-- <tm-input type=textarea autoHeight focusColor="#F9F9F9" color="#F9F9F9" :inputPadding="[12]"
@ -238,7 +247,7 @@
}} }}
</span> </span>
<span <span
v-if="state?.quoteInfo" v-if="state?.quoteInfo?.msg_type !== 1"
class="text-[28rpx] text-[#999]" class="text-[28rpx] text-[#999]"
> >
{{ {{
@ -639,6 +648,9 @@ const handleHidePanel = () => {
const onEditorClick = () => { const onEditorClick = () => {
handleHidePanel() handleHidePanel()
const quill = getQuill() const quill = getQuill()
// if (quill.getText().endsWith('@\n')) {
// showMentionSelectDebounced(quill)
// }
quill.focus() quill.focus()
} }
@ -816,6 +828,9 @@ const onEmoticonEvent = (data) => {
} }
const onEditorChange = () => { const onEditorChange = () => {
if (getQuill().getText() !== state.value.lastMentionText) {
state.value.lastMentionTriggered = false
}
let delta = getQuill().getContents() let delta = getQuill().getContents()
let text = deltaToString(delta) let text = deltaToString(delta)
@ -1638,23 +1653,14 @@ onUnmounted(() => {
const showMentionSelectDebounced = (quill) => { const showMentionSelectDebounced = (quill) => {
const text = quill.getText() const text = quill.getText()
// //
console.log(
'lastMentionText',
state.value.lastMentionText,
state.value.lastMentionText.length,
)
console.log('text', text, text.length)
console.log(state.value.lastMentionTriggered)
if (text !== state.value.lastMentionText) { if (text !== state.value.lastMentionText) {
state.value.lastMentionTriggered = false state.value.lastMentionTriggered = false
} }
if (text.length === 2) {
state.value.lastMentionText = text
state.value.lastMentionTriggered = true
state.value.isShowMentionSelect = true
}
// //
if (state.value.lastMentionTriggered) { if (state.value.lastMentionTriggered) {
console.log('return')
return return
} }
@ -1718,13 +1724,16 @@ const showMentionSelectDebounced = (quill) => {
justify-content: space-between; justify-content: space-between;
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
span { span {
display: -webkit-inline-box; display: -webkit-inline-box;
text-overflow: ellipsis; text-overflow: ellipsis;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
width: 100%; width: 100%;
word-break: break-all;
} }
img { img {
margin: 0 0 0 30rpx; margin: 0 0 0 30rpx;
flex-shrink: 0; flex-shrink: 0;
@ -1937,6 +1946,7 @@ const showMentionSelectDebounced = (quill) => {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
:deep(.ql-clipboard) { :deep(.ql-clipboard) {
position: relative; position: relative;
opacity: 0; opacity: 0;
@ -1988,6 +1998,7 @@ const showMentionSelectDebounced = (quill) => {
z-index: 1; z-index: 1;
/* 确保 z-index 低于 deepBubble */ /* 确保 z-index 低于 deepBubble */
} }
.divider { .divider {
width: 100%; width: 100%;
height: 1rpx; height: 1rpx;
@ -2000,20 +2011,24 @@ const showMentionSelectDebounced = (quill) => {
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 36rpx 32rpx 0; padding: 36rpx 32rpx 0;
.cancel-btns { .cancel-btns {
flex-shrink: 0; flex-shrink: 0;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.hide-btn { .hide-btn {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: relative; position: relative;
text { text {
} }
img { img {
width: 18rpx; width: 18rpx;
height: 10rpx; height: 10rpx;
@ -2030,6 +2045,7 @@ const showMentionSelectDebounced = (quill) => {
background-color: #f3f3f3; background-color: #f3f3f3;
border-radius: 8rpx; border-radius: 8rpx;
flex-shrink: 0; flex-shrink: 0;
span { span {
color: #bababa; color: #bababa;
line-height: 40rpx; line-height: 40rpx;
@ -2039,6 +2055,7 @@ const showMentionSelectDebounced = (quill) => {
.mention-done-btn-can-do { .mention-done-btn-can-do {
background-color: #46299d; background-color: #46299d;
span { span {
color: #fff; color: #fff;
} }
@ -2050,11 +2067,13 @@ const showMentionSelectDebounced = (quill) => {
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
flex-shrink: 0; flex-shrink: 0;
span { span {
flex-shrink: 0; flex-shrink: 0;
} }
} }
} }
:deep(.mention) { :deep(.mention) {
color: #1890ff; color: #1890ff;
} }

View File

@ -1,4 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { ServeGetForwardRecords } from '@/api/chat' import { ServeGetForwardRecords } from '@/api/chat'
import { MessageComponents } from '@/constant/message' import { MessageComponents } from '@/constant/message'
@ -47,12 +48,12 @@ onMounted(() => {
</script> </script>
<template> <template>
<div class="outer-layer"> <div class="forward-record-page">
<div> <zPaging ref="zPaging" :show-scrollbar="false">
<tm-navbar :hideBack="false" hideHome :title="`${title}的会话记录`" > <template #top>
</tm-navbar> <customNavbar :title="`${title}的会话记录`"></customNavbar>
</div> </template>
<div class="main-box"> <div class="main-box">
<div v-if="items.length === 0" class="flex justify-center items-center w-full mt-[200rpx]"> <div v-if="items.length === 0" class="flex justify-center items-center w-full mt-[200rpx]">
<wd-loading /> <wd-loading />
</div> </div>
@ -76,16 +77,15 @@ onMounted(() => {
</div> </div>
</div> </div>
</div> </div>
</zPaging>
</div> </div>
</template> </template>
<style lang="less" scoped> <style lang="less" scoped>
.outer-layer { .forward-record-page {
overflow-y: auto;
flex: 1; flex: 1;
background-image: url("@/static/image/clockIn/z3280@3x.png"); background-image: url("@/static/image/clockIn/z3280@3x.png");
background-size: cover; background-size: cover;
padding: 0 66rpx 20rpx 50rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
@ -96,7 +96,7 @@ onMounted(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: auto; overflow: auto;
padding-top: 28rpx; padding: 28rpx 66rpx 20rpx 50rpx;
} }
.message-item { .message-item {

View File

@ -265,6 +265,7 @@ const handleDelete = () => {
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 1; -webkit-line-clamp: 1;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
word-break: break-all;
} }
.divider { .divider {