index.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. <template>
  2. <view>
  3. <view class="bottom-operation-box" @tap.stop="onBottom">
  4. <!-- <view class="flex_r line-break" v-if="keyboardHeight"> -->
  5. <view class="flex_r line-break" v-show="keyboardHeight">
  6. <view class="icon_ text_28 color__ line-break-box" @click="lineBreak">
  7. <view class="icon_ line-break-icon">
  8. <image class="img"
  9. src="data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTAgMGgxMDI0djEwMjRIMHoiIGZpbGw9IiMyYzJjMmMiIGZpbGwtb3BhY2l0eT0iLjAxIi8+PHBhdGggZD0iTTY4Mi42NjcgMTI4YTI5OC42NjcgMjk4LjY2NyAwIDAgMSAxMC4yNCA1OTcuMTYzbC0xMC4yNC4xN2gtNTEyYTQyLjY2NyA0Mi42NjcgMCAwIDEtNC45OTItODUuMDM0bDQuOTkyLS4yOTloNTEyYTIxMy4zMzMgMjEzLjMzMyAwIDAgMCA5LjI1OC00MjYuNDUzbC05LjI1OC0uMjE0aC01MTJhNDIuNjY3IDQyLjY2NyAwIDAgMS00Ljk5Mi04NS4wMzRsNC45OTItLjI5OWg1MTJ6IiBmaWxsPSIjMmMyYzJjIi8+PHBhdGggZD0iTTI0Ny4xNjggNDYwLjUwMWE0Mi42NjcgNDIuNjY3IDAgMCAxIDYzLjg3MiA1Ni4zMmwtMy41NDEgNC4wMTEtMTYwIDE2MCAxNTguMTY1IDE0MC42M2E0Mi42NjcgNDIuNjY3IDAgMCAxIDYuODI3IDU1Ljk3OGwtMy4yODYgNC4yNjdhNDIuNjY3IDQyLjY2NyAwIDAgMS01NS45NzggNi44MjZsLTQuMjY3LTMuMzI4LTE5Mi0xNzAuNjY2YTQyLjY2NyA0Mi42NjcgMCAwIDEtNS4yNDgtNTguMTU1bDMuNDEzLTMuODgzIDE5Mi0xOTJ6IiBmaWxsPSIjMmMyYzJjIi8+PC9zdmc+"
  10. mode="aspectFill"></image>
  11. </view>
  12. 换行
  13. </view>
  14. </view>
  15. <view class="flex_r bottom-operation">
  16. <view style="width: 10rpx"></view>
  17. <view class="flex_c_c flex1">
  18. <view class="bottom-operation-input" v-if="isKeyboard">
  19. <textarea class="input" auto-height="true" confirm-type="send" type="text" :focus="isFocus"
  20. :maxlength="-1" :adjust-position="false" v-model="text" confirm-hold
  21. :show-confirm-bar="false" @input="input" @confirm="sendingText" @focus="focus"
  22. @blur="isFocus = false" @keyboardheightchange="keyboardheightchange" />
  23. </view>
  24. <!-- inputmode="none" -->
  25. <view class="icon_ text_32 bold_ bottom-operation-input" @touchend="touchend" @touchmove="touchmove"
  26. @touchstart="touchstart" v-else>
  27. <view>按住</view>
  28. <view style="width: 10rpx"></view>
  29. <view>说话</view>
  30. </view>
  31. <view class="icon_ text_26 quote" v-if="isQuote">
  32. <view class="flex1 quote-row">
  33. <view class="" v-if="quoteSource.type === 'image' || quoteSource.type === 'image_transmit'">
  34. <m-image :value="quoteSource"></m-image>
  35. </view>
  36. <view class="" v-else-if="quoteSource.type === 'audio'">
  37. <m-audio :value="quoteSource"></m-audio>
  38. </view>
  39. <view class="" v-else-if="quoteSource.type === 'text' || quoteSource.type === 'text_quote'">
  40. <m-text :value="quoteSource"></m-text>
  41. </view>
  42. <view class="" v-else>
  43. <m-other :value="quoteSource"></m-other>
  44. </view>
  45. </view>
  46. <view class="quote-icon" @click="cancelQuote">
  47. <image class="img"
  48. src="data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTg5NS4xIDUxMi40Yy0uNi0xMDIuMy00MS0xOTguNC0xMTMuOC0yNzAuNy03Mi44LTcyLjMtMTY5LjItMTEyLTI3MS41LTExMS45LTEwMi4zLjItMTk4LjMgNDAuMi0yNzAuMyAxMTIuN1MxMjguMiA0MTEuMyAxMjguOCA1MTMuNmMuNiAxMDIuMyA0MSAxOTguNCAxMTMuOCAyNzAuN3MxNjkuMiAxMTIgMjcxLjUgMTExLjhjMTAyLjQtLjEgMTk4LjUtNDAuMSAyNzAuNC0xMTIuNiA3Mi03Mi41IDExMS4zLTE2OC43IDExMC42LTI3MS4xek02MjkgNjY3LjhsLTExNi44LTExNi0xMTYgMTE2LjhjLTEwLjcgMTAuOC0yOCAxMC44LTM4LjguMS0xMC43LTEwLjctMTAuOC0yOC0uMS0zOC44bDExNS45LTExNi44LTExNi44LTExNS45Yy0xMC43LTEwLjctMTAuOC0yOC0uMS0zOC44IDEwLjctMTAuNyAyOC0xMC44IDM4LjgtLjFsMTE2LjggMTE1LjkgMTE1LjktMTE2LjhjMTAuNy0xMC43IDI4LTEwLjggMzguOC0uMSAxMC43IDEwLjcgMTAuOCAyOCAuMSAzOC44TDU1MC44IDUxMi45bDExNi44IDExNS45YzEwLjggMTAuNyAxMC44IDI4IC4xIDM4LjgtMTAuNiAxMC44LTI4IDEwLjgtMzguNy4yem0wIDAiIGRhdGEtc3BtLWFuY2hvci1pZD0iYTMxM3guc2VhcmNoX2luZGV4LjAuaTExLjFkYjQzYTgxVE1Sd1EyIiBjbGFzcz0ic2VsZWN0ZWQiIGZpbGw9IiNhMWExYTEiLz48L3N2Zz4="
  49. mode="aspectFill"></image>
  50. </view>
  51. </view>
  52. </view>
  53. <view style="width: 10rpx"></view>
  54. <view class="icon_ bottom-operation-icon" @click="tapEmoji">
  55. <image class="img" :src="b" mode="aspectFill"></image>
  56. </view>
  57. <view class="icon_ bottom-operation-icon" @click="tapMore">
  58. <image class="img" :src="c" mode="aspectFill"></image>
  59. </view>
  60. </view>
  61. <view>
  62. <emoji v-model="isEmoji" @onEmoji="onEmoji" @deleteFn="deleteFn" @sendingText="sendingText"
  63. @sendingEmojiPack="sendingEmojiPack"></emoji>
  64. </view>
  65. <view>
  66. <more v-model="isMore" @onMore="onMore"></more>
  67. </view>
  68. <!-- 键盘高度 -->
  69. <view class="keyboard" :style="{ height: keyboardHeight + 'px' }"></view>
  70. <view v-if="keyboardHeight === 0">
  71. <m-bottom-paceholder></m-bottom-paceholder>
  72. </view>
  73. <!-- 语音输入 -->
  74. <m-recorder v-model="isRecorder" :isCancel="isCancel" @recorderTop="recorderTop"
  75. @touchend="touchend"></m-recorder>
  76. </view>
  77. </view>
  78. </template>
  79. <script>
  80. import {
  81. show,
  82. to as tofn,
  83. throttle,
  84. vibrateShortFn
  85. } from '@/utils/index.js';
  86. import emoji from './emoji.vue';
  87. import more from './more.vue';
  88. import mRecorder from './m-recorder.vue';
  89. import mText from '../item/quoteType/m-text.vue';
  90. import mImage from '../item/quoteType/m-image.vue';
  91. import mAudio from '../item/quoteType/m-audio.vue';
  92. import mOther from '../item/quoteType/m-other.vue';
  93. const recorderManager = uni.getRecorderManager();
  94. //录音时长
  95. let startTime = 0;
  96. //
  97. let inputValue = '';
  98. let getSelectedTextRangeSetInterval = null;
  99. let cursor = 0; //输入框光标
  100. export default {
  101. components: {
  102. emoji,
  103. more,
  104. mRecorder,
  105. // memberSelection,
  106. mText,
  107. mImage,
  108. mAudio,
  109. mOther
  110. },
  111. props: {
  112. to: {
  113. type: Object,
  114. default: {}
  115. },
  116. userList: {
  117. type: Array,
  118. default: () => {
  119. return [];
  120. }
  121. },
  122. isPrivate: {
  123. type: Boolean,
  124. default: false
  125. }
  126. },
  127. data() {
  128. return {
  129. a: 'data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4LmNvbGxlY3Rpb25zX2RldGFpbC4wLmkxLjQ0MjMzYTgxRURKTEhBIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTUxMyA5NTkuNWMtNTguMSAwLTExNC44LTExLTE2OC40LTMyLjgtNTUuNS0yMi41LTEwNS4zLTU1LjYtMTQ4LjEtOTguMy00Mi43LTQyLjctNzUuOC05Mi41LTk4LjMtMTQ4Qzc2LjUgNjI2LjggNjUuNSA1NzAuMSA2NS41IDUxMmMwLTU4LjEgMTEtMTE0LjggMzIuOC0xNjguNCAyMi41LTU1LjUgNTUuNi0xMDUuMyA5OC4zLTE0OCA0Mi43LTQyLjcgOTIuNS03NS44IDE0OC05OC4zQzM5OC4yIDc1LjUgNDU0LjkgNjQuNSA1MTMgNjQuNXMxMTQuOCAxMSAxNjguNCAzMi44YzU1LjUgMjIuNSAxMDUuMyA1NS42IDE0OCA5OC4zIDQyLjcgNDIuNyA3NS44IDkyLjUgOTguMyAxNDggMjEuNyA1My42IDMyLjggMTEwLjMgMzIuOCAxNjguNCAwIDU4LjEtMTEgMTE0LjgtMzIuOCAxNjguNC0yMi41IDU1LjUtNTUuNiAxMDUuMy05OC4zIDE0OC00Mi43IDQyLjctOTIuNSA3NS44LTE0OCA5OC4zLTUzLjcgMjEuOC0xMTAuMyAzMi44LTE2OC40IDMyLjh6bTAtODM5Yy01MC45IDAtMTAwLjQgOS42LTE0Ny4zIDI4LjctNDguNSAxOS43LTkyLjEgNDguNi0xMjkuNSA4Ni0zNy40IDM3LjQtNjYuMyA4MC45LTg2IDEyOS41LTE5IDQ2LjktMjguNyA5Ni41LTI4LjcgMTQ3LjMgMCA1MC45IDkuNiAxMDAuNCAyOC43IDE0Ny4zIDE5LjcgNDguNSA0OC42IDkyLjEgODYgMTI5LjUgMzcuNCAzNy40IDgwLjkgNjYuMyAxMjkuNSA4NiA0Ni45IDE5IDk2LjUgMjguNyAxNDcuMyAyOC43IDUwLjkgMCAxMDAuNC05LjYgMTQ3LjMtMjguNyA0OC41LTE5LjcgOTIuMS00OC42IDEyOS41LTg2IDM3LjQtMzcuNCA2Ni4zLTgxIDg2LTEyOS41IDE5LTQ2LjkgMjguNy05Ni41IDI4LjctMTQ3LjNzLTkuNi0xMDAuNC0yOC43LTE0Ny4zYy0xOS43LTQ4LjUtNDguNi05Mi4xLTg2LTEyOS41LTM3LjQtMzcuNC04MC45LTY2LjMtMTI5LjUtODYtNDYuOS0xOS05Ni41LTI4LjctMTQ3LjMtMjguN3oiIGRhdGEtc3BtLWFuY2hvci1pZD0iYTMxM3guY29sbGVjdGlvbnNfZGV0YWlsLjAuaTAuNDQyMzNhODFFREpMSEEiIGNsYXNzPSJzZWxlY3RlZCIvPjxwYXRoIGQ9Ik01NjkuMSA3NjRjLTEwLjUtMTAuMi0xMS40LTI2LjctMi4xLTM4IDQ5LjgtNjAuMSA3Ny0xMzUuMiA3Ny0yMTQgMC03OC44LTI3LjItMTUzLjktNzctMjE0LTkuMy0xMS4zLTguNS0yNy44IDIuMS0zOCAxMS43LTExLjMgMzAuNi0xMC4zIDQxIDIuMkM2NjguMyAzMzIuNCA3MDAgNDIwIDcwMCA1MTJzLTMxLjcgMTc5LjYtODkuOSAyNDkuOGMtMTAuNCAxMi41LTI5LjMgMTMuNi00MSAyLjJ6TTQ1MC43IDY0OS43Yy0xMC05LjctMTEuNS0yNS4zLTMuMy0zNi41IDIxLjMtMjkuMiAzMi44LTY0LjQgMzIuOC0xMDEuMnMtMTEuNS03MS45LTMyLjgtMTAxLjJjLTguMi0xMS4yLTYuNy0yNi44IDMuMy0zNi41IDEyLjItMTEuOCAzMi4xLTEwLjEgNDIgMy42IDI4LjMgMzguOCA0My41IDg1LjQgNDMuNSAxMzQuMSAwIDQ4LjctMTUuMyA5NS4zLTQzLjUgMTM0LjEtMTAgMTMuNy0yOS44IDE1LjQtNDIgMy42em0tMTAxLjQtOTcuOWMtNy44LTcuNS0xMC40LTE4LjctNy4xLTI5IDEuMS0zLjQgMS43LTcuMSAxLjctMTAuOCAwLTMuNy0uNi03LjMtMS43LTEwLjgtMy4zLTEwLjMtLjYtMjEuNSA3LjEtMjkgMTQuOS0xNC40IDM5LjctOC4yIDQ2LjEgMTEuNCAyLjkgOSA0LjQgMTguNiA0LjQgMjguM3MtMS41IDE5LjMtNC40IDI4LjNjLTYuNCAxOS44LTMxLjIgMjUuOS00Ni4xIDExLjZ6IiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4LmNvbGxlY3Rpb25zX2RldGFpbC4wLmk2LjQ0MjMzYTgxRURKTEhBIiBjbGFzcz0ic2VsZWN0ZWQiLz48L3N2Zz4=',
  130. a_b: 'data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTUxMS43IDk2MC42Yy01OC4xIDAtMTE0LjgtMTEtMTY4LjQtMzIuOC01NS41LTIyLjUtMTA1LjMtNTUuNi0xNDgtOTguMy00Mi43LTQyLjctNzUuOC05Mi41LTk4LjMtMTQ4LTIxLjctNTMuNi0zMi44LTExMC4zLTMyLjgtMTY4LjQgMC01OC4xIDExLTExNC44IDMyLjgtMTY4LjQgMjIuNS01NS41IDU1LjYtMTA1LjMgOTguMy0xNDggMzkuNC0zOS40IDg0LjYtNzAuNCAxMzQuNy05Mi43IDE0LjgtNi42IDMyLjEuOCAzNy42IDE2IDUuMSAxMy45LTEuNiAyOS4zLTE1LjEgMzUuMy00My44IDE5LjQtODMuMyA0Ni42LTExNy43IDgxLTM3LjQgMzcuNC02Ni4zIDgwLjktODYgMTI5LjUtMTkgNDYuOS0yOC43IDk2LjUtMjguNyAxNDcuM3M5LjYgMTAwLjQgMjguNyAxNDcuM2MxOS43IDQ4LjUgNDguNiA5Mi4xIDg2IDEyOS41IDM3LjQgMzcuNCA4MC45IDY2LjMgMTI5LjUgODYgNDYuOSAxOSA5Ni41IDI4LjcgMTQ3LjMgMjguNyA1MC45IDAgMTAwLjQtOS42IDE0Ny4zLTI4LjcgNDguNS0xOS43IDkyLjEtNDguNiAxMjkuNS04NiAzNy40LTM3LjQgNjYuMy04MSA4Ni0xMjkuNSAxOS00Ni45IDI4LjctOTYuNSAyOC43LTE0Ny4zcy05LjYtMTAwLjQtMjguNy0xNDcuM2MtMTkuNy00OC41LTQ4LjYtOTIuMS04Ni0xMjkuNS0zNC41LTM0LjUtNzQuMS02MS43LTExOC04MS4xLTEzLjUtNi0yMC4yLTIxLjQtMTUuMS0zNS4zIDUuNi0xNS4yIDIyLjgtMjIuNiAzNy42LTE2IDUwLjMgMjIuMiA5NS42IDUzLjQgMTM1IDkyLjggNDIuNyA0Mi43IDc1LjggOTIuNSA5OC4zIDE0OEM5NDcuOSAzOTguMyA5NTkgNDU1IDk1OSA1MTMuMWMwIDU4LjEtMTEgMTE0LjgtMzIuOCAxNjguNC0yMi41IDU1LjUtNTUuNiAxMDUuMy05OC4zIDE0OC00Mi43IDQyLjctOTIuNSA3NS44LTE0OC4xIDk4LjMtNTMuNCAyMS44LTExMCAzMi44LTE2OC4xIDMyLjh6Ii8+PHBhdGggZD0iTTc2OC4xIDM1OC41Yy0xNS41IDAtMjggMTIuNS0yOCAyOHYyMjUuMkgyODMuM2MtMTUuNSAwLTI4IDEyLjUtMjggMjhzMTIuNSAyOCAyOCAyOGg0ODQuOHYtLjFjMTUuNi0xIDI4LTE0IDI4LTI5LjlWMzg2LjVjMC0xNS40LTEyLjYtMjgtMjgtMjh6Ii8+PHBhdGggZD0iTTI4My4zIDU1MS45aDEyNS45YzE1LjUgMCAyOC0xMi41IDI4LTI4cy0xMi41LTI4LTI4LTI4SDI4My4zYy0xNS41IDAtMjggMTIuNS0yOCAyOHMxMi41IDI4IDI4IDI4em0yMjEuMS0yOGMwIDE1LjUgMTIuNSAyOCAyOCAyOGgxMjUuOWMxNS41IDAgMjgtMTIuNSAyOC0yOHMtMTIuNS0yOC0yOC0yOEg1MzIuNGMtMTUuNCAwLTI4IDEyLjYtMjggMjh6bS0yMjEuMS04Ni43SDM0MGMxNS41IDAgMjgtMTIuNSAyOC0yOHMtMTIuNS0yOC0yOC0yOGgtNTYuN2MtMTUuNSAwLTI4IDEyLjUtMjggMjggMCAxNS40IDEyLjUgMjggMjggMjh6bTMxOC40IDBoNTYuN2MxNS41IDAgMjgtMTIuNSAyOC0yOHMtMTIuNS0yOC0yOC0yOGgtNTYuN2MtMTUuNSAwLTI4IDEyLjUtMjggMjggMCAxNS40IDEyLjUgMjggMjggMjh6bS0xNTkuMiAwaDU2LjdjMTUuNSAwIDI4LTEyLjUgMjgtMjhzLTEyLjUtMjgtMjgtMjhoLTU2LjdjLTE1LjUgMC0yOCAxMi41LTI4IDI4IDAgMTUuNCAxMi41IDI4IDI4IDI4ek01MTguOCA2N2w4Ni4xIDg4LjNjNi4yIDYuMyAxLjcgMTctNy4yIDE3SDQyNS41Yy04LjggMC0xMy4zLTEwLjYtNy4yLTE3TDUwNC41IDY3YzMuOS00IDEwLjQtNCAxNC4zIDB6Ii8+PC9zdmc+',
  131. b: 'data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTUxMyA5NTljLTYwLjQgMC0xMTguOS0xMS44LTE3NC4xLTM1LjItNTMuMy0yMi41LTEwMS4xLTU0LjgtMTQyLjEtOTUuOC00MS4xLTQxLjEtNzMuMy04OC45LTk1LjgtMTQyLjEtMjMuMy01NS4yLTM1LjItMTEzLjctMzUuMi0xNzQuMVM3Ny42IDM5Mi45IDEwMSAzMzcuN2MyMi41LTUzLjMgNTQuOC0xMDEuMSA5NS44LTE0Mi4xIDQxLjEtNDEuMSA4OC45LTczLjMgMTQyLjEtOTUuOEMzOTQuMSA3Ni40IDQ1Mi42IDY0LjYgNTEzIDY0LjZzMTE4LjkgMTEuOCAxNzQuMSAzNS4yYzUzLjMgMjIuNSAxMDEuMSA1NC44IDE0Mi4xIDk1LjggNDEuMSA0MS4xIDczLjMgODguOSA5NS44IDE0Mi4xIDIzLjMgNTUuMiAzNS4yIDExMy43IDM1LjIgMTc0LjFTOTQ4LjQgNjMwLjcgOTI1IDY4NS45QzkwMi41IDczOS4xIDg3MC4zIDc4NyA4MjkuMiA4MjhjLTQxLjEgNDEuMS04OC45IDczLjMtMTQyLjEgOTUuOEM2MzEuOSA5NDcuMiA1NzMuNCA5NTkgNTEzIDk1OXptMC04MzguNGMtNTIuOCAwLTEwNC4xIDEwLjMtMTUyLjMgMzAuNy00Ni42IDE5LjctODguNCA0Ny45LTEyNC40IDgzLjktMzUuOSAzNS45LTY0LjIgNzcuOC04My45IDEyNC40LTIwLjQgNDguMi0zMC43IDk5LjQtMzAuNyAxNTIuM1MxMzIgNjE2IDE1Mi40IDY2NC4yYzE5LjcgNDYuNiA0Ny45IDg4LjQgODMuOSAxMjQuNCAzNS45IDM1LjkgNzcuOCA2NC4yIDEyNC40IDgzLjlDNDA4LjkgODkyLjcgNDYwLjIgOTAzIDUxMyA5MDNzMTA0LjEtMTAuMyAxNTIuMy0zMC43YzQ2LjYtMTkuNyA4OC40LTQ3LjkgMTI0LjQtODMuOSAzNS45LTM1LjkgNjQuMi03Ny44IDgzLjktMTI0LjQgMjAuNC00OC4yIDMwLjctOTkuNCAzMC43LTE1Mi4zUzg5NCA0MDcuNiA4NzMuNiAzNTkuNGMtMTkuNy00Ni42LTQ3LjktODguNC04My45LTEyNC40LTM1LjktMzUuOS03Ny44LTY0LjItMTI0LjQtODMuOS00OC4yLTIwLjItOTkuNS0zMC41LTE1Mi4zLTMwLjV6IiBkYXRhLXNwbS1hbmNob3ItaWQ9ImEzMTN4LmNvbGxlY3Rpb25zX2RldGFpbC4wLmkxMS40NDIzM2E4MUVESkxIQSIgY2xhc3M9InNlbGVjdGVkIi8+PHBhdGggZD0iTTU4My45IDM5OC4zYTQ2LjcgNDYuNyAwIDEgMCA5My40IDAgNDYuNyA0Ni43IDAgMSAwLTkzLjQgMHpNMzQ3IDM5OC4zYTQ2LjcgNDYuNyAwIDEgMCA5My40IDAgNDYuNyA0Ni43IDAgMSAwLTkzLjQgMHpNNTEzIDc5MGMtNTUuMiAwLTExMC0xOC40LTE1NC4zLTUxLjgtNDIuNC0zMS45LTcyLjUtNzQuOS04NC45LTEyMC45LTQuNy0xNy40LTEtMzUuNiAxMC01MCAxMS4xLTE0LjUgMjcuOS0yMi44IDQ2LjEtMjIuOGwzNjYuMy0uMWMxOC4yIDAgMzUgOC4zIDQ2LjEgMjIuNyAxMSAxNC40IDE0LjcgMzIuNiAxMCA1MC0xMi4zIDQ2LTQyLjUgODktODQuOSAxMjAuOS00NC40IDMzLjYtOTkuMiA1Mi0xNTQuNCA1MnptMTgzLjEtMTg5LjZsLTM2Ni4zLjFjLS4zIDAtMSAwLTEuNy44LS41LjctLjQgMS4yLS4zIDEuNCA5IDMzLjUgMzIuNSA2Ni41IDY0LjUgOTAuNkM0MjcuMSA3MTkuNiA0NjkuOSA3MzQgNTEzIDczNGM0My4xIDAgODUuOS0xNC40IDEyMC43LTQwLjYgMzItMjQuMSA1NS41LTU3LjIgNjQuNS05MC43LjEtLjMuMi0uNy0uMy0xLjQtLjctLjktMS41LS45LTEuOC0uOXoiLz48L3N2Zz4=',
  132. c: 'data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTUxMS4zIDk1OS43Yy02MC40IDAtMTE5LTExLjgtMTc0LjItMzUuMi01My4zLTIyLjUtMTAxLjEtNTQuOC0xNDIuMi05NS45LTQxLjEtNDEuMS03My40LTg4LjktOTUuOS0xNDIuMi0yMy4zLTU1LjItMzUuMi0xMTMuOC0zNS4yLTE3NC4yUzc1LjYgMzkzLjEgOTkgMzM4YzIyLjUtNTMuMyA1NC44LTEwMS4xIDk1LjktMTQyLjIgNDEuMS00MS4xIDg4LjktNzMuNCAxNDIuMi05NS45IDU1LjItMjMuMyAxMTMuOC0zNS4yIDE3NC4yLTM1LjIgNjAuNCAwIDExOSAxMS44IDE3NC4yIDM1LjIgNTMuMyAyMi41IDEwMS4xIDU0LjggMTQyLjIgOTUuOSA0MS4xIDQxLjEgNzMuNCA4OC45IDk1LjkgMTQyLjIgMjMuMyA1NS4yIDM1LjIgMTEzLjggMzUuMiAxNzQuMnMtMTEuOCAxMTktMzUuMiAxNzQuMmMtMjIuNSA1My4zLTU0LjggMTAxLjEtOTUuOSAxNDIuMi00MS4xIDQxLjEtODguOSA3My40LTE0Mi4yIDk1LjktNTUuMiAyMy4zLTExMy44IDM1LjItMTc0LjIgMzUuMnptMC04MzljLTUyLjkgMC0xMDQuMSAxMC4zLTE1Mi40IDMwLjgtNDYuNiAxOS43LTg4LjUgNDcuOS0xMjQuNSA4My45LTM2IDM2LTY0LjIgNzcuOC04My45IDEyNC41LTIwLjQgNDguMi0zMC44IDk5LjUtMzAuOCAxNTIuNHMxMC4zIDEwNC4xIDMwLjggMTUyLjRjMTkuNyA0Ni42IDQ3LjkgODguNSA4My45IDEyNC41IDM2IDM2IDc3LjggNjQuMiAxMjQuNSA4My45IDQ4LjIgMjAuNCA5OS41IDMwLjggMTUyLjQgMzAuOCA1Mi45IDAgMTA0LjEtMTAuMyAxNTIuNC0zMC44IDQ2LjYtMTkuNyA4OC41LTQ3LjkgMTI0LjUtODMuOXM2NC4yLTc3LjggODMuOS0xMjQuNWMyMC40LTQ4LjIgMzAuOC05OS41IDMwLjgtMTUyLjRTODkyLjQgNDA4IDg3MiAzNTkuOGMtMTkuNy00Ni42LTQ3LjktODguNS04My45LTEyNC41cy03Ny44LTY0LjItMTI0LjUtODMuOWMtNDguMi0yMC40LTk5LjUtMzAuNy0xNTIuMy0zMC43eiIvPjxwYXRoIGQ9Ik03MzcuMyA0ODQuMmgtMTk4di0xOThjMC0xNS41LTEyLjUtMjgtMjgtMjhzLTI4IDEyLjUtMjggMjh2MTk4aC0xOThjLTE1LjUgMC0yOCAxMi41LTI4IDI4czEyLjUgMjggMjggMjhoMTk4djE5OGMwIDE1LjUgMTIuNSAyOCAyOCAyOHMyOC0xMi41IDI4LTI4di0xOThoMTk4YzE1LjUgMCAyOC0xMi41IDI4LTI4cy0xMi42LTI4LTI4LTI4eiIvPjwvc3ZnPg==',
  133. isFocus: false, //键盘焦点
  134. isKeyboard: true,
  135. isEmoji: false,
  136. isMore: false,
  137. isRecorder: false,
  138. isCancel: false, //是否滑动到取消
  139. text: '',
  140. keyboardHeight: 0,
  141. isQuote: false, //是否引用
  142. quoteSource: {} //引用的源
  143. };
  144. },
  145. created() {
  146. this.initRecorderListeners();
  147. // 监听设置群公告
  148. uni.$off('getNoticeSendMessage', this.sendMessage);
  149. uni.$on('getNoticeSendMessage', this.sendMessage);
  150. // 监听修改群明
  151. uni.$off('getGroupNameMessage', this.sendMessage);
  152. uni.$on('getGroupNameMessage', this.sendMessage);
  153. },
  154. beforeDestroy() {
  155. uni.$off('getNoticeSendMessage', this.sendMessage);
  156. uni.$off('getGroupNameMessage', this.sendMessage);
  157. cursor = 0;
  158. clearInterval(getSelectedTextRangeSetInterval);
  159. },
  160. methods: {
  161. setCursor() {
  162. // getSelectedTextRangeSetInterval = setInterval(() => {
  163. // uni.getSelectedTextRange({
  164. // success: (res) => {
  165. // cursor = res.start;
  166. // },
  167. // fail: () => {
  168. // clearInterval(getSelectedTextRangeSetInterval);
  169. // }
  170. // });
  171. // }, 800);
  172. },
  173. // 滚动到底部
  174. backToBottom() {
  175. this.$emit('backToBottom');
  176. },
  177. // 关闭全部弹出/输入框/表情包
  178. closeAll() {
  179. this.isMore = false;
  180. this.isEmoji = false;
  181. this.isFocus = false;
  182. },
  183. onBottom() {
  184. this.$emit('onBottom');
  185. },
  186. // 重新编辑
  187. recalledEdit(item) {
  188. this.text = item.payload.text;
  189. this.$nextTick(() => {
  190. this.isFocus = true;
  191. });
  192. },
  193. // 关闭
  194. close() {
  195. this.isMore = false;
  196. this.isEmoji = false;
  197. // #ifdef H5
  198. // this.keyboardHeight = 0;
  199. // #endif
  200. this.$emit('keyboardheightchange', 0)
  201. },
  202. // 切换语音输入
  203. onKeyboard() {
  204. this.isKeyboard = !this.isKeyboard;
  205. this.isMore = false;
  206. this.isEmoji = false;
  207. },
  208. keyboardheightchange(e) {
  209. uni.showToast({
  210. title:'啊实打实的'
  211. })
  212. console.log("e.detail.height",e.detail.height)
  213. if (e.detail.duration > 0) {
  214. this.backToBottom();
  215. }
  216. // #ifdef APP
  217. let height = e.detail.height;
  218. this.keyboardHeight = height;
  219. if (height > 0) {
  220. const res = uni.getSystemInfoSync();
  221. let bottom = res.safeAreaInsets.bottom;
  222. height -= bottom;
  223. height -= uni.upx2px(20)//补偿高度
  224. }
  225. this.isMore = false;
  226. this.isEmoji = false;
  227. this.$emit('keyboardheightchange', height, true)
  228. // #endif
  229. // #ifdef MP
  230. if (e.detail.duration > 0) {
  231. throttle(() => {
  232. this.keyboardHeight = e.detail.height;
  233. this.isMore = false;
  234. this.isEmoji = false;
  235. this.$emit('keyboardheightchange', this.keyboardHeight)
  236. }, 300);
  237. }
  238. // #endif
  239. },
  240. tapEmoji() {
  241. this.backToBottom();
  242. this.isEmoji = !this.isEmoji;
  243. if (this.isEmoji) {
  244. this.isKeyboard = true;
  245. }
  246. this.isMore = false;
  247. // #ifdef H5
  248. this.keyboardHeight = 0;
  249. // #endif
  250. this.$emit('keyboardheightchange', uni.upx2px(690))
  251. },
  252. tapMore() {
  253. this.backToBottom();
  254. this.isMore = !this.isMore;
  255. this.isEmoji = false;
  256. // #ifdef H5
  257. // this.keyboardHeight = 0;
  258. // #endif
  259. this.$emit('keyboardheightchange', uni.upx2px(430))
  260. },
  261. onEmoji(key) {
  262. const text = `${this.text.slice(0, cursor)}${key}${this.text.slice(cursor)}`;
  263. this.text = text;
  264. },
  265. // ===========================
  266. // 获取焦点
  267. focus(e) {
  268. this.$emit('focus');
  269. this.isFocus = true;
  270. this.isEmoji = false;
  271. this.isMore = false;
  272. // #ifdef H5
  273. // this.keyboardHeight = 300;
  274. // this.$emit('keyboardheightchange', this.keyboardHeight)
  275. // this.backToBottom();
  276. // #endif
  277. clearInterval(getSelectedTextRangeSetInterval);
  278. this.setCursor();
  279. },
  280. // 监听输入
  281. input() {
  282. if (inputValue.length > this.text.length) {} else {
  283. const str = this.text.charAt(this.text.length - 1);
  284. if (str === '@') {
  285. if (this.isFocus === false) return;
  286. this.$refs.memberSelectionLoadingRef.open();
  287. this.$nextTick(() => {
  288. this.isFocus = false;
  289. });
  290. }
  291. }
  292. inputValue = this.text;
  293. },
  294. // 插入换行符合
  295. lineBreak() {
  296. console.log('回车');
  297. console.log(cursor);
  298. const text = `${this.text.slice(0, cursor)}\n${this.text.slice(cursor)}`;
  299. this.text = text;
  300. // this.text = `${this.text}\r\n`;
  301. this.$nextTick(() => {
  302. this.isFocus = true;
  303. });
  304. },
  305. // 输入@某个成员
  306. itemclick(item) {
  307. if (item) {
  308. this.text = `${this.text}${item.name} `;
  309. }
  310. this.$nextTick(() => {
  311. this.isFocus = true;
  312. });
  313. },
  314. // 删除表情
  315. deleteFn() {
  316. const str = this.text.charAt(this.text.length - 1);
  317. if (str === ']') {
  318. let metaChars = /\[.*?(\u4e00*\u597d*)\]/g;
  319. let xstr = '';
  320. this.text.replace(metaChars, (match) => {
  321. xstr = match;
  322. });
  323. var text = this.text;
  324. function del(str) {
  325. return text.slice(0, text.length - str.length);
  326. }
  327. this.text = del(xstr);
  328. } else {
  329. this.text = this.text.substring(0, this.text.length - 1);
  330. }
  331. },
  332. // 引用
  333. quote(item) {
  334. // 删除嵌套引用
  335. const itemx = JSON.parse(JSON.stringify(item));
  336. itemx.payload['quoteSource'] = {};
  337. this.isQuote = true;
  338. this.quoteSource = itemx;
  339. this.$nextTick(() => {
  340. this.isFocus = true;
  341. });
  342. },
  343. //谢谢红包
  344. thank(item) {
  345. this.text = '[彩带][玫瑰]谢谢红包!';
  346. this.sendingText();
  347. },
  348. //长按@某人
  349. mention(item) {
  350. this.text = `${this.text}@${item.senderData.name} `;
  351. this.$nextTick(() => {
  352. setTimeout(() => {
  353. this.isFocus = true;
  354. }, 500);
  355. });
  356. try {
  357. vibrateShortFn();
  358. } catch (e) {
  359. //TODO handle the exception
  360. }
  361. },
  362. cancelQuote() {
  363. this.isQuote = false;
  364. },
  365. // 录音相关===============
  366. recorderTop(e) {
  367. this.recorderTopValue = e?.top;
  368. },
  369. initRecorderListeners() {
  370. // 监听录音开始
  371. recorderManager.onStart(() => {
  372. // console.log('开始录音');
  373. startTime = Date.now();
  374. });
  375. //录音结束后,发送
  376. recorderManager.onStop((res) => {
  377. this.isRecorder = false;
  378. if (this.isCancel) return console.log('取消发送'); //取消发送
  379. let endTime = Date.now();
  380. let duration = endTime - startTime;
  381. if (duration < 1000) return show('录音时间太短', 1000, 'error');
  382. res.duration = duration;
  383. // 创建信息
  384. this.sendingRecorder(res);
  385. });
  386. // 监听录音报错
  387. recorderManager.onError((res) => {
  388. this.isRecorder = false;
  389. recorderManager.stop();
  390. show('请检查麦克风权限');
  391. });
  392. },
  393. // 按下
  394. touchstart() {
  395. this.isRecorder = true;
  396. this.isCancel = false;
  397. try {
  398. recorderManager.start();
  399. } catch (e) {
  400. show('H5不支持');
  401. }
  402. },
  403. // 拖拽中
  404. touchmove(e) {
  405. let touch = e.touches[0]; //滑动过程中,手指滑动的坐标信息 返回的是Objcet对象
  406. if (touch.clientY <= this.recorderTopValue) {
  407. // 取消发送
  408. this.isCancel = true;
  409. } else {
  410. this.isCancel = false;
  411. }
  412. },
  413. // 松手
  414. touchend() {
  415. try {
  416. recorderManager.stop();
  417. } catch (e) {
  418. console.log('e:', e);
  419. }
  420. this.isRecorder = false;
  421. },
  422. // ===================
  423. // 更多操作相关===============
  424. onMore(item) {
  425. switch (item.type) {
  426. // 拍摄
  427. case 'shot':
  428. this.openShot();
  429. break;
  430. case 'img':
  431. this.sendImageMessage();
  432. break;
  433. case 'video':
  434. this.sendVideoMessage();
  435. break;
  436. case 'red_envelope':
  437. // 发红包
  438. uni.$off('send_red_envelope', this.sendMessage);
  439. uni.$on('send_red_envelope', this.sendMessage);
  440. // 是否是单聊
  441. if (this.isPrivate) {
  442. tofn('/pagesGoEasy/envelope_sending/index-private', {
  443. ...this.to
  444. });
  445. } else {
  446. tofn('/pagesGoEasy/envelope_sending/index', {
  447. ...this.to
  448. });
  449. }
  450. break;
  451. case 'mutualism':
  452. // 蝌蚪互转
  453. tofn('/pagesThree/tadpoleChange/index?type=1');
  454. break;
  455. case 'map':
  456. // 位置
  457. uni.chooseLocation({
  458. success: async (res) => {
  459. console.log(res);
  460. uni.showLoading({
  461. title: '发送中'
  462. });
  463. if (res2) {
  464. this.createCustomMessageMap(res,
  465. 'http://xxxxxxxx/map/staticMap?location=116.459044,39.918732&size=300*170'
  466. );
  467. }
  468. uni.hideLoading();
  469. },
  470. fail(e) {
  471. console.log(e);
  472. }
  473. });
  474. break;
  475. default:
  476. break;
  477. }
  478. },
  479. openShot() {
  480. show('这个用的是原生插件,Html5App-CameraView');
  481. return;
  482. const plug = uni.requireNativePlugin('Html5App-CameraView');
  483. plug.open({
  484. setMaxduration: 30,
  485. SpeedColor: '#05c160',
  486. ratio: '9/16'
  487. }, (retult) => {
  488. const {
  489. type,
  490. mp4 = '',
  491. duration = '',
  492. size = '',
  493. image
  494. } = retult;
  495. if (type == 'video') {
  496. const file = {
  497. errMsg: 'chooseVideo:ok',
  498. tempFilePath: mp4,
  499. size: Number(size) * 1000,
  500. duration: duration, //视频时间
  501. width: 360,
  502. height: 640
  503. };
  504. this.createVideoMessage(file);
  505. } else if (type == 'image') {
  506. this.createImageMessage({
  507. size: Number(size) * 1000,
  508. path: image
  509. });
  510. }
  511. //用户取消拍摄
  512. if (retult.retult == 'cancel') {}
  513. });
  514. },
  515. // =====================
  516. // 创建发送输入框内容
  517. sendingText() {
  518. if (this.text === '')
  519. return uni.showModal({
  520. showCancel: false,
  521. content: '不能发送空白信息',
  522. success: function(res) {}
  523. });
  524. let body = this.text;
  525. if (this.text.length >= 50) {
  526. body = this.text.substring(0, 30) + '...';
  527. }
  528. if (this.isQuote) {
  529. this.createCustomMessageText(body);
  530. return;
  531. }
  532. this.sendMessage({
  533. payload: {
  534. text: this.text
  535. },
  536. type: 'text'
  537. });
  538. this.text = '';
  539. },
  540. // 发送位置信息
  541. createCustomMessageMap(res, image) {
  542. const {
  543. latitude,
  544. longitude,
  545. address,
  546. name
  547. } = res;
  548. this.sendMessage({
  549. payload: {
  550. latitude,
  551. longitude,
  552. title: name,
  553. address,
  554. image //使用高德api生成图片
  555. },
  556. type: 'map'
  557. });
  558. },
  559. // 引用并发送文本
  560. createCustomMessageText(body) {
  561. this.sendMessage({
  562. payload: {
  563. text: this.text,
  564. //引用源
  565. quoteSource: {
  566. ...this.quoteSource
  567. }
  568. },
  569. type: 'text_quote'
  570. });
  571. this.text = '';
  572. },
  573. // 创建发送照片内容
  574. sendImageMessage() {
  575. uni.chooseImage({
  576. count: 9,
  577. success: async (res) => {
  578. res.tempFiles.forEach((file) => {
  579. console.log(file);
  580. this.createImageMessage(file);
  581. });
  582. }
  583. });
  584. },
  585. // 创建发送照片内容
  586. createImageMessage(file) {
  587. this.sendMessage({
  588. payload: {
  589. contentType: 'image/png',
  590. name: 'uni-image.png',
  591. size: 82942,
  592. url: file.path,
  593. width: 2732,
  594. height: 2732,
  595. thumbnail: file.path
  596. },
  597. type: 'image'
  598. });
  599. },
  600. // 创建发送视频内容
  601. sendVideoMessage() {
  602. uni.chooseVideo({
  603. success: async (res) => {
  604. console.log(res);
  605. this.createVideoMessage(res);
  606. }
  607. });
  608. },
  609. createVideoMessage(file) {
  610. this.sendMessage({
  611. payload: {
  612. video: {
  613. name: '3003009356267921_uni-video.mp4',
  614. url: file.tempFilePath,
  615. width: 640,
  616. height: 352,
  617. contentType: 'video/mp4',
  618. size: 501774,
  619. duration: 8.32
  620. },
  621. thumbnail: {
  622. name: 'uni-thumbnail.jpg',
  623. url: '封面路径',
  624. width: 364,
  625. height: 200,
  626. contentType: 'image/jpg'
  627. }
  628. },
  629. type: 'video'
  630. });
  631. },
  632. // 创建语音内容
  633. sendingRecorder(file) {
  634. this.sendMessage({
  635. payload: {
  636. contentType: 'audio/mp3',
  637. name: 'uni-audio.mp3',
  638. size: 2357,
  639. url: file.tempFilePath,
  640. duration: 1.148
  641. },
  642. type: 'audio'
  643. });
  644. },
  645. // 创建自定义表情包
  646. sendingEmojiPack(e) {
  647. this.sendMessage({
  648. payload: {
  649. ext: e.ext,
  650. url: e.url,
  651. path: e.path,
  652. text: e.text || '[表情包]'
  653. },
  654. type: 'emoji_pack'
  655. });
  656. },
  657. // 最终提交发送
  658. sendMessage({
  659. payload,
  660. type
  661. }) {
  662. const message = {
  663. groupId: '22',
  664. senderData: {},
  665. senderId: 0,
  666. messageId: Date.now(),
  667. payload: payload,
  668. timestamp: Date.now(),
  669. type: type,
  670. recalled: false,
  671. status: 'success',
  672. isHide: 0
  673. };
  674. this.$emit('pushList', message);
  675. this.isQuote = false;
  676. this.quoteSource = {};
  677. }
  678. }
  679. };
  680. </script>
  681. <style lang="scss" scoped>
  682. .bottom-operation-box {
  683. position: relative;
  684. z-index: 9999;
  685. width: 100vw;
  686. background-color: #f6f6f6;
  687. .line-break {
  688. position: absolute;
  689. z-index: 99;
  690. left: 0;
  691. top: -58rpx;
  692. width: 100%;
  693. height: 60rpx;
  694. flex-direction: row-reverse;
  695. .line-break-box {
  696. position: relative;
  697. width: 160rpx;
  698. height: 100%;
  699. color: #2c2c2c;
  700. border-radius: 20rpx 0 0 0;
  701. background-color: #f6f6f6;
  702. .line-break-icon {
  703. width: 36rpx;
  704. height: 36rpx;
  705. margin-right: 10rpx;
  706. }
  707. }
  708. .line-break-box::before {
  709. position: absolute;
  710. left: -60rpx;
  711. top: 0;
  712. content: '';
  713. width: 60rpx;
  714. height: 60rpx;
  715. display: block;
  716. text-align: center;
  717. background-image: radial-gradient(240rpx at 2rpx 0px, rgba(168, 195, 59, 0) 60rpx, #f6f6f6 60rpx);
  718. }
  719. }
  720. }
  721. .bottom-operation {
  722. box-sizing: border-box;
  723. padding: 14rpx 10rpx;
  724. width: 100%;
  725. align-items: flex-end;
  726. .bottom-operation-icon {
  727. width: 80rpx;
  728. height: 80rpx;
  729. .img {
  730. width: 80%;
  731. height: 80%;
  732. }
  733. }
  734. .bottom-operation-input {
  735. width: 100%;
  736. box-sizing: border-box;
  737. padding: 10rpx 14rpx;
  738. min-height: 84rpx;
  739. max-height: 300rpx;
  740. overflow: auto;
  741. border-radius: 10rpx;
  742. background-color: #fff;
  743. .input {
  744. width: 100%;
  745. margin: 10rpx 0;
  746. }
  747. }
  748. }
  749. .keyboard {
  750. transition: all 0.2s;
  751. }
  752. // 引用
  753. .quote {
  754. box-sizing: border-box;
  755. padding: 0 20rpx;
  756. width: 100%;
  757. height: 50rpx;
  758. margin-top: 8rpx;
  759. border-radius: 10rpx;
  760. background-color: #eaeaea;
  761. color: #686868;
  762. .quote-row {
  763. width: 200rpx;
  764. text-overflow: ellipsis;
  765. overflow: auto;
  766. white-space: nowrap;
  767. ::v-deep .quote-box {
  768. width: 100%;
  769. box-sizing: border-box;
  770. padding: 0;
  771. border-radius: 0;
  772. margin-top: 0;
  773. background-color: #eaeaea;
  774. color: #6b6b6b;
  775. .quote-name {}
  776. .m-image {
  777. border-radius: 6rpx;
  778. overflow: hidden;
  779. .img {
  780. width: 40rpx;
  781. height: 40rpx;
  782. border-radius: 6rpx;
  783. overflow: hidden;
  784. background-color: #fff;
  785. }
  786. }
  787. }
  788. }
  789. .quote-icon {
  790. width: 40rpx;
  791. height: 40rpx;
  792. }
  793. }
  794. </style>