uniapp实现图文聊天功能

Uniapp 实现图文聊天功能

下面我将介绍如何在 Uniapp 中实现一个基本的图文聊天功能,包括消息发送、接收和展示。

一、准备工作

  1. 创建 Uniapp 项目
  2. 准备后端接口(可以使用云开发、自己的服务器或第三方服务)

二、实现步骤

1. 页面结构

<template>
  <view class="chat-container">
    <!-- 聊天消息区域 -->
    <scroll-view 
      class="message-list" 
      scroll-y="true" 
      :scroll-with-animation="true"
      :scroll-top="scrollTop"
    >
      <view 
        v-for="(item, index) in messageList" 
        :key="index" 
        :class="['message-item', item.isMe ? 'my-message' : 'other-message']"
      >
        <!-- 头像 -->
        <image 
          class="avatar" 
          :src="item.isMe ? myAvatar : otherAvatar" 
          mode="aspectFill"
        ></image>
        
        <!-- 消息内容 -->
        <view class="message-content">
          <!-- 文本消息 -->
          <text v-if="item.type === 'text'" class="text-message">{{ item.content }}</text>
          
          <!-- 图片消息 -->
          <image 
            v-else-if="item.type === 'image'" 
            class="image-message" 
            :src="item.content" 
            mode="widthFix"
            @click="previewImage(item.content)"
          ></image>
        </view>
      </view>
    </scroll-view>
    
    <!-- 输入区域 -->
    <view class="input-area">
      <!-- 图片选择按钮 -->
      <view class="action-btn" @click="chooseImage">
        <uni-icons type="image" size="24" color="#666"></uni-icons>
      </view>
      
      <!-- 文本输入框 -->
      <input 
        class="input-box" 
        v-model="inputText" 
        placeholder="输入消息..." 
        @confirm="sendTextMessage"
      />
      
      <!-- 发送按钮 -->
      <view class="send-btn" @click="sendTextMessage">
        <text>发送</text>
      </view>
    </view>
  </view>
</template>

2. JavaScript 逻辑

<script>
export default {
  data() {
    return {
      messageList: [], // 消息列表
      inputText: '', // 输入文本
      scrollTop: 0, // 滚动位置
      myAvatar: '/static/avatars/my-avatar.jpg', // 我的头像
      otherAvatar: '/static/avatars/other-avatar.jpg', // 对方头像
      socket: null // WebSocket 连接
    }
  },
  onLoad() {
    this.initWebSocket();
    // 加载历史消息
    this.loadHistoryMessages();
  },
  onUnload() {
    // 关闭 WebSocket 连接
    if (this.socket) {
      this.socket.close();
    }
  },
  methods: {
    // 初始化 WebSocket
    initWebSocket() {
      // 这里替换为你的 WebSocket 地址
      this.socket = new WebSocket('wss://your-websocket-url.com');
      
      this.socket.onopen = () => {
        console.log('WebSocket 连接成功');
      };
      
      this.socket.onmessage = (res) => {
        const message = JSON.parse(res.data);
        this.receiveMessage(message);
      };
      
      this.socket.onerror = (err) => {
        console.error('WebSocket 错误:', err);
      };
      
      this.socket.onclose = () => {
        console.log('WebSocket 连接关闭');
      };
    },
    
    // 加载历史消息
    loadHistoryMessages() {
      // 这里调用你的 API 获取历史消息
      uni.request({
        url: 'https://your-api-url.com/messages',
        success: (res) => {
          this.messageList = res.data.messages;
          this.scrollToBottom();
        }
      });
    },
    
    // 发送文本消息
    sendTextMessage() {
      if (!this.inputText.trim()) return;
      
      const message = {
        id: Date.now(),
        type: 'text',
        content: this.inputText,
        isMe: true,
        time: new Date().toLocaleTimeString()
      };
      
      // 添加到消息列表
      this.messageList.push(message);
      this.inputText = '';
      
      // 发送到服务器
      this.sendToServer(message);
      
      // 滚动到底部
      this.$nextTick(() => {
        this.scrollToBottom();
      });
    },
    
    // 选择图片
    chooseImage() {
      uni.chooseImage({
        count: 1,
        sizeType: ['compressed'],
        sourceType: ['album', 'camera'],
        success: (res) => {
          const tempFilePaths = res.tempFilePaths;
          this.uploadImage(tempFilePaths[0]);
        }
      });
    },
    
    // 上传图片
    uploadImage(filePath) {
      uni.showLoading({ title: '上传中...' });
      
      // 这里替换为你的上传 API
      uni.uploadFile({
        url: 'https://your-api-url.com/upload',
        filePath: filePath,
        name: 'file',
        success: (uploadRes) => {
          const res = JSON.parse(uploadRes.data);
          if (res.code === 0) {
            const message = {
              id: Date.now(),
              type: 'image',
              content: res.data.url,
              isMe: true,
              time: new Date().toLocaleTimeString()
            };
            
            this.messageList.push(message);
            this.sendToServer(message);
            
            this.$nextTick(() => {
              this.scrollToBottom();
            });
          }
        },
        complete: () => {
          uni.hideLoading();
        }
      });
    },
    
    // 发送消息到服务器
    sendToServer(message) {
      if (this.socket && this.socket.readyState === WebSocket.OPEN) {
        this.socket.send(JSON.stringify(message));
      } else {
        // 如果 WebSocket 不可用,使用 HTTP 请求
        uni.request({
          url: 'https://your-api-url.com/send',
          method: 'POST',
          data: message,
          success: () => {
            console.log('消息发送成功');
          }
        });
      }
    },
    
    // 接收消息
    receiveMessage(message) {
      message.isMe = false; // 标记为对方消息
      this.messageList.push(message);
      
      this.$nextTick(() => {
        this.scrollToBottom();
      });
    },
    
    // 预览图片
    previewImage(url) {
      uni.previewImage({
        urls: this.messageList
          .filter(item => item.type === 'image')
          .map(item => item.content),
        current: url
      });
    },
    
    // 滚动到底部
    scrollToBottom() {
      // 这里需要根据实际内容高度计算
      this.scrollTop = 99999;
    }
  }
}
</script>

3. CSS 样式

<style>
.chat-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: #f5f5f5;
}

.message-list {
  flex: 1;
  padding: 20rpx;
  overflow: auto;
}

.message-item {
  display: flex;
  margin-bottom: 30rpx;
}

.my-message {
  flex-direction: row-reverse;
}

.other-message {
  flex-direction: row;
}

.avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 10rpx;
}

.message-content {
  max-width: 60%;
  margin: 0 20rpx;
}

.text-message {
  padding: 15rpx 20rpx;
  border-radius: 10rpx;
  background-color: #fff;
  font-size: 28rpx;
  line-height: 1.5;
}

.my-message .text-message {
  background-color: #95ec69;
}

.image-message {
  max-width: 100%;
  border-radius: 10rpx;
}

.input-area {
  display: flex;
  align-items: center;
  padding: 20rpx;
  background-color: #fff;
  border-top: 1rpx solid #eee;
}

.input-box {
  flex: 1;
  height: 70rpx;
  padding: 0 20rpx;
  margin: 0 20rpx;
  border-radius: 35rpx;
  background-color: #f5f5f5;
  font-size: 28rpx;
}

.action-btn {
  padding: 10rpx;
}

.send-btn {
  padding: 10rpx 20rpx;
  color: #007aff;
  font-size: 28rpx;
}
</style>

三、功能扩展建议

  1. 消息状态:添加发送中、已发送、已读等状态
  2. 消息撤回:实现消息撤回功能
  3. 语音消息:添加语音消息功能
  4. 表情包:支持表情包发送
  5. 消息分页:实现消息分页加载
  6. 离线消息:处理离线消息同步
  7. 消息加密:增加消息加密功能

四、注意事项

  1. 实际开发中需要替换示例中的 API 地址和 WebSocket 地址
  2. 图片上传需要根据后端接口调整参数
  3. 生产环境需要考虑安全性、性能优化等问题
  4. 对于复杂的聊天应用,建议使用成熟的即时通讯 SDK(如融云、环信等)

这个实现提供了基本的图文聊天功能,你可以根据实际需求进行扩展和优化。

### 关于 UniApp 的登录和注册功能 #### 手机号码一键登录 在 UniApp 开发中,实现 App 端手机号码的一键登录是一项重要功能。通过此方式,用户可以利用本机号码快速完成免密登录操作而无需接收短信验证码。该方法支持中国移动、中国联通以及中国电信三大运营商,并提供详细的图文教程帮助开发者顺利集成这一特性[^1]。 ```javascript // 示例代码:初始化一键登录插件并调用接口获取手机号 import { init, getPhoneNumber } from 'path-to-plugin'; init({ appId: 'your_app_id', }); getPhoneNumber().then((res) => { console.log('Phone number:', res.phoneNumber); }).catch((err) => { console.error(err); }); ``` #### 使用 OpenIM SDK 进行即时通讯应用中的账号管理 对于更复杂的场景比如构建具备聊天功能的应用程序来说,则可以通过引入 `open-uniapp` 来简化工作流程。这个开源项目提供了完整的 API 文档和支持多种设备同步的消息传递机制,在此基础上还可以方便地扩展其他社交属性的功能模块[^2]。 ```javascript // 示例代码:基于 OpenIM SDK 创建新账户或执行登录逻辑 const sdk = require('@openim/sdk'); sdk.init({ /* 初始化参数 */ }); async function loginOrCreateAccount() { try { await sdk.login({ userID: 'user-id', token: 'token' }); // 登录成功后的处理... } catch (error) { if (error.code === 404) { const result = await sdk.createAccount(/* 用户信息 */); // 新建账户成功的后续动作... } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值