face.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <template>
  2. <view class="face">
  3. <view class="icon icon-face" @click="toggleShow"></view>
  4. <view class="face-main" v-show="show" ref="dialog">
  5. <view class="face-main-box" v-for="(item, index) in list" :key="index">
  6. <view class="face-list" v-if="currentIndex === index">
  7. <view class="face-list-item" v-for="(childrenItem, childrenIndex) in item" :key="childrenIndex" @click="select(childrenItem, childrenIndex)">
  8. <image class="emo-image" v-if="index === 0" :src="emojiUrl + emojiMap[childrenItem]"></image>
  9. <image class="face-img" v-else :src="faceUrl + childrenItem + '@2x.png'"></image>
  10. </view>
  11. </view>
  12. </view>
  13. <view class="face-tab">
  14. <view class="face-tab-item" @click="selectFace(0)">
  15. <view class="icon icon-face"></view>
  16. </view>
  17. <view class="face-tab-item" v-for="(item, index) in bigEmojiList" :key="index" @click="selectFace(index+1)">
  18. <image class="face-icon" :src="faceUrl + item.icon + '@2x.png'"></image>
  19. </view>
  20. <view class="send-btn" @click="handleSendEmoji">发送</view>
  21. </view>
  22. </view>
  23. </view>
  24. </template>
  25. <script lang="ts">
  26. import { defineComponent, reactive, watchEffect, toRefs, computed, ref } from 'vue';
  27. import { emojiUrl, emojiMap, emojiName, faceUrl, bigEmojiList } from "../../../../../utils/emojiMap";
  28. // import TUIMessage from '../../../../components/message';
  29. // import { onClickOutside } from '@vueuse/core';
  30. const Face = defineComponent({
  31. props: {
  32. show: {
  33. type: Boolean,
  34. default: () => false,
  35. },
  36. isMute: {
  37. type: Boolean,
  38. default: () => false,
  39. },
  40. },
  41. setup(props:any, ctx:any) {
  42. const data = reactive({
  43. emojiUrl,
  44. emojiMap,
  45. emojiName,
  46. faceUrl,
  47. bigEmojiList,
  48. show: false,
  49. currentIndex: 0,
  50. isMute: false,
  51. });
  52. const dialog:any = ref();
  53. watchEffect(() => {
  54. data.show = props.show;
  55. data.isMute = props.isMute;
  56. });
  57. const toggleShow = () => {
  58. if (!data.isMute) {
  59. data.show = !data.show;
  60. }
  61. if (!data.show) {
  62. selectFace(0);
  63. }
  64. };
  65. // onClickOutside(dialog, () => {
  66. // data.show = false;
  67. // });
  68. const select = async (item:string, index?:number) => {
  69. const options:any = {
  70. name: item,
  71. };
  72. if (data.currentIndex === 0) {
  73. options.type = 'emo';
  74. options.url = emojiUrl + emojiMap[item];
  75. options.template = `<image src="${emojiUrl + emojiMap[item]}"></image>`;
  76. // toggleShow();
  77. return ctx.emit('send', options);
  78. }
  79. try {
  80. await uni.$TUIKit.TUIChatServer.sendFaceMessage({
  81. index,
  82. data: item,
  83. });
  84. } catch (error) {
  85. // TUIMessage({ message: error });
  86. }
  87. // toggleShow();
  88. };
  89. const list = computed(() => {
  90. const emjiList = [data.emojiName];
  91. for (let i = 0; i < data.bigEmojiList.length; i++) {
  92. emjiList.push(data.bigEmojiList[i].list);
  93. }
  94. return emjiList;
  95. });
  96. const selectFace = (index:number) => {
  97. data.currentIndex = index;
  98. };
  99. const handleSendEmoji = () => {
  100. return ctx.emit('handleSendEmoji')
  101. };
  102. return {
  103. ...toRefs(data),
  104. toggleShow,
  105. select,
  106. selectFace,
  107. list,
  108. dialog,
  109. handleSendEmoji,
  110. };
  111. },
  112. });
  113. export default Face;
  114. </script>
  115. <style lang="scss" scoped>
  116. .face {
  117. position: relative;
  118. cursor: pointer;
  119. width: 100%;
  120. height: 100%;
  121. &-main {
  122. position: absolute;
  123. // z-index: 5;
  124. width: 100%;
  125. height: 100%;
  126. background: #ffffff;
  127. box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
  128. // padding: 10px;
  129. display: flex;
  130. flex-direction: column;
  131. }
  132. &-main-box {
  133. width: 100%;
  134. height: 80%;
  135. box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
  136. display: flex;
  137. flex-direction: column;
  138. }
  139. &-list {
  140. flex: 1;
  141. display: flex;
  142. flex-wrap: wrap;
  143. overflow-y: auto;
  144. justify-content: center;
  145. &-item {
  146. padding: 5px;
  147. .emo-image {
  148. display: block;
  149. height: 30px;
  150. width: 30px;
  151. }
  152. }
  153. .face-img {
  154. display: block;
  155. width: 60px;
  156. height: 60px;
  157. }
  158. }
  159. &-tab {
  160. display: flex;
  161. align-items: center;
  162. &-item {
  163. padding: 8px;
  164. .face-icon {
  165. display: block;
  166. height: 30px;
  167. width: 30px;
  168. }
  169. img {
  170. width: 30px;
  171. }
  172. }
  173. .send-btn {
  174. position: absolute;
  175. background-color: #55C06A;
  176. color: #ffffff;
  177. line-height: 30px;
  178. font-size: 13px;
  179. text-align: center;
  180. width: 50px;
  181. height: 30px;
  182. right: 0;
  183. bottom: 10px;
  184. }
  185. }
  186. }
  187. </style>