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

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

@@ -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```

View File

@@ -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>

View File

@@ -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>

View File

@@ -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,

View File

@@ -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';

View File

@@ -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'

View File

@@ -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('发送失败,对方不是你的好友')
} }

View File

@@ -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) {

View File

@@ -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.该用户不在群组内'

View File

@@ -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;

View File

@@ -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
})
}

View File

@@ -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'

View File

@@ -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>

View File

@@ -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' },

View File

@@ -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>

View File

@@ -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',