处理各种场景热更新;新增1106消息类型处理解散;群聊按图片视频类型查看增加视频播放;修改选择图片组件为plus组件
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-25 19:40:19 +08:00
parent 17d9ed737d
commit 8ed2bf7113
10 changed files with 228 additions and 47 deletions

3
components.d.ts vendored
View File

@ -30,8 +30,6 @@ declare module 'vue' {
LoginMessage: typeof import('./src/components/talk/message/LoginMessage.vue')['default']
Message: typeof import('./src/components/x-message/message/index.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']
RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
@ -39,6 +37,7 @@ declare module 'vue' {
SysGroupAdminMessage: typeof import('./src/components/talk/message/system/SysGroupAdminMessage.vue')['default']
SysGroupCancelMutedMessage: typeof import('./src/components/talk/message/system/SysGroupCancelMutedMessage.vue')['default']
SysGroupCreateMessage: typeof import('./src/components/talk/message/system/SysGroupCreateMessage.vue')['default']
SysGroupDismissed: typeof import('./src/components/talk/message/system/SysGroupDismissed.vue')['default']
SysGroupInfoChangeMessage: typeof import('./src/components/talk/message/system/SysGroupInfoChangeMessage.vue')['default']
SysGroupJoinMessage: typeof import('./src/components/talk/message/system/SysGroupJoinMessage.vue')['default']
SysGroupMemberCancelMutedMessage: typeof import('./src/components/talk/message/system/SysGroupMemberCancelMutedMessage.vue')['default']

View File

@ -58,7 +58,7 @@ const img = computed(() => {
}"
>
<div class="image-container">
<tm-image preview :width="img.width" :height="img.height" :src="extra.url" />
<tm-image preview :width="img.width" :height="img.height" :src="extra.url" model="aspectFill"/>
<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>
</section>

View File

@ -0,0 +1,19 @@
<script setup>
import './sys-message.less'
import { useInject } from '@/hooks'
const { showUserInfoModal } = useInject()
defineProps({
extra: Object,
data: Object
})
</script>
<template>
<div class="im-message-sys-text">
<div class="sys-text">
<span>{{ extra.content }}</span>
</div>
</div>
</template>

View File

@ -85,7 +85,7 @@ export const MessageComponents = {
[ChatMsgSysGroupMemberQuit]: 'sys-group-member-quit-message',
[ChatMsgSysGroupMemberKicked]: 'sys-group-member-kicked-message',
// [ChatMsgSysGroupMessageRevoke]: '[撤回消息]',
// [ChatMsgSysGroupDismissed]: '[群解散消息]',
[ChatMsgSysGroupDismissed]: 'sys-group-dismissed',
[ChatMsgSysGroupMuted]: 'sys-group-muted-message',
[ChatMsgSysGroupCancelMuted]: 'sys-group-cancel-muted-message',
[ChatMsgSysGroupMemberMuted]: 'sys-group-member-muted-message',

View File

@ -125,22 +125,27 @@ class Talk extends Base {
this.insertTalkRecord()
} else {
this.updateTalkItem()
if (typeof plus !== 'undefined') {
let OAWebView = plus.webview.all()
OAWebView.forEach((webview) => {
if (webview.id === 'webviewId1') {
webview.evalJS(`updateUnreadMsgNumAdd()`)
}
})
} else {
document.addEventListener('plusready', () => {
if (
!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()`)
}
})
})
}
}
}
}
@ -204,6 +209,30 @@ class Talk extends Base {
if ([1102, 1103, 1104, 1115].includes(record.msg_type)) {
useDialogueStore().updateGroupMembers()
}
//群解散时,需要更新群成员权限
if ([1106].includes(record.msg_type)) {
useDialogueStore().updateDismiss()
}
//群成员被移出时,需要更新群成员权限
if ([1104, 1115].includes(record.msg_type)) {
useDialogueStore().updateQuit()
}
//群禁言变化时,需要更新群禁言状态——即更新群成员列表
if ([1107, 1108, 1109, 1110].includes(record.msg_type)) {
useDialogueStore().updateGroupMembers()
}
//群公告变化时,需要更新群公告(新增和修改有热更新,删除没有)
if ([13].includes(record.msg_type)) {
useGroupStore().ServeGetGroupNotices()
}
//群管理员变化时,需要更新群管理员列表——即更新群成员列表,同时更新群信息
if ([1114].includes(record.msg_type)) {
useDialogueStore().updateGroupMembers()
useGroupStore().ServeGroupDetail()
}
if ([1116].includes(record.msg_type)) {
// 更新会话信息
useDialogueStore().setDialogue({

View File

@ -267,8 +267,8 @@ onLoad(async (options) => {
if (options.groupId) {
console.log(options.groupId)
state.groupId = Number(options.groupId)
await groupStore.ServeGroupDetail()
if (dialogueParams.type === 2) {
await groupStore.ServeGroupDetail()
await groupStore.ServeGetGroupNotices()
}
}
@ -566,7 +566,10 @@ const showConfirmPrompt = (flag) => {
confirmContent = t('group.dismiss.confirm')
} else if (flag === 3) {
//退
if (dialogueParams.adminList.length === 1 && dialogueParams.adminList[0].id === dialogueParams.uid) {
if (
dialogueParams.adminList.length === 1 &&
dialogueParams.adminList[0].id === dialogueParams.uid
) {
//
confirmContent = t('ok') + t('group.quit.btn')
subContent = t('groupManage.disband.hint')
@ -604,7 +607,10 @@ const showConfirmPrompt = (flag) => {
}
} else if (flag === 3) {
//退
if (dialogueParams.adminList.length === 1 && dialogueParams.adminList[0].id === dialogueParams.uid) {
if (
dialogueParams.adminList.length === 1 &&
dialogueParams.adminList[0].id === dialogueParams.uid
) {
//
let params = {
group_id: dialogueParams.receiver_id, //id
@ -624,7 +630,9 @@ const showConfirmPrompt = (flag) => {
group_id: dialogueParams.receiver_id,
}).then(({ code, message }) => {
if (code == 200) {
// dialogueStore.apiClearRecord()
uni.navigateBack({
delta: 2,
})
} else {
}
})

View File

@ -72,7 +72,7 @@ const props = defineProps({
})
const state = reactive({
base64Url: ''
base64Url: '',
})
const uploadsStore = useUploadsStore()
@ -94,17 +94,54 @@ const onProgressFn = (progress, id) => {
const photoActionsSelect = (index) => {
if (index === 0) {
uni.chooseImage({
sourceType: ['album'],
count: 9,
success: async (res) => {
console.log(res, 'res')
res.tempFiles.forEach(async (file) => {
let data = await onUploadImageVideo(file, 'image')
emit('selectImg', data, data.file_num)
})
},
})
if (typeof plus === 'undefined') {
uni.chooseImage({
sourceType: ['album'],
count: 9,
success: async (res) => {
console.log(res, 'res')
res.tempFiles.forEach(async (file) => {
let data = await onUploadImageVideo(file, 'image')
emit('selectImg', data, data.file_num)
})
},
})
} else {
plus?.gallery.pick(
(res) => {
console.log(res, 'res')
res.files.reverse()
res.files.forEach(async (filePath) => {
plus?.io?.resolveLocalFileSystemURL(
filePath,
async (entry) => {
entry.file((file) => {
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, 'image')
emit('selectImg', data, data.file_num)
}
})
},
(err) => {
console.log(err)
},
)
})
},
(err) => {
console.log(err)
},
{
filter: 'image',
maximum: 9,
multiple: true,
},
)
}
} else {
uni.chooseVideo({
sourceType: ['album'],

View File

@ -65,6 +65,9 @@
</div>
<div class="chatInfo_2 w-full mr-[6rpx]">
<div class="w-full chatInfo_2_1 textEllipsis">
<span v-if="props.data.atsign_num" style="color: red;">
[有人@]
</span>
{{ props.data.msg_text }}
</div>
</div>
@ -135,10 +138,13 @@ const cellClick = () => {
//
if (props.data.unread_num > 0) {
ServeClearTalkUnreadNum({
talk_type: props.data.talk_type,
receiver_id: props.data.receiver_id,
},dialogueParams.unReadNum).then(() => {
ServeClearTalkUnreadNum(
{
talk_type: props.data.talk_type,
receiver_id: props.data.receiver_id,
},
dialogueParams.unReadNum,
).then(() => {
talkStore.updateItem({
index_name: props.data.index_name,
unread_num: 0,

View File

@ -123,7 +123,10 @@
state.condition === 'imgAndVideo' ? '0 0 10rpx' : '',
}"
>
<div class="condition-result-member">
<div
class="condition-result-member"
v-if="state.condition === 'member'"
>
<searchItem
@click="toDialogueByMember(item)"
:searchResultKey="'search_by_member_condition'"
@ -157,17 +160,24 @@
class="condition-result-imgAndVideo-area"
v-if="item?.extra?.url"
>
<tm-image
preview
:src="
item?.msg_type === 3
? item?.extra?.url
: item?.msg_type === 5
? item?.extra?.cover
: ''
"
model="aspectFill"
/>
<template v-if="item?.msg_type === 3">
<tm-image
preview
:src="item?.extra?.url"
model="aspectFill"
/>
</template>
<template v-else-if="item?.msg_type === 5">
<div class="video-preview" @click="onPlay(item?.extra?.url)">
<tm-image
:src="item?.extra?.cover"
model="aspectFill"
/>
<div class="play-icon">
<img :src="playCircle" />
</div>
</div>
</template>
</div>
</div>
<div
@ -254,6 +264,18 @@
</div>
</div>
</ZPaging>
<div v-show="open">
<video
:src="currentVideoUrl"
controls
@fullscreenchange="fullscreenchange"
:id="currentVideoUrl"
playsinline
webkit-playsinline
x5-playsinline
>
</video>
</div>
</div>
</div>
</template>
@ -263,13 +285,14 @@ import fileType_EXCEL from '@/static/image/search/fileType_EXCEL.png'
import fileType_WORD from '@/static/image/search/fileType_WORD.png'
import fileType_PDF from '@/static/image/search/fileType_PDF.png'
import fileType_Files from '@/static/image/search/fileType_Files.png'
import playCircle from "@/static/image/chatList/playCircle@2x.png"
import { fileFormatSize, fileSuffix } from '@/utils/strings'
import searchItem from '../components/searchItem.vue'
import customInput from '@/components/custom-input/custom-input.vue'
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
import { parseTime } from '@/utils/datetime'
import { onMounted, reactive, computed, ref } from 'vue'
import { onMounted, reactive, computed, ref, nextTick } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { ServeTalkDate, ServeGetSessionId } from '@/api/search/index'
import { ServeFindTalkRecords } from '@/api/chat/index'
@ -308,6 +331,37 @@ const state = reactive({
flatList: [], //
})
const videoContext = ref()
const open = ref(false)
const currentVideoUrl = ref('')
const fullscreenchange = (e) => {
if (!e.detail.fullScreen) {
videoContext.value.stop()
videoContext.value.seek(0)
open.value = false
}
}
async function onPlay(url) {
currentVideoUrl.value = url
open.value = true
// DOM
await nextTick()
//
videoContext.value = uni.createVideoContext(url, getCurrentInstance())
//
videoContext.value.requestFullScreen({ direction: 2 })
//
setTimeout(() => {
videoContext.value.play()
}, 100)
}
onLoad((options) => {
console.log(options)
if (options.condition) {
@ -829,6 +883,25 @@ body::v-deep .round-3 {
width: 164rpx !important;
height: 164rpx !important;
}
.video-preview {
position: relative;
width: 164rpx;
height: 164rpx;
cursor: pointer;
.play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
img{
width: 80rpx !important;
height: 80rpx !important;
}
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
}

View File

@ -98,6 +98,16 @@ export const useDialogueStore = defineStore('dialogue', {
this.unreadNum = 0
},
// 更新群解散状态
updateDismiss() {
this.isDismiss = true
},
// 更新群成员退出状态
updateQuit() {
this.isQuit = true
},
// 更新对话信息
setDialogue(data = {}) {
this.online = data.is_online == 1