发送红包接口有问题,添加群恢复

This commit is contained in:
bobobobo
2026-01-08 01:44:39 +08:00
parent 1634425c17
commit c0619ea4ec
20 changed files with 2070 additions and 1531 deletions

View File

@@ -213,7 +213,6 @@
)
}
TUIChatService.sendCustomMessage(
options as SendMessageParams,
sendMessageOptions

View File

@@ -59,10 +59,10 @@
v-if="featureConfig.InputQuickReplies"
@onDialogPopupShowOrHide="handleSwiperDotShow"
/>
<Evaluate
<!-- <Evaluate
v-if="featureConfig.InputEvaluation"
@onDialogPopupShowOrHide="handleSwiperDotShow"
/>
/> -->
<!-- 红包 -->
<RedEnvelope />
</template>

View File

@@ -3,17 +3,50 @@
import ToolbarItemContainer from '../toolbar-item-container/index.vue'
import custom from '../../../../assets/icon/red-packet.svg'
import { isUniFrameWork } from '../../../../utils/env'
import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant'
import TUIChatEngine, {
type IConversationModel,
type SendMessageParams,
SendMessageOptions,
StoreName,
TUIChatService,
TUIStore
} from '@tencentcloud/chat-uikit-engine-lite'
import { isEnabledMessageReadReceiptGlobal } from '../../utils/utils'
import OfflinePushInfoManager, {
type IOfflinePushInfoCreateParams
} from '../../offlinePushInfoManager'
import { getUserPayPwd } from '@/api/my-index'
import { useUI } from '@/utils/use-ui'
import { navigateTo } from '@/utils/router'
import { sendRedEnvelope } from '../../../../../api/tui-kit'
const placeholderStyle = `font-family: PingFang SC, PingFang SC; font-weight: 500; color: #666666; font-size: 32rpx; font-style: normal; text-transform: none;`
const { showDialog } = useUI()
const placeholderStyle = `font-family: PingFang SC, PingFang SC; font-weight: 500; color: #a9a9a9; font-size: 32rpx; font-style: normal; text-transform: none;`
const evaluateIcon = custom
/** 提示框 */
const message = ref()
const currentConversation = ref<IConversationModel>()
TUIStore.watch(StoreName.CONV, {
currentConversation: (conversation: IConversationModel) => {
currentConversation.value = conversation
}
})
const tixian = ref()
/** 错误提示 */
const errorData = reactive({
integralShow: false,
numShow: false,
color: '#f56c6c'
})
const container = ref()
const formData = reactive({
// 积分
integral: '',
// 红包数量
num: '',
// 红包标题
title: ''
})
@@ -27,16 +60,49 @@
if (!formData.integral) {
data.valid = true
data.message = '请输入积分'
message.value.open()
return data
}
if (Number(formData.integral) > 2000) {
data.valid = true
data.message = '积分不能大于2000'
message.value.open()
return data
}
return data
})
/** 监听是否是群组 */
const isGroup = computed(
() => currentConversation?.value?.type === 'GROUP'
)
/** 监听群人数 */
const memberCount = computed(
() => currentConversation?.value?.groupProfile?.memberCount
)
/** 监听红包个数 */
const monitorNum = computed(() => {
const data = {
valid: false,
message: ''
}
if (!formData.num) {
data.valid = true
data.message = '请输入红包个数'
return data
}
if (Number(formData.num) === 0) {
data.valid = true
data.message = '红包个数不能为 0'
return data
}
if (Number(formData.num) > memberCount.value) {
data.valid = true
data.message = '红包个数不能大于群人数'
return data
}
return data
})
@@ -44,6 +110,9 @@
console.log('弹出窗口')
formData.integral = ''
formData.title = ''
formData.num = ''
errorData.integralShow = false
errorData.numShow = false
}
const onDialogClose = () => {
@@ -54,9 +123,106 @@
container?.value?.toggleDialogDisplay(false)
}
const onSubmit = () => {
if (!formData.integral) return
console.log('确认')
/** 监听输入 */
const monitorInput = () => {
if (monitorPoints.value.valid) {
errorData.integralShow = true
return
}
errorData.integralShow = false
}
/** 监听红包个数输入值 */
const numInput = () => {
if (monitorNum.value.valid) {
errorData.numShow = true
return
}
errorData.numShow = false
}
const onSubmit = async () => {
if (isGroup.value) {
if (monitorNum.value.valid) {
errorData.numShow = true
return
}
}
if (monitorPoints.value.valid) {
errorData.integralShow = true
return
}
const res = await getUserPayPwd()
if (res?.data) {
tixian.value.open()
} else {
const show = await showDialog('提示', '请先设置支付密码')
if (show) {
navigateTo('/pages/my-index/wallet/edit-password', { type: 0 })
}
}
}
const pwdModalSubmit = async (e: number[]) => {
// 默认文本
const text = `${formData.title || '恭喜发财,大吉大利'}`
const payload = {
data: JSON.stringify({
businessID: CHAT_MSG_CUSTOM_TYPE.RED_ENVELOPE,
version: 1,
// 积分
integral: Number(formData.integral),
// 红包个数
num: Number(formData.num || '1'),
// 发送类型
type: currentConversation?.value?.type,
title: text
}),
description: text,
extension: text
}
const options = {
to:
currentConversation?.value?.groupProfile?.groupID ||
currentConversation?.value?.userProfile?.userID,
conversationType: currentConversation?.value?.type,
payload,
needReadReceipt: isEnabledMessageReadReceiptGlobal()
}
const offlinePushInfoCreateParams: IOfflinePushInfoCreateParams = {
conversation: currentConversation.value as IConversationModel,
payload: options.payload,
messageType: TUIChatEngine.TYPES.MSG_CUSTOM
}
const sendMessageOptions: SendMessageOptions = {
offlinePushInfo: OfflinePushInfoManager.create(
offlinePushInfoCreateParams
)
}
const isGroup = currentConversation?.value?.type === 'GROUP'
const data = {
password: e.join(''),
title: text,
packetType: isGroup ? 2 : 1,
receiverType: isGroup ? 2 : 1,
totalAmount: Number(formData.integral),
totalCount: Number(formData.num || '1')
}
try {
tixian.value.close()
await sendRedEnvelope(data)
TUIChatService.sendCustomMessage(
options as SendMessageParams,
sendMessageOptions
)
container?.value?.toggleDialogDisplay(false)
} catch (error) {
tixian.value.close()
}
}
</script>
@@ -71,6 +237,11 @@
@onDialogShow="onDialogShow"
@onDialogClose="onDialogClose"
>
<uu-pwdModal
ref="tixian"
class="pwd-modal"
@success="pwdModalSubmit"
></uu-pwdModal>
<view class="red-envelope">
<view class="top-title">
<text class="title">发红包</text>
@@ -81,22 +252,59 @@
@click.stop="closeDialog"
></uni-icons>
</view>
<!-- 输入框 -->
<view
:class="{ 'on-reminder': monitorPoints.valid }"
class="input-box"
>
<text>积分</text>
<input
v-model="formData.integral"
:placeholder-style="placeholderStyle"
confirm-type="done"
type="number"
placeholder="0.00"
@confirm="onSubmit"
/>
<!-- 红包个数 -->
<view v-if="isGroup" class="group-box">
<view
:class="{ 'on-reminder': errorData.numShow }"
class="input-box"
>
<view class="form-box">
<text>红包个数</text>
<view class="num-box">
<input
v-model="formData.num"
:placeholder-style="`font-family: PingFang SC, PingFang SC; font-weight: 500; color: ${
errorData.numShow ? '#f56c6c' : '#a9a9a9'
}; font-size: 32rpx; font-style: normal; text-transform: none;`"
confirm-type="done"
type="number"
placeholder="填写红包个数"
@input="numInput"
@confirm="onSubmit"
/>
<text></text>
</view>
</view>
<text v-if="errorData.numShow" class="error-text">
{{ monitorNum.message }}
</text>
</view>
<text class="num">本群共{{ memberCount }}</text>
</view>
<!-- 输入框 -->
<view
:class="{ 'on-reminder': errorData.integralShow }"
class="input-box"
>
<view class="form-box">
<text>积分</text>
<input
v-model="formData.integral"
:placeholder-style="`font-family: PingFang SC, PingFang SC; font-weight: 500; color: ${
errorData.integralShow ? '#f56c6c' : '#a9a9a9'
}; font-size: 32rpx; font-style: normal; text-transform: none;`"
confirm-type="done"
type="digit"
placeholder="0.00"
@input="monitorInput"
@confirm="onSubmit"
/>
</view>
<text v-if="errorData.integralShow" class="error-text">
{{ monitorPoints.message }}
</text>
</view>
<view class="input-box title-box">
<input
v-model="formData.title"
@@ -115,15 +323,6 @@
<button class="btn" @click.stop="onSubmit">塞进红包</button>
</view>
</view>
<!-- 提示框 -->
<uni-popup ref="message" type="message">
<uni-popup-message
type="error"
:message="monitorPoints.message"
:duration="2000"
></uni-popup-message>
</uni-popup>
</ToolbarItemContainer>
</template>

View File

@@ -5,7 +5,7 @@
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 26rpx;
margin-bottom: 30rpx;
.title {
font-size: 32rpx;
color: #1c1c1c;
@@ -13,13 +13,19 @@
}
.input-box {
margin-bottom: 26rpx;
margin-bottom: 60rpx;
background: #ffffff;
border-radius: 16rpx;
padding: 24rpx 34rpx;
display: flex;
justify-content: space-between;
align-items: center;
.form-box {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
text {
font-size: 32rpx;
color: #1c1c1c;
@@ -30,6 +36,16 @@
color: #1c1c1c;
text-align: right;
}
.num-box {
display: flex;
align-items: center;
justify-content: right;
text {
margin-left: 10rpx;
margin-bottom: 1rpx;
color: #1c1c1c;
}
}
}
.title-box {
@@ -73,11 +89,40 @@
// 警告提现
.on-reminder {
display: flex;
flex-direction: column;
align-items: flex-start;
text {
color: #f56c6c;
color: #f56c6c !important;
}
input {
color: #f56c6c;
}
.error-text {
margin-top: 10rpx;
font-size: 24rpx;
}
}
// 群红包个数
.group-box {
display: flex;
flex-direction: column;
.input-box {
margin-bottom: 10rpx;
}
.num {
margin-bottom: 30rpx;
margin-left: 34rpx;
font-size: 28rpx;
color: #5e5e5e;
}
}
}
.pwd-modal {
:deep(.modal) {
position: relative;
right: 20rpx;
}
}

View File

@@ -4,13 +4,13 @@
:class="[
'toolbar-item-container',
!isPC && 'toolbar-item-container-h5',
isUniFrameWork && 'toolbar-item-container-uni',
isUniFrameWork && 'toolbar-item-container-uni'
]"
>
<div
:class="[
'toolbar-item-container-icon',
isUniFrameWork && 'toolbar-item-container-uni-icon',
isUniFrameWork && 'toolbar-item-container-uni-icon'
]"
@click="toggleToolbarItem"
>
@@ -34,7 +34,7 @@
'toolbar-item-container-dialog',
isDark && 'toolbar-item-container-dialog-dark',
!isPC && 'toolbar-item-container-h5-dialog',
isUniFrameWork && 'toolbar-item-container-uni-dialog',
isUniFrameWork && 'toolbar-item-container-uni-dialog'
]"
>
<BottomPopup
@@ -51,88 +51,95 @@
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from '../../../../adapter-vue';
import { outsideClick } from '@tencentcloud/universal-api';
import Icon from '../../../common/Icon.vue';
import BottomPopup from '../../../common/BottomPopup/index.vue';
import { isPC, isUniFrameWork } from '../../../../utils/env';
import TUIChatConfig from '../../config';
import { ref, watch } from '../../../../adapter-vue'
import { outsideClick } from '@tencentcloud/universal-api'
import Icon from '../../../common/Icon.vue'
import BottomPopup from '../../../common/BottomPopup/index.vue'
import { isPC, isUniFrameWork } from '../../../../utils/env'
import TUIChatConfig from '../../config'
const props = defineProps({
iconFile: {
type: String,
required: true,
},
title: {
type: String,
default: '',
},
needDialog: {
type: Boolean,
default: true,
},
iconWidth: {
type: String,
default: '20px',
},
iconHeight: {
type: String,
default: '20px',
},
// Whether to display the bottom popup dialog on mobile devices
// Invalid on PC
needBottomPopup: {
type: Boolean,
default: false,
},
});
const props = defineProps({
iconFile: {
type: String,
required: true
},
title: {
type: String,
default: ''
},
needDialog: {
type: Boolean,
default: true
},
iconWidth: {
type: String,
default: '20px'
},
iconHeight: {
type: String,
default: '20px'
},
// Whether to display the bottom popup dialog on mobile devices
// Invalid on PC
needBottomPopup: {
type: Boolean,
default: false
}
})
const emits = defineEmits(['onIconClick', 'onDialogClose', 'onDialogShow']);
const emits = defineEmits([
'onIconClick',
'onDialogClose',
'onDialogShow'
])
const isDark = ref(TUIChatConfig.getTheme() === 'dark');
const showDialog = ref(false);
const toolbarItemRef = ref();
const dialogRef = ref();
const isDark = ref(TUIChatConfig.getTheme() === 'dark')
const showDialog = ref(false)
const toolbarItemRef = ref()
const dialogRef = ref()
watch(() => showDialog.value, (newVal) => {
if (!newVal) {
emits('onDialogClose', dialogRef);
} else {
emits('onDialogShow', dialogRef);
watch(
() => showDialog.value,
newVal => {
if (!newVal) {
emits('onDialogClose', dialogRef)
} else {
emits('onDialogShow', dialogRef)
}
}
)
const toggleToolbarItem = () => {
emits('onIconClick', dialogRef)
if (isPC) {
outsideClick.listen({
domRefs: toolbarItemRef.value,
handler: closeToolbarItem
})
}
if (!props.needDialog) {
return
}
toggleDialogDisplay(!showDialog.value)
}
});
const toggleToolbarItem = () => {
emits('onIconClick', dialogRef);
if (isPC) {
outsideClick.listen({
domRefs: toolbarItemRef.value,
handler: closeToolbarItem,
});
const closeToolbarItem = () => {
showDialog.value = false
}
if (!props.needDialog) {
return;
const toggleDialogDisplay = (showStatus: boolean) => {
if (showDialog.value === showStatus) {
return
}
showDialog.value = showStatus
}
toggleDialogDisplay(!showDialog.value);
};
const closeToolbarItem = () => {
showDialog.value = false;
};
const toggleDialogDisplay = (showStatus: boolean) => {
if (showDialog.value === showStatus) {
return;
const onPopupClose = () => {
showDialog.value = false
}
showDialog.value = showStatus;
};
const onPopupClose = () => {
showDialog.value = false;
};
defineExpose({
toggleDialogDisplay,
});
defineExpose({
toggleDialogDisplay
})
</script>
<style lang="scss" scoped src="./style/index.scss"></style>