index.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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
  11. v-if="currentConversationID"
  12. :class="['tui-chat', !isPC && 'tui-chat-h5']"
  13. >
  14. <ChatHeader
  15. :class="[
  16. 'tui-chat-header',
  17. !isPC && 'tui-chat-H5-header',
  18. isUniFrameWork && 'tui-chat-uniapp-header',
  19. ]"
  20. @closeChat="closeChat"
  21. />
  22. <Forward />
  23. <MessageList
  24. :address="address"
  25. ref="messageListRef"
  26. :class="[
  27. 'tui-chat-message-list',
  28. !isPC && 'tui-chat-h5-message-list',
  29. ]"
  30. :isGroup="isGroup"
  31. :groupID="groupID"
  32. @handleEditor="handleEditor"
  33. @closeInputToolBar="() => changeToolbarDisplayType('none')"
  34. :infoData="infoData"
  35. />
  36. <!-- 兼容 uni 打包支付宝小程序 v-show 无效问题 -->
  37. <MessageInputToolbar
  38. v-if="isInputToolbarShow"
  39. :class="[
  40. 'tui-chat-message-input-toolbar',
  41. !isPC && 'tui-chat-h5-message-input-toolbar',
  42. isUniFrameWork && 'tui-chat-uni-message-input-toolbar',
  43. ]"
  44. :displayType="inputToolbarDisplayType"
  45. :infoData="infoData"
  46. @insertEmoji="insertEmoji"
  47. @changeToolbarDisplayType="changeToolbarDisplayType"
  48. @scrollToLatestMessage="scrollToLatestMessage"
  49. />
  50. <MessageInput
  51. ref="messageInputRef"
  52. :class="[
  53. 'tui-chat-message-input',
  54. !isPC && 'tui-chat-h5-message-input',
  55. isUniFrameWork && 'tui-chat-uni-message-input',
  56. isWeChat && 'tui-chat-wx-message-input',
  57. ]"
  58. :isMuted="false"
  59. :muteText="TUITranslateService.t('TUIChat.您已被管理员禁言')"
  60. :placeholder="TUITranslateService.t('TUIChat.请输入消息')"
  61. :inputToolbarDisplayType="inputToolbarDisplayType"
  62. @changeToolbarDisplayType="changeToolbarDisplayType"
  63. :infoData="infoData"
  64. />
  65. </div>
  66. <!-- 群组管理 -->
  67. <div
  68. v-if="isUniFrameWork && isGroup && groupManageExt"
  69. class="group-profile"
  70. @click="handleGroup"
  71. >
  72. {{ groupManageExt.text }}
  73. <!-- 更多 -->
  74. </div>
  75. </div>
  76. </div>
  77. </template>
  78. <script lang="ts" setup>
  79. import TUIChatEngine, {
  80. TUITranslateService,
  81. TUIConversationService,
  82. TUIStore,
  83. StoreName,
  84. IMessageModel,
  85. IConversationModel,
  86. } from "@tencentcloud/chat-uikit-engine";
  87. import TUICore, { TUIConstants, ExtensionInfo } from "@tencentcloud/tui-core";
  88. import { ref, onMounted, onUnmounted, computed } from "../../adapter-vue";
  89. import ChatHeader from "./chat-header/index.vue";
  90. import MessageList from "./message-list/index.vue";
  91. import MessageInput from "./message-input/index.vue";
  92. import Forward from "./forward/index.vue";
  93. import MessageInputToolbar from "./message-input-toolbar/index.vue";
  94. import { isPC, isWeChat, isUniFrameWork } from "../../utils/env";
  95. import { ToolbarDisplayType } from "../../interface";
  96. import TUIChatConfig from "./config";
  97. import config from "@/request/config";
  98. import { onLoad, onShow } from "@dcloudio/uni-app";
  99. const address = ref();
  100. onShow(() => {
  101. uni.$on("commitMapClick", function (res) {
  102. address.value = res;
  103. });
  104. });
  105. const emits = defineEmits(["closeChat"]);
  106. const messageInputRef = ref();
  107. const messageListRef = ref<InstanceType<typeof MessageList>>();
  108. const currentConversationID = ref();
  109. // 是否显示群组管理
  110. const isGroup = ref(false);
  111. const groupID = ref("");
  112. const groupManageExt = ref<ExtensionInfo | undefined>(undefined);
  113. const inputToolbarDisplayType = ref<ToolbarDisplayType>("none");
  114. // 沟通职位信息
  115. const infoData = ref({});
  116. // 获取地址栏参数
  117. function getParamValue(paramName) {
  118. const regExp = new RegExp("[?&]" + paramName + "=([^&#]*)");
  119. const results = regExp.exec(window.location.href);
  120. if (results) {
  121. return decodeURIComponent(results[1]);
  122. } else {
  123. return null;
  124. }
  125. }
  126. onMounted(() => {
  127. TUIStore.watch(StoreName.CONV, {
  128. currentConversation: onCurrentConversationUpdate,
  129. });
  130. initData();
  131. });
  132. const initData = () => {
  133. let data = {
  134. shopUserId: getParamValue("shopUserId"),
  135. userId: getParamValue("recruitUserId"),
  136. houseId: getParamValue("houseId"),
  137. };
  138. debugger
  139. let url = config.baseUrl + "/house/communicate/status";
  140. const header = {
  141. "Content-Type": "application/x-www-form-urlencoded",
  142. Authorization: uni.getStorageSync("token")
  143. ? uni.getStorageSync("token")
  144. : uni.getStorageSync("unitoken"),
  145. };
  146. uni.request({
  147. url: url,
  148. method: "GET",
  149. header: header,
  150. data: data,
  151. success: function (res) {
  152. infoData.value = res.data.data;
  153. },
  154. });
  155. };
  156. onUnmounted(() => {
  157. TUIStore.unwatch(StoreName.CONV, {
  158. currentConversation: onCurrentConversationUpdate,
  159. });
  160. reset();
  161. });
  162. function onCurrentConversationUpdate(conversation: IConversationModel) {
  163. if (currentConversationID.value === conversation?.conversationID) {
  164. return;
  165. }
  166. // TUIChat 每次切换会话,需要初始化 chatType;
  167. TUIChatConfig.setChatType(conversation?.type);
  168. // 由 TUICustomerServicePlugin 插件判断如果当前会话是客服会话,则设置 chatType 并激活会话。
  169. TUICore.callService({
  170. serviceName: TUIConstants.TUICustomerServicePlugin.SERVICE.NAME,
  171. method:
  172. TUIConstants.TUICustomerServicePlugin.SERVICE.METHOD.ACTIVE_CONVERSATION,
  173. params: { conversationID: conversation?.conversationID },
  174. });
  175. currentConversationID.value = conversation?.conversationID;
  176. isGroup.value = conversation?.type === TUIChatEngine.TYPES.CONV_GROUP;
  177. // while chat converstaion changed, notify callkit current conversation type, c2c or group
  178. TUICore.notifyEvent(
  179. TUIConstants.TUIChat.EVENT.CHAT_STATE_CHANGED,
  180. TUIConstants.TUIChat.EVENT_SUB_KEY.CHAT_OPENED,
  181. {
  182. groupID: conversation?.groupProfile?.groupID,
  183. }
  184. );
  185. if (
  186. isUniFrameWork &&
  187. isGroup.value &&
  188. groupID.value !== conversation?.groupProfile?.groupID
  189. ) {
  190. const extList = TUICore.getExtensionList(
  191. TUIConstants.TUIChat.EXTENSION.CHAT_HEADER.EXT_ID,
  192. {
  193. filterManageGroup: !isGroup.value,
  194. }
  195. );
  196. groupManageExt.value = extList[0];
  197. }
  198. if (isUniFrameWork && !isGroup.value) {
  199. groupManageExt.value = undefined;
  200. }
  201. groupID.value = conversation?.groupProfile?.groupID;
  202. }
  203. const isInputToolbarShow = computed<boolean>(() => {
  204. return isUniFrameWork ? inputToolbarDisplayType.value !== "none" : true;
  205. });
  206. // 清空当前 conversationID
  207. const reset = () => {
  208. TUIConversationService.switchConversation();
  209. };
  210. const closeChat = (conversationID: string) => {
  211. emits("closeChat", conversationID);
  212. reset();
  213. };
  214. const insertEmoji = (emojiObj: object) => {
  215. messageInputRef.value?.insertEmoji(emojiObj);
  216. };
  217. const handleEditor = (message: IMessageModel, type: string) => {
  218. if (!message || !type) return;
  219. switch (type) {
  220. case "reference":
  221. // todo
  222. break;
  223. case "reply":
  224. // todo
  225. break;
  226. case "reedit":
  227. if (message?.payload?.text) {
  228. messageInputRef?.value?.reEdit(message?.payload?.text);
  229. }
  230. break;
  231. default:
  232. break;
  233. }
  234. };
  235. const handleGroup = () => {
  236. groupManageExt.value.listener.onClicked({ groupID: groupID.value });
  237. };
  238. function changeToolbarDisplayType(type: ToolbarDisplayType) {
  239. inputToolbarDisplayType.value =
  240. inputToolbarDisplayType.value === type ? "none" : type;
  241. if (inputToolbarDisplayType.value !== "none" && isUniFrameWork) {
  242. uni.$emit("scroll-to-bottom");
  243. }
  244. }
  245. function scrollToLatestMessage() {
  246. messageListRef.value?.scrollToLatestMessage();
  247. }
  248. </script>
  249. <style scoped lang="scss" src="./style/index.scss"></style>