index.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. :jobInfoData="jobInfoData"
  35. @emitStatus="emitStatus"
  36. />
  37. <!-- 兼容 uni 打包支付宝小程序 v-show 无效问题 -->
  38. <MessageInputToolbar
  39. v-if="isInputToolbarShow"
  40. :class="[
  41. 'tui-chat-message-input-toolbar',
  42. !isPC && 'tui-chat-h5-message-input-toolbar',
  43. isUniFrameWork && 'tui-chat-uni-message-input-toolbar',
  44. ]"
  45. :displayType="inputToolbarDisplayType"
  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. :jobInfoData="jobInfoData"
  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. console.log("11111", address.value); // 为 B 页面传过来的值
  104. });
  105. });
  106. const emits = defineEmits(["closeChat"]);
  107. const messageInputRef = ref();
  108. const messageListRef = ref<InstanceType<typeof MessageList>>();
  109. const currentConversationID = ref();
  110. // 是否显示群组管理
  111. const isGroup = ref(false);
  112. const groupID = ref("");
  113. const groupManageExt = ref<ExtensionInfo | undefined>(undefined);
  114. const inputToolbarDisplayType = ref<ToolbarDisplayType>("none");
  115. // 沟通职位信息
  116. const jobInfoData: any = ref({});
  117. function getQueryString(name) {
  118. var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
  119. var r = window.location.search.substr(1).match(reg);
  120. if (r != null) {
  121. return unescape(r[2]);
  122. }
  123. return null;
  124. }
  125. onMounted(() => {
  126. TUIStore.watch(StoreName.CONV, {
  127. currentConversation: onCurrentConversationUpdate,
  128. });
  129. initData();
  130. });
  131. onShow((option) => {
  132. console.log("option", option);
  133. });
  134. const initData = () => {
  135. console.log("window.location.search", window.location.search);
  136. const companyUserId = uni.getStorageSync("companyUserId");
  137. const recruitUserId = uni.getStorageSync("recruitUserId");
  138. let data = {
  139. companyUserId: getQueryString("companyUserId") || companyUserId,
  140. recruitUserId: getQueryString("recruitUserId") || recruitUserId,
  141. postId: getQueryString("postId"),
  142. };
  143. // 发送消息后本地存储文本
  144. let url = config.baseUrl + "/recruit/recruitCommunicate/status";
  145. const header = {
  146. "Content-Type": "application/x-www-form-urlencoded",
  147. Authorization: uni.getStorageSync("token")
  148. ? uni.getStorageSync("token")
  149. : uni.getStorageSync("unitoken"),
  150. };
  151. uni.request({
  152. url: url,
  153. method: "GET",
  154. header: header,
  155. data: data,
  156. success: function (res) {
  157. jobInfoData.value = res.data.data;
  158. },
  159. });
  160. };
  161. onUnmounted(() => {
  162. TUIStore.unwatch(StoreName.CONV, {
  163. currentConversation: onCurrentConversationUpdate,
  164. });
  165. reset();
  166. });
  167. function onCurrentConversationUpdate(conversation: IConversationModel) {
  168. if (currentConversationID.value === conversation?.conversationID) {
  169. return;
  170. }
  171. // TUIChat 每次切换会话,需要初始化 chatType;
  172. TUIChatConfig.setChatType(conversation?.type);
  173. // 由 TUICustomerServicePlugin 插件判断如果当前会话是客服会话,则设置 chatType 并激活会话。
  174. TUICore.callService({
  175. serviceName: TUIConstants.TUICustomerServicePlugin.SERVICE.NAME,
  176. method:
  177. TUIConstants.TUICustomerServicePlugin.SERVICE.METHOD.ACTIVE_CONVERSATION,
  178. params: { conversationID: conversation?.conversationID },
  179. });
  180. currentConversationID.value = conversation?.conversationID;
  181. isGroup.value = conversation?.type === TUIChatEngine.TYPES.CONV_GROUP;
  182. // while chat converstaion changed, notify callkit current conversation type, c2c or group
  183. TUICore.notifyEvent(
  184. TUIConstants.TUIChat.EVENT.CHAT_STATE_CHANGED,
  185. TUIConstants.TUIChat.EVENT_SUB_KEY.CHAT_OPENED,
  186. {
  187. groupID: conversation?.groupProfile?.groupID,
  188. }
  189. );
  190. if (
  191. isUniFrameWork &&
  192. isGroup.value &&
  193. groupID.value !== conversation?.groupProfile?.groupID
  194. ) {
  195. const extList = TUICore.getExtensionList(
  196. TUIConstants.TUIChat.EXTENSION.CHAT_HEADER.EXT_ID,
  197. {
  198. filterManageGroup: !isGroup.value,
  199. }
  200. );
  201. groupManageExt.value = extList[0];
  202. }
  203. if (isUniFrameWork && !isGroup.value) {
  204. groupManageExt.value = undefined;
  205. }
  206. groupID.value = conversation?.groupProfile?.groupID;
  207. }
  208. const isInputToolbarShow = computed<boolean>(() => {
  209. return isUniFrameWork ? inputToolbarDisplayType.value !== "none" : true;
  210. });
  211. // 清空当前 conversationID
  212. const reset = () => {
  213. TUIConversationService.switchConversation();
  214. };
  215. const closeChat = (conversationID: string) => {
  216. emits("closeChat", conversationID);
  217. reset();
  218. };
  219. const insertEmoji = (emojiObj: object) => {
  220. messageInputRef.value?.insertEmoji(emojiObj);
  221. };
  222. const handleEditor = (message: IMessageModel, type: string) => {
  223. if (!message || !type) return;
  224. switch (type) {
  225. case "reference":
  226. // todo
  227. break;
  228. case "reply":
  229. // todo
  230. break;
  231. case "reedit":
  232. if (message?.payload?.text) {
  233. messageInputRef?.value?.reEdit(message?.payload?.text);
  234. }
  235. break;
  236. default:
  237. break;
  238. }
  239. };
  240. const emitStatus = (status: Boolean) => {
  241. if (status) {
  242. initData();
  243. }
  244. };
  245. const handleGroup = () => {
  246. groupManageExt.value.listener.onClicked({ groupID: groupID.value });
  247. };
  248. function changeToolbarDisplayType(type: ToolbarDisplayType) {
  249. inputToolbarDisplayType.value =
  250. inputToolbarDisplayType.value === type ? "none" : type;
  251. if (inputToolbarDisplayType.value !== "none" && isUniFrameWork) {
  252. uni.$emit("scroll-to-bottom");
  253. }
  254. }
  255. function scrollToLatestMessage() {
  256. messageListRef.value?.scrollToLatestMessage();
  257. }
  258. </script>
  259. <style scoped lang="scss" src="./style/index.scss"></style>