Files
uniapp-im-shop/TUIKit/components/TUIChat/message-input-toolbar/red-envelope/index.vue
2026-01-08 01:44:39 +08:00

330 lines
9.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed, reactive, ref } from '../../../../adapter-vue'
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 { 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 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: ''
})
/** 监听积分输入值 */
const monitorPoints = computed(() => {
const data = {
valid: false,
message: ''
}
if (!formData.integral) {
data.valid = true
data.message = '请输入积分'
return data
}
if (Number(formData.integral) > 2000) {
data.valid = true
data.message = '积分不能大于2000'
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
})
const onDialogShow = () => {
console.log('弹出窗口')
formData.integral = ''
formData.title = ''
formData.num = ''
errorData.integralShow = false
errorData.numShow = false
}
const onDialogClose = () => {
console.log('关闭窗口')
}
const closeDialog = () => {
container?.value?.toggleDialogDisplay(false)
}
/** 监听输入 */
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>
<template>
<ToolbarItemContainer
ref="container"
needBottomPopup
:iconFile="evaluateIcon"
:iconWidth="isUniFrameWork ? '26px' : '20px'"
:iconHeight="isUniFrameWork ? '26px' : '20px'"
title="红包"
@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>
<uni-icons
type="closeempty"
color="#333333"
size="24"
@click.stop="closeDialog"
></uni-icons>
</view>
<!-- 红包个数 -->
<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"
:placeholder-style="placeholderStyle"
placeholder="恭喜发财,大吉大利"
/>
</view>
<!-- 底部显示 -->
<view class="bottom-box">
<view class="text-box">
<text>积分</text>
<text v-if="formData.integral">{{ formData.integral }}</text>
<text v-else>0.00</text>
</view>
<button class="btn" @click.stop="onSubmit">塞进红包</button>
</view>
</view>
</ToolbarItemContainer>
</template>
<style scoped lang="scss" src="./style/index.scss"></style>