index.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <template>
  2. <div
  3. ref="searchMoreRef"
  4. :class="['tui-search-more', !isPC && 'tui-search-more-h5']"
  5. >
  6. <div
  7. class="more"
  8. @click="toggleMore()"
  9. >
  10. <Icon
  11. class="more-icon"
  12. :file="searchMoreSVG"
  13. :width="isPC ? '28px' : '34px'"
  14. :height="isPC ? '28px' : '34px'"
  15. />
  16. </div>
  17. <ul
  18. v-if="isListShow"
  19. class="tui-search-more-list"
  20. >
  21. <li
  22. v-for="(extension, index) in extensionList"
  23. :key="index"
  24. class="list-item"
  25. @click="handleMenu(extension)"
  26. >
  27. <Icon
  28. v-if="extension.icon"
  29. class="list-item-icon"
  30. :file="extension.icon"
  31. />
  32. <div class="list-item-title">
  33. {{ extension.text }}
  34. </div>
  35. </li>
  36. </ul>
  37. </div>
  38. </template>
  39. <script lang="ts" setup>
  40. import { ref, watch, onMounted } from '../../../adapter-vue';
  41. import { TUIStore, StoreName } from '@tencentcloud/chat-uikit-engine';
  42. import TUICore, { ExtensionInfo, TUIConstants } from '@tencentcloud/tui-core';
  43. import { outsideClick } from '@tencentcloud/universal-api';
  44. import Icon from '../../common/Icon.vue';
  45. import searchMoreSVG from '../../../assets/icon/search-more.svg';
  46. import { isPC, isUniFrameWork } from '../../../utils/env';
  47. const props = defineProps({
  48. searchType: {
  49. type: String,
  50. default: 'global', // "global" / "conversation"
  51. validator(value: string) {
  52. return ['global', 'conversation'].includes(value);
  53. },
  54. },
  55. });
  56. const searchMoreRef = ref<HTMLElement | null>();
  57. const isListShow = ref<boolean>(false);
  58. const toggleMore = () => {
  59. isListShow.value = !isListShow.value;
  60. if (!isUniFrameWork && isListShow.value) {
  61. outsideClick.listen({
  62. domRefs: searchMoreRef.value,
  63. handler: closeSearchMore,
  64. });
  65. }
  66. };
  67. const extensionList = ref<ExtensionInfo[]>([]);
  68. const handleMenu = (item: ExtensionInfo) => {
  69. const { listener = { onClicked: () => { } } } = item;
  70. listener?.onClicked?.(item);
  71. toggleMore();
  72. };
  73. const closeSearchMore = () => {
  74. isListShow.value = false;
  75. };
  76. onMounted(() => {
  77. // extensions
  78. extensionList.value = [
  79. ...TUICore.getExtensionList(TUIConstants.TUISearch.EXTENSION.SEARCH_MORE.EXT_ID),
  80. ];
  81. // hide conversation header
  82. TUICore.callService({
  83. serviceName: TUIConstants.TUIConversation.SERVICE.NAME,
  84. method: TUIConstants.TUIConversation.SERVICE.METHOD.HIDE_CONVERSATION_HEADER,
  85. params: {},
  86. });
  87. });
  88. watch(
  89. () => isListShow.value,
  90. () => {
  91. if (isListShow.value) {
  92. TUIStore.update(StoreName.SEARCH, 'currentSearchingStatus', {
  93. isSearching: false,
  94. searchType: props.searchType,
  95. });
  96. }
  97. },
  98. );
  99. </script>
  100. <style lang="scss" scoped>
  101. .tui-search-more {
  102. display: flex;
  103. flex-direction: column;
  104. position: relative;
  105. .more {
  106. width: 28px;
  107. height: 28px;
  108. margin-right: 6px;
  109. }
  110. &-list {
  111. margin: 10px 0;
  112. position: absolute;
  113. list-style: none;
  114. cursor: pointer;
  115. right: 6px;
  116. top: 20px;
  117. z-index: 1000;
  118. background: #fff;
  119. display: flex;
  120. flex-direction: column;
  121. justify-content: center;
  122. align-items: flex-start;
  123. padding: 0;
  124. box-shadow: rgba(0,0,0,0.16) 0 3px 6px, rgba(0,0,0,0.23) 0 3px 6px;
  125. .list-item {
  126. display: flex;
  127. flex-direction: row;
  128. justify-content: space-between;
  129. align-items: center;
  130. height: 40px;
  131. padding: 0 10px;
  132. &-icon {
  133. margin-right: 2px;
  134. }
  135. &-title {
  136. font-size: 14px;
  137. text-wrap: nowrap;
  138. word-break: keep-all;
  139. }
  140. }
  141. }
  142. }
  143. .tui-search-more-h5{
  144. .more{
  145. width: 34px;
  146. height: 34px;
  147. }
  148. }
  149. </style>