indexlink.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. <template>
  2. <div class="chat">
  3. <div :class="['tui-chat', !isPC && 'tui-chat-h5']">
  4. <div
  5. v-if="!currentConversationID"
  6. :class="['tui-chat-default', !isPC && 'tui-chat-h5-default']"
  7. >
  8. <slot />
  9. </div>
  10. <div v-if="currentConversationID" :class="['tui-chat', !isPC && 'tui-chat-h5']">
  11. <ChatHeader
  12. :class="[
  13. 'tui-chat-header',
  14. !isPC && 'tui-chat-H5-header',
  15. isUniFrameWork && 'tui-chat-uniapp-header',
  16. ]"
  17. :headerExtensionList="headerExtensionList"
  18. @closeChat="closeChat"
  19. />
  20. <Forward @toggleMultipleSelectMode="toggleMultipleSelectMode" />
  21. <MessageList
  22. ref="messageListRef"
  23. :class="['tui-chat-message-list', !isPC && 'tui-chat-h5-message-list']"
  24. :isGroup="isGroup"
  25. :groupID="groupID"
  26. :isNotInGroup="isNotInGroup"
  27. :isMultipleSelectMode="isMultipleSelectMode"
  28. @handleEditor="handleEditor"
  29. @closeInputToolBar="() => changeToolbarDisplayType('none')"
  30. @toggleMultipleSelectMode="toggleMultipleSelectMode"
  31. />
  32. <div
  33. v-if="isNotInGroup"
  34. :class="{
  35. 'tui-chat-leave-group': true,
  36. 'tui-chat-leave-group-mobile': isMobile,
  37. }"
  38. >
  39. {{ leaveGroupReasonText }}
  40. </div>
  41. <MultipleSelectPanel
  42. v-else-if="isMultipleSelectMode"
  43. @oneByOneForwardMessage="oneByOneForwardMessage"
  44. @mergeForwardMessage="mergeForwardMessage"
  45. @toggleMultipleSelectMode="toggleMultipleSelectMode"
  46. />
  47. <template v-else>
  48. <MessageInputToolbar
  49. v-if="isInputToolbarShow"
  50. :class="[
  51. 'tui-chat-message-input-toolbar',
  52. !isPC && 'tui-chat-h5-message-input-toolbar',
  53. isUniFrameWork && 'tui-chat-uni-message-input-toolbar',
  54. ]"
  55. :displayType="inputToolbarDisplayType"
  56. @insertEmoji="insertEmoji"
  57. @changeToolbarDisplayType="changeToolbarDisplayType"
  58. @scrollToLatestMessage="scrollToLatestMessage"
  59. />
  60. <MessageInput
  61. ref="messageInputRef"
  62. :class="[
  63. 'tui-chat-message-input',
  64. !isPC && 'tui-chat-h5-message-input',
  65. isUniFrameWork && 'tui-chat-uni-message-input',
  66. isWeChat && 'tui-chat-wx-message-input',
  67. ]"
  68. :enableAt="featureConfig.InputMention"
  69. :isMuted="false"
  70. :muteText="TUITranslateService.t('TUIChat.您已被管理员禁言')"
  71. :placeholder="TUITranslateService.t('TUIChat.请输入消息')"
  72. :inputToolbarDisplayType="inputToolbarDisplayType"
  73. @changeToolbarDisplayType="changeToolbarDisplayType"
  74. />
  75. </template>
  76. </div>
  77. <!-- Group Management -->
  78. <div
  79. v-if="
  80. !isNotInGroup && isUniFrameWork && isGroup && headerExtensionList.length > 0
  81. "
  82. class="group-profile"
  83. @click="handleGroup"
  84. >
  85. {{ headerExtensionList[0].text }}
  86. </div>
  87. </div>
  88. </div>
  89. </template>
  90. <script lang="ts" setup>
  91. import { ref, onMounted, onUnmounted, computed } from "../../adapter-vue";
  92. import TUIChatEngine, {
  93. TUITranslateService,
  94. TUIConversationService,
  95. TUIStore,
  96. StoreName,
  97. IMessageModel,
  98. IConversationModel,
  99. } from "@tencentcloud/chat-uikit-engine";
  100. import TUICore, { TUIConstants, ExtensionInfo } from "@tencentcloud/tui-core";
  101. import ChatHeader from "./chat-header/index.vue";
  102. import MessageList from "./message-list/index.vue";
  103. import MessageInput from "./message-input/index.vue";
  104. import MultipleSelectPanel from "./mulitple-select-panel/index.vue";
  105. import Forward from "./forward/index.vue";
  106. import MessageInputToolbar from "./message-input-toolbar/index.vue";
  107. import { isPC, isWeChat, isUniFrameWork, isMobile } from "../../utils/env";
  108. import { ToolbarDisplayType } from "../../interface";
  109. import TUIChatConfig from "./config";
  110. // @Start uniapp use Chat only
  111. import { onLoad, onUnload } from "@dcloudio/uni-app";
  112. import { initChat, logout } from "./entry-chat-only.ts";
  113. onLoad((options) => {
  114. initChat(options);
  115. });
  116. onUnload(() => {
  117. // Whether logout is decided by yourself when the page is unloaded. The default is false.
  118. logout(false)
  119. .then(() => {
  120. // Handle success result from promise.then when you set true.
  121. })
  122. .catch(() => {
  123. // handle error
  124. });
  125. });
  126. // @End uniapp use Chat only
  127. const emits = defineEmits(["closeChat"]);
  128. const groupID = ref(undefined);
  129. const isGroup = ref(false);
  130. const isNotInGroup = ref(false);
  131. const notInGroupReason = ref<number>();
  132. const currentConversationID = ref();
  133. const isMultipleSelectMode = ref(false);
  134. const inputToolbarDisplayType = ref<ToolbarDisplayType>("none");
  135. const messageInputRef = ref();
  136. const messageListRef = ref<InstanceType<typeof MessageList>>();
  137. const headerExtensionList = ref<ExtensionInfo[]>([]);
  138. const featureConfig = TUIChatConfig.getFeatureConfig();
  139. onMounted(() => {
  140. TUIStore.watch(StoreName.CONV, {
  141. currentConversationID: onCurrentConversationIDUpdate,
  142. currentConversation: onCurrentConversationUpdate,
  143. });
  144. });
  145. onUnmounted(() => {
  146. TUIStore.unwatch(StoreName.CONV, {
  147. currentConversationID: onCurrentConversationIDUpdate,
  148. currentConversation: onCurrentConversationUpdate,
  149. });
  150. reset();
  151. });
  152. const isInputToolbarShow = computed<boolean>(() => {
  153. return isUniFrameWork ? inputToolbarDisplayType.value !== "none" : true;
  154. });
  155. const leaveGroupReasonText = computed<string>(() => {
  156. let text = "";
  157. switch (notInGroupReason.value) {
  158. case 4:
  159. text = TUITranslateService.t("TUIChat.您已被管理员移出群聊");
  160. break;
  161. case 5:
  162. text = TUITranslateService.t("TUIChat.该群聊已被解散");
  163. break;
  164. case 8:
  165. text = TUITranslateService.t("TUIChat.您已退出该群聊");
  166. break;
  167. default:
  168. text = TUITranslateService.t("TUIChat.您已退出该群聊");
  169. break;
  170. }
  171. return text;
  172. });
  173. const reset = () => {
  174. TUIConversationService.switchConversation("");
  175. };
  176. const closeChat = (conversationID: string) => {
  177. emits("closeChat", conversationID);
  178. reset();
  179. };
  180. const insertEmoji = (emojiObj: object) => {
  181. messageInputRef.value?.insertEmoji(emojiObj);
  182. };
  183. const handleEditor = (message: IMessageModel, type: string) => {
  184. if (!message || !type) return;
  185. switch (type) {
  186. case "reference":
  187. // todo
  188. break;
  189. case "reply":
  190. // todo
  191. break;
  192. case "reedit":
  193. if (message?.payload?.text) {
  194. messageInputRef?.value?.reEdit(message?.payload?.text);
  195. }
  196. break;
  197. default:
  198. break;
  199. }
  200. };
  201. const handleGroup = () => {
  202. headerExtensionList.value[0].listener.onClicked({ groupID: groupID.value });
  203. };
  204. function changeToolbarDisplayType(type: ToolbarDisplayType) {
  205. inputToolbarDisplayType.value = inputToolbarDisplayType.value === type ? "none" : type;
  206. if (inputToolbarDisplayType.value !== "none" && isUniFrameWork) {
  207. uni.$emit("scroll-to-bottom");
  208. }
  209. }
  210. function scrollToLatestMessage() {
  211. messageListRef.value?.scrollToLatestMessage();
  212. }
  213. function toggleMultipleSelectMode(visible?: boolean) {
  214. isMultipleSelectMode.value =
  215. visible === undefined ? !isMultipleSelectMode.value : visible;
  216. }
  217. function mergeForwardMessage() {
  218. messageListRef.value?.mergeForwardMessage();
  219. }
  220. function oneByOneForwardMessage() {
  221. messageListRef.value?.oneByOneForwardMessage();
  222. }
  223. function onCurrentConversationUpdate(conversation: IConversationModel) {
  224. if (conversation?.operationType > 0) {
  225. headerExtensionList.value = [];
  226. isNotInGroup.value = true;
  227. /**
  228. * 4 - be removed from the group
  229. * 5 - group is dismissed
  230. * 8 - quit group
  231. */
  232. notInGroupReason.value = conversation?.operationType;
  233. } else {
  234. isNotInGroup.value = false;
  235. notInGroupReason.value = undefined;
  236. }
  237. }
  238. function onCurrentConversationIDUpdate(conversationID: string) {
  239. if (currentConversationID.value === conversationID) {
  240. return;
  241. }
  242. isGroup.value = false;
  243. let conversationType = TUIChatEngine.TYPES.CONV_C2C;
  244. if (conversationID.startsWith(TUIChatEngine.TYPES.CONV_GROUP)) {
  245. conversationType = TUIChatEngine.TYPES.CONV_GROUP;
  246. isGroup.value = true;
  247. groupID.value = conversationID.replace(TUIChatEngine.TYPES.CONV_GROUP, "");
  248. }
  249. headerExtensionList.value = [];
  250. currentConversationID.value = conversationID;
  251. isMultipleSelectMode.value = false;
  252. // Initialize chatType
  253. TUIChatConfig.setChatType(conversationType);
  254. // While converstaion change success, notify callkit and roomkit、or other components.
  255. TUICore.notifyEvent(
  256. TUIConstants.TUIChat.EVENT.CHAT_STATE_CHANGED,
  257. TUIConstants.TUIChat.EVENT_SUB_KEY.CHAT_OPENED,
  258. { groupID: groupID.value }
  259. );
  260. // The TUICustomerServicePlugin plugin determines if the current conversation is a customer service conversation, then sets chatType and activates the conversation.
  261. TUICore.callService({
  262. serviceName: TUIConstants.TUICustomerServicePlugin.SERVICE.NAME,
  263. method: TUIConstants.TUICustomerServicePlugin.SERVICE.METHOD.ACTIVE_CONVERSATION,
  264. params: { conversationID: conversationID },
  265. });
  266. // Get chat header extensions
  267. if (TUIChatConfig.getChatType() === TUIConstants.TUIChat.TYPE.GROUP) {
  268. headerExtensionList.value = TUICore.getExtensionList(
  269. TUIConstants.TUIChat.EXTENSION.CHAT_HEADER.EXT_ID
  270. );
  271. }
  272. }
  273. </script>
  274. <style scoped lang="scss" src="./style/index.scss"></style>