搜索:判断某个成员是不是禁言

This commit is contained in:
cbb
2026-02-12 17:51:42 +08:00
parent a040b56c74
commit 2191f46317
16 changed files with 388 additions and 212 deletions

View File

@@ -73,6 +73,7 @@
]"
:enableAt="featureConfig.InputMention"
:isMuted="false"
:groupID="groupID"
:muteText="TUITranslateService.t('TUIChat.您已被管理员禁言')"
:placeholder="TUITranslateService.t('TUIChat.请输入消息')"
:inputToolbarDisplayType="inputToolbarDisplayType"
@@ -361,8 +362,6 @@
)
currentConversationID.value = conversationID
}
</script>
<style scoped lang="scss" src="./style/index.scss"></style>

View File

@@ -4,7 +4,7 @@
<MessageInputAudio
v-if="(isWeChat || isApp) && isRenderVoice"
:class="{
'message-input-wx-audio-open': displayType === 'audio',
'message-input-wx-audio-open': displayType === 'audio'
}"
:isEnableAudio="displayType === 'audio'"
@changeDisplayType="changeDisplayType"
@@ -49,192 +49,251 @@
/>
</div>
<div>
<MessageQuote
:style="{minWidth: 0}"
:displayType="displayType"
/>
<MessageQuote :style="{ minWidth: 0 }" :displayType="displayType" />
</div>
</div>
</template>
<script setup lang="ts">
import TUIChatEngine, {
TUIStore,
StoreName,
IMessageModel,
IConversationModel,
} from '@tencentcloud/chat-uikit-engine-lite';
import { ref, watch, onMounted, onUnmounted } from '../../../adapter-vue';
import MessageInputEditor from './message-input-editor.vue';
import MessageInputAt from './message-input-at/index.vue';
import MessageInputAudio from './message-input-audio.vue';
import MessageQuote from './message-input-quote/index.vue';
import Icon from '../../common/Icon.vue';
import faceIcon from '../../../assets/icon/face-uni.png';
import moreIcon from '../../../assets/icon/more-uni.png';
import { isPC, isH5, isWeChat, isApp } from '../../../utils/env';
import { sendTyping } from '../utils/sendMessage';
import { ToolbarDisplayType, InputDisplayType } from '../../../interface';
import TUIChatConfig from '../config';
import TUIChatEngine, {
TUIStore,
StoreName,
IMessageModel,
IConversationModel,
TUIGroupService
} from '@tencentcloud/chat-uikit-engine-lite'
import {
ref,
watch,
onMounted,
onUnmounted
} from '../../../adapter-vue'
import MessageInputEditor from './message-input-editor.vue'
import MessageInputAt from './message-input-at/index.vue'
import MessageInputAudio from './message-input-audio.vue'
import MessageQuote from './message-input-quote/index.vue'
import Icon from '../../common/Icon.vue'
import faceIcon from '../../../assets/icon/face-uni.png'
import moreIcon from '../../../assets/icon/more-uni.png'
import { isPC, isH5, isWeChat, isApp } from '../../../utils/env'
import { sendTyping } from '../utils/sendMessage'
import {
ToolbarDisplayType,
InputDisplayType
} from '../../../interface'
import TUIChatConfig from '../config'
import { useAuthUser } from '../../../../composables/useAuthUser'
import { useUI } from '../../../../utils/use-ui'
interface IProps {
placeholder: string;
isMuted?: boolean;
muteText?: string;
enableInput?: boolean;
enableAt?: boolean;
enableTyping?: boolean;
replyOrReference?: Record<string, any>;
inputToolbarDisplayType: ToolbarDisplayType;
}
interface IEmits {
(e: 'changeToolbarDisplayType', displayType: ToolbarDisplayType): void;
}
const emits = defineEmits<IEmits>();
const props = withDefaults(defineProps<IProps>(), {
placeholder: 'this is placeholder',
replyOrReference: () => ({}),
isMuted: true,
muteText: '',
enableInput: true,
enableAt: true,
enableTyping: true,
inputToolbarDisplayType: 'none',
});
const editor = ref();
const messageInputAtRef = ref();
const currentConversation = ref<IConversationModel>();
const isGroup = ref<boolean>(false);
const displayType = ref<InputDisplayType>('editor');
const featureConfig = TUIChatConfig.getFeatureConfig();
const isRenderVoice = ref<boolean>(featureConfig.InputVoice);
const isRenderEmojiPicker = ref<boolean>(featureConfig.InputEmoji || featureConfig.InputStickers);
const isRenderMore = ref<boolean>(featureConfig.InputImage || featureConfig.InputVideo || featureConfig.InputEvaluation || featureConfig.InputQuickReplies);
onMounted(() => {
TUIStore.watch(StoreName.CONV, {
currentConversation: onCurrentConversationUpdated,
});
TUIStore.watch(StoreName.CHAT, {
quoteMessage: onQuoteMessageUpdated,
});
});
onUnmounted(() => {
TUIStore.unwatch(StoreName.CONV, {
currentConversation: onCurrentConversationUpdated,
});
TUIStore.unwatch(StoreName.CHAT, {
quoteMessage: onQuoteMessageUpdated,
});
});
watch(() => props.inputToolbarDisplayType, (newVal: ToolbarDisplayType) => {
if (newVal !== 'none') {
changeDisplayType('editor');
interface IProps {
placeholder: string
groupID?: string
isMuted?: boolean
muteText?: string
enableInput?: boolean
enableAt?: boolean
enableTyping?: boolean
replyOrReference?: Record<string, any>
inputToolbarDisplayType: ToolbarDisplayType
}
});
function changeDisplayType(display: InputDisplayType) {
displayType.value = display;
if (display === 'audio') {
emits('changeToolbarDisplayType', 'none');
interface IEmits {
(e: 'changeToolbarDisplayType', displayType: ToolbarDisplayType): void
}
}
function changeToolbarDisplayType(displayType: ToolbarDisplayType) {
emits('changeToolbarDisplayType', displayType);
}
const { showDialog } = useUI()
const { tencentUserSig } = useAuthUser()
const emits = defineEmits<IEmits>()
const props = withDefaults(defineProps<IProps>(), {
placeholder: 'this is placeholder',
replyOrReference: () => ({}),
isMuted: true,
groupID: '',
muteText: '',
enableInput: true,
enableAt: true,
enableTyping: true,
inputToolbarDisplayType: 'none'
})
const onTyping = (inputContentEmpty: boolean, inputBlur: boolean) => {
sendTyping(inputContentEmpty, inputBlur);
};
const editor = ref()
const messageInputAtRef = ref()
const currentConversation = ref<IConversationModel>()
const isGroup = ref<boolean>(false)
const displayType = ref<InputDisplayType>('editor')
const featureConfig = TUIChatConfig.getFeatureConfig()
const isRenderVoice = ref<boolean>(featureConfig.InputVoice)
const isRenderEmojiPicker = ref<boolean>(
featureConfig.InputEmoji || featureConfig.InputStickers
)
const isRenderMore = ref<boolean>(
featureConfig.InputImage ||
featureConfig.InputVideo ||
featureConfig.InputEvaluation ||
featureConfig.InputQuickReplies
)
const onAt = (show: boolean) => {
messageInputAtRef?.value?.toggleAtList(show);
};
onMounted(() => {
TUIStore.watch(StoreName.CONV, {
currentConversation: onCurrentConversationUpdated
})
const onFocus = () => {
emits('changeToolbarDisplayType', 'none');
};
TUIStore.watch(StoreName.CHAT, {
quoteMessage: onQuoteMessageUpdated
})
})
const insertEmoji = (emoji: any) => {
editor?.value?.addEmoji && editor?.value?.addEmoji(emoji);
};
onUnmounted(() => {
TUIStore.unwatch(StoreName.CONV, {
currentConversation: onCurrentConversationUpdated
})
const insertAt = (atInfo: any) => {
editor?.value?.insertAt && editor?.value?.insertAt(atInfo);
};
TUIStore.unwatch(StoreName.CHAT, {
quoteMessage: onQuoteMessageUpdated
})
})
const onAtListOpen = () => {
editor?.value?.blur && editor?.value?.blur();
};
watch(
() => props.inputToolbarDisplayType,
(newVal: ToolbarDisplayType) => {
if (newVal !== 'none') {
changeDisplayType('editor')
}
}
)
const reEdit = (content: any) => {
editor?.value?.resetEditor();
editor?.value?.setEditorContent(content);
};
function onCurrentConversationUpdated(conversation: IConversationModel) {
currentConversation.value = conversation;
isGroup.value = currentConversation.value?.type === TUIChatEngine.TYPES.CONV_GROUP;
}
function onQuoteMessageUpdated(options?: { message: IMessageModel; type: string }) {
// switch text input mode when there is a quote message
if (options?.message && options?.type === 'quote') {
changeDisplayType('editor');
function changeDisplayType(display: InputDisplayType) {
displayType.value = display
if (display === 'audio') {
emits('changeToolbarDisplayType', 'none')
}
}
}
defineExpose({
insertEmoji,
reEdit,
});
/** 禁言数据获取 */
const getMuteTime = async (displayType: ToolbarDisplayType) => {
TUIGroupService.getGroupProfile({
groupID: props.groupID
}).then(res => {
// muteAllMembers
console.log(res.data.group.muteAllMembers)
if (res.data.group.muteAllMembers) {
// 禁言了
showDialog('提示', '当前群组已全员禁言', false)
} else {
// emits('changeToolbarDisplayType', displayType)
// 判断某个成员是不是禁言
}
})
}
const changeToolbarDisplayType = async (
displayType: ToolbarDisplayType
) => {
if (props.groupID) {
const res = await TUIGroupService.getGroupMemberProfile({
groupID: props.groupID,
userIDList: [tencentUserSig.value.userId]
})
if (res.data.memberList[0].role === 'Member') {
getMuteTime(displayType)
} else {
emits('changeToolbarDisplayType', displayType)
}
return
}
emits('changeToolbarDisplayType', displayType)
}
const onTyping = (inputContentEmpty: boolean, inputBlur: boolean) => {
sendTyping(inputContentEmpty, inputBlur)
}
const onAt = (show: boolean) => {
messageInputAtRef?.value?.toggleAtList(show)
}
const onFocus = () => {
emits('changeToolbarDisplayType', 'none')
}
const insertEmoji = (emoji: any) => {
editor?.value?.addEmoji && editor?.value?.addEmoji(emoji)
}
const insertAt = (atInfo: any) => {
editor?.value?.insertAt && editor?.value?.insertAt(atInfo)
}
const onAtListOpen = () => {
editor?.value?.blur && editor?.value?.blur()
}
const reEdit = (content: any) => {
editor?.value?.resetEditor()
editor?.value?.setEditorContent(content)
}
function onCurrentConversationUpdated(
conversation: IConversationModel
) {
currentConversation.value = conversation
isGroup.value =
currentConversation.value?.type === TUIChatEngine.TYPES.CONV_GROUP
}
function onQuoteMessageUpdated(options?: {
message: IMessageModel
type: string
}) {
// switch text input mode when there is a quote message
if (options?.message && options?.type === 'quote') {
changeDisplayType('editor')
}
}
defineExpose({
insertEmoji,
reEdit
})
</script>
<style scoped lang="scss">
@import "../../../assets/styles/common";
@import '../../../assets/styles/common';
:not(not) {
display: flex;
flex-direction: column;
min-width: 0;
box-sizing: border-box;
}
.message-input {
position: relative;
display: flex;
flex-direction: column;
border: none;
overflow: hidden;
background: #ffffff;
&-h5 {
padding: 10px 10px 15px;
}
&-editor {
flex: 1;
:not(not) {
display: flex;
flex-direction: column;
min-width: 0;
box-sizing: border-box;
}
.icon {
margin-left: 3px;
.message-input {
position: relative;
display: flex;
flex-direction: column;
border: none;
overflow: hidden;
background: #ffffff;
&-h5 {
padding: 10px 10px 15px;
}
&-editor {
flex: 1;
display: flex;
}
.icon {
margin-left: 3px;
}
&-wx-audio-open {
flex: 1;
}
}
&-wx-audio-open {
flex: 1;
.audio-main-content-line {
display: flex;
flex-direction: row;
align-items: center;
}
}
.audio-main-content-line {
display: flex;
flex-direction: row;
align-items: center;
}
</style>

View File

@@ -47,6 +47,7 @@
:class="'message-li ' + item.flow"
>
<MessageTimestamp
v-if="!isExitGroup(item.getMessageContent()?.text)"
:currTime="item.time"
:prevTime="index > 0 ? messageList[index - 1].time : 0"
/>
@@ -376,6 +377,17 @@
}
}
/** 更新用户群状态 */
const setUserAudioPlayed = async () => {
if (props.isGroup) {
const res = await TUIGroupService.getGroupMemberProfile({
groupID: props.groupID,
userIDList: [tencentUserSig.value.userId]
})
userType.value = res.data.memberList[0].role
}
}
onMounted(async () => {
// Retrieve the information about whether the audio has been played from localStorage
audioPlayedMapping.value =
@@ -401,13 +413,7 @@
isNotInGroup: boolean
*/
if (props.isGroup) {
const res = await TUIGroupService.getGroupMemberProfile({
groupID: props.groupID,
userIDList: [tencentUserSig.value.userId]
})
userType.value = res.data.memberList[0].role
}
setUserAudioPlayed()
})
onUnmounted(() => {
@@ -452,6 +458,7 @@
}
async function onMessageListUpdated(list: IMessageModel[]) {
setUserAudioPlayed()
observer?.disconnect()
messageList.value = list
.filter(message => !message.isDeleted)
@@ -914,6 +921,11 @@
audioPlayedMapping.value[messageID] = true
}
/** 是否包含【退出群组】文字 */
const isExitGroup = (str: string): boolean => {
return str?.includes('退出群组')
}
defineExpose({
oneByOneForwardMessage,
mergeForwardMessage,

View File

@@ -1,10 +1,10 @@
<template>
<div class="message-tip">
<div v-if="!isExitGroup" class="message-tip">
<span>{{ tipContent }}</span>
</div>
</template>
<script lang="ts" setup>
<script setup>
import { computed } from '../../../../adapter-vue'
const props = defineProps({
content: {
@@ -19,6 +19,12 @@
}
return props.content?.text || props.content?.custom || ''
})
/** 是否包含【退出群组】文字 */
const isExitGroup = computed(() => {
const str = props?.content?.text
return str?.includes('退出群组')
})
</script>
<style lang="scss" scoped>
@import '../../../../assets/styles/common';

View File

@@ -58,7 +58,6 @@
import TUIChatConfig from '../../config'
import AiRobotManager from '../../aiRobotManager'
import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant'
// uni-app conditional compilation will not run the following code
// #ifndef APP || APP-PLUS || MP || H5
import CopyManager from '../../utils/copy'

View File

@@ -4,7 +4,8 @@ import TUIChatEngine, {
StoreName,
TUITranslateService,
IConversationModel,
SendMessageParams
SendMessageParams,
TUIGroupService
} from '@tencentcloud/chat-uikit-engine-lite'
import { Toast, TOAST_TYPE } from '../../common/Toast/index'
import { isEnabledMessageReadReceiptGlobal } from '../utils/utils'
@@ -13,6 +14,8 @@ import { enableSampleTaskStatus } from '../../../utils/enableSampleTaskStatus'
import OfflinePushInfoManager, {
IOfflinePushInfoCreateParams
} from '../offlinePushInfoManager/index'
import { useAuthUser } from '../../../../composables/useAuthUser'
import { useUI } from '../../../../utils/use-ui'
export const sendMessageErrorCodeMap: Map<number, string> = new Map([
[3123, '文本包含本地审核拦截词'],
@@ -59,6 +62,8 @@ export const sendMessages = async (
messageList: ITipTapEditorContent[],
currentConversation: IConversationModel
) => {
const { tencentUserSig } = useAuthUser()
const { showDialog } = useUI()
// In case of messageJumping, the sent message is automatically cleared and returns to the bottom
if (TUIStore.getData(StoreName.CHAT, 'messageSource')) {
TUIStore.update(StoreName.CHAT, 'messageSource', undefined)
@@ -108,7 +113,36 @@ export const sendMessages = async (
} else {
try {
console.log('发送成功')
await TUIChatService.sendTextMessage(options, sendMessageOptions);
if (currentConversation?.groupProfile?.groupID) {
console.log(
'群发送==',
currentConversation?.groupProfile?.groupID
)
const res = await TUIGroupService.getGroupMemberProfile({
groupID: currentConversation?.groupProfile?.groupID,
userIDList: [tencentUserSig.value.userId]
})
if (res.data.memberList[0].role === 'Member') {
const g = await TUIGroupService.getGroupProfile({
groupID: currentConversation?.groupProfile?.groupID
})
if (g.data.group.muteAllMembers) {
showDialog('提示', '当前群组已全员禁言', false)
} else {
// 判断某个成员是不是禁言
}
} else {
await TUIChatService.sendTextMessage(
options,
sendMessageOptions
)
}
return
}
await TUIChatService.sendTextMessage(
options,
sendMessageOptions
)
} catch (err) {
console.log('发送失败,对方不是你的好友')
}