index.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <template>
  2. <ToolbarItemContainer
  3. ref="container"
  4. :iconFile="evaluateIcon"
  5. title="评价"
  6. :needBottomPopup="true"
  7. :iconWidth="isUniFrameWork ? '26px' : '20px'"
  8. :iconHeight="isUniFrameWork ? '26px' : '20px'"
  9. @onDialogShow="onDialogShow"
  10. @onDialogClose="onDialogClose"
  11. >
  12. <div :class="['evaluate', !isPC && 'evaluate-h5']">
  13. <div :class="['evaluate-header', !isPC && 'evaluate-h5-header']">
  14. <div
  15. :class="[
  16. 'evaluate-header-content',
  17. !isPC && 'evaluate-h5-header-content',
  18. ]"
  19. >
  20. {{ TUITranslateService.t("Evaluate.请对本次服务进行评价") }}
  21. </div>
  22. <div
  23. v-if="!isPC"
  24. :class="[
  25. 'evaluate-header-close',
  26. !isPC && 'evaluate-h5-header-close',
  27. ]"
  28. @click.stop="closeDialog"
  29. >
  30. {{ TUITranslateService.t("关闭") }}
  31. </div>
  32. </div>
  33. <div :class="['evaluate-content', !isPC && 'evaluate-h5-content']">
  34. <ul
  35. :class="[
  36. 'evaluate-content-list',
  37. !isPC && 'evaluate-h5-content-list',
  38. ]"
  39. >
  40. <li
  41. v-for="(item, index) in starList"
  42. :key="index"
  43. :class="[
  44. 'evaluate-content-list-item',
  45. !isPC && 'evaluate-h5-content-list-item',
  46. ]"
  47. @click.stop="selectStar(index)"
  48. >
  49. <Icon
  50. v-if="index <= currentStarIndex"
  51. :file="starLightIcon"
  52. :width="isPC ? '20px' : '30px'"
  53. :height="isPC ? '20px' : '30px'"
  54. />
  55. <Icon
  56. v-else
  57. :file="starIcon"
  58. :width="isPC ? '20px' : '30px'"
  59. :height="isPC ? '20px' : '30px'"
  60. />
  61. </li>
  62. </ul>
  63. <textarea
  64. v-model="comment"
  65. :class="[
  66. 'evaluate-content-text',
  67. !isPC && 'evaluate-h5-content-text',
  68. ]"
  69. />
  70. <div
  71. :class="[
  72. 'evaluate-content-button',
  73. !isPC && 'evaluate-h5-content-button',
  74. ]"
  75. >
  76. <button
  77. :class="['btn', isEvaluateValid ? 'btn-valid' : 'btn-invalid']"
  78. @click="submitEvaluate"
  79. >
  80. {{ TUITranslateService.t("Evaluate.提交评价") }}
  81. </button>
  82. </div>
  83. </div>
  84. <div :class="['evaluate-adv', !isPC && 'evaluate-h5-adv']">
  85. {{ TUITranslateService.t("Evaluate.服务评价工具") }}
  86. {{ "(" + TUITranslateService.t("Evaluate.使用") }}
  87. <a @click="openLink(Link.customMessage)">
  88. {{ TUITranslateService.t(`Evaluate.${Link.customMessage.label}`) }}
  89. </a>
  90. {{ TUITranslateService.t("Evaluate.搭建") + ")" }}
  91. </div>
  92. </div>
  93. </ToolbarItemContainer>
  94. </template>
  95. <script setup lang="ts">
  96. import TUIChatEngine, {
  97. TUITranslateService,
  98. TUIStore,
  99. StoreName,
  100. IConversationModel,
  101. TUIChatService,
  102. SendMessageParams,
  103. SendMessageOptions,
  104. } from '@tencentcloud/chat-uikit-engine';
  105. import { ref, computed } from '../../../../adapter-vue';
  106. import ToolbarItemContainer from '../toolbar-item-container/index.vue';
  107. import evaluateIcon from '../../../../assets/icon/evaluate.svg';
  108. import Link from '../../../../utils/documentLink';
  109. import Icon from '../../../common/Icon.vue';
  110. import starIcon from '../../../../assets/icon/star.png';
  111. import starLightIcon from '../../../../assets/icon/star-light.png';
  112. import { CHAT_MSG_CUSTOM_TYPE } from '../../../../constant';
  113. import { isPC, isH5, isUniFrameWork } from '../../../../utils/env';
  114. import { isEnabledMessageReadReceiptGlobal } from '../../utils/utils';
  115. import OfflinePushInfoManager, { IOfflinePushInfoCreateParams } from '../../offlinePushInfoManager/index';
  116. const props = defineProps({
  117. starTotal: {
  118. type: Number,
  119. default: 5,
  120. },
  121. });
  122. const emits = defineEmits(['onDialogPopupShowOrHide']);
  123. const container = ref();
  124. const starList = ref<number>(props.starTotal);
  125. const currentStarIndex = ref<number>(-1);
  126. const comment = ref('');
  127. const currentConversation = ref<IConversationModel>();
  128. TUIStore.watch(StoreName.CONV, {
  129. currentConversation: (conversation: IConversationModel) => {
  130. currentConversation.value = conversation;
  131. },
  132. });
  133. const isEvaluateValid = computed(() => comment.value.length || currentStarIndex.value >= 0);
  134. const onDialogShow = () => {
  135. emits('onDialogPopupShowOrHide', true);
  136. };
  137. const onDialogClose = () => {
  138. resetEvaluate();
  139. emits('onDialogPopupShowOrHide', false);
  140. };
  141. const openLink = () => {
  142. if (isPC || isH5) {
  143. window.open(Link?.customMessage?.url);
  144. }
  145. };
  146. const closeDialog = () => {
  147. container?.value?.toggleDialogDisplay(false);
  148. };
  149. const resetEvaluate = () => {
  150. currentStarIndex.value = -1;
  151. comment.value = '';
  152. };
  153. const selectStar = (starIndex?: any) => {
  154. if (currentStarIndex.value === starIndex) {
  155. currentStarIndex.value = currentStarIndex.value - 1;
  156. } else {
  157. currentStarIndex.value = starIndex;
  158. }
  159. };
  160. const submitEvaluate = () => {
  161. // The evaluate message must have at least one star or comment to be submitted.
  162. if (currentStarIndex.value < 0 && !comment.value.length) {
  163. return;
  164. }
  165. const payload = {
  166. data: JSON.stringify({
  167. businessID: CHAT_MSG_CUSTOM_TYPE.EVALUATE,
  168. version: 1,
  169. score: currentStarIndex.value + 1,
  170. comment: comment.value,
  171. }),
  172. description: '对本次的服务评价',
  173. extension: '对本次的服务评价',
  174. };
  175. const options = {
  176. to:
  177. currentConversation?.value?.groupProfile?.groupID
  178. || currentConversation?.value?.userProfile?.userID,
  179. conversationType: currentConversation?.value?.type,
  180. payload,
  181. needReadReceipt: isEnabledMessageReadReceiptGlobal(),
  182. };
  183. const offlinePushInfoCreateParams: IOfflinePushInfoCreateParams = {
  184. conversation: currentConversation.value,
  185. payload: options.payload,
  186. messageType: TUIChatEngine.TYPES.MSG_CUSTOM,
  187. };
  188. const sendMessageOptions: SendMessageOptions = {
  189. offlinePushInfo: OfflinePushInfoManager.create(offlinePushInfoCreateParams),
  190. };
  191. TUIChatService.sendCustomMessage(options as SendMessageParams, sendMessageOptions);
  192. // close dialog after submit evaluate
  193. container?.value?.toggleDialogDisplay(false);
  194. };
  195. </script>
  196. <style scoped lang="scss" src="./style/index.scss"></style>