搜索:判断某个成员是不是禁言
This commit is contained in:
@@ -17,6 +17,9 @@ unaipp多端im+会议+积分商城
|
|||||||
|
|
||||||
<!-- show-loading-more-no-more-view 去除没有更多 -->
|
<!-- show-loading-more-no-more-view 去除没有更多 -->
|
||||||
|
|
||||||
|
### UI 设计图地址
|
||||||
|
```https://lanhuapp.com/web/#/item/project/stage?pid=c8ab83e4-8e48-4e5b-87cc-620f9ce8512b&image_id=4236317e-0912-490c-91e1-6c816e7396af&tid=8050e376-3e33-43e8-bfdc-51ddb2c371b1```
|
||||||
|
|
||||||
### TUILiveKit 文档地址
|
### TUILiveKit 文档地址
|
||||||
|
|
||||||
```https://trtc.io/zh/document/60034?platform=ios&product=live```
|
```https://trtc.io/zh/document/60034?platform=ios&product=live```
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
]"
|
]"
|
||||||
:enableAt="featureConfig.InputMention"
|
:enableAt="featureConfig.InputMention"
|
||||||
:isMuted="false"
|
:isMuted="false"
|
||||||
|
:groupID="groupID"
|
||||||
:muteText="TUITranslateService.t('TUIChat.您已被管理员禁言')"
|
:muteText="TUITranslateService.t('TUIChat.您已被管理员禁言')"
|
||||||
:placeholder="TUITranslateService.t('TUIChat.请输入消息')"
|
:placeholder="TUITranslateService.t('TUIChat.请输入消息')"
|
||||||
:inputToolbarDisplayType="inputToolbarDisplayType"
|
:inputToolbarDisplayType="inputToolbarDisplayType"
|
||||||
@@ -361,8 +362,6 @@
|
|||||||
)
|
)
|
||||||
currentConversationID.value = conversationID
|
currentConversationID.value = conversationID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss" src="./style/index.scss"></style>
|
<style scoped lang="scss" src="./style/index.scss"></style>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<MessageInputAudio
|
<MessageInputAudio
|
||||||
v-if="(isWeChat || isApp) && isRenderVoice"
|
v-if="(isWeChat || isApp) && isRenderVoice"
|
||||||
:class="{
|
:class="{
|
||||||
'message-input-wx-audio-open': displayType === 'audio',
|
'message-input-wx-audio-open': displayType === 'audio'
|
||||||
}"
|
}"
|
||||||
:isEnableAudio="displayType === 'audio'"
|
:isEnableAudio="displayType === 'audio'"
|
||||||
@changeDisplayType="changeDisplayType"
|
@changeDisplayType="changeDisplayType"
|
||||||
@@ -49,192 +49,251 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<MessageQuote
|
<MessageQuote :style="{ minWidth: 0 }" :displayType="displayType" />
|
||||||
:style="{minWidth: 0}"
|
|
||||||
:displayType="displayType"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import TUIChatEngine, {
|
import TUIChatEngine, {
|
||||||
TUIStore,
|
TUIStore,
|
||||||
StoreName,
|
StoreName,
|
||||||
IMessageModel,
|
IMessageModel,
|
||||||
IConversationModel,
|
IConversationModel,
|
||||||
} from '@tencentcloud/chat-uikit-engine-lite';
|
TUIGroupService
|
||||||
import { ref, watch, onMounted, onUnmounted } from '../../../adapter-vue';
|
} from '@tencentcloud/chat-uikit-engine-lite'
|
||||||
import MessageInputEditor from './message-input-editor.vue';
|
import {
|
||||||
import MessageInputAt from './message-input-at/index.vue';
|
ref,
|
||||||
import MessageInputAudio from './message-input-audio.vue';
|
watch,
|
||||||
import MessageQuote from './message-input-quote/index.vue';
|
onMounted,
|
||||||
import Icon from '../../common/Icon.vue';
|
onUnmounted
|
||||||
import faceIcon from '../../../assets/icon/face-uni.png';
|
} from '../../../adapter-vue'
|
||||||
import moreIcon from '../../../assets/icon/more-uni.png';
|
import MessageInputEditor from './message-input-editor.vue'
|
||||||
import { isPC, isH5, isWeChat, isApp } from '../../../utils/env';
|
import MessageInputAt from './message-input-at/index.vue'
|
||||||
import { sendTyping } from '../utils/sendMessage';
|
import MessageInputAudio from './message-input-audio.vue'
|
||||||
import { ToolbarDisplayType, InputDisplayType } from '../../../interface';
|
import MessageQuote from './message-input-quote/index.vue'
|
||||||
import TUIChatConfig from '../config';
|
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 {
|
interface IProps {
|
||||||
placeholder: string;
|
placeholder: string
|
||||||
isMuted?: boolean;
|
groupID?: string
|
||||||
muteText?: string;
|
isMuted?: boolean
|
||||||
enableInput?: boolean;
|
muteText?: string
|
||||||
enableAt?: boolean;
|
enableInput?: boolean
|
||||||
enableTyping?: boolean;
|
enableAt?: boolean
|
||||||
replyOrReference?: Record<string, any>;
|
enableTyping?: boolean
|
||||||
inputToolbarDisplayType: ToolbarDisplayType;
|
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 IEmits {
|
||||||
|
(e: 'changeToolbarDisplayType', displayType: ToolbarDisplayType): void
|
||||||
function changeDisplayType(display: InputDisplayType) {
|
|
||||||
displayType.value = display;
|
|
||||||
if (display === 'audio') {
|
|
||||||
emits('changeToolbarDisplayType', 'none');
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function changeToolbarDisplayType(displayType: ToolbarDisplayType) {
|
const { showDialog } = useUI()
|
||||||
emits('changeToolbarDisplayType', displayType);
|
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) => {
|
const editor = ref()
|
||||||
sendTyping(inputContentEmpty, inputBlur);
|
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) => {
|
onMounted(() => {
|
||||||
messageInputAtRef?.value?.toggleAtList(show);
|
TUIStore.watch(StoreName.CONV, {
|
||||||
};
|
currentConversation: onCurrentConversationUpdated
|
||||||
|
})
|
||||||
|
|
||||||
const onFocus = () => {
|
TUIStore.watch(StoreName.CHAT, {
|
||||||
emits('changeToolbarDisplayType', 'none');
|
quoteMessage: onQuoteMessageUpdated
|
||||||
};
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const insertEmoji = (emoji: any) => {
|
onUnmounted(() => {
|
||||||
editor?.value?.addEmoji && editor?.value?.addEmoji(emoji);
|
TUIStore.unwatch(StoreName.CONV, {
|
||||||
};
|
currentConversation: onCurrentConversationUpdated
|
||||||
|
})
|
||||||
|
|
||||||
const insertAt = (atInfo: any) => {
|
TUIStore.unwatch(StoreName.CHAT, {
|
||||||
editor?.value?.insertAt && editor?.value?.insertAt(atInfo);
|
quoteMessage: onQuoteMessageUpdated
|
||||||
};
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const onAtListOpen = () => {
|
watch(
|
||||||
editor?.value?.blur && editor?.value?.blur();
|
() => props.inputToolbarDisplayType,
|
||||||
};
|
(newVal: ToolbarDisplayType) => {
|
||||||
|
if (newVal !== 'none') {
|
||||||
|
changeDisplayType('editor')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const reEdit = (content: any) => {
|
function changeDisplayType(display: InputDisplayType) {
|
||||||
editor?.value?.resetEditor();
|
displayType.value = display
|
||||||
editor?.value?.setEditorContent(content);
|
if (display === 'audio') {
|
||||||
};
|
emits('changeToolbarDisplayType', 'none')
|
||||||
|
}
|
||||||
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,
|
const getMuteTime = async (displayType: ToolbarDisplayType) => {
|
||||||
reEdit,
|
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>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import "../../../assets/styles/common";
|
@import '../../../assets/styles/common';
|
||||||
|
|
||||||
:not(not) {
|
: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;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.message-input {
|
||||||
margin-left: 3px;
|
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 {
|
.audio-main-content-line {
|
||||||
flex: 1;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.audio-main-content-line {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
:class="'message-li ' + item.flow"
|
:class="'message-li ' + item.flow"
|
||||||
>
|
>
|
||||||
<MessageTimestamp
|
<MessageTimestamp
|
||||||
|
v-if="!isExitGroup(item.getMessageContent()?.text)"
|
||||||
:currTime="item.time"
|
:currTime="item.time"
|
||||||
:prevTime="index > 0 ? messageList[index - 1].time : 0"
|
: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 () => {
|
onMounted(async () => {
|
||||||
// Retrieve the information about whether the audio has been played from localStorage
|
// Retrieve the information about whether the audio has been played from localStorage
|
||||||
audioPlayedMapping.value =
|
audioPlayedMapping.value =
|
||||||
@@ -401,13 +413,7 @@
|
|||||||
isNotInGroup: boolean
|
isNotInGroup: boolean
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (props.isGroup) {
|
setUserAudioPlayed()
|
||||||
const res = await TUIGroupService.getGroupMemberProfile({
|
|
||||||
groupID: props.groupID,
|
|
||||||
userIDList: [tencentUserSig.value.userId]
|
|
||||||
})
|
|
||||||
userType.value = res.data.memberList[0].role
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
@@ -452,6 +458,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function onMessageListUpdated(list: IMessageModel[]) {
|
async function onMessageListUpdated(list: IMessageModel[]) {
|
||||||
|
setUserAudioPlayed()
|
||||||
observer?.disconnect()
|
observer?.disconnect()
|
||||||
messageList.value = list
|
messageList.value = list
|
||||||
.filter(message => !message.isDeleted)
|
.filter(message => !message.isDeleted)
|
||||||
@@ -914,6 +921,11 @@
|
|||||||
audioPlayedMapping.value[messageID] = true
|
audioPlayedMapping.value[messageID] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 是否包含【退出群组】文字 */
|
||||||
|
const isExitGroup = (str: string): boolean => {
|
||||||
|
return str?.includes('退出群组')
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
oneByOneForwardMessage,
|
oneByOneForwardMessage,
|
||||||
mergeForwardMessage,
|
mergeForwardMessage,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="message-tip">
|
<div v-if="!isExitGroup" class="message-tip">
|
||||||
<span>{{ tipContent }}</span>
|
<span>{{ tipContent }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script setup>
|
||||||
import { computed } from '../../../../adapter-vue'
|
import { computed } from '../../../../adapter-vue'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
content: {
|
content: {
|
||||||
@@ -19,6 +19,12 @@
|
|||||||
}
|
}
|
||||||
return props.content?.text || props.content?.custom || ''
|
return props.content?.text || props.content?.custom || ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/** 是否包含【退出群组】文字 */
|
||||||
|
const isExitGroup = computed(() => {
|
||||||
|
const str = props?.content?.text
|
||||||
|
return str?.includes('退出群组')
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '../../../../assets/styles/common';
|
@import '../../../../assets/styles/common';
|
||||||
|
|||||||
@@ -58,7 +58,6 @@
|
|||||||
import TUIChatConfig from '../../config'
|
import TUIChatConfig from '../../config'
|
||||||
import AiRobotManager from '../../aiRobotManager'
|
import AiRobotManager from '../../aiRobotManager'
|
||||||
import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant'
|
import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant'
|
||||||
|
|
||||||
// uni-app conditional compilation will not run the following code
|
// uni-app conditional compilation will not run the following code
|
||||||
// #ifndef APP || APP-PLUS || MP || H5
|
// #ifndef APP || APP-PLUS || MP || H5
|
||||||
import CopyManager from '../../utils/copy'
|
import CopyManager from '../../utils/copy'
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import TUIChatEngine, {
|
|||||||
StoreName,
|
StoreName,
|
||||||
TUITranslateService,
|
TUITranslateService,
|
||||||
IConversationModel,
|
IConversationModel,
|
||||||
SendMessageParams
|
SendMessageParams,
|
||||||
|
TUIGroupService
|
||||||
} from '@tencentcloud/chat-uikit-engine-lite'
|
} from '@tencentcloud/chat-uikit-engine-lite'
|
||||||
import { Toast, TOAST_TYPE } from '../../common/Toast/index'
|
import { Toast, TOAST_TYPE } from '../../common/Toast/index'
|
||||||
import { isEnabledMessageReadReceiptGlobal } from '../utils/utils'
|
import { isEnabledMessageReadReceiptGlobal } from '../utils/utils'
|
||||||
@@ -13,6 +14,8 @@ import { enableSampleTaskStatus } from '../../../utils/enableSampleTaskStatus'
|
|||||||
import OfflinePushInfoManager, {
|
import OfflinePushInfoManager, {
|
||||||
IOfflinePushInfoCreateParams
|
IOfflinePushInfoCreateParams
|
||||||
} from '../offlinePushInfoManager/index'
|
} from '../offlinePushInfoManager/index'
|
||||||
|
import { useAuthUser } from '../../../../composables/useAuthUser'
|
||||||
|
import { useUI } from '../../../../utils/use-ui'
|
||||||
|
|
||||||
export const sendMessageErrorCodeMap: Map<number, string> = new Map([
|
export const sendMessageErrorCodeMap: Map<number, string> = new Map([
|
||||||
[3123, '文本包含本地审核拦截词'],
|
[3123, '文本包含本地审核拦截词'],
|
||||||
@@ -59,6 +62,8 @@ export const sendMessages = async (
|
|||||||
messageList: ITipTapEditorContent[],
|
messageList: ITipTapEditorContent[],
|
||||||
currentConversation: IConversationModel
|
currentConversation: IConversationModel
|
||||||
) => {
|
) => {
|
||||||
|
const { tencentUserSig } = useAuthUser()
|
||||||
|
const { showDialog } = useUI()
|
||||||
// In case of messageJumping, the sent message is automatically cleared and returns to the bottom
|
// In case of messageJumping, the sent message is automatically cleared and returns to the bottom
|
||||||
if (TUIStore.getData(StoreName.CHAT, 'messageSource')) {
|
if (TUIStore.getData(StoreName.CHAT, 'messageSource')) {
|
||||||
TUIStore.update(StoreName.CHAT, 'messageSource', undefined)
|
TUIStore.update(StoreName.CHAT, 'messageSource', undefined)
|
||||||
@@ -108,7 +113,36 @@ export const sendMessages = async (
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
console.log('发送成功')
|
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) {
|
} catch (err) {
|
||||||
console.log('发送失败,对方不是你的好友')
|
console.log('发送失败,对方不是你的好友')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -305,23 +305,31 @@
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
getRandomGroup().then(async (id: any) => {
|
getRandomGroup().then(async (id: any) => {
|
||||||
const res = await TUIGroupService.createGroup({
|
try {
|
||||||
...options,
|
const res = await TUIGroupService.createGroup({
|
||||||
groupID: id.data,
|
...options,
|
||||||
avatar: groupAvatar.value
|
groupID: id.data + '',
|
||||||
})
|
avatar: groupAvatar.value
|
||||||
const { type } = res.data.group
|
})
|
||||||
if (type === TUIChatEngine.TYPES.GRP_AVCHATROOM) {
|
const { type } = res.data.group
|
||||||
await TUIGroupService.joinGroup({
|
if (type === TUIChatEngine.TYPES.GRP_AVCHATROOM) {
|
||||||
groupID: res.data.group.groupID,
|
await TUIGroupService.joinGroup({
|
||||||
applyMessage: ''
|
groupID: res.data.group.groupID,
|
||||||
|
applyMessage: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
handleCompleteCreate(res.data.group)
|
||||||
|
Toast({
|
||||||
|
message: TUITranslateService.t('TUIGroup.群组创建成功'),
|
||||||
|
type: TOAST_TYPE.SUCCESS
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.log('创建失败 = ', err)
|
||||||
|
Toast({
|
||||||
|
message: '创建失败',
|
||||||
|
type: TOAST_TYPE.ERROR
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
handleCompleteCreate(res.data.group)
|
|
||||||
Toast({
|
|
||||||
message: TUITranslateService.t('TUIGroup.群组创建成功'),
|
|
||||||
type: TOAST_TYPE.SUCCESS
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.code === 10025) {
|
if (err.code === 10025) {
|
||||||
|
|||||||
@@ -255,8 +255,10 @@
|
|||||||
deleteImGroup,
|
deleteImGroup,
|
||||||
quitImGroup
|
quitImGroup
|
||||||
} from '../../../../api/tui-kit'
|
} from '../../../../api/tui-kit'
|
||||||
|
import { useAuthUser } from '../../../../composables/useAuthUser'
|
||||||
|
|
||||||
const { showLoading, hideLoading, showDialog } = useUI()
|
const { showLoading, hideLoading, showDialog } = useUI()
|
||||||
|
const { tencentUserSig } = useAuthUser()
|
||||||
|
|
||||||
const TUIGroupServer = Server.getInstance()
|
const TUIGroupServer = Server.getInstance()
|
||||||
const TUIConstants = TUIGroupServer.constants
|
const TUIConstants = TUIGroupServer.constants
|
||||||
@@ -307,7 +309,7 @@
|
|||||||
const delDialogShow = ref(false)
|
const delDialogShow = ref(false)
|
||||||
const groupMemberList = ref<IGroupMember[]>([])
|
const groupMemberList = ref<IGroupMember[]>([])
|
||||||
const deletedUserList = ref([])
|
const deletedUserList = ref([])
|
||||||
const currentGroup = ref<IGroupModel>()
|
const currentGroup = ref<any>()
|
||||||
const currentSelfRole = ref('')
|
const currentSelfRole = ref('')
|
||||||
const groupIDValue = ref<string>('')
|
const groupIDValue = ref<string>('')
|
||||||
const groupMemberOffset = ref<number | string>(0)
|
const groupMemberOffset = ref<number | string>(0)
|
||||||
@@ -324,10 +326,20 @@
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/** 更新用户群状态 */
|
||||||
|
const setUserAudioPlayed = async (group: any) => {
|
||||||
|
const res = await TUIGroupService.getGroupMemberProfile({
|
||||||
|
groupID: group.groupID,
|
||||||
|
userIDList: [tencentUserSig.value.userId]
|
||||||
|
})
|
||||||
|
currentGroup.value = group
|
||||||
|
currentGroup.value.selfInfo.role = res.data.memberList[0].role
|
||||||
|
}
|
||||||
|
|
||||||
TUIStore.watch(StoreName.GRP, {
|
TUIStore.watch(StoreName.GRP, {
|
||||||
currentGroup: (group: IGroupModel) => {
|
currentGroup: (group: IGroupModel) => {
|
||||||
if (group) {
|
if (group) {
|
||||||
currentGroup.value = group
|
setUserAudioPlayed(group)
|
||||||
currentSelfRole.value = currentGroup.value?.selfInfo?.role
|
currentSelfRole.value = currentGroup.value?.selfInfo?.role
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -393,7 +405,11 @@
|
|||||||
|
|
||||||
const isAdmin = computed(() => {
|
const isAdmin = computed(() => {
|
||||||
const userRole = currentGroup.value?.selfInfo?.role
|
const userRole = currentGroup.value?.selfInfo?.role
|
||||||
return userRole === TUIChatEngine.TYPES.GRP_MBR_ROLE_OWNER
|
|
||||||
|
return [
|
||||||
|
TUIChatEngine.TYPES.GRP_MBR_ROLE_OWNER,
|
||||||
|
TUIChatEngine.TYPES.GRP_MBR_ROLE_ADMIN
|
||||||
|
].includes(userRole)
|
||||||
})
|
})
|
||||||
|
|
||||||
const isWorkGroup = computed(() => {
|
const isWorkGroup = computed(() => {
|
||||||
@@ -749,9 +765,8 @@
|
|||||||
switch (transferType.value) {
|
switch (transferType.value) {
|
||||||
case 'add':
|
case 'add':
|
||||||
try {
|
try {
|
||||||
imMemberResponse = await TUIGroupService.getGroupMemberProfile(
|
imMemberResponse =
|
||||||
options
|
await TUIGroupService.getGroupMemberProfile(options)
|
||||||
)
|
|
||||||
transferList.value = transferList.value.filter(
|
transferList.value = transferList.value.filter(
|
||||||
(item: any) => item.userID !== imResponse.data[0]?.userID
|
(item: any) => item.userID !== imResponse.data[0]?.userID
|
||||||
)
|
)
|
||||||
@@ -777,9 +792,8 @@
|
|||||||
break
|
break
|
||||||
case 'remove':
|
case 'remove':
|
||||||
try {
|
try {
|
||||||
imResponse = await TUIGroupService.getGroupMemberProfile(
|
imResponse =
|
||||||
options
|
await TUIGroupService.getGroupMemberProfile(options)
|
||||||
)
|
|
||||||
if (imResponse.data.memberList.length === 0) {
|
if (imResponse.data.memberList.length === 0) {
|
||||||
const message = TUITranslateService.t(
|
const message = TUITranslateService.t(
|
||||||
'TUIGroup.该用户不在群组内'
|
'TUIGroup.该用户不在群组内'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="admin-main">
|
<div class="admin-main">
|
||||||
<view class="admin-box">
|
<view class="admin-box">
|
||||||
<div class="admin-manage">
|
<div v-if="!isAdmin" class="admin-manage">
|
||||||
<div class="admin-manage-header">
|
<div class="admin-manage-header">
|
||||||
{{ TUITranslateService.t(`TUIGroup.群管理员`) }}
|
{{ TUITranslateService.t(`TUIGroup.群管理员`) }}
|
||||||
</div>
|
</div>
|
||||||
@@ -112,11 +112,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {
|
import TUIChatEngine, {
|
||||||
TUITranslateService,
|
TUITranslateService,
|
||||||
IGroupModel
|
IGroupModel
|
||||||
} from '@tencentcloud/chat-uikit-engine-lite'
|
} from '@tencentcloud/chat-uikit-engine-lite'
|
||||||
import { watchEffect, ref } from '../../../adapter-vue'
|
import { watchEffect, ref, computed } from '../../../adapter-vue'
|
||||||
import Slider from '../../common/Slider/index.vue'
|
import Slider from '../../common/Slider/index.vue'
|
||||||
import Icon from '../../common/Icon.vue'
|
import Icon from '../../common/Icon.vue'
|
||||||
import plusSVG from '../../../assets/icon/plus.svg'
|
import plusSVG from '../../../assets/icon/plus.svg'
|
||||||
@@ -156,6 +156,13 @@
|
|||||||
currentGroupAdmin.value = props.currentGroup
|
currentGroupAdmin.value = props.currentGroup
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isAdmin = computed(() => {
|
||||||
|
return (
|
||||||
|
props.currentGroup?.selfInfo?.role ===
|
||||||
|
TUIChatEngine.TYPES.GRP_MBR_ROLE_ADMIN
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
const emits = defineEmits([
|
const emits = defineEmits([
|
||||||
'addAdmin',
|
'addAdmin',
|
||||||
'removeAdmin',
|
'removeAdmin',
|
||||||
@@ -287,7 +294,7 @@
|
|||||||
|
|
||||||
.admin-mute-all {
|
.admin-mute-all {
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
padding: 20rpx ;
|
padding: 20rpx;
|
||||||
border-bottom: 1px solid #e8e8e9;
|
border-bottom: 1px solid #e8e8e9;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|||||||
@@ -110,7 +110,9 @@ export const imAddLive = (data, method = 'post') => {
|
|||||||
export const imDataStartLive = roomId => {
|
export const imDataStartLive = roomId => {
|
||||||
return http({
|
return http({
|
||||||
url: `/api/service/imLiveRoom/start/${roomId}`,
|
url: `/api/service/imLiveRoom/start/${roomId}`,
|
||||||
method: 'post'
|
method: 'post',
|
||||||
|
/** 错误是否返回上一页 */
|
||||||
|
isErrorBack: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,3 +182,12 @@ export const getLiveId = () => {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 直播间列表 */
|
||||||
|
export const getLiveRoomList = data => {
|
||||||
|
return http({
|
||||||
|
url: `/api/service/imLiveRoom/list/all`,
|
||||||
|
method: 'get',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
import { navigateTo } from '@/utils/router'
|
import { navigateTo } from '@/utils/router'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useUI } from '@/utils/use-ui'
|
import { useUI } from '@/utils/use-ui'
|
||||||
|
import { getLiveRoomList } from '../../api/tui-kit'
|
||||||
|
|
||||||
const { showDialog } = useUI()
|
const { showDialog } = useUI()
|
||||||
|
|
||||||
@@ -51,6 +52,12 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (item === 'liveStream') {
|
if (item === 'liveStream') {
|
||||||
|
getLiveRoomList({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 15
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
let url = ''
|
let url = ''
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
url = '/pages/discover/livelist/index'
|
url = '/pages/discover/livelist/index'
|
||||||
|
|||||||
@@ -60,13 +60,13 @@
|
|||||||
>
|
>
|
||||||
第三方客服
|
第三方客服
|
||||||
</button>
|
</button>
|
||||||
<button
|
<!-- <button
|
||||||
v-if="customerData?.imUserId"
|
v-if="customerData?.imUserId"
|
||||||
class="btn"
|
class="btn"
|
||||||
@click="handleSwitchConversation"
|
@click="handleSwitchConversation"
|
||||||
>
|
>
|
||||||
APP客服
|
APP客服
|
||||||
</button>
|
</button> -->
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
{ name: '拼单获得', id: '1', state: '+', color: '#2ecc71' },
|
{ name: '拼单获得', id: '1', state: '+', color: '#2ecc71' },
|
||||||
{ name: '消费', id: '2', state: '-', color: '#e74c3c' },
|
{ name: '消费', id: '2', state: '-', color: '#e74c3c' },
|
||||||
{ name: '退款', id: '3', state: '-', color: '#f39c12' },
|
{ name: '退款', id: '3', state: '-', color: '#f39c12' },
|
||||||
{ name: '系统赠送', id: '4', state: '+', color: '#2ecc71' },
|
{ name: '推荐奖励', id: '4', state: '+', color: '#2ecc71' },
|
||||||
{ name: '系统扣除', id: '5', state: '-', color: '#e74c3c' },
|
{ name: '系统扣除', id: '5', state: '-', color: '#e74c3c' },
|
||||||
{ name: '签到', id: '6', state: '+', color: '#2ecc71' },
|
{ name: '签到', id: '6', state: '+', color: '#2ecc71' },
|
||||||
{ name: '提现', id: '7', state: '-', color: '#e74c3c' },
|
{ name: '提现', id: '7', state: '-', color: '#e74c3c' },
|
||||||
|
|||||||
@@ -58,7 +58,11 @@
|
|||||||
{{
|
{{
|
||||||
viewData.status === 1
|
viewData.status === 1
|
||||||
? viewData.commissionAmount
|
? viewData.commissionAmount
|
||||||
: (viewData.commissionRate / 100) * viewData.groupPrice
|
: Math.trunc(
|
||||||
|
(viewData.commissionRate / 100) *
|
||||||
|
viewData.groupPrice *
|
||||||
|
100
|
||||||
|
) / 100
|
||||||
}}
|
}}
|
||||||
</text>
|
</text>
|
||||||
<text>积分</text>
|
<text>积分</text>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useUserStore } from '../stores/user'
|
import { useUserStore } from '../stores/user'
|
||||||
|
import { navigateBack } from './router'
|
||||||
import { getToken } from './storage'
|
import { getToken } from './storage'
|
||||||
|
|
||||||
const BASE_URL = import.meta.env.VITE_SYSTEM_URL
|
const BASE_URL = import.meta.env.VITE_SYSTEM_URL
|
||||||
@@ -55,7 +56,11 @@ const request = options => {
|
|||||||
resolve(response.data)
|
resolve(response.data)
|
||||||
} else {
|
} else {
|
||||||
// 注意:这里也要 reject,否则调用方无法感知失败
|
// 注意:这里也要 reject,否则调用方无法感知失败
|
||||||
const err = handleError(response.data.code, response.data)
|
const err = handleError(
|
||||||
|
response.data.code,
|
||||||
|
response.data,
|
||||||
|
options?.isErrorBack
|
||||||
|
)
|
||||||
reject(err || response.data)
|
reject(err || response.data)
|
||||||
// handleError(response.data.code, response.data)
|
// handleError(response.data.code, response.data)
|
||||||
}
|
}
|
||||||
@@ -63,7 +68,11 @@ const request = options => {
|
|||||||
// 状态码错误处理
|
// 状态码错误处理
|
||||||
// handleError(response.statusCode, response.data)
|
// handleError(response.statusCode, response.data)
|
||||||
// reject(response)
|
// reject(response)
|
||||||
const err = handleError(response.statusCode, response.data)
|
const err = handleError(
|
||||||
|
response.statusCode,
|
||||||
|
response.data,
|
||||||
|
options?.isErrorBack
|
||||||
|
)
|
||||||
reject(err || response)
|
reject(err || response)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -91,8 +100,9 @@ const request = options => {
|
|||||||
* 错误处理函数
|
* 错误处理函数
|
||||||
* @param {Number} statusCode HTTP状态码
|
* @param {Number} statusCode HTTP状态码
|
||||||
* @param {Object} data 响应数据
|
* @param {Object} data 响应数据
|
||||||
|
* @param {Boolean} isErrorBack 是否返回上一页
|
||||||
*/
|
*/
|
||||||
const handleError = (statusCode, data) => {
|
const handleError = (statusCode, data, isErrorBack) => {
|
||||||
// 如果是 401 且正在处理中,直接返回(避免重复处理)
|
// 如果是 401 且正在处理中,直接返回(避免重复处理)
|
||||||
if (statusCode === 401) {
|
if (statusCode === 401) {
|
||||||
if (isHandling401) {
|
if (isHandling401) {
|
||||||
@@ -156,6 +166,9 @@ const handleError = (statusCode, data) => {
|
|||||||
showCancel: false,
|
showCancel: false,
|
||||||
confirmText: '确定'
|
confirmText: '确定'
|
||||||
})
|
})
|
||||||
|
if (isErrorBack) {
|
||||||
|
navigateBack()
|
||||||
|
}
|
||||||
// uni.showToast({
|
// uni.showToast({
|
||||||
// title: data.msg || '服务器内部错误',
|
// title: data.msg || '服务器内部错误',
|
||||||
// icon: 'none',
|
// icon: 'none',
|
||||||
|
|||||||
Reference in New Issue
Block a user