chatInput.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <template>
  2. <view class="chat-input-container" :class="{ 'parent-container-focused': isFocus }">
  3. <view class="x-f input-container" :class="{
  4. 'input-container-focused': isFocus,
  5. 'input-container-normal': !isFocus
  6. }">
  7. <input id="txgMsg"
  8. :placeholder="placeholderText"
  9. v-model="inputValue"
  10. placeholder-style="color:#e7e7e7;"
  11. placeholder-class="placeholder-style"
  12. class="ml20 input-native input-field"
  13. :class="{ 'input-focused': isFocus }"
  14. @focus="handleFocus"
  15. @blur="handleBlur"
  16. cursor-spacing="100"
  17. :adjust-position="false" />
  18. <view class="send-btn" @click="handleSend">发送</view>
  19. </view>
  20. <view class="icon-container" :class="{ 'icon-hidden': isFocus }">
  21. <view class="icon-bg ml20" @tap="handleOpenCart">
  22. <image src="/static/images/shopping.png" class="w58 h58" />
  23. </view>
  24. <view class="icon-bg ml20" @click="handleMoreClick">
  25. <image src="/static/images/more_icon.png" class="w58 h58" />
  26. </view>
  27. </view>
  28. </view>
  29. </template>
  30. <script>
  31. export default {
  32. name: 'ChatInput',
  33. props: {
  34. placeholderText: {
  35. type: String,
  36. default: '说点什么...'
  37. },
  38. value: {
  39. type: String,
  40. default: ''
  41. },
  42. focused: {
  43. type: Boolean,
  44. default: false
  45. }
  46. },
  47. data() {
  48. return {
  49. isFocus: false,
  50. inputValue: ''
  51. };
  52. },
  53. watch: {
  54. focused: {
  55. immediate: true,
  56. handler(newVal) {
  57. this.isFocus = newVal;
  58. }
  59. },
  60. inputValue(newVal) {
  61. this.$emit('input', newVal);
  62. },
  63. value: {
  64. immediate: true,
  65. handler(newVal) {
  66. this.inputValue = newVal;
  67. }
  68. }
  69. },
  70. methods: {
  71. handleMoreClick() {
  72. this.$emit('show-more');
  73. },
  74. handleFocus() {
  75. this.isFocus = true;
  76. this.$emit('focus', this.inputValue);
  77. },
  78. handleBlur() {
  79. this.isFocus = false;
  80. this.$emit('blur', this.inputValue);
  81. },
  82. handleSend() {
  83. if (this.inputValue.trim()) {
  84. this.$emit('send', this.inputValue);
  85. this.inputValue = '';
  86. } else {
  87. uni.showToast({
  88. title: '不能发送空消息',
  89. icon: 'none'
  90. });
  91. }
  92. },
  93. handleOpenCart() {
  94. this.$emit('open-cart');
  95. },
  96. handleShowGift() {
  97. this.$emit('show-gift');
  98. },
  99. clearInput() {
  100. this.inputValue = '';
  101. },
  102. setInputValue(value) {
  103. this.inputValue = value;
  104. },
  105. getInputValue() {
  106. return this.inputValue;
  107. }
  108. }
  109. };
  110. </script>
  111. <style scoped lang="scss">
  112. .chat-input-container {
  113. display: flex;
  114. justify-content: space-between;
  115. align-items: center;
  116. padding: 24rpx;
  117. width: 100%;
  118. box-sizing: border-box;
  119. transition: all 0.3s ease;
  120. &.parent-container-focused {
  121. justify-content: flex-start;
  122. }
  123. }
  124. .input-container {
  125. background: rgba(0, 0, 0, 0.3);
  126. height: 90rpx;
  127. box-sizing: border-box;
  128. border-radius: 36rpx;
  129. display: flex;
  130. align-items: center;
  131. transition: all 0.3s ease;
  132. overflow: hidden;
  133. &.input-container-normal {
  134. padding: 10rpx 14rpx 10rpx 32rpx;
  135. flex: 1;
  136. justify-content: space-between;
  137. }
  138. &.input-container-focused {
  139. padding: 10rpx 10rpx 10rpx 20rpx;
  140. width: 100%;
  141. flex: 1 0 auto;
  142. justify-content: flex-start;
  143. gap: 20rpx;
  144. }
  145. }
  146. .input-field {
  147. border: none;
  148. font-size: 32rpx;
  149. color: #ffffff;
  150. background: transparent;
  151. flex: 1;
  152. min-width: 0;
  153. transition: all 0.3s ease;
  154. &.input-focused {
  155. flex: 1;
  156. min-width: 0;
  157. }
  158. }
  159. .send-btn {
  160. background-color: #fafafa;
  161. border-radius: 28rpx;
  162. padding: 12rpx 16rpx;
  163. color: #181818;
  164. font-weight: 500;
  165. min-width: 80rpx;
  166. text-align: center;
  167. flex-shrink: 0;
  168. white-space: nowrap;
  169. cursor: pointer;
  170. transition: all 0.2s ease;
  171. &:active {
  172. opacity: 0.8;
  173. transform: scale(0.98);
  174. }
  175. }
  176. .icon-container {
  177. display: flex;
  178. align-items: center;
  179. justify-content: space-between;
  180. flex-shrink: 0;
  181. transition: all 0.3s ease;
  182. margin-left: 20rpx;
  183. &.icon-hidden {
  184. opacity: 0;
  185. visibility: hidden;
  186. width: 0;
  187. margin-left: 0;
  188. flex: 0;
  189. }
  190. }
  191. .icon-bg {
  192. background: rgba(0, 0, 0, 0.3);
  193. border-radius: 50%;
  194. width: 88rpx;
  195. height: 88rpx;
  196. display: flex;
  197. justify-content: center;
  198. align-items: center;
  199. transition: transform 0.2s ease;
  200. cursor: pointer;
  201. &:active {
  202. transform: scale(0.95);
  203. }
  204. & + & {
  205. margin-left: 20rpx;
  206. }
  207. }
  208. .ml20 {
  209. margin-left: 20rpx;
  210. }
  211. .w58 {
  212. width: 58rpx;
  213. }
  214. .h58 {
  215. height: 58rpx;
  216. }
  217. </style>