| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- <template>
- <view class="chat-input-container" :class="{ 'parent-container-focused': isFocus }">
- <view class="x-f input-container-optimized" :class="{
- 'input-container-focused': isFocus,
- 'justify-between': !isFocus
- }" :style="containerStyle">
- <input id="txgMsg" :placeholder="placeholderText" v-model="inputValue" placeholder-style="color:#e7e7e7;"
- placeholder-class="placeholder-style" class="ml20 input-native input-optimized"
- :class="{ 'input-focused': isFocus }" @focus="handleFocus" @blur="handleBlur" cursor-spacing="100"
- :adjust-position="false" />
- <view v-if="isFocus" class="send" @click="handleSend">发送</view>
- </view>
- <view class="justify-between mr15 align-center shopping-icon-container" :style="iconContainerStyle">
- <view class="icon-bg ml20" @tap="handleOpenCart">
- <image src="/static/images/shopping.png" class="w58 h58" />
- </view>
- <view class="icon-bg ml20" @click="handleShowGift">
- <image src="/static/images/gift.png" class="w58 h58" />
- </view>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'ChatInput',
- props: {
- // 输入框占位符文本
- placeholderText: {
- type: String,
- default: '说点什么...'
- },
- // 初始输入值
- value: {
- type: String,
- default: ''
- },
- // 是否聚焦状态(从父组件传递)
- focused: {
- type: Boolean,
- default: false
- }
- },
- data() {
- return {
- isFocus: false,
- inputValue: ''
- };
- },
- computed: {
- // 输入框容器样式
- containerStyle() {
- return {
- padding: this.isFocus ? '10rpx 10rpx 10rpx 20rpx' : '10rpx 14rpx 10rpx 32rpx',
-
- width: this.isFocus ? 'calc(100% - 20rpx)' : '100%',
- maxWidth: this.isFocus ? 'calc(100% - 20rpx)' : 'auto',
- marginRight: this.isFocus ? '20rpx' : '0',
- flex: this.isFocus ? '1' : 'auto'
- };
- },
- // 图标容器样式
- iconContainerStyle() {
- return {
- opacity: this.isFocus ? 0 : 1,
- visibility: this.isFocus ? 'hidden' : 'visible',
- transform: 'translateZ(0)'
- };
- }
- },
- watch: {
- // 监听父组件传递的聚焦状态
- focused: {
- immediate: true,
- handler(newVal) {
- this.isFocus = newVal;
- }
- },
- // 监听输入值变化,同步到父组件
- inputValue(newVal) {
- this.$emit('input', newVal);
- },
- // 监听父组件传递的值变化
- value: {
- immediate: true,
- handler(newVal) {
- this.inputValue = newVal;
- }
- }
- },
- methods: {
- // 输入框聚焦事件
- handleFocus() {
- this.isFocus = true;
- this.$emit('focus', this.inputValue);
- },
- // 输入框失焦事件
- handleBlur() {
- this.isFocus = false;
- this.$emit('blur', this.inputValue);
- },
- // 发送消息
- handleSend() {
- if (this.inputValue.trim()) {
- this.$emit('send', this.inputValue);
- this.inputValue = ''; // 清空输入框
- } else {
- uni.showToast({
- title: '不能发送空消息',
- icon: 'none'
- });
- }
- },
- // 打开购物车
- handleOpenCart() {
- this.$emit('open-cart');
- },
- // 显示礼物弹窗
- handleShowGift() {
- this.$emit('show-gift');
- },
- // 清空输入框(供父组件调用)
- clearInput() {
- this.inputValue = '';
- },
- // 设置输入框值(供父组件调用)
- setInputValue(value) {
- this.inputValue = value;
- },
- // 获取输入框值(供父组件调用)
- getInputValue() {
- return this.inputValue;
- }
- }
- };
- </script>
- <style scoped lang="scss">
- .chat-input-container {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 24rpx;
- width: 100%;
- box-sizing: border-box;
- &.parent-container-focused {
- justify-content: flex-start !important;
- align-items: stretch !important;
- }
- }
- .input-container-optimized {
- background: #393939;
- height: 90rpx;
- box-sizing: border-box;
- border-radius: 36rpx;
- transform: translateZ(0);
- will-change: transform;
- backface-visibility: hidden;
- perspective: 1000px;
- display: flex;
- align-items: center;
- &.input-container-focused {
- box-sizing: border-box;
- width: calc(100% - 20rpx) !important;
- max-width: calc(100% - 20rpx) !important;
- min-width: calc(100% - 20rpx) !important;
- margin-right: 20rpx !important;
- padding: 10rpx 10rpx 10rpx 20rpx !important;
- justify-content: flex-start !important;
- gap: 20rpx !important;
- flex: 1 !important;
- flex-grow: 1 !important;
- flex-shrink: 0 !important;
- flex-basis: calc(100% - 20rpx) !important;
- }
- &.justify-between {
- justify-content: space-between;
- }
- }
- .input-optimized {
- border: none !important;
- font-size: 32rpx !important;
- color: #ffffff !important;
- background: transparent !important;
- width: 70% !important;
- transform: translateZ(0);
- will-change: contents, width;
- backface-visibility: hidden;
- flex: 1;
- &.input-focused {
- width: auto !important;
- flex: 1 !important;
- min-width: 0 !important;
- margin-left: 10rpx !important;
- max-width: none !important;
- }
- }
- .send {
- background-color: #fafafa;
- border-radius: 28rpx;
- padding: 14rpx 16rpx;
- color: #181818;
- font-weight: 500;
- min-width: 80rpx;
- text-align: center;
- flex-shrink: 0;
- white-space: nowrap;
- }
- .shopping-icon-container {
- will-change: opacity, visibility;
- backface-visibility: hidden;
- display: flex;
- align-items: center;
- justify-content: space-between;
- flex-shrink: 0;
- }
- .icon-bg {
- background-color: rgba(57, 57, 57, 0.8);
- border-radius: 50%;
- width: 88rpx;
- height: 88rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- transition: transform 0.2s ease;
- &:active {
- transform: scale(0.95);
- }
- }
- </style>
|