index.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. const companyUserId = uni.getStorageSync("companyUserId");
  136. const recruitUserId = uni.getStorageSync("recruitUserId");
  137. let data = {
  138. companyUserId: getQueryString("companyUserId") || companyUserId,
  139. recruitUserId: getQueryString("recruitUserId") || recruitUserId,
  140. postId: getQueryString("postId"),
  141. };
  142. // 发送消息后本地存储文本
  143. let url = config.baseUrl + "/recruit/recruitCommunicate/status";
  144. const header = {
  145. "Content-Type": "application/x-www-form-urlencoded",
  146. Authorization: uni.getStorageSync("token")
  147. ? uni.getStorageSync("token")
  148. : uni.getStorageSync("unitoken"),
  149. };
  150. uni.request({
  151. url: url,
  152. method: "GET",
  153. header: header,
  154. data: data,
  155. success: function (res) {
  156. jobInfoData.value = res.data.data;
  157. },
  158. });
  159. };
  160. onUnmounted(() => {
  161. TUIStore.unwatch(StoreName.CONV, {
  162. currentConversation: onCurrentConversationUpdate,
  163. });
  164. reset();
  165. });
  166. function onCurrentConversationUpdate(conversation: IConversationModel) {
  167. if (currentConversationID.value === conversation?.conversationID) {
  168. return;
  169. }
  170. // TUIChat 每次切换会话,需要初始化 chatType;
  171. TUIChatConfig.setChatType(conversation?.type);
  172. // 由 TUICustomerServicePlugin 插件判断如果当前会话是客服会话,则设置 chatType 并激活会话。
  173. TUICore.callService({
  174. serviceName: TUIConstants.TUICustomerServicePlugin.SERVICE.NAME,
  175. method:
  176. TUIConstants.TUICustomerServicePlugin.SERVICE.METHOD.ACTIVE_CONVERSATION,
  177. params: { conversationID: conversation?.conversationID },
  178. });
  179. currentConversationID.value = conversation?.conversationID;
  180. isGroup.value = conversation?.type === TUIChatEngine.TYPES.CONV_GROUP;
  181. // while chat converstaion changed, notify callkit current conversation type, c2c or group
  182. TUICore.notifyEvent(
  183. TUIConstants.TUIChat.EVENT.CHAT_STATE_CHANGED,
  184. TUIConstants.TUIChat.EVENT_SUB_KEY.CHAT_OPENED,
  185. {
  186. groupID: conversation?.groupProfile?.groupID,
  187. }
  188. );
  189. if (
  190. isUniFrameWork &&
  191. isGroup.value &&
  192. groupID.value !== conversation?.groupProfile?.groupID
  193. ) {
  194. const extList = TUICore.getExtensionList(
  195. TUIConstants.TUIChat.EXTENSION.CHAT_HEADER.EXT_ID,
  196. {
  197. filterManageGroup: !isGroup.value,
  198. }
  199. );
  200. groupManageExt.value = extList[0];
  201. }
  202. if (isUniFrameWork && !isGroup.value) {
  203. groupManageExt.value = undefined;
  204. }
  205. groupID.value = conversation?.groupProfile?.groupID;
  206. }
  207. const isInputToolbarShow = computed<boolean>(() => {
  208. return isUniFrameWork ? inputToolbarDisplayType.value !== "none" : true;
  209. });
  210. // 清空当前 conversationID
  211. const reset = () => {
  212. TUIConversationService.switchConversation();
  213. };
  214. const closeChat = (conversationID: string) => {
  215. emits("closeChat", conversationID);
  216. reset();
  217. };
  218. const insertEmoji = (emojiObj: object) => {
  219. messageInputRef.value?.insertEmoji(emojiObj);
  220. };
  221. const handleEditor = (message: IMessageModel, type: string) => {
  222. if (!message || !type) return;
  223. switch (type) {
  224. case "reference":
  225. // todo
  226. break;
  227. case "reply":
  228. // todo
  229. break;
  230. case "reedit":
  231. if (message?.payload?.text) {
  232. messageInputRef?.value?.reEdit(message?.payload?.text);
  233. }
  234. break;
  235. default:
  236. break;
  237. }
  238. };
  239. const emitStatus = (status: Boolean) => {
  240. if (status) {
  241. initData();
  242. }
  243. };
  244. const handleGroup = () => {
  245. groupManageExt.value.listener.onClicked({ groupID: groupID.value });
  246. };
  247. function changeToolbarDisplayType(type: ToolbarDisplayType) {
  248. inputToolbarDisplayType.value =
  249. inputToolbarDisplayType.value === type ? "none" : type;
  250. if (inputToolbarDisplayType.value !== "none" && isUniFrameWork) {
  251. uni.$emit("scroll-to-bottom");
  252. }
  253. }
  254. function scrollToLatestMessage() {
  255. messageListRef.value?.scrollToLatestMessage();
  256. }
  257. </script>
  258. <style scoped lang="scss" src="./style/index.scss"></style>