红包需要添加样式

This commit is contained in:
cbb
2026-01-07 17:49:17 +08:00
parent 1c021cdd21
commit 1634425c17
5 changed files with 450 additions and 237 deletions

View File

@@ -14,27 +14,27 @@
<div <div
:class="[ :class="[
'evaluate-header-content', 'evaluate-header-content',
!isPC && 'evaluate-h5-header-content', !isPC && 'evaluate-h5-header-content'
]" ]"
> >
{{ TUITranslateService.t("Evaluate.请对本次服务进行评价") }} {{ TUITranslateService.t('Evaluate.请对本次服务进行评价') }}
</div> </div>
<div <div
v-if="!isPC" v-if="!isPC"
:class="[ :class="[
'evaluate-header-close', 'evaluate-header-close',
!isPC && 'evaluate-h5-header-close', !isPC && 'evaluate-h5-header-close'
]" ]"
@click.stop="closeDialog" @click.stop="closeDialog"
> >
{{ TUITranslateService.t("关闭") }} {{ TUITranslateService.t('关闭') }}
</div> </div>
</div> </div>
<div :class="['evaluate-content', !isPC && 'evaluate-h5-content']"> <div :class="['evaluate-content', !isPC && 'evaluate-h5-content']">
<ul <ul
:class="[ :class="[
'evaluate-content-list', 'evaluate-content-list',
!isPC && 'evaluate-h5-content-list', !isPC && 'evaluate-h5-content-list'
]" ]"
> >
<li <li
@@ -42,7 +42,7 @@
:key="index" :key="index"
:class="[ :class="[
'evaluate-content-list-item', 'evaluate-content-list-item',
!isPC && 'evaluate-h5-content-list-item', !isPC && 'evaluate-h5-content-list-item'
]" ]"
@click.stop="selectStar(index)" @click.stop="selectStar(index)"
> >
@@ -64,30 +64,35 @@
v-model="comment" v-model="comment"
:class="[ :class="[
'evaluate-content-text', 'evaluate-content-text',
!isPC && 'evaluate-h5-content-text', !isPC && 'evaluate-h5-content-text'
]" ]"
/> />
<div <div
:class="[ :class="[
'evaluate-content-button', 'evaluate-content-button',
!isPC && 'evaluate-h5-content-button', !isPC && 'evaluate-h5-content-button'
]" ]"
> >
<button <button
:class="['btn', isEvaluateValid ? 'btn-valid' : 'btn-invalid']" :class="[
'btn',
isEvaluateValid ? 'btn-valid' : 'btn-invalid'
]"
@click="submitEvaluate" @click="submitEvaluate"
> >
{{ TUITranslateService.t("Evaluate.提交评价") }} {{ TUITranslateService.t('Evaluate.提交评价') }}
</button> </button>
</div> </div>
</div> </div>
<div :class="['evaluate-adv', !isPC && 'evaluate-h5-adv']"> <div :class="['evaluate-adv', !isPC && 'evaluate-h5-adv']">
{{ TUITranslateService.t("Evaluate.服务评价工具") }} {{ TUITranslateService.t('Evaluate.服务评价工具') }}
{{ "(" + TUITranslateService.t("Evaluate.使用") }} {{ '(' + TUITranslateService.t('Evaluate.使用') }}
<a @click="openLink(Link.customMessage)"> <a @click="openLink(Link.customMessage)">
{{ TUITranslateService.t(`Evaluate.${Link.customMessage.label}`) }} {{
TUITranslateService.t(`Evaluate.${Link.customMessage.label}`)
}}
</a> </a>
{{ TUITranslateService.t("Evaluate.搭建") + ")" }} {{ TUITranslateService.t('Evaluate.搭建') + ')' }}
</div> </div>
</div> </div>
</ToolbarItemContainer> </ToolbarItemContainer>
@@ -100,110 +105,121 @@ import TUIChatEngine, {
IConversationModel, IConversationModel,
TUIChatService, TUIChatService,
SendMessageParams, SendMessageParams,
SendMessageOptions, SendMessageOptions
} from '@tencentcloud/chat-uikit-engine-lite'; } from '@tencentcloud/chat-uikit-engine-lite'
import { ref, computed } from '../../../../adapter-vue'; import { ref, computed } from '../../../../adapter-vue'
import ToolbarItemContainer from '../toolbar-item-container/index.vue'; import ToolbarItemContainer from '../toolbar-item-container/index.vue'
import custom from '../../../../assets/icon/custom.svg'; import custom from '../../../../assets/icon/custom.svg'
import Link from '../../../../utils/documentLink'; import Link from '../../../../utils/documentLink'
import Icon from '../../../common/Icon.vue'; import Icon from '../../../common/Icon.vue'
import starIcon from '../../../../assets/icon/star.png'; import starIcon from '../../../../assets/icon/star.png'
import starLightIcon from '../../../../assets/icon/star-light.png'; import starLightIcon from '../../../../assets/icon/star-light.png'
import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant'; import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant'
import { isPC, isH5, isUniFrameWork } from '../../../../utils/env'; import { isPC, isH5, isUniFrameWork } from '../../../../utils/env'
import { isEnabledMessageReadReceiptGlobal } from '../../utils/utils'; import { isEnabledMessageReadReceiptGlobal } from '../../utils/utils'
import OfflinePushInfoManager, { IOfflinePushInfoCreateParams } from '../../offlinePushInfoManager/index'; import OfflinePushInfoManager, {
IOfflinePushInfoCreateParams
} from '../../offlinePushInfoManager/index'
const evaluateIcon = custom; const evaluateIcon = custom
const props = defineProps({ const props = defineProps({
starTotal: { starTotal: {
type: Number, type: Number,
default: 5, default: 5
}, }
}); })
const emits = defineEmits(['onDialogPopupShowOrHide']); const emits = defineEmits(['onDialogPopupShowOrHide'])
const container = ref(); const container = ref()
const starList = ref<number>(props.starTotal); const starList = ref<number>(props.starTotal)
const currentStarIndex = ref<number>(-1); const currentStarIndex = ref<number>(-1)
const comment = ref(''); const comment = ref('')
const currentConversation = ref<IConversationModel>(); const currentConversation = ref<IConversationModel>()
TUIStore.watch(StoreName.CONV, { TUIStore.watch(StoreName.CONV, {
currentConversation: (conversation: IConversationModel) => { currentConversation: (conversation: IConversationModel) => {
currentConversation.value = conversation; currentConversation.value = conversation
}, }
}); })
const isEvaluateValid = computed(() => comment.value.length || currentStarIndex.value >= 0); const isEvaluateValid = computed(
() => comment.value.length || currentStarIndex.value >= 0
)
const onDialogShow = () => { const onDialogShow = () => {
emits('onDialogPopupShowOrHide', true); emits('onDialogPopupShowOrHide', true)
}; }
const onDialogClose = () => { const onDialogClose = () => {
resetEvaluate(); resetEvaluate()
emits('onDialogPopupShowOrHide', false); emits('onDialogPopupShowOrHide', false)
}; }
const openLink = () => { const openLink = () => {
if (isPC || isH5) { if (isPC || isH5) {
window.open(Link?.customMessage?.url); window.open(Link?.customMessage?.url)
}
} }
};
const closeDialog = () => { const closeDialog = () => {
container?.value?.toggleDialogDisplay(false); container?.value?.toggleDialogDisplay(false)
}; }
const resetEvaluate = () => { const resetEvaluate = () => {
currentStarIndex.value = -1; currentStarIndex.value = -1
comment.value = ''; comment.value = ''
}; }
const selectStar = (starIndex?: any) => { const selectStar = (starIndex?: any) => {
if (currentStarIndex.value === starIndex) { if (currentStarIndex.value === starIndex) {
currentStarIndex.value = currentStarIndex.value - 1; currentStarIndex.value = currentStarIndex.value - 1
} else { } else {
currentStarIndex.value = starIndex; currentStarIndex.value = starIndex
}
} }
};
const submitEvaluate = () => { const submitEvaluate = () => {
// The evaluate message must have at least one star or comment to be submitted. // The evaluate message must have at least one star or comment to be submitted.
if (currentStarIndex.value < 0 && !comment.value.length) { if (currentStarIndex.value < 0 && !comment.value.length) {
return; return
} }
const payload = { const payload = {
data: JSON.stringify({ data: JSON.stringify({
businessID: CHAT_MSG_CUSTOM_TYPE.EVALUATE, businessID: CHAT_MSG_CUSTOM_TYPE.EVALUATE,
version: 1, version: 1,
score: currentStarIndex.value + 1, score: currentStarIndex.value + 1,
comment: comment.value, comment: comment.value
}), }),
description: '对本次的服务评价', description: '对本次的服务评价',
extension: '对本次的服务评价', extension: '对本次的服务评价'
}; }
const options = { const options = {
to: to:
currentConversation?.value?.groupProfile?.groupID currentConversation?.value?.groupProfile?.groupID ||
|| currentConversation?.value?.userProfile?.userID, currentConversation?.value?.userProfile?.userID,
conversationType: currentConversation?.value?.type, conversationType: currentConversation?.value?.type,
payload, payload,
needReadReceipt: isEnabledMessageReadReceiptGlobal(), needReadReceipt: isEnabledMessageReadReceiptGlobal()
}; }
const offlinePushInfoCreateParams: IOfflinePushInfoCreateParams = { const offlinePushInfoCreateParams: IOfflinePushInfoCreateParams = {
conversation: currentConversation.value, conversation: currentConversation.value,
payload: options.payload, payload: options.payload,
messageType: TUIChatEngine.TYPES.MSG_CUSTOM, messageType: TUIChatEngine.TYPES.MSG_CUSTOM
}; }
const sendMessageOptions: SendMessageOptions = { const sendMessageOptions: SendMessageOptions = {
offlinePushInfo: OfflinePushInfoManager.create(offlinePushInfoCreateParams), offlinePushInfo: OfflinePushInfoManager.create(
}; offlinePushInfoCreateParams
TUIChatService.sendCustomMessage(options as SendMessageParams, sendMessageOptions); )
}
TUIChatService.sendCustomMessage(
options as SendMessageParams,
sendMessageOptions
)
// close dialog after submit evaluate // close dialog after submit evaluate
container?.value?.toggleDialogDisplay(false); container?.value?.toggleDialogDisplay(false)
}; }
</script> </script>
<style scoped lang="scss" src="./style/index.scss"></style> <style scoped lang="scss" src="./style/index.scss"></style>

View File

@@ -63,6 +63,7 @@
v-if="featureConfig.InputEvaluation" v-if="featureConfig.InputEvaluation"
@onDialogPopupShowOrHide="handleSwiperDotShow" @onDialogPopupShowOrHide="handleSwiperDotShow"
/> />
<!-- 红包 -->
<RedEnvelope /> <RedEnvelope />
</template> </template>
</swiper-item> </swiper-item>

View File

@@ -1,20 +1,130 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive, ref } from '../../../../adapter-vue'
import ToolbarItemContainer from '../toolbar-item-container/index.vue' import ToolbarItemContainer from '../toolbar-item-container/index.vue'
import custom from '../../../../assets/icon/red-packet.svg' import custom from '../../../../assets/icon/red-packet.svg'
import { isUniFrameWork } from '../../../../utils/env' import { isUniFrameWork } from '../../../../utils/env'
const evaluateIcon = custom; const placeholderStyle = `font-family: PingFang SC, PingFang SC; font-weight: 500; color: #666666; font-size: 32rpx; font-style: normal; text-transform: none;`
const evaluateIcon = custom
/** 提示框 */
const message = ref()
const container = ref()
const formData = reactive({
// 积分
integral: '',
// 红包标题
title: ''
})
/** 监听积分输入值 */
const monitorPoints = computed(() => {
const data = {
valid: false,
message: ''
}
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 onDialogShow = () => {
console.log('弹出窗口')
formData.integral = ''
formData.title = ''
}
const onDialogClose = () => {
console.log('关闭窗口')
}
const closeDialog = () => {
container?.value?.toggleDialogDisplay(false)
}
const onSubmit = () => {
if (!formData.integral) return
console.log('确认')
}
</script> </script>
<template> <template>
<ToolbarItemContainer <ToolbarItemContainer
ref="container"
needBottomPopup
:iconFile="evaluateIcon" :iconFile="evaluateIcon"
:iconWidth="isUniFrameWork ? '26px' : '20px'" :iconWidth="isUniFrameWork ? '26px' : '20px'"
:iconHeight="isUniFrameWork ? '26px' : '20px'" :iconHeight="isUniFrameWork ? '26px' : '20px'"
title="红包" title="红包"
@onDialogShow="onDialogShow"
@onDialogClose="onDialogClose"
> >
<view>弹出窗口</view> <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
: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>
<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>
<!-- 提示框 -->
<uni-popup ref="message" type="message">
<uni-popup-message
type="error"
:message="monitorPoints.message"
:duration="2000"
></uni-popup-message>
</uni-popup>
</ToolbarItemContainer> </ToolbarItemContainer>
</template> </template>
<style scoped lang="scss"></style> <style scoped lang="scss" src="./style/index.scss"></style>

View File

@@ -0,0 +1,83 @@
.red-envelope {
padding: 34rpx 24rpx;
background-color: #f7f7f7;
.top-title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 26rpx;
.title {
font-size: 32rpx;
color: #1c1c1c;
}
}
.input-box {
margin-bottom: 26rpx;
background: #ffffff;
border-radius: 16rpx;
padding: 24rpx 34rpx;
display: flex;
justify-content: space-between;
align-items: center;
text {
font-size: 32rpx;
color: #1c1c1c;
}
input {
width: 60%;
font-size: 32rpx;
color: #1c1c1c;
text-align: right;
}
}
.title-box {
input {
width: 100%;
text-align: left;
}
}
.bottom-box {
margin-top: 5vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.text-box {
display: flex;
align-items: baseline;
text {
font-weight: 600;
font-size: 28rpx;
color: #1c1c1c;
&:last-child {
font-size: 68rpx;
}
}
}
.btn {
margin-top: 28rpx;
font-size: 30rpx;
color: #ffffff;
background: #f56c6c;
width: 46%;
&::after {
display: none;
}
}
}
// 警告提现
.on-reminder {
text {
color: #f56c6c;
}
input {
color: #f56c6c;
}
}
}

View File

@@ -1,6 +1,8 @@
<template> <template>
<div class="custom"> <div class="custom">
<template v-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.SERVICE"> <template
v-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.SERVICE"
>
<div> <div>
<h1> <h1>
<label>{{ extension.title }}</label> <label>{{ extension.title }}</label>
@@ -8,18 +10,19 @@
v-if="extension.hyperlinks_text" v-if="extension.hyperlinks_text"
:href="extension.hyperlinks_text.value" :href="extension.hyperlinks_text.value"
target="view_window" target="view_window"
>{{ extension.hyperlinks_text.key }}</a> >
{{ extension.hyperlinks_text.key }}
</a>
</h1> </h1>
<ul v-if="extension.item && extension.item.length > 0"> <ul v-if="extension.item && extension.item.length > 0">
<li <li v-for="(item, index) in extension.item" :key="index">
v-for="(item, index) in extension.item"
:key="index"
>
<a <a
v-if="isUrl(item.value)" v-if="isUrl(item.value)"
:href="item.value" :href="item.value"
target="view_window" target="view_window"
>{{ item.key }}</a> >
{{ item.key }}
</a>
<p v-else> <p v-else>
{{ item.key }} {{ item.key }}
</p> </p>
@@ -28,32 +31,30 @@
<article>{{ extension.description }}</article> <article>{{ extension.description }}</article>
</div> </div>
</template> </template>
<template v-else-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.EVALUATE"> <template
v-else-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.EVALUATE"
>
<div class="evaluate"> <div class="evaluate">
<h1>{{ TUITranslateService.t("message.custom.对本次服务评价") }}</h1> <h1>
{{ TUITranslateService.t('message.custom.对本次服务评价') }}
</h1>
<ul class="evaluate-list"> <ul class="evaluate-list">
<li <li
v-for="(item, index) in Math.max(customData.score, 0)" v-for="(item, index) in Math.max(customData.score, 0)"
:key="index" :key="index"
class="evaluate-list-item" class="evaluate-list-item"
> >
<Icon <Icon :file="star" class="file-icon" />
:file="star"
class="file-icon"
/>
</li> </li>
</ul> </ul>
<article>{{ customData.comment }}</article> <article>{{ customData.comment }}</article>
</div> </div>
</template> </template>
<template v-else-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.ORDER"> <template
<div v-else-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.ORDER"
class="order"
@click="openLink(customData.link)"
>
<img
:src="customData.imageUrl"
> >
<div class="order" @click="openLink(customData.link)">
<img :src="customData.imageUrl" />
<main> <main>
<h1>{{ customData.title }}</h1> <h1>{{ customData.title }}</h1>
<p>{{ customData.description }}</p> <p>{{ customData.description }}</p>
@@ -61,15 +62,14 @@
</main> </main>
</div> </div>
</template> </template>
<template v-else-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.LINK"> <template
v-else-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.LINK"
>
<div class="textLink"> <div class="textLink">
<p>{{ customData.text }}</p> <p>{{ customData.text }}</p>
<a <a :href="customData.link" target="view_window">
:href="customData.link" {{ TUITranslateService.t('message.custom.查看详情>>') }}
target="view_window" </a>
>{{
TUITranslateService.t("message.custom.查看详情>>")
}}</a>
</div> </div>
</template> </template>
<template v-else> <template v-else>
@@ -79,46 +79,49 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { watchEffect, ref } from '../../../../adapter-vue'; import { watchEffect, ref } from '../../../../adapter-vue'
import { TUITranslateService, IMessageModel } from '@tencentcloud/chat-uikit-engine-lite'; import {
import { isUrl, JSONToObject } from '../../../../utils/index'; TUITranslateService,
import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant'; IMessageModel
import { ICustomMessagePayload } from '../../../../interface'; } from '@tencentcloud/chat-uikit-engine-lite'
import Icon from '../../../common/Icon.vue'; import { isUrl, JSONToObject } from '../../../../utils/index'
import star from '../../../../assets/icon/star-light.png'; import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant'
import { ICustomMessagePayload } from '../../../../interface'
import Icon from '../../../common/Icon.vue'
import star from '../../../../assets/icon/star-light.png'
interface Props { interface Props {
messageItem: IMessageModel; messageItem: IMessageModel
content: any; content: any
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
messageItem: undefined, messageItem: undefined,
content: undefined, content: undefined
}); })
const custom = ref(); const custom = ref()
const message = ref<IMessageModel>(); const message = ref<IMessageModel>()
const extension = ref(); const extension = ref()
const customData = ref<ICustomMessagePayload>({ const customData = ref<ICustomMessagePayload>({
businessID: '', businessID: ''
}); })
watchEffect(() => { watchEffect(() => {
custom.value = props.content; custom.value = props.content
message.value = props.messageItem; message.value = props.messageItem
const { payload } = props.messageItem; const { payload } = props.messageItem
customData.value = payload.data || ''; customData.value = payload.data || ''
customData.value = JSONToObject(payload.data); customData.value = JSONToObject(payload.data)
if (payload.data === CHAT_MSG_CUSTOM_TYPE.SERVICE) { if (payload.data === CHAT_MSG_CUSTOM_TYPE.SERVICE) {
extension.value = JSONToObject(payload.extension); extension.value = JSONToObject(payload.extension)
} }
}); })
const openLink = (url: any) => { const openLink = (url: any) => {
window.open(url); window.open(url)
}; }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../../../../assets/styles/common"; @import '../../../../assets/styles/common';
a { a {
color: #679ce1; color: #679ce1;