用uniapp 及socket.io做一个简单聊天app 5

聊天中的通知及好友申请:

如下图效果

聊天的效果:

这里的friends,好友例表,里面有相关代码:

php 复制代码
<template>
  <view class="friends-container">
    <view v-if="!isLoggedIn" class="not-logged-in">
      <text>您尚未登录。请先登录以查看好友列表。</text>
      <button @click="goToLogin">去登录</button>
    </view>
    <view>
      <view v-if="friends.length === 0">
        <uni-list>
          <uni-list-chat
            :avatar-circle="true"
            title="增加好友"
            note="输入用户帐号或群号"
            :avatar="'../../static/addfriend.png'"
            showArrow
            link
            @click="gotadd"
          ></uni-list-chat>
        </uni-list>
      </view>
      <view>
        <uni-list>
          <uni-list-chat
            v-for="(friend, index) in friendsInv"
            :key="index"
            :title="friend.group ? friend.group.name : friend.user.username"
            :avatar-circle="true"
            :note="formatDate(friend.created_at) + ' 邀请'"
            badge-position="left"
            badge-text="邀请"
            showArrow
            link
            @tap="aggrees(friend.id)"
            :avatar="friend.group ? friend.group.avatar_url : friend.user.avatar_url"
          ></uni-list-chat>
        </uni-list>
      </view>
      <view v-if="friends.length > 0">
        <uni-list>
          <uni-list-chat
            :avatar-circle="true"
            title="增加好友"
            note="输入用户帐号或群号"
            :avatar="'../../static/addfriend.png'"
            showArrow
            link
            @click="gotadd"
          ></uni-list-chat>
        </uni-list>
        <uni-list>
          <uni-list-chat
            v-for="(friend, index) in friends"
            :key="index"
            :title="friend.type === 'group' ? '[群]' + friend.group.name : friend.user.username"
            :avatar-circle="true"
            :avatar="friend.type === 'group' ? friend.group.avatar_url : friend.user.avatar_url"
            :note="friend.message||'暂无聊天'"
            :time="friend.time"
            badge-position="left"
            :badge-text="friend.type === 'group' ? friend.count + '人' : ''"
            showArrow
            link
            @click="toChat(friend)"
          ></uni-list-chat>
        </uni-list>
      </view>
      <button @click="loadMoreFriends" v-if="hasMoreFriends">加载更多</button>
    </view>
    <uni-popup ref="popupBag" type="center">
      <view class="bagDetail">
        <view class="title flex align-center justify-content-between">
          <view class="flex-sub">添加好友</view>
          <view class="close-button" style="font-size: 22px" @tap="closepopupBag">×</view>
        </view>
        <uni-list :border="true">
          <uni-list-item title="邀请好友" note="请输入正确的帐号" badge-position="right" badge-text="dot" link @tap="goaddurl"></uni-list-item>
          <uni-list-item title="创建群" note="群号创建后不能修改" badge-position="right" badge-text="dot" link @tap="gogroupurl"></uni-list-item>
        </uni-list>
      </view>
    </uni-popup>
    <uni-popup ref="popupAggreeBag" type="center">
      <view class="bagDetail">
        <view class="title flex align-center justify-content-between">
          <view class="flex-sub">邀请操作</view>
        </view>
        <uni-list :border="true">
          <uni-list-item title="同意" note="同意后加入" badge-position="right" badge-text="dot" link @tap="aggree(1)"></uni-list-item>
          <uni-list-item title="拒绝" note="拒绝后则不再显示" badge-position="right" badge-text="dot" link @tap="aggree(0)"></uni-list-item>
        </uni-list>
      </view>
    </uni-popup>
    <button @click="myself">我的信息</button>
  </view>
</template>

<script>
import { mapState, mapActions } from 'vuex';
import io from 'socket.io-client';
import config from '@/config/config.js';

export default {
  data() {
    return {
      page: 1,
      perPage: 20,
      loading: false,
      hasMoreFriends: false,
      message: '',
      friends: [],
      friendsInv: [],
      aggreeid: '',
    };
  },

  computed: {
    ...mapState(['token', 'lastMessages']),
    isLoggedIn() {
      return !!this.token;
    },
  },

  onLoad() {
    this.invateFriends();
		this.loadFriends();
  },

  mounted() {
    this.socket = io(config.apiBaseUrl, {
      query: {
        token: this.token,
      },
    });
    this.socket.on('connect', () => {
      console.log('Socket connected:', this.socket.id);
    });
    this.socket.on('disconnect', () => {
      console.log('Socket disconnected');
    });

		this.socket.on('message', (msg) => {
			console.log('Received message:', msg);
    this.friends = this.friends.map((friend) => {
        if (friend.id == msg.group_name || (friend.group && friend.group.id == msg.group_name.replace("g_", ""))) {
          friend.message = msg.content;
        }
        return friend;
      });
			
			console.log(this.friends)
		});
		
		
  },
  beforeDestroy() {
    if (this.socket) {
      this.socket.off('message', this.handleNewMessage);
      this.socket.disconnect();
    }
  },
  methods: {
    ...mapActions(['fetchFriends']),
    handleNewMessage(msg) {
      this.friends = this.friends.map((friend) => {
        if (friend.id == msg.group_name || (friend.group && friend.group.id == msg.group_name.replace("g_", ""))) {
          friend.message = msg.content;
        }
        return friend;
      });
			console.log(this.friends)
			
    },
    async aggrees(id) {
      this.aggreeid = id;
      this.$refs.popupAggreeBag.open();
    },
    async aggree(agid) {
      try {
        this.$refs.popupAggreeBag.close();
        const token = uni.getStorageSync('token');
        const [error, response] = await uni.request({
          url: `${config.apiBaseUrl}/agree`,
          method: 'POST',
          header: {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json',
          },
          data: {
            id: this.aggreeid,
            status: agid === 1 ? 'accepted' : 'declined',
          },
        });
        if (response.data.code === 0) {
          uni.showToast({
            title: response.data.message,
            duration: 2000,
          });
          this.loadFriends();
          this.invateFriends();
        } else {
          uni.showToast({
            title: response.data.message,
          });
        }
      } catch (error) {
        console.error(error);
      }
    },
    formatDate(date) {
      const d = new Date(date);
      const year = d.getFullYear();
      const month = (d.getMonth() + 1).toString().padStart(2, '0');
      const day = d.getDate().toString().padStart(2, '0');
      const hours = d.getHours().toString().padStart(2, '0');
      const minutes = d.getMinutes().toString().padStart(2, '0');
      return `${year}年${month}月${day}日 ${hours}:${minutes}`;
    },
    async loadFriends() {
      const token = uni.getStorageSync('token');
      if (!token) return;
      try {
        const [error, response] = await uni.request({
          url: `${config.apiBaseUrl}/friends`,
          method: 'GET',
          header: {
            Authorization: `Bearer ${token}`,
          },
        });
        if (response.data) {
          this.friends = response.data.data;
        }
      } catch (error) {
        console.error(error);
      }
    },
    toChat(item) {
      const url = item.type === 'user'
        ? `/pages/index/chat?id=${item.id}&type=${item.type}&tid=${item.group_friend_id}`
        : `/pages/index/chat?id=g_${item.group_friend_id}&type=${item.type}&tid=${item.group_friend_id}`;
      uni.navigateTo({ url });
    },
    loadMoreFriends() {
      this.page++;
      this.loadFriends();
    },
    async invateFriends() {
      try {
        const token = uni.getStorageSync('token');
        const [error, response] = await uni.request({
          url: `${config.apiBaseUrl}/invateFriends`,
          method: 'GET',
          header: {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json',
          },
        });
        if (response.data.code === 0) {
          this.friendsInv = response.data.data.map(friend => ({
            ...friend,
            id: friend.id.toString(),
          }));
        } else {
          this.friendsInv = [];
        }
      } catch (error) {
        console.error(error);
      }
    },
    goToLogin() {
      uni.navigateTo({
        url: '/pages/index/login',
      });
    },
    gotadd() {
      this.$refs.popupBag.open();
    },
    goaddurl() {
      this.closepopupBag();
      uni.navigateTo({
        url: '/pages/index/addfriend',
      });
    },
    gogroupurl() {
      this.closepopupBag();
      uni.navigateTo({
        url: '/pages/index/addgroup',
      });
    },
    myself() {
      uni.navigateTo({
        url: '/pages/index/profile',
      });
    },
    closepopupBag() {
      this.$refs.popupBag.close();
    },
  },
};
</script>

<style>
.container {
  padding: 20px;
}

.bagDetail {
  padding: 10px;
  width: 100%;
  height: 30%;
  position: fixed;
  background-color: #ffffff;
  left: 0;
  display: flex;
  flex-direction: column;
}

#messages {
  height: 300px;
  overflow-y: scroll;
  border: 1px solid #ccc;
  margin-bottom: 10px;
}

input {
  display: block;
  margin: 10px 0;
}

button {
  display: block;
  margin: 10px 0;
}

.user-list {
  margin-top: 20px;
  border: 1px solid #ccc;
  padding: 10px;
}

.title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 10px;
}

.close-button {
  font-size: 22px;
  cursor: pointer;
}
</style>
相关推荐
sun00770037 分钟前
android ndk编译valgrind
android
AI视觉网奇2 小时前
android studio 断点无效
android·ide·android studio
jiaxi的天空2 小时前
android studio gradle 访问不了
android·ide·android studio
No Silver Bullet3 小时前
android组包时会把从maven私服获取的包下载到本地吗
android
catchadmin3 小时前
PHP serialize 序列化完全指南
android·开发语言·php
Q_Q19632884754 小时前
python+springboot+uniapp微信小程序题库系统 在线答题 题目分类 错题本管理 学习记录查询系统
spring boot·python·django·uni-app·node.js·php
tangweiguo030519874 小时前
Kable使用指南:Android BLE开发的现代化解决方案
android·kotlin
百思可瑞教育5 小时前
使用UniApp实现一个AI对话页面
javascript·vue.js·人工智能·uni-app·xcode·北京百思可瑞教育·百思可瑞教育
不想吃饭e6 小时前
在uniapp/vue项目中全局挂载component
前端·vue.js·uni-app
00后程序员张7 小时前
iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
android·安全·ios·小程序·uni-app·cocoa·iphone