界面结构:
- 消息列表: 使用
scroll-view
实现滚动,每条消息使用view
组件包裹,根据消息类型 (文本、图片、文件) 显示不同内容。 - 输入框区域: 包含输入框 (
textarea
)、发送按钮 (button
) 和上传文件按钮 (view
组件模拟)。 - 头像: 使用
image
组件展示。
功能实现:
- 多行输入框高度自适应: 使用
textarea
组件的auto-height
属性,并监听linechange
事件动态调整高度。 - 消息气泡样式: 使用 CSS 实现不同类型消息的气泡样式。
- 发送消息: 点击发送按钮或输入框回车时,将消息内容添加到消息列表中,并清空输入框。
- 上传文件: 点击上传文件按钮,调用小程序 API 选择文件并上传。
代码示例:
<!-- pages/chat/chat.wxml -->
<view class="container">
<scroll-view class="message-list" scroll-y="true" style="height:{{scrollHeight}}px;">
<view class="message-item {{item.isMe?'message-item-right':'message-item-left'}}" wx:for="{{messages}}" wx:key="index">
<image class="avatar" src="{{item.isMe?'my-avatar.png':'other-avatar.png'}}"></image>
<view class="message-content {{item.isMe?'message-content-right':'message-content-left'}}">
<view wx:if="{{item.type === 'text'}}">{{item.content}}</view>
<image wx:if="{{item.type === 'image'}}" src="{{item.content}}" mode="widthFix"></image>
<view wx:if="{{item.type === 'file'}}" class="file-message">
<text class="file-name">{{item.content.name}}</text>
<text class="file-size">{{item.content.size}}</text>
</view>
</view>
</view>
</scroll-view>
<view class="input-area">
<view class="input-bar">
<view class="upload-btn" bindtap="uploadFile">+</view>
<textarea class="input-text" auto-height value="{{inputValue}}" bindinput="onInput" bindconfirm="sendMessage" placeholder="请输入消息内容" />
<button class="send-btn" bindtap="sendMessage">发送</button>
</view>
</view>
</view>
// pages/chat/chat.js
Page({
data: {
scrollHeight: 0, // 滚动区域高度
inputValue: '', // 输入框内容
messages: [
{ isMe: false, type: 'text', content: '你好' },
{ isMe: true, type: 'text', content: '你好,请问有什么可以帮您?' },
],
},
// 页面加载时获取滚动区域高度
onLoad: function () {
const that = this;
wx.getSystemInfo({
success: function (res) {
that.setData({
scrollHeight: res.windowHeight - 50, // 50 为输入框区域高度
});
},
});
},
// 监听输入框内容变化
onInput: function (e) {
this.setData({
inputValue: e.detail.value,
});
},
// 发送消息
sendMessage: function () {
if (this.data.inputValue.trim() === '') return;
this.data.messages.push({
isMe: true,
type: 'text',
content: this.data.inputValue,
});
this.setData({
messages: this.data.messages,
inputValue: '',
});
// 滚动到底部
this.scrollToBottom();
},
// 上传文件
uploadFile: function () {
const that = this;
wx.chooseMessageFile({
count: 1, // 只允许选择一个文件
type: 'all', // 可以选择任意类型的文件
success: function (res) {
const file = res.tempFiles[0];
// 将文件信息添加到消息列表中
that.data.messages.push({
isMe: true,
type: 'file',
content: {
name: file.name,
size: that.formatFileSize(file.size),
},
});
that.setData({
messages: that.data.messages,
});
// 滚动到底部
that.scrollToBottom();
// TODO: 上传文件到服务器
// wx.uploadFile({
// // ...
// });
},
});
},
// 格式化文件大小
formatFileSize: function (size) {
if (size < 1024) {
return size + 'B';
} else if (size < 1024 * 1024) {
return (size / 1024).toFixed(1) + 'KB';
} else if (size < 1024 * 1024 * 1024) {
return (size / (1024 * 1024)).toFixed(1) + 'MB';
} else {
return (size / (1024 * 1024 * 1024)).toFixed(1) + 'GB';
}
},
// 滚动到底部
scrollToBottom: function () {
this.setData({
scrollTop: 999999,
});
},
});
/* pages/chat/chat.wxss */
.container {
display: flex;
flex-direction: column;
height: 100%;
padding-bottom: 0rpx;
padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/
}
.message-list {
flex: 1;
padding: 20rpx;
}
.message-item {
display: flex;
padding-bottom: 20rpx;
}
.message-item-left {
justify-content: flex-start;
}
.message-item-right {
flex-direction: row-reverse;
}
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin: 10rpx;
}
.message-content {
max-width: 70%;
padding: 20rpx;
border-radius: 10rpx;
}
.message-content-left {
background-color: #77dbd3;
}
.message-content-right {
background-color: #9eea6a;
}
.input-area {
height: 50px;
padding: 10rpx;
background-color: #f6f6f6;
}
.input-bar {
display: flex;
align-items: center;
background-color: #fff;
border-radius: 10rpx;
}
.upload-btn {
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
margin-left: 10rpx;
background-color: #f6f6f6;
border-radius: 50%;
}
.input-text {
flex: 1;
height: 80rpx;
padding: 10rpx;
font-size: 28rpx;
line-height: 40rpx;
}
.send-btn {
width: 120rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
margin-left: 10rpx;
background-color: #07c160;
color: #fff;
border-radius: 10rpx;
}
.file-message {
display: flex;
flex-direction: column;
}
.file-name {
font-size: 24rpx;
}
.file-size {
font-size: 20rpx;
color: #999;
}
注意:
- 代码中只实现了基本功能,还有很多细节可以优化,例如消息时间显示、图片预览、文件下载等。
- 上传文件功能需要配合后端接口实现。
- 样式可以根据实际需求进行调整。
希望以上代码可以帮助你!