Compare commits

...

2 Commits

Author SHA1 Message Date
04dcbdf331 处理未读消息数量场景补全情况
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
2025-03-25 10:33:30 +08:00
fa2098c565 处理oa底部tabbar未读消息数量显示 2025-03-24 20:03:52 +08:00
10 changed files with 110 additions and 43 deletions

2
components.d.ts vendored
View File

@ -30,6 +30,8 @@ declare module 'vue' {
LoginMessage: typeof import('./src/components/talk/message/LoginMessage.vue')['default'] LoginMessage: typeof import('./src/components/talk/message/LoginMessage.vue')['default']
Message: typeof import('./src/components/x-message/message/index.vue')['default'] Message: typeof import('./src/components/x-message/message/index.vue')['default']
MixedMessage: typeof import('./src/components/talk/message/MixedMessage.vue')['default'] MixedMessage: typeof import('./src/components/talk/message/MixedMessage.vue')['default']
NButton: typeof import('naive-ui')['NButton']
NIcon: typeof import('naive-ui')['NIcon']
PageAnimation: typeof import('./src/components/page-animation/index.vue')['default'] PageAnimation: typeof import('./src/components/page-animation/index.vue')['default']
RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default'] RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']

View File

@ -38,7 +38,19 @@ export const ServeTopTalkList = (data) => {
} }
// 清除聊天消息未读数服务接口 // 清除聊天消息未读数服务接口
export const ServeClearTalkUnreadNum = (data) => { export const ServeClearTalkUnreadNum = (data, unReadNum) => {
console.log("=======chatApp==UnreadNum",unReadNum)
if (typeof plus !== 'undefined') {
let OAWebView = plus.webview.all()
//all里面第一个是入口webview
OAWebView[0].evalJS(`updateUnreadMsgNumReduce('${unReadNum}')`)
} else {
document.addEventListener('plusready', () => {
let OAWebView = plus.webview.all()
//all里面第一个是入口webview
OAWebView[0].evalJS(`updateUnreadMsgNumReduce('${unReadNum}')`)
})
}
return request({ return request({
url: '/api/v1/talk/unread/clear', url: '/api/v1/talk/unread/clear',
method: 'POST', method: 'POST',

View File

@ -5,8 +5,16 @@ import { parseTime } from '@/utils/datetime'
import * as message from '@/constant/message' import * as message from '@/constant/message'
import { formatTalkItem, palyMusic, formatTalkRecord } from '@/utils/talk' import { formatTalkItem, palyMusic, formatTalkRecord } from '@/utils/talk'
// import { isElectronMode } from '@/utils/common' // import { isElectronMode } from '@/utils/common'
import { ServeClearTalkUnreadNum, ServeCreateTalkList } from '@/api/chat/index.js' import {
import { useTalkStore, useDialogueStore,useDialogueListStore,useGroupStore } from '@/store' ServeClearTalkUnreadNum,
ServeCreateTalkList,
} from '@/api/chat/index.js'
import {
useTalkStore,
useDialogueStore,
useDialogueListStore,
useGroupStore,
} from '@/store'
/** /**
* 好友状态事件 * 好友状态事件
@ -49,7 +57,7 @@ class Talk extends Base {
this.receiver_id = resource.receiver_id this.receiver_id = resource.receiver_id
this.talk_type = resource.talk_type this.talk_type = resource.talk_type
// this.fileNum = resource.file_num // this.fileNum = resource.file_num
if(resource.file_num){ if (resource.file_num) {
resource.data.file_num = resource.file_num resource.data.file_num = resource.file_num
} }
this.resource = resource.data this.resource = resource.data
@ -98,7 +106,6 @@ class Talk extends Base {
play() { play() {
// 客户端有消息提示 // 客户端有消息提示
// if (isElectronMode()) return // if (isElectronMode()) return
// useSettingsStore().isPromptTone && palyMusic() // useSettingsStore().isPromptTone && palyMusic()
} }
@ -118,6 +125,17 @@ class Talk extends Base {
this.insertTalkRecord() this.insertTalkRecord()
} else { } else {
this.updateTalkItem() this.updateTalkItem()
if (typeof plus !== 'undefined') {
let OAWebView = plus.webview.all()
//all里面第一个是入口webview
OAWebView[0].evalJS(`updateUnreadMsgNumAdd()`)
} else {
document.addEventListener('plusready', () => {
let OAWebView = plus.webview.all()
//all里面第一个是入口webview
OAWebView[0].evalJS(`updateUnreadMsgNumAdd()`)
})
}
} }
} }
@ -132,7 +150,6 @@ class Talk extends Base {
// lang: 'zh-CN', // lang: 'zh-CN',
// body: '您有新的消息请注意查收' // body: '您有新的消息请注意查收'
// }) // })
// notification.onclick = () => { // notification.onclick = () => {
// notification.close() // notification.close()
// } // }
@ -160,7 +177,7 @@ class Talk extends Base {
ServeCreateTalkList({ ServeCreateTalkList({
talk_type, talk_type,
receiver_id receiver_id,
}).then(({ code, data }) => { }).then(({ code, data }) => {
if (code == 200) { if (code == 200) {
let item = formatTalkItem(data) let item = formatTalkItem(data)
@ -175,8 +192,8 @@ class Talk extends Base {
*/ */
insertTalkRecord() { insertTalkRecord() {
let record = this.resource let record = this.resource
let newRecord = formatTalkRecord(this.getAccountId(), this.resource); let newRecord = formatTalkRecord(this.getAccountId(), this.resource)
const {addDialogueRecord,addChatRecord} = useDialogueListStore() const { addDialogueRecord, addChatRecord } = useDialogueListStore()
// 群成员变化的消息,需要更新群成员列表 // 群成员变化的消息,需要更新群成员列表
if ([1102, 1103, 1104, 1115].includes(record.msg_type)) { if ([1102, 1103, 1104, 1115].includes(record.msg_type)) {
useDialogueStore().updateGroupMembers() useDialogueStore().updateGroupMembers()
@ -194,13 +211,15 @@ class Talk extends Base {
avatar: record.extra.group_avatar, avatar: record.extra.group_avatar,
}) })
// 更新会话列表中的会话信息 // 更新会话列表中的会话信息
const dialogue = useDialogueListStore().getDialogueList(`${record.talk_type}_${record.receiver_id}`) const dialogue = useDialogueListStore().getDialogueList(
`${record.talk_type}_${record.receiver_id}`,
)
if (dialogue) { if (dialogue) {
dialogue.talk.username = record.extra.group_name dialogue.talk.username = record.extra.group_name
} }
} }
addDialogueRecord([newRecord],'add') addDialogueRecord([newRecord], 'add')
addChatRecord(this.getIndexName(),newRecord) addChatRecord(this.getIndexName(), newRecord)
useDialogueStore().addDialogueRecord(newRecord) useDialogueStore().addDialogueRecord(newRecord)
if (!this.isCurrSender()) { if (!this.isCurrSender()) {
@ -208,7 +227,7 @@ class Talk extends Base {
setTimeout(() => { setTimeout(() => {
ws.emit('im.message.read', { ws.emit('im.message.read', {
receiver_id: this.sender_id, receiver_id: this.sender_id,
msg_ids: [this.resource.msg_id] msg_ids: [this.resource.msg_id],
}) })
}, 1000) }, 1000)
} }
@ -218,7 +237,8 @@ class Talk extends Base {
if (!el) return if (!el) return
// 判断的滚动条是否在底部 // 判断的滚动条是否在底部
const isBottom = Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight const isBottom =
Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight
if (isBottom || record.user_id == this.getAccountId()) { if (isBottom || record.user_id == this.getAccountId()) {
nextTick(() => { nextTick(() => {
@ -231,14 +251,15 @@ class Talk extends Base {
useTalkStore().updateItem({ useTalkStore().updateItem({
index_name: this.getIndexName(), index_name: this.getIndexName(),
msg_text: this.getTalkText(), msg_text: this.getTalkText(),
updated_at: parseTime(new Date()) updated_at: parseTime(new Date()),
}) })
if (this.talk_type == 1 && this.getAccountId() !== this.sender_id) { if (this.talk_type == 1 && this.getAccountId() !== this.sender_id) {
ServeClearTalkUnreadNum({ //不在此处维护未读消息数量
talk_type: 1, // ServeClearTalkUnreadNum({
receiver_id: this.sender_id // talk_type: 1,
}) // receiver_id: this.sender_id,
// })
} }
} }
@ -249,11 +270,13 @@ class Talk extends Base {
useTalkStore().updateMessage({ useTalkStore().updateMessage({
index_name: this.getIndexName(), index_name: this.getIndexName(),
msg_text: this.getTalkText(), msg_text: this.getTalkText(),
updated_at: parseTime(new Date()) updated_at: parseTime(new Date()),
}) })
if(this.resource.msg_type == 1116){ if (this.resource.msg_type == 1116) {
// 更新会话列表中的会话信息 // 更新会话列表中的会话信息
const dialogue = useDialogueListStore().getDialogueList(`${this.resource.talk_type}_${this.resource.receiver_id}`) const dialogue = useDialogueListStore().getDialogueList(
`${this.resource.talk_type}_${this.resource.receiver_id}`,
)
if (dialogue) { if (dialogue) {
dialogue.talk.username = this.resource.extra.group_name dialogue.talk.username = this.resource.extra.group_name
} }

View File

@ -17,10 +17,17 @@
</div> </div>
<div class="avatarImg"> <div class="avatarImg">
<avatarModule <avatarModule
:mode="2" :mode="props?.data?.group_type === 0 ? 1 : 2"
:avatar="props?.data?.avatar" :avatar="props?.data?.avatar"
:groupType="props?.data?.group_type" :groupType="props?.data?.group_type"
:userName="props?.data?.name"
:customStyle="{ width: '96rpx', height: '96rpx' }" :customStyle="{ width: '96rpx', height: '96rpx' }"
:customTextStyle="{
fontSize: '32rpx',
fontWeight: 'bold',
color: '#fff',
lineHeight: '44rpx',
}"
></avatarModule> ></avatarModule>
</div> </div>
<div class="chatInfo"> <div class="chatInfo">
@ -30,16 +37,18 @@
class="text-[#171717] text-[32rpx] font-medium leading-[44rpx]" class="text-[#171717] text-[32rpx] font-medium leading-[44rpx]"
> >
<span>{{ props.data.name }}</span> <span>{{ props.data.name }}</span>
<span v-if="props.data.talk_type === 2">{{ props.data.group_member_num }}</span> <span v-if="props.data.talk_type === 2">
{{ props.data.group_member_num }}
</span>
<span v-if="props.data.group_type === 2" class="depTag tag"> <span v-if="props.data.group_type === 2" class="depTag tag">
部门 部门
</span> </span>
<span v-if="props.data.group_type === 3" class="projectTag tag"> <span v-if="props.data.group_type === 3" class="projectTag tag">
项目 项目
</span> </span>
<span v-if="props.data.group_type === 4" class="companyTag tag"> <span v-if="props.data.group_type === 4" class="companyTag tag">
公司 公司
</span> </span>
</div> </div>
</div> </div>
</div> </div>
@ -127,7 +136,7 @@ const cellClick = () => {
opacity: 40%; opacity: 40%;
} }
.tag{ .tag {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
text-align: center; text-align: center;
@ -142,16 +151,16 @@ const cellClick = () => {
font-weight: bold; font-weight: bold;
} }
.companyTag { .companyTag {
border: 1px solid #7a58de; border: 1px solid #7a58de;
color: #7a58de; color: #7a58de;
} }
.depTag { .depTag {
border: 1px solid #377ec6; border: 1px solid #377ec6;
color: #377ec6; color: #377ec6;
} }
.projectTag { .projectTag {
border: 1px solid #c1681c; border: 1px solid #c1681c;
color: #c1681c; color: #c1681c;
} }
.textEllipsis { .textEllipsis {

View File

@ -219,7 +219,7 @@ watch(
onMounted(() => { onMounted(() => {
talkStore.loadTalkList() talkStore.loadTalkList()
console.log(talkStore.talkItems) console.log(talkStore.talkItems)
items.value = lodash.cloneDeep(talkStore.talkItems) items.value = lodash.cloneDeep(talkStore.talkItems).filter(item=>item.is_dismiss === 0 && item.is_quit === 0)
}) })
onUnmounted(() => { onUnmounted(() => {
dialogueStore.setForwardType('') dialogueStore.setForwardType('')

View File

@ -544,6 +544,7 @@ const talkParams = reactive({
isDismiss: computed(() => dialogueStore.isDismiss), isDismiss: computed(() => dialogueStore.isDismiss),
isQuit: computed(() => dialogueStore.isQuit), isQuit: computed(() => dialogueStore.isQuit),
adminList: computed(() => dialogueStore.getAdminList), adminList: computed(() => dialogueStore.getAdminList),
unReadNum: computed(() => dialogueStore.unreadNum),
}) })
const state = ref({ const state = ref({
@ -597,11 +598,12 @@ uniOnUnload(() => {
ServeClearTalkUnreadNum({ ServeClearTalkUnreadNum({
talk_type: Number(talkParams.type), talk_type: Number(talkParams.type),
receiver_id: Number(talkParams.receiver_id), receiver_id: Number(talkParams.receiver_id),
}).then(() => { },talkParams.unReadNum).then(() => {
talkStore.updateItem({ talkStore.updateItem({
index_name: talkParams.index_name, index_name: talkParams.index_name,
unread_num: 0, unread_num: 0,
}) })
dialogueStore.clearUnreadNum()
}) })
}) })
const handleEmojiPanel = () => { const handleEmojiPanel = () => {

View File

@ -107,6 +107,9 @@ import { useSessionMenu } from '@/hooks'
const talkStore = useTalkStore() const talkStore = useTalkStore()
const { onToTopTalk, onRemoveTalk } = useSessionMenu() const { onToTopTalk, onRemoveTalk } = useSessionMenu()
const dialogueStore = useDialogueStore() const dialogueStore = useDialogueStore()
const dialogueParams = reactive({
unReadNum: computed(() => dialogueStore.unreadNum),
})
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object, type: Object,
@ -135,11 +138,12 @@ const cellClick = () => {
ServeClearTalkUnreadNum({ ServeClearTalkUnreadNum({
talk_type: props.data.talk_type, talk_type: props.data.talk_type,
receiver_id: props.data.receiver_id, receiver_id: props.data.receiver_id,
}).then(() => { },dialogueParams.unReadNum).then(() => {
talkStore.updateItem({ talkStore.updateItem({
index_name: props.data.index_name, index_name: props.data.index_name,
unread_num: 0, unread_num: 0,
}) })
dialogueStore.clearUnreadNum()
}) })
} }
uni.navigateTo({ uni.navigateTo({

View File

@ -138,6 +138,9 @@ const isEmptyViewShow = ref(false)
const talkStore = useTalkStore() const talkStore = useTalkStore()
const userStore = useUserStore() const userStore = useUserStore()
const dialogueStore = useDialogueStore() const dialogueStore = useDialogueStore()
const dialogueParams = reactive({
unReadNum: computed(() => dialogueStore.unreadNum),
})
const { userInfo } = useAuth() const { userInfo } = useAuth()
const topItems = computed(() => talkStore.topItems) const topItems = computed(() => talkStore.topItems)
@ -244,11 +247,12 @@ onLoad((options) => {
ServeClearTalkUnreadNum({ ServeClearTalkUnreadNum({
talk_type: openSession.talk_type, talk_type: openSession.talk_type,
receiver_id: openSession.receiver_id, receiver_id: openSession.receiver_id,
}).then(() => { },dialogueParams.unReadNum).then(() => {
talkStore.updateItem({ talkStore.updateItem({
index_name: openSession.index_name, index_name: openSession.index_name,
unread_num: 0, unread_num: 0,
}) })
dialogueStore.clearUnreadNum()
}) })
} }
uni.navigateTo({ uni.navigateTo({

View File

@ -54,6 +54,9 @@ export const useDialogueStore = defineStore('dialogue', {
//是否退群/移出群 //是否退群/移出群
isQuit: false, isQuit: false,
//未读消息数量
unreadNum:0,
// 群成员列表 // 群成员列表
members: [], members: [],
@ -90,6 +93,11 @@ export const useDialogueStore = defineStore('dialogue', {
this.online = status this.online = status
}, },
// 更新未读消息数量-清空未读
clearUnreadNum() {
this.unreadNum = 0
},
// 更新对话信息 // 更新对话信息
setDialogue(data = {}) { setDialogue(data = {}) {
this.online = data.is_online == 1 this.online = data.is_online == 1
@ -107,6 +115,8 @@ export const useDialogueStore = defineStore('dialogue', {
this.isDismiss = data?.is_dismiss === 1 ? true : false this.isDismiss = data?.is_dismiss === 1 ? true : false
this.isQuit = data?.is_quit === 1 ? true : false this.isQuit = data?.is_quit === 1 ? true : false
this.unreadNum = data?.unread_num || 0
this.members = [] this.members = []
if (data.talk_type == 2) { if (data.talk_type == 2) {
this.updateGroupMembers() this.updateGroupMembers()

View File

@ -42,6 +42,7 @@ export const useDialogueListStore = createGlobalState(() => {
isShowSessionList: dialogue.isShowSessionList, isShowSessionList: dialogue.isShowSessionList,
isDismiss: dialogue.isDismiss, isDismiss: dialogue.isDismiss,
isQuit: dialogue.isQuit, isQuit: dialogue.isQuit,
unreadNum: dialogue.unreadNum,
members: dialogue.members.map(member => ({ members: dialogue.members.map(member => ({
id: member.id, id: member.id,
nickname: member.nickname, nickname: member.nickname,