message-abstract-custom.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <template>
  2. <!-- 自定义消息 keyword 关键词搜寻 description, 所以此处仅对几个需要展示高亮 description 类型的自定义消息进行解析 -->
  3. <div :class="['message-abstract-custom']" @click.capture.stop>
  4. <template v-if="businessID === CHAT_MSG_CUSTOM_TYPE.SERVICE">
  5. <div :class="['service']">
  6. <h1 :class="['service-header']">
  7. <label :class="['service-header-title']">{{
  8. extensionJSON.title
  9. }}</label>
  10. <a
  11. v-if="extensionJSON.hyperlinks_text"
  12. :class="['service-header-link', 'link']"
  13. :href="extensionJSON.hyperlinks_text.value"
  14. target="view_window"
  15. >
  16. {{ extensionJSON.hyperlinks_text.key }}
  17. </a>
  18. </h1>
  19. <ul
  20. v-if="extensionJSON.item && extensionJSON.item.length > 0"
  21. :class="['service-list']"
  22. >
  23. <li
  24. v-for="(item, index) in extensionJSON.item"
  25. :key="index"
  26. :class="['service-list-item']"
  27. >
  28. <a
  29. v-if="isUrl(item.value)"
  30. :class="['service-list-item-link', 'link']"
  31. :href="item.value"
  32. target="view_window"
  33. >{{ item.key }}</a
  34. >
  35. <p v-else :class="['service-list-item-key']">
  36. {{ item.key }}
  37. </p>
  38. </li>
  39. </ul>
  40. <div :class="['service-description', 'description']">
  41. <span
  42. v-for="(contentItem, index) in descriptionForShow"
  43. :key="index"
  44. :class="[
  45. contentItem && contentItem.isHighlight ? 'highlight' : 'normal',
  46. ]"
  47. >
  48. {{ contentItem.text }}
  49. </span>
  50. </div>
  51. </div>
  52. </template>
  53. <template v-else-if="businessID === CHAT_MSG_CUSTOM_TYPE.EVALUATE">
  54. <div class="evaluate">
  55. <div :class="['evaluate-description', 'description']">
  56. <span
  57. v-for="(contentItem, index) in descriptionForShow"
  58. :key="index"
  59. :class="[
  60. contentItem && contentItem.isHighlight ? 'highlight' : 'normal',
  61. ]"
  62. >
  63. {{ contentItem.text }}
  64. </span>
  65. </div>
  66. <ul v-if="extensionJSON.score" class="evaluate-list">
  67. <li
  68. v-for="(item, index) in Math.max(extensionJSON.score, 0)"
  69. :key="index"
  70. class="evaluate-list-item"
  71. >
  72. <Icon :file="star" class="file-icon" />
  73. </li>
  74. </ul>
  75. <article>{{ extensionJSON.comment }}</article>
  76. </div>
  77. </template>
  78. <template v-else-if="businessID === CHAT_MSG_CUSTOM_TYPE.ORDER">
  79. <div class="order">
  80. <img class="order-image" :src="extensionJSON.imageUrl" alt="" />
  81. <main class="order-main">
  82. <h1 class="order-main-title">
  83. {{ extensionJSON.title }}
  84. </h1>
  85. <div :class="['order-main-description', 'description']">
  86. <span
  87. v-for="(contentItem, index) in descriptionForShow"
  88. :key="index"
  89. :class="[
  90. contentItem && contentItem.isHighlight ? 'highlight' : 'normal',
  91. ]"
  92. >
  93. {{ contentItem.text }}
  94. </span>
  95. </div>
  96. <span class="order-main-price">{{ extensionJSON.price }}</span>
  97. </main>
  98. </div>
  99. </template>
  100. <template v-else-if="businessID === CHAT_MSG_CUSTOM_TYPE.LINK">
  101. <div class="text-link">
  102. <div :class="['text-link-description', 'description']">
  103. <p>{{ extensionJSON.text }}</p>
  104. </div>
  105. <a :class="['link']" :href="extensionJSON.link" target="view_window">{{
  106. TUITranslateService.t("message.custom.查看详情>>")
  107. }}</a>
  108. </div>
  109. </template>
  110. <template v-else>
  111. <span>{{ defaultMessageContent }}</span>
  112. </template>
  113. </div>
  114. </template>
  115. <script setup lang="ts">
  116. import {
  117. TUITranslateService,
  118. IMessageModel,
  119. } from "@tencentcloud/chat-uikit-engine";
  120. import { ref, computed, withDefaults } from "../../../../../adapter-vue";
  121. import { CHAT_MSG_CUSTOM_TYPE } from "../../../../../constant";
  122. import { JSONToObject, isUrl } from "../../../../../utils/index";
  123. import Icon from "../../../../common/Icon.vue";
  124. import star from "../../../../../assets/icon/star-light.png";
  125. import { IHighlightContent } from "../../../type";
  126. import { ISearchResultListItem } from "../../../../../interface";
  127. interface IProps {
  128. contentText: Array<IHighlightContent>;
  129. message: IMessageModel | ISearchResultListItem;
  130. messageContent: Record<string, unknown> | undefined;
  131. }
  132. const props = withDefaults(defineProps<IProps>(), {
  133. contentText: () => [] as Array<IHighlightContent>,
  134. message: () => ({} as IMessageModel),
  135. messageContent: () => ({} as Record<string, unknown>),
  136. });
  137. const custom = ref<{ data?: string; description?: string; extension?: string }>(
  138. (props?.message as IMessageModel)?.payload
  139. );
  140. const extensionJSON = computed(() =>
  141. custom?.value?.data ? JSONToObject(custom.value.data) : custom?.value?.data
  142. );
  143. const businessID = computed(() => extensionJSON?.value?.businessID);
  144. const descriptionForShow = ref<Array<{ text: string; isHighlight: boolean }>>(
  145. props?.contentText
  146. );
  147. const defaultMessageContent = ref<string>(
  148. (props?.messageContent?.custom as string) || "[自定义消息]"
  149. );
  150. </script>
  151. <style scoped lang="scss">
  152. @import "../../../../../assets/styles/common";
  153. .message-abstract-custom {
  154. .service {
  155. .service-header {
  156. font-size: 14px;
  157. color: #000;
  158. }
  159. .service-list {
  160. .service-list-item {
  161. font-size: 14px;
  162. }
  163. }
  164. }
  165. .evaluate {
  166. .evaluate-list {
  167. padding: 5px 0;
  168. display: flex;
  169. flex-direction: row;
  170. .evaluate-item {
  171. padding: 0 2px;
  172. }
  173. }
  174. }
  175. .order {
  176. display: flex;
  177. .order-main {
  178. padding-left: 5px;
  179. .order-main-title {
  180. font-size: 14px;
  181. color: #000;
  182. }
  183. .order-main-description {
  184. font-family: PingFangSC-Regular, sans-serif;
  185. width: 145px;
  186. line-height: 17px;
  187. font-size: 14px;
  188. color: #999;
  189. letter-spacing: 0;
  190. margin-bottom: 6px;
  191. word-break: break-word;
  192. }
  193. .order-main-price {
  194. font-family: PingFangSC-Regular, sans-serif;
  195. line-height: 25px;
  196. color: #ff7201;
  197. }
  198. }
  199. .order-img {
  200. width: 67px;
  201. height: 67px;
  202. }
  203. }
  204. .link {
  205. font-size: 14px;
  206. color: #00b693;
  207. }
  208. .description {
  209. font-size: 14px;
  210. color: #000;
  211. .highlight {
  212. background-color: #007aff33;
  213. }
  214. .normal {
  215. font-size: 14px;
  216. color: #000;
  217. }
  218. }
  219. }
  220. </style>