index.vue 8.0 KB

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