index.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <div
  3. :class="[
  4. 'message-input-toolbar',
  5. 'message-input-toolbar-h5',
  6. 'message-input-toolbar-uni',
  7. ]"
  8. >
  9. <div v-if="props.displayType === 'emojiPicker'">
  10. <EmojiPickerDialog />
  11. </div>
  12. <div v-else>
  13. <swiper
  14. :class="['message-input-toolbar-swiper']"
  15. :indicator-dots="isSwiperIndicatorDotsEnable"
  16. :autoplay="false"
  17. :circular="false"
  18. >
  19. <swiper-item
  20. :class="[
  21. 'message-input-toolbar-list',
  22. 'message-input-toolbar-h5-list',
  23. 'message-input-toolbar-uni-list',
  24. ]"
  25. >
  26. <ImageUpload imageSourceType="camera" />
  27. <ImageUpload imageSourceType="album" />
  28. <Words
  29. v-if="currentExtensionList.length < 3"
  30. @onDialogPopupShowOrHide="handleSwiperDotShow"
  31. />
  32. </swiper-item>
  33. <swiper-item
  34. v-if="currentExtensionList[2] && currentExtensionList.length >= 3"
  35. :class="[
  36. 'message-input-toolbar-list',
  37. 'message-input-toolbar-h5-list',
  38. 'message-input-toolbar-uni-list',
  39. ]"
  40. >
  41. <div
  42. v-for="(extension, index) in currentExtensionList.slice(4)"
  43. :key="index"
  44. >
  45. <ToolbarItemContainer
  46. v-if="extension"
  47. :iconFile="genExtensionIcon(extension)"
  48. :title="genExtensionText(extension)"
  49. iconWidth="25px"
  50. iconHeight="25px"
  51. :needDialog="false"
  52. @onIconClick="onExtensionClick(extension)"
  53. />
  54. </div>
  55. <Evaluate
  56. v-if="currentExtensionList.length >= 4"
  57. @onDialogPopupShowOrHide="handleSwiperDotShow"
  58. />
  59. <Words
  60. v-if="currentExtensionList.length >= 3"
  61. @onDialogPopupShowOrHide="handleSwiperDotShow"
  62. />
  63. </swiper-item>
  64. </swiper>
  65. </div>
  66. <UserSelector
  67. ref="userSelectorRef"
  68. :type="selectorShowType"
  69. :currentConversation="currentConversation"
  70. :isGroup="isGroup"
  71. @submit="onUserSelectorSubmit"
  72. @cancel="onUserSelectorCancel"
  73. />
  74. </div>
  75. </template>
  76. <script setup lang="ts">
  77. import { ref, onUnmounted, onMounted } from "../../../adapter-vue";
  78. import TUIChatEngine, {
  79. IConversationModel,
  80. TUIStore,
  81. StoreName,
  82. } from "@tencentcloud/chat-uikit-engine";
  83. import TUICore, { ExtensionInfo, TUIConstants } from "@tencentcloud/tui-core";
  84. import ImageUpload from "./image-upload/index.vue";
  85. import VideoUpload from "./video-upload/index.vue";
  86. import OtgoingCAll from "./otgoing-call/index.vue";
  87. import Evaluate from "./evaluate/index.vue";
  88. import Words from "./words/index.vue";
  89. import ToolbarItemContainer from "./toolbar-item-container/index.vue";
  90. import EmojiPickerDialog from "./emoji-picker/emoji-picker-dialog.vue";
  91. import UserSelector from "./user-selector/index.vue";
  92. import TUIChatConfig from "../config";
  93. import { enableSampleTaskStatus } from "../../../utils/enableSampleTaskStatus";
  94. import { ToolbarDisplayType } from "../../../interface";
  95. interface IProps {
  96. displayType: ToolbarDisplayType;
  97. }
  98. const props = withDefaults(defineProps<IProps>(), {});
  99. const currentConversation = ref<IConversationModel>();
  100. const isGroup = ref<boolean>(false);
  101. const selectorShowType = ref<string>("");
  102. const userSelectorRef = ref();
  103. const currentUserSelectorExtension = ref<ExtensionInfo | null>();
  104. const currentExtensionList = ref<ExtensionInfo[]>([]);
  105. const isSwiperIndicatorDotsEnable = ref<boolean>(false);
  106. // extensions
  107. const extensionList: ExtensionInfo[] = [
  108. ...TUICore.getExtensionList(TUIConstants.TUIChat.EXTENSION.INPUT_MORE.EXT_ID),
  109. ];
  110. const getExtensionList = (conversationID: string) => {
  111. if (!conversationID) {
  112. // uniapp build ios app has null in last index need to filter
  113. return (currentExtensionList.value = extensionList.filter(
  114. (extension) => extension
  115. ));
  116. }
  117. const chatType = TUIChatConfig.getChatType();
  118. const options: any = {
  119. chatType,
  120. };
  121. // 向下兼容,callkit 没有chatType 判断时,使用 filterVoice、filterVideo 过滤
  122. if (chatType === "customerService") {
  123. options.filterVoice = true;
  124. options.filterVideo = true;
  125. enableSampleTaskStatus("customerService");
  126. }
  127. // uniapp build ios app has null in last index need to filter
  128. currentExtensionList.value = [
  129. ...TUICore.getExtensionList(
  130. TUIConstants.TUIChat.EXTENSION.INPUT_MORE.EXT_ID,
  131. options
  132. ),
  133. ].filter((extension) => extension);
  134. };
  135. const onCurrentConversationUpdate = (conversation: IConversationModel) => {
  136. if (
  137. conversation?.conversationID &&
  138. currentConversation.value?.conversationID !== conversation?.conversationID
  139. ) {
  140. getExtensionList(conversation?.conversationID);
  141. if (currentExtensionList.value.length > 2) {
  142. isSwiperIndicatorDotsEnable.value = true;
  143. }
  144. }
  145. currentConversation.value = conversation;
  146. if (currentConversation?.value?.type === TUIChatEngine.TYPES.CONV_GROUP) {
  147. isGroup.value = true;
  148. } else {
  149. isGroup.value = false;
  150. }
  151. };
  152. onMounted(() => {
  153. TUIStore.watch(StoreName.CONV, {
  154. currentConversation: onCurrentConversationUpdate,
  155. });
  156. });
  157. onUnmounted(() => {
  158. TUIStore.unwatch(StoreName.CONV, {
  159. currentConversation: onCurrentConversationUpdate,
  160. });
  161. });
  162. // handle extensions onclick
  163. const onExtensionClick = (extension: ExtensionInfo) => {
  164. // uniapp vue2 build wx lose listener proto
  165. const extensionModel = currentExtensionList.value.find(
  166. (targetExtension) => targetExtension?.data?.name === extension?.data?.name
  167. );
  168. switch (extensionModel?.data?.name) {
  169. case "voiceCall":
  170. onCallExtensionClicked(extensionModel, 1);
  171. break;
  172. case "videoCall":
  173. onCallExtensionClicked(extensionModel, 2);
  174. break;
  175. case "search":
  176. extensionModel?.listener?.onClicked?.();
  177. break;
  178. default:
  179. break;
  180. }
  181. };
  182. const onCallExtensionClicked = (extension: ExtensionInfo, callType: number) => {
  183. selectorShowType.value = extension?.data?.name;
  184. if (currentConversation?.value?.type === TUIChatEngine.TYPES.CONV_C2C) {
  185. extension?.listener?.onClicked?.({
  186. userIDList: [currentConversation?.value?.conversationID?.slice(3)],
  187. type: callType,
  188. });
  189. } else if (isGroup.value) {
  190. currentUserSelectorExtension.value = extension;
  191. userSelectorRef?.value?.toggleShow &&
  192. userSelectorRef.value.toggleShow(true);
  193. }
  194. };
  195. const genExtensionIcon = (extension: any) => {
  196. return extension?.icon;
  197. };
  198. const genExtensionText = (extension: any) => {
  199. return extension?.text;
  200. };
  201. const onUserSelectorSubmit = (selectedInfo: any) => {
  202. currentUserSelectorExtension.value?.listener?.onClicked?.(selectedInfo);
  203. currentUserSelectorExtension.value = null;
  204. };
  205. const onUserSelectorCancel = () => {
  206. currentUserSelectorExtension.value = null;
  207. };
  208. const handleSwiperDotShow = (showStatus: boolean) => {
  209. isSwiperIndicatorDotsEnable.value =
  210. currentExtensionList.value.length > 2 ? !showStatus : false;
  211. };
  212. </script>
  213. <script lang="ts">
  214. export default {
  215. options: {
  216. styleIsolation: "shared",
  217. },
  218. };
  219. </script>
  220. <style lang="scss">
  221. @import "../../../assets/styles/common";
  222. @import "./style/uni";
  223. </style>