# 一、多进程处理前端调整
在项目上线前,为了应对高并发量和高可用性的海量webscoket请求,后端[具体文档查看:eggjs多进程处理]会使用多进程处理,那么对应前端部分基本不用改动什么,只是对有些地方请求websocket的逻辑做一下调整即可。
# 1. 针对登录用户(角色为user的用户)
在类文件 /common/js/chatClass.js
...
// 连接websocket
connectSocket() {
this.chatSocket = uni.connectSocket({
// http://192.168.2.7:7001
// ws://192.168.2.7:7001/ws
// https://lesson07.51yrc.com
// wss://lesson07.51yrc.com/ws
url: this.url + `/ws?token=${this.user.token}`,
complete: () => {},
timeout: 10000, // 10秒超时
});
// 连接成功
this.chatSocket.onOpen(() => {
console.log('websocket连接成功');
// 调用方法
this.onOpen();
//启动心跳
this.heartbeatTimer = setInterval(() => {
if (this.chatSocket && this.chatSocket.readyState === 1) {
// 确保发送的是字符串格式的JSON
const heartbeatMsg = JSON.stringify({
type: 'ping',
token: this.user.token,
timestamp: Date.now() // 添加时间戳便于调试
});
// console.log('发送心跳消息:', heartbeatMsg);
// this.chatSocket.send(heartbeatMsg);
}
}, 5000); // 每隔5秒发送一次心跳
});
// 接收信息
this.chatSocket.onMessage(res => {
// 处理一下不同平台消息格式
try {
const data = typeof res.data === 'string' ?
JSON.parse(res.data) : res.data;
console.log('监听接收消息', data);
// 处理接收的websocket消息
this.onMessage(data);
// 如果服务器返回ping
if (data.type === 'ping') {
console.log('响应服务器心跳');
// 响应心跳 -- 自由发挥
}
} catch (e) {
console.error('接收信息错误', e);
}
});
// 断开连接
this.chatSocket.onClose(res => {
console.log('断开连接的原因', res);
// 清除心跳
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
//调用方法
this.onClose();
// 对用户做个提示
if(this.user.role == 'user'){
// 如果修改服务器代码可能异常关闭1006,这种情况除外
if(!(res.code && res.code == 1006)){
uni.showModal({
title: '账号异地登录',
content: '您的账号在异地登录,本设备将会退出',
showCancel: false,
confirmText: '我知道了',
success: res => {},
});
console.log('则清空本地登录信息,在换成游客模式');
let _that = this;
store.dispatch('logoutAction', ()=>{
_that.doRegisterGuest();
});
}else{
// 尝试重新连接
setTimeout(() => {
console.log('断开连接尝试重新连接websocket');
//dispatch('initChatuserAction');
this.connectSocket();
}, 1000);
}
}else{
// 游客尝试重新连接
setTimeout(() => {
console.log('断开连接尝试重新连接websocket');
//dispatch('initChatuserAction');
this.connectSocket();
}, 1000);
}
});
// 错误处理
this.chatSocket.onError(err => {
console.error('websocket 错误:', err);
// 清除心跳
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
//调用方法
this.onClose();
// 尝试重新连接
setTimeout(() => {
console.log('错误处理尝试重新连接websocket');
//dispatch('initChatuserAction');
this.connectSocket();
}, 1000);
});
}
...
// 关闭链接
close() {
// 用户退出登录
// 调用socketTask 对象 close方法
if (this.chatSocket) {
this.chatSocket.close();
}
}
...
// 获取离线消息(不在线的时候别人或者群发的消息)
chatGetmessageOffLine(){
uni.$u.http.post(requestUrl.http + `/api/chat/chatGetmessageOffLine`, {}, {
header: {
token: this.user.token,
},
}).then(res => {
console.log('服务器返回离线消息', res);
}).catch(err => {
console.log('服务器返回离线消息失败', err);
if(err.data && err.data.data == 'Token 令牌不合法!'){
if(this.user.role == 'visitor'){
console.log('游客如果token令牌错误,重新获取token并连接websocket');
// this.registerGuestAndConnect(); // 游客不需要提示,会自动重连的
}else if(this.user.role == 'user'){
console.log('登录用户token不正确,说明在的别的设备登录了,则清空本地登录信息,在换成游客模式');
store.dispatch('logoutAction', ()=>{
this.doRegisterGuest();
});
}
}
});
}
...
# 2. 类文件 /common/js/chatClass.js 完整代码
具体查看:类文件 /common/js/chatClass.js 完整代码
# 3. 聊天页
在页面 /pages/chat/chat.nvue
<!-- 底部聊天输入区域 --><!-- 修改:添加ref获取textarea实例 -->
<view v-if="arg.action != 'searhChatData' && arg.id"
...>
</view>
...
computed:{
...
//标题
pagetitle(){
if(this.arg && this.arg.name){
// #ifdef H5 || APP
if(this.arg.name.length > 15){
return this.arg.name.substring(0,15) + '...';
}
return this.arg.name;
// #endif
// #ifdef MP
if(this.arg.name.length > 5){
return this.arg.name.substring(0,5) + '...';
}
return this.arg.name;
// #endif
}
return ``;
},
...
}
# 二、游客扫码加入群聊
# 1. H5端扫码(比如用微信扫一扫、手机浏览器等)
说明:
- 注意H5端打开群二维码,(如果你用的是本地服务器)需要用ip地址作为前缀,不要用localhost打开,否则页面无法开发;
# ① 页面处理
在页面 /pages/setpageInfo/setpageInfo.vue
<template>
<view>
<!-- 导航栏 -->
...
<!-- 内容 -->
<view>
<!-- 聊天相关 -->
...
<!-- 聊天页设置 -->
...
<!-- 群二维码 -->
...
<!-- 扫码之后的页面 -->
<view v-if="setdata.action == 'autoAddGroup'">
<!-- 群头像及介绍 -->
...
<!-- 加群按钮 -->
<view class="p-3">
<view v-if="chatpageset.showAddGroupDesc"
class="mb-2">
<u-textarea v-model="chatpageset.addGroupDesc"
border="surround" :maxlength="500"
:adjustPosition="false"
placeholder="说明一下加群理由,方便群主快速通过,选填(可不填)"
count :autoHeight="false"
@confirm="ScanQrcodeApplyAddGroup"
:height = "100"></u-textarea>
</view>
<!-- 页面按钮 -->
<u-button v-if="!chatpageset.showAddGroupDesc"
:text="chatpageset.buttonText"
type="success" @click="addGroupfn"></u-button>
<!-- 申请加群 -->
<u-button v-if="chatpageset.showAddGroupDesc"
text="提 交 加 群 申 请"
type="primary" @click="ScanQrcodeApplyAddGroup"></u-button>
</view>
<!-- 群公告 -->
...
<!-- h5端页面在微信打开没有导航栏给它一个底部导航栏 -->
...
</view>
<!-- 账号信息设置 -->
...
<!-- 头像剪裁500rpx * 500rpx -->
...
<!-- 删除群成员 -->
...
<!-- 添加好友进群 -->
...
<!-- 群主审批进群处理 -->
<view ...>
<!-- 要加入的群 -->
...
<!-- 申请信息 -->
<view v-if="chatpageset.applydesc">
<!-- 进群方式 -->
...
<!-- 邀请人 -->
...
<!-- 邀请时间 -->
...
<!-- 加群申请说明 -->
...
</view>
<!-- 申请人 -->
<view>
<!-- 申请人头像昵称 -->
<view ...>
...
<view ...>
<!-- 申请人头像 -->
...
<!-- 申请人昵称 -->
...
<!-- 申请人角色 -->
<text class="font text-warning ml-2">{{chatpageset.addGroupUserRole}}</text>
</view>
</view>
</view>
<!-- 处理 -->
...
</view>
</view>
</view>
</template>
<script>
...
export default {
...
data() {
return {
...
chatpageset:{
...,
showAddGroupDesc: false, // 是否显示加群说明输入框
},
}
},
onLoad(e) {
...
// 动态生成数据
if(e.action){
this.setdata.action = e.action;
if(this.setdata.action == 'chatset'){
...
}else if(this.setdata.action == 'chatpageset'){
...
}else if(this.setdata.action == 'groupQrcode'){
...
}else if(this.setdata.action == 'autoAddGroup'){
...
}else if(this.setdata.action == 'userinfoSet'){
...
}else if(this.setdata.action == 'avatarCut'){
...
}else if(this.setdata.action == 'deleteUserFromGroup'){
...
}else if(this.setdata.action == 'addUserFromGroup'){
...
}else if(this.setdata.action == 'applyAddGroup'){
...
// 点击申请人跳转到用户详情
...
// 申请人角色
this.chatpageset.addGroupUserRole = this.chatpageset.applydesc ?
this.chatpageset.applydesc.addGroupUserRole : '';
this.chatpageset.addGroupUserRole =
this.chatpageset.addGroupUserRole == 'visitor' ? '游客' : '平台用户';
}
}
},
...
}
</script>
# ② 功能实现
在文件 /pages/setpageInfo/group.js
...
export default {
...,
methods: {
// 扫二维码申请加群
ScanQrcodeApplyAddGroup(){
console.log('扫二维码申请加群提交');
this.addGroupUser({
friend_id: this.me.id,
inviteuser_id: -1, // 邀请者如果小于0,则是自主进群
addGroupDesc: this.chatpageset.addGroupDesc, // 进群说明
});
},
// 处理进群的申请
...,
// 进群设置
...,
// 添加好友进群
...,
// 搜索好友
...,
// 往群里面加人
...,
// 点击群成员
...,
// 搜索群成员
...,
// 清空搜索
...,
// 删除群成员
...,
// 加入群聊
addGroupfn(){
console.log('加入群聊,看管理员怎么设置的');
console.log('看一下群信息', this.chatpageset);
// 如果扫码用户就是群成员或者群主,则直接进群聊天
if(this.chatpageset.isGroupUser){
// 是群成员则直接进群
// 进入聊天页 传一下用户的信息过去在页面展示
const userchat = {
id: this.chatpageset.id,
name: this.chatpageset.name,
avatar: this.chatpageset.avatar,
chatType: 'group', // 单聊 single 群聊 group
};
uni.navigateTo({
url: `/pages/chat/chat?arg=${encodeURIComponent(JSON.stringify(userchat))}`,
});
return;
}
// 非群成员
if(this.chatpageset.invite_confirm == 0){
// 不需要群主同意可直接提交进群
this.ScanQrcodeApplyAddGroup();
}else if(this.chatpageset.invite_confirm == 1){
// 需要经过群主同意
this.chatpageset.showAddGroupDesc = true;
}else if(this.chatpageset.invite_confirm == 2){
// 游客需要先登录在申请,登录用户需要群主同意
if(this.me.role == 'visitor'){
let redirectUrl = ``;
// #ifdef H5
redirectUrl = window.location.href.split('#')[1];
// #endif
uni.showModal({
content: '群主设为:先登录或注册账号再进群',
cancelText: '取消',
confirmText: '登录或注册',
success: res => {
if(res.confirm){
uni.navigateTo({
url: `/pages/loginCenter/loginCenter?redirectUrl=${redirectUrl}`,
});
}
},
});
}
}
},
// 解散群或者退群或者删除好友
...,
// 获取群资料
getgroupinfo(){
return new Promise((resolve,reject)=>{
uni.$u.http.get(...).then(res => {
...
// 群名称
...
console.log('显示到页面的群资料',this.chatpageset);
// 新增一个判断当前用户是不是群成员
this.chatpageset.isGroupUser = false;
this.chatpageset.buttonText = '加入群聊';
// 获取群成员的id集合
let groupUsersIds = [];
if(this.chatpageset.users.length){
groupUsersIds = this.chatpageset.users.map(v => v.user_id);
}
if(groupUsersIds.length){
if(groupUsersIds.includes(this.me.id)){
// 是群成员
this.chatpageset.isGroupUser = true;
this.chatpageset.buttonText = '进群聊天';
}
}
resolve(this.chatpageset);
}).catch(err =>{
this.navigateBack();
});
});
},
...
}
}
# 三、游客界面调整
# ① 消息页页面调整
由于我的页面很多需要登录,作为游客可简化页面只留一个消息页, 在页面 /pages/xiaoxi/xiaoxi.nvue
<template>
<view>
...
</view>
</template>
<script>
import toolJs from '@/common/mixins/tool.js';
...
export default {
mixins:[parseTimeJs,toolJs],
...
onLoad() {
...
// 是否显示底部tab栏
this.tabbarShow();
},
onShow() {
...
// 是否显示底部tab栏
this.tabbarShow();
},
...
}
</script>
# ② 混入方法计算属性等到tool.js
在文件 /common/mixins/tool.js
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
export default {
computed: {
...mapState({
me : state => state.Chatuser.regloginUser,
}),
// 是否是游客
isVisitor(){
if(this.me && this.me.role == 'visitor'){
return true;
}
return false;
},
},
methods: {
// 是否显示底部tab栏
tabbarShow(){
if(this.me.role == 'visitor'){
uni.hideTabBar();
}else{
uni.showTabBar();
}
},
...
}
}
# ③ 顶部导航栏处理
在组件 /components/chat-navbar/chat-navbar.vue
<template>
<view>
<!-- 导航栏 -->
<view ...>
<!-- 状态栏 -->
...
<!-- 导航 -->
<!-- #ifdef APP || H5 -->
<view ...>
<!-- 左边 -->
...
<!-- 右边 -->
<view class="flex align-center">
<!-- 游客 -->
<view v-if="isVisitor">
<chat-navbar-icon-button @click="openAddGroup">
<text class="iconfont font-lg"></text>
</chat-navbar-icon-button>
</view>
<!-- 登录用户 -->
<view v-else
class="flex align-center">
<chat-navbar-icon-button @click="openUser" v-if="showUser">
<text class="iconfont font-lg"></text>
</chat-navbar-icon-button>
<chat-navbar-icon-button @click="openPlus" v-if="showPlus">
<text class="iconfont font-md"></text>
</chat-navbar-icon-button>
<slot name="right"></slot>
</view>
</view>
</view>
<!-- #endif -->
<!-- #ifdef MP -->
<view ...>
<!-- 左边 -->
<view class="flex align-center flex-1">
<!-- 返回箭头 -->
<chat-navbar-icon-button v-if="showBack" @click="navigateBack">
<text class="iconfont font-md"></text>
</chat-navbar-icon-button>
<!-- 游客 -->
<view v-if="isVisitor">
<chat-navbar-icon-button @click="openAddGroup">
<text class="iconfont font-lg"></text>
</chat-navbar-icon-button>
</view>
<!-- 登录用户 -->
<view v-else
class="flex align-center flex-1">
<chat-navbar-icon-button @click="openPlus" v-if="showPlus">
<text class="iconfont font-md"></text>
</chat-navbar-icon-button>
<chat-navbar-icon-button @click="openUser" v-if="showUser">
<text class="iconfont font-lg"></text>
</chat-navbar-icon-button>
</view>
</view>
<!-- 中间 -->
...
<!-- 右边 -->
...
</view>
<!-- #endif -->
</view>
<!-- 占位符:占用 状态栏 + 导航栏的高度 -->
...
<!-- 导航栏点击加号的弹出菜单 -->
...
</view>
</template>
<script>
import toolJs from '@/common/mixins/tool.js';
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
export default {
...
mixins:[toolJs],
...,
methods: {
...,
openAddGroup(){
uni.redirectTo({
url:`/pages/applyMyfriend/applyMyfriend?action=grouplist&title=${encodeURIComponent('我的群聊列表')}`,
});
},
},
...
}
</script>
# ④ 我的页面调整
在页面 /pages/wode/wode.nvue
<template>
<view>
...
<!-- 我的二维码 -->
<view v-if="!isVisitor">
<!-- 间隔槽 -->
<u-gap height="10" bgColor="#EDEDED"></u-gap>
<u-cell-group>
<u-cell icon="grid" title="我的二维码"
:border="false" clickable isLink
:customStyle="customStyles"
:iconStyle="iconStyles"
:titleStyle="titleStyles"
@click="openMyQrcode"></u-cell>
</u-cell-group>
</view>
</view>
</template>
<script>
import toolJs from '@/common/mixins/tool.js';
import {requestUrl} from '@/common/mixins/configData.js';
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
export default {
mixins:[toolJs],
data() {
return {
...
uCellMenus:[
{icon:'plus-people-fill',title:'添加朋友',url:'/pages/search/search'},
{icon:'man-add-fill',title:'我的群聊',url:`/pages/applyMyfriend/applyMyfriend?action=grouplist&title=${encodeURIComponent('我的群聊列表')}`},
// #ifndef H5
{icon:'scan',title:'扫一扫',url:''},
// #endif
],
}
},
onLoad() {
...
console.log('用户或者游客的信息', this.me);
},
computed:{
// ...mapState({
// user : state => state.Chatuser.regloginUser,
// }),
...,
//头像
avatarShow(){
let avatar = ``;
if(this.me){
avatar = this.me.avatar;
if(avatar && avatar.startsWith('/')){
avatar = requestUrl.http + avatar;
}
}
return avatar;
},
// 账号
nicknameShow(){
let str = ``;
if(this.me){
if(this.me.role == 'user'){
str = this.me.nickname || this.me.username;
}else if(this.me.role == 'visitor'){
str = `登 录`;
}
}
return str;
},
// 账号下面的小字
nicknameNextShow(){
let str = ``;
if(this.me){
if(this.me.role == 'user'){
str = `账号:${this.me.username}`;
}else if(this.me.role == 'visitor'){
str = `登录获取更多服务`;
}
}
return str;
},
},
methods: {
//点击Cell菜单
openCell(item,index){
console.log('点击Cell菜单',item);
if(!item.url) return;
if(!this.me || this.me.role == 'visitor'){
return uni.navigateTo({
url:'/pages/loginCenter/loginCenter'
});
}
uni.navigateTo({
url:item.url,
});
},
//点击头像昵称
clickAvatarNickname(){
if(!this.me || this.me.role == 'visitor'){
return uni.navigateTo({
url: '/pages/loginCenter/loginCenter',
});
}
// 打开设置页
uni.navigateTo({
url: '/pages/setpage/setpage',
});
},
// 我的二维码
openMyQrcode(){
console.log('打开我的二维码');
let name = this.me.nickname || this.me.username;
let op = {
action: 'groupQrcode',
title: encodeURIComponent(`我的二维码`),
id: this.me.id,
name: encodeURIComponent(name),
avatar: encodeURIComponent(this.me.avatar),
chatType: 'single',
};
uni.redirectTo({
url:`/pages/setpageInfo/setpageInfo?action=${op.action}&title=${op.title}&id=${op.id}&name=${op.name}&avatar=${op.avatar}&chatType=${op.chatType}`,
});
},
}
}
</script>
# 四、游客扫码加好友
# 1、完成界面部分
# ① 在页面 /pages/setpageInfo/setpageInfo.vue
<template>
<view>
<!-- 导航栏 -->
...
<!-- 内容 -->
<view>
<!-- 聊天相关 -->
...
<!-- 聊天页设置 -->
...
<!-- 扫码之后的页面 -->
<view v-if="setdata.action == 'autoAddGroup'">
<!-- 群头像及介绍 -->
<view class="m-3 bg-light p-3">
<!-- 群 -->
<view v-if="chatpageset.chatType == 'group'"
class="flex flex-row align-center">
<!-- 群头像 -->
...
<!-- 群名称及介绍 -->
...
</view>
<!-- 个人 -->
<view v-if="chatpageset.chatType == 'single'"
class="flex flex-row align-center">
<!-- 头像 -->
<u--image :src="chatpageset.avatar" mode="widthFix"
width="90rpx" height="90rpx" radius="8rpx"></u--image>
<!-- 介绍 -->
<view class="flex flex-column justify-center ml-2">
<text class="mb-1 u-line-1">{{chatpageset.name}}</text>
<!-- 关注度 -->
<!-- 粉丝 -->
</view>
</view>
</view>
<!-- 加群按钮 -->
<view class="p-3">
<!-- 进群理由 -->
<view v-if="chatpageset.showAddGroupDesc"
class="mb-2">
<u-textarea v-model="chatpageset.addGroupDesc"
border="surround" :maxlength="500"
:adjustPosition="false"
:placeholder="chatpageset.areaPlaceHolder ||
`说明一下加群理由,方便群主快速通过,选填(可不填)`"
count :autoHeight="false"
:height="100"
@confirm="ScanQrcodeApplyAddGroup"></u-textarea>
</view>
<!-- 页面初始按钮 -->
<u-button v-if="!chatpageset.showAddGroupDesc"
:text="chatpageset.buttonText" type="success" @click="addGroupfn"></u-button>
<!-- 申请加群按钮 -->
<u-button v-if="chatpageset.showAddGroupDesc"
:text="chatpageset.btnText || `提 交 加 群 申 请`"
type="primary"
@click="ScanQrcodeApplyAddGroup"></u-button>
</view>
<!-- 群公告 -->
...
<!-- h5端页面在微信打开没有导航栏给它一个底部导航栏 -->
...
</view>
<!-- 账号信息设置 -->
...
<!-- 头像剪裁500rpx * 500rpx -->
...
<!-- 删除群成员 -->
...
<!-- 添加好友进群 -->
...
<!-- 群主审批进群处理 -->
...
</view>
</view>
</template>
<script>
...
export default {
...
onLoad(e) {
...
// 动态生成数据
if(e.action){
this.setdata.action = e.action;
if(this.setdata.action == 'chatset'){
...
}else if(this.setdata.action == 'chatpageset'){
...
}else if(this.setdata.action == 'groupQrcode'){
...
//二维码提示说明
let sysinfo = uni.getSystemInfoSync().appName;
let _type = this.chatpageset.chatType == 'group' ? '加群' : '加好友';
// #ifdef H5
this.chatpageset.sysinfo = `使用微信或者手机浏览器扫码${_type}`;
// #endif
// #ifdef MP
this.chatpageset.sysinfo = `使用${sysinfo}小程序扫码${_type}`;
// #endif
// #ifdef APP
this.chatpageset.sysinfo = `使用${sysinfo}APP扫码${_type}`;
// #endif
}else if(this.setdata.action == 'autoAddGroup'){
console.log('扫码之后打开的地址', e);
this.chatpageset.id = e.id;
this.chatpageset.chatType = e.chatType;
this.chatpageset.name = decodeURIComponent(e.name);
this.chatpageset.avatar = decodeURIComponent(e.avatar);
this.chatpageset.avatar = this.chatpageset.avatar && this.chatpageset.avatar.startsWith('/') ?
requestUrl.http + this.chatpageset.avatar : this.chatpageset.avatar;
// 获取群资料
if(this.chatpageset.chatType == 'group'){
this.getgroupinfo();
}else{
// 个人
this.chatpageset.buttonText = `加 为 好 友`;
}
}else if(this.setdata.action == 'userinfoSet'){
...
}else if(this.setdata.action == 'avatarCut'){
...
}else if(this.setdata.action == 'deleteUserFromGroup'){
...
}else if(this.setdata.action == 'addUserFromGroup'){
...
}else if(this.setdata.action == 'applyAddGroup'){
...
}
}
},
...
}
</script>
# ② 在文件 /pages/setpageInfo/group.js
...
export default {
...,
methods: {
// 申请加好友提交
ScanQrcodeApplyAddUser(){
console.log('申请加好友提交', this.chatpageset);
},
// 加个人为好友
addUserFriend(){
console.log('加个人为好友', this.chatpageset);
this.chatpageset.showAddGroupDesc = true;
this.chatpageset.areaPlaceHolder = `可描述一下加好友理由,方便对方快速通过`;
this.chatpageset.btnText = '申 请 加 为 好 友';
},
// 通过扫码方式来申请加入群聊
ScanQrcodeApplyAddGroup(){
if(this.chatpageset.chatType == 'single') return this.ScanQrcodeApplyAddUser();
console.log('通过扫码方式来申请加入群聊提交申请',this.chatpageset.addGroupDesc);
...
},
// 处理进群的申请
...,
// 进群设置
...,
// 添加好友进群
...,
// 搜索好友
...,
// 往群里面加人
...,
// 点击群成员
...,
// 搜索群成员
...,
// 清空搜索
...,
// 删除群成员
...,
// 加入群聊
addGroupfn(){
if(this.chatpageset.chatType == 'single') return this.addUserFriend();
console.log('加入群聊,看管理员怎么设置的');
console.log('显示到页面的群资料',this.chatpageset);
...
},
...
}
}
# 2. 关于 游客:visitor 和 用户:user 在消息页初始化接收消息的处理
大家可以发现,本节课开始我们的消息页会在刚打开的时候接收到一些消息。
# ① 聊天类文件 /common/js/chatClass.js 更新
具体是对:针对跳转链接的消息,消息页只接收一次:doMessage(msg)方法,具体查看类文件代码:类文件 /common/js/chatClass.js 完整代码
# ② 针对混入文件 /common/mixins/tool.js 更新
- 完善底部导航栏tabbar的显示隐藏;
- 完善返回上一页(新增对网址中有跳转链接
redirectUrl及跳转类型redirectType的判断);
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
export default {
onShow() {
// 是否显示底部tabbar
this.tabbarShow();
},
computed: {
...mapState({
me : state => state.Chatuser.regloginUser,
// xiaoxiList : state => state.Chatuser.xiaoxiList,
// totalNoReadNum : state => state.Chatuser.totalNoReadNum,
// chatClass : state => state.Chatuser.chatClass,
}),
// 是否是游客
isVisitor(){
if(this.me && this.me.role == 'visitor'){
return true;
}
return false;
},
},
methods: {
// 是否显示底部tabbar
tabbarShow(){
// 获取当前页面实例
const currentPage = getCurrentPages().pop();
if (!currentPage) return;
// 检查当前页面是否是TabBar页面
const tabBarPages = [
'/pages/xiaoxi/xiaoxi',
'/pages/wode/wode',
// 添加所有TabBar页面路径
];
const isTabBarPage = tabBarPages.includes('/' + currentPage.route);
if (this.me && this.me.role == 'visitor') {
isTabBarPage && uni.hideTabBar().catch(() => {});
} else {
isTabBarPage && uni.showTabBar().catch(() => {});
}
},
/**
* 判断当前H5环境是否在微信内置浏览器打开
* @returns {Boolean} true:微信环境 false:非微信环境
*/
isWeixinBrowser() {
// 非H5环境直接返回false
if (process.env.VUE_APP_PLATFORM !== 'h5') return false
// 获取浏览器userAgent并转换为小写
const ua = navigator.userAgent.toLowerCase()
// 检测微信特有标识
return ua.includes('micromessenger')
},
/**
* 扩展方法:获取详细的H5环境信息
* @returns {Object} 环境信息对象
*/
getBrowserEnv() {
if (process.env.VUE_APP_PLATFORM !== 'h5') {
return {
inWeixin: false,
inQQ: false,
inWeibo: false
}
}
const ua = navigator.userAgent.toLowerCase()
return {
inWeixin: ua.includes('micromessenger'), // 微信浏览器
inQQ: ua.includes('qq/'), // QQ内置浏览器
inWeibo: ua.includes('weibo'), // 微博内置浏览器
inAlipay: ua.includes('alipay'), // 支付宝浏览器
inUC: ua.includes('ucbrowser'), // UC浏览器
isMobile: /mobile|android|iphone|ipad/.test(ua) // 是否移动设备
}
},
/**
* 从URL中获取指定参数(增强版,解决双重编码问题)
* @param {String} name 参数名
* @returns {String} 解码后的参数值
*/
getQueryParam(name) {
let value = null;
// 在H5环境中
if (process.env.VUE_APP_PLATFORM === 'h5') {
// 方法1: 尝试从URL的search参数获取
const urlParams = new URLSearchParams(window.location.search);
value = urlParams.get(name);
// 方法2: 如果search中没有,尝试从hash中获取
if (value === null && window.location.hash.includes('?')) {
const hashParts = window.location.hash.split('?');
if (hashParts.length > 1) {
const hashParams = new URLSearchParams(hashParts[1]);
value = hashParams.get(name);
}
}
}
// 在小程序或App环境中
else {
// 获取当前页面实例
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
if (currentPage && currentPage.options) {
value = currentPage.options[name];
}
}
// 双重解码处理:先解码一次,再解码第二次(处理双重编码情况)
if (value !== null && value !== undefined) {
try {
// 先解码一次
let decodedValue = decodeURIComponent(value);
// 检查是否还包含编码字符,如果是则再次解码
if (decodedValue.includes('%')) {
decodedValue = decodeURIComponent(decodedValue);
}
return decodedValue;
} catch (e) {
console.error('参数解码错误:', e);
return value;
}
}
return value;
},
/**
* 处理URL参数重定向
*/
handleUrlRedirect() {
const redirectUrl = this.getQueryParam('redirectUrl');
const redirectType = this.getQueryParam('redirectType');
console.log('重定向参数:', { redirectUrl, redirectType });
if (redirectUrl && redirectType) {
// 检查redirectType是否有效
if (typeof uni[redirectType] === 'function') {
try {
console.log(`执行重定向: uni.${redirectType}(${redirectUrl})`);
uni[redirectType]({ url: redirectUrl });
} catch (e) {
console.error('跳转失败:', e);
this.navigateBack(); // 失败时使用默认返回逻辑
}
} else {
console.error('无效的跳转类型:', redirectType);
this.navigateBack(); // 无效的跳转类型使用默认返回逻辑
}
} else {
console.log('无重定向参数,使用默认返回逻辑');
this.navigateBack(); // 无参数时使用默认返回逻辑
}
},
//页面返回逻辑
// 返回首页逻辑
async redirectToHome() {
try {
// 优先尝试标准跳转
await uni.redirectTo({
url: '/pages/xiaoxi/xiaoxi'
})
} catch (e) {
// 处理tab页情况
try {
await uni.switchTab({
url: '/pages/xiaoxi/xiaoxi'
})
} catch (e) {
// 终极兜底方案
uni.reLaunch({
url: '/pages/xiaoxi/xiaoxi'
})
}
}
},
//页面返回
navigateBack() {
// 首先检查是否有URL重定向参数
const redirectUrl = this.getQueryParam('redirectUrl');
const redirectType = this.getQueryParam('redirectType');
console.log('URL重定向参数检查:', {
redirectUrl,
redirectType
});
if (redirectUrl && redirectType) {
// 如果有重定向参数,优先使用重定向逻辑
this.handleUrlRedirect();
return;
}
const pages = getCurrentPages()
// 判断是否是分享进入的独立页面
if (pages.length === 1 || pages.length === 0) {
// 尝试多种跳转方式确保可靠性
this.redirectToHome().catch(() => {
uni.showToast({
title: '返回首页失败',
icon: 'none'
})
})
} else {
uni.navigateBack()
}
},
}
}
# 3. 提交加好友申请
(跟着一起学习后端,在本地调试的同学注意):
后端在之前的设计中没有 invite_confirm(是否需要用户确认才能加为好友(0-不需要 1- 需要用户确认 2-其他情况))字段,如果有同学用的我们本课之前的数据库,那么你可以加上这个字段在数据库中。
另外,记得把迁移文件和模型都加上这个字段。
或者你可以直接下载本节课课件,把数据库替换一下(更建议大家去群里面下载最终的后端完整代码和数据库)。
# ① 页面处理
在页面 /pages/setpageInfo/setpageInfo.vue
<template>
<view>
<!-- 导航栏 -->
...
<!-- 内容 -->
<view>
<!-- 聊天相关 -->
...
<!-- 聊天页设置 -->
...
<!-- 群二维码 -->
...
<!-- 扫码之后的页面 -->
<view v-if="setdata.action == 'autoAddGroup'">
...
<!-- 加群按钮 -->
<view class="p-3">
<!-- 进群理由 -->
<view v-if="chatpageset.showAddGroupDesc"
class="mb-2">
<u-textarea v-model="chatpageset.addGroupDesc"
border="surround" :maxlength="500"
:adjustPosition="false"
:placeholder="chatpageset.areaPlaceHolder || `说明一下加群理由,方便群主快速通过,选填(可不填)`"
count :autoHeight="false"
:height="100"
@confirm="ScanQrcodeApplyAddGroup"></u-textarea>
</view>
<!-- 页面初始按钮 -->
<u-button v-if="!chatpageset.showAddGroupDesc"
:text="chatpageset.buttonText" type="success" @click="addGroupfn"
:disabled="chatpageset.btndisabled"></u-button>
<!-- 申请加群按钮 -->
<u-button v-if="chatpageset.showAddGroupDesc"
:text="chatpageset.btnText || `提 交 加 群 申 请`"
type="primary" @click="ScanQrcodeApplyAddGroup"
></u-button>
</view>
<!-- 群公告 -->
...
<!-- h5端页面在微信打开没有导航栏给它一个底部导航栏 -->
...
</view>
<!-- 账号信息设置 -->
...
<!-- 头像剪裁500rpx * 500rpx -->
...
<!-- 删除群成员 -->
...
<!-- 添加好友进群 -->
...
<!-- 群主审批进群处理 -->
...
</view>
</view>
</template>
<script>
...
export default {
mixins:[toolJs,updateUserInfoJs,avatarCutJs,GroupJs,parseTimeJs],
data() {
return {
...
chatpageset:{
users:[],
avatar:'',
applydesc:'',
showAddGroupDesc:false, //是否显示加入群聊的说明文本框
btndisabled: false, // 初始时候按钮不可用状态
buttonText: '', //初始时按钮文字
},
}
},
onLoad(e) {
...
// 动态生成数据
if(e.action){
this.setdata.action = e.action;
if(this.setdata.action == 'chatset'){
...
}else if(this.setdata.action == 'chatpageset'){
...
}else if(this.setdata.action == 'groupQrcode'){
...
}else if(this.setdata.action == 'autoAddGroup'){
console.log('扫码之后打开的地址', e);
this.chatpageset.id = e.id;
this.chatpageset.chatType = e.chatType;
this.chatpageset.name = decodeURIComponent(e.name);
this.chatpageset.avatar = decodeURIComponent(e.avatar);
this.chatpageset.avatar = this.chatpageset.avatar && this.chatpageset.avatar.startsWith('/') ?
requestUrl.http + this.chatpageset.avatar : this.chatpageset.avatar;
// 获取群资料
if(this.chatpageset.chatType == 'group'){
this.getgroupinfo();
}else{
// 个人
this.chatpageset.buttonText = '加 为 好 友';
// 获取用户设置信息
this.getUserSetInfo();
}
}else if(this.setdata.action == 'userinfoSet'){
...
}else if(this.setdata.action == 'avatarCut'){
...
}else if(this.setdata.action == 'deleteUserFromGroup'){
...
}else if(this.setdata.action == 'addUserFromGroup'){
...
}else if(this.setdata.action == 'applyAddGroup'){
...
}
}
},
...
}
</script>
# ② 逻辑处理
用到先获取用户加好友的设置信息,接口查看:三十九、获取用户一些设置信息
在混入文件 /pages/setpageInfo/group.js
...
export default {
...
methods: {
// 获取用户设置信息
getUserSetInfo(){
// 1. 自己
if(this.me.id == this.chatpageset.id){
this.chatpageset.btndisabled = true;
return;
};
// 2. 请求
return new Promise((resolve,reject)=>{
uni.$u.http.post(requestUrl.http + `/api/chat/getUserSetInfo`,{
userid: this.chatpageset.id,
},{
header:{
token: this.me.token,
}
}).then(res=>{
let UserSetInfo = res.data.data;
console.log('用户的设置信息',UserSetInfo);
// 1. 是否是自己的好友
if(UserSetInfo.isgoodfriend){
if(UserSetInfo.isgoodfriend_status){
// 是自己好友且状态正常 - 开始聊天
console.log('开始聊天');
this.chatpageset.buttonText = `开 始 聊 天`;
}else{
console.log('状态异常');
this.chatpageset.btndisabled = true;
this.chatpageset.buttonText = `好 友 状 态 异 常,不 能 聊 天`;
}
}
// 2. 设置信息存入chatpageset
this.chatpageset = {
...this.chatpageset,
...UserSetInfo,
};
// 回调
resolve(this.chatpageset);
});
});
},
// 申请加为好友提交数据
ScanQrcodeApplyAddUser(){
console.log('申请加为好友提交数据', this.chatpageset);
uni.$u.http.post(requestUrl.http + `/api/chat/applyfriend`,{
friend_id: this.chatpageset.id,
nickname: this.chatpageset.addGroupDesc,
},{
header:{
token: this.me.token
}
}).then(res=>{
uni.showToast({title: '等待对方同意', icon:'success'});
setTimeout(()=>{
this.navigateBack();
},1500);
}).catch(err=>{
uni.showToast({title: err.data.data, icon:'none',duration:5000});
});
},
// 加个人为好友
addUserFriend(){
console.log('加个人为好友', this.chatpageset);
// 是好友
if(this.chatpageset.isgoodfriend && this.chatpageset.isgoodfriend_status){
console.log('是我的朋友,可以直接聊天了', this.chatpageset);
// 进入聊天页 传一下用户的信息过去在页面展示
const userchat = {
id: this.chatpageset.id,
name: this.chatpageset.name,
avatar: this.chatpageset.avatar,
chatType: 'single', // 单聊 single 群聊 group
};
uni.navigateTo({
url: `/pages/chat/chat?arg=${encodeURIComponent(JSON.stringify(userchat))}`,
});
return;
}
// 非好友
if(this.chatpageset.invite_confirm == 0){
console.log('直接加为好友');
}else if(this.chatpageset.invite_confirm == 1){
console.log('先申请,等待对方同意');
this.chatpageset.showAddGroupDesc = true;
this.chatpageset.areaPlaceHolder = `可描述一下加好友的理由,方便对方快速通过`;
this.chatpageset.btnText = `申 请 加 为 好 友`;
}
},
// 通过扫码方式来申请加入群聊
...
// 处理进群的申请
...
// 进群设置
...
// 添加好友进群
...
// 搜索好友
...
// 往群里面加人
...
// 点击群成员
...
// 搜索群成员
...
// 清空搜索
...
// 删除群成员
...
// 加入群聊
...
// 解散群或者退群或者删除好友
...
// 获取群资料
...
// 修改我在群里面的昵称
...
// 更新群公告
...
// 更新群名称
...
// 更新群信息
...
// 点击开关
...
}
}
# ③ 聊天页显示一下发送消息失败原因
# 1. 在混入文件 /pages/chat/plusIconAction.js
//发送消息
sendMessage(msgType, option = {}){
...
// 发给服务器消息
if(msg.isSendToServer){
this.chatClass.sendmessage(serverMsg).then(result => {
...
}).catch(error => {
console.log('页面接收服务器错误结果',error);
this.chatDataList[sendmsgIndex].sendStatus = 'fail';
this.chatDataList[sendmsgIndex].failText = error.data.data;
// 返回错误
reject(error);
});
}else{
...
}
...
}
# 2. 在组件 /components/chat-item/chat-item.vue
<!-- 聊天内容主体 -->
<view ...>
<!-- 昵称的显示 -->
<view v-if="setdata.shownickname"
class="position-absolute"
style="max-width: 500rpx;top: -36rpx;min-width:140rpx ;"
:style="contentStyle"
:class="[isMe ? 'right-0' : 'left-0']">
<text class="text-light-muted u-line-1" style="font-size: 20rpx;">{{item.nickname}}</text>
</view>
...
</view>
...
<!-- 给服务器发消息状态 -->
<view v-if="item.sendStatus && item.sendStatus != 'success' &&
item.sendStatus !== 'pendingFile' "
class="flex align-center justify-end pr-5 pb-5">
<text class="font-small"
:class="[item.sendStatus == 'fail' ?
'text-danger' : 'text-success']">{{item.sendStatus == 'fail' ?
`消息发送失败${item.failText?':' + item.failText : ''}` : '消息正在发送中...'}}</text>
</view>
# 3. 如果是游客聊天,加一下标识在聊天页
在页面 /pages/chat/chat.nvue
onLoad(e) {
if(!e.arg) return this.navigateBack();
let arg = decodeURIComponent(e.arg);
try{
this.arg = JSON.parse(arg);
console.log('聊天页参数对象',this.arg);
if(this.arg && this.arg.name.startsWith('VIS')){
this.arg.name = this.arg.name + `[游客]`;
}
...
}catch(err){
...
}
}
...
# 4. 完善申请加我为好友设置
# 1 界面完善
在用户申请加对方为好友时候,一般客服是不需要审核的,用户需要审核,先完善这个页面。
# 1-1. 在页面 /pages/setpage/setpage.vue
...
<!-- 账号 -->
...
<!-- 加我为好友设置 -->
<u-cell-group>
<u-cell title="申请加我为好友设置"
:customStyle="{'background-color':'#ffffff'}"
isLink titleStyle="font-size:18px;"
@click="setfun('applyAddMeFriendSet','申请加我为好友设置')"></u-cell>
</u-cell-group>
<!-- 聊天相关 -->
...
# 1-2. 在页面 /pages/setpageInfo/setpageInfo.vue
<template>
<view>
<!-- 导航栏 -->
...
<!-- 内容 -->
<view>
<!-- 聊天相关 -->
...
<!-- 聊天页设置 -->
...
<!-- 群二维码 -->
...
<!-- 扫码之后的页面 -->
...
<!-- 账号信息设置 -->
...
<!-- 头像剪裁500rpx * 500rpx -->
...
<!-- 删除群成员 -->
...
<!-- 添加好友进群 -->
...
<!-- 群主审批进群处理 -->
...
<!-- 申请加我为好友设置 -->
<view v-if="setdata.action == 'applyAddMeFriendSet'">
<!-- 设置选项 -->
<view>
<u-cell-group>
<u-cell
title="加我为好友时需要我验证"
:border="false" clickable
:customStyle="customStyles"
:iconStyle="iconStyles"
:titleStyle="titleStyles">
<view slot="value">
<u-switch v-model="chatpageset.invite_confirm"
@change="changeSwitch('invite_confirm', setdata.action)"></u-switch>
</view>
</u-cell>
</u-cell-group>
<u-gap height="10" bgColor="#EDEDED"></u-gap>
</view>
</view>
</view>
</view>
</template>
<script>
...
export default {
...
data() {
return {
...,
chatpageset:{
...
buttonText: '', // 初始化按钮文字
invite_confirm: true, // 加我为好友字段设置
},
}
},
onLoad(e) {
...
// 动态生成数据
if(e.action){
this.setdata.action = e.action;
if(this.setdata.action == 'chatset'){
...
}else if(this.setdata.action == 'chatpageset'){
...
}else if(this.setdata.action == 'groupQrcode'){
...
}else if(this.setdata.action == 'autoAddGroup'){
...
// 是否有跳转字段
this.chatpageset.redirect = e.redirect ? e.redirect : false ;
// 获取群资料
if(this.chatpageset.chatType == 'group'){
this.getgroupinfo();
}else{
// 个人
this.chatpageset.buttonText = '加 为 好 友';
// 获取用户设置信息
this.getUseraSetInfo().then(res=>{
this.chatpageset = res;
console.log('---获取用户设置信息',this.chatpageset);
if(this.chatpageset.redirect){
if(this.chatpageset.isgoodfriend && this.chatpageset.isgoodfriend_status){
this.groupOrSingleChatRedirect('single');
}else{
console.log('非好友或者状态有问题');
if(this.chatpageset.invite_confirm == 0){
console.log('非好友或者状态有问题,但是你可以加他,不用它审核就可以成为朋友');
// 接下来自动加好友成功后直接聊天
this.autoAddFriendAndAgree().then(res=>{
uni.showToast({title:'连线成功',icon:'success'});
// 已是好友关系,直接聊天
setTimeout(()=>{
this.groupOrSingleChatRedirect('single');
},1000);
});
}else if(this.chatpageset.invite_confirm == 1){
console.log('非好友或者状态有问题,但是你可以加他,要他审核');
}
}
}
});
}
}else if(this.setdata.action == 'userinfoSet'){
...
}else if(this.setdata.action == 'avatarCut'){
...
}else if(this.setdata.action == 'deleteUserFromGroup'){
...
}else if(this.setdata.action == 'addUserFromGroup'){
...
}else if(this.setdata.action == 'applyAddGroup'){
...
}else if(this.setdata.action == 'applyAddMeFriendSet'){
// 获取用户设置信息
this.initGetUseraSetInfo().then(res=>{
console.log('获取用户设置信息',res);
if(res){
this.chatpageset = {
...res,
invite_confirm: !!res.invite_confirm,
};
console.log('获取用户设置信息this.chatpageset',this.chatpageset);
}
});
}
}
},
...
}
</script>
# 1-3. 在文件 /pages/setpageInfo/group.js
...
export default {
...
methods: {
// 获取用户设置信息 - 页面初始化就要执行
initGetUseraSetInfo(){
return new Promise((resolve,reject)=>{
let meInfo = uni.getStorageSync('chatuser');
meInfo = meInfo ? JSON.parse(meInfo) : '';
if(meInfo){
uni.$u.http.post(requestUrl.http + `/api/chat/getUserSetInfo`,{
userid: meInfo.id,
},{
header:{
token: meInfo.token,
}
}).then(res=>{
let UserSetInfo = res.data.data;
resolve(UserSetInfo);
});
}
});
},
// 获取用户设置信息
...
// 申请加为好友提交数据
...
// 加个人为好友
addUserFriend(){
console.log('加个人为好友', this.chatpageset);
if(this.chatpageset.isgoodfriend && this.chatpageset.isgoodfriend_status){
console.log('是好友了,可以直接聊天了',this.chatpageset);
// 进入聊天页 传一下用户的信息过去在页面展示
const userchat = {
id: this.chatpageset.id,
name: this.chatpageset.name,
avatar: this.chatpageset.avatar,
chatType: 'single', // 单聊 single 群聊 group
};
uni.navigateTo({
url: `/pages/chat/chat?arg=${encodeURIComponent(JSON.stringify(userchat))}`,
});
return;
}
// 非好友
if(this.chatpageset.invite_confirm == 0){
console.log('非好友对方是客服,一般直接聊天,客服一般不会让你加客服为好友');
}else if(this.chatpageset.invite_confirm == 1){
console.log('先申请,等待对方同意');
this.chatpageset.showAddGroupDesc = true;
this.chatpageset.areaPlaceHolder = `可描述一下加好友的理由,方便对方快速通过`;
this.chatpageset.btnText = `申 请 加 为 好 友`;
}
},
// 通过扫码方式来申请加入群聊
...
// 处理进群的申请
...
// 进群设置
...
// 添加好友进群
...
// 搜索好友
...
// 往群里面加人
...
// 点击群成员
...
// 搜索群成员
...
// 清空搜索
...
// 删除群成员
...
// 加入群聊
...
// 解散群或者退群或者删除好友
...
// 获取群资料
...
// 修改我在群里面的昵称
...
// 更新群公告
...
// 更新群名称
...
// 更新群信息
...
// 点击开关
changeSwitch(key,action = false){
console.log(`点击开关${key}`,this.chatpageset[key]);
if(action){
if(action == 'applyAddMeFriendSet'){
console.log('申请叫我为好友设置',this.chatpageset);
this.updateUserInfo('invite_confirm');
}
}else{
console.log('通过开关设置单聊或者群聊信息',this.chatpageset);
this.chatClass.updateSomeOneChatItem({
id: this.chatpageset.id,
chatType: this.chatpageset.chatType,
}, this.chatpageset).then(res =>{
console.log('设置之后的数据', res);
// 方式一: 全局通知聊天页
// 方式二:直接在聊天页获取消息页的信息进行处理
});
}
},
}
}
# 1-4. 在文件 /pages/setpageInfo/updateUserInfo.js
// 修改我的账号信息
updateUserInfo(fieldname) {
let arg = {};
switch (fieldname) {
case 'nickname':
...
break;
case 'avatar':
...
break;
case 'invite_confirm':
arg = {
apiurl: '/api/chat/updateUserinfo',
data: {
fieldname: fieldname,
fieldValue: Number(this.chatpageset.invite_confirm),
},
};
// 我的信息更新一下
this.me[fieldname] = this.chatpageset.invite_confirm;
break;
}
// 服务器处理
...
},
# 5. 根据地址是否有redirect参数来简化按钮操作
如果地址有redirect参数,则不需要点击按钮直达下一步操作。
# 5-1. 在页面 /pages/setpageInfo/setpageInfo.vue
...}else if(this.setdata.action == 'autoAddGroup'){
console.log('扫码之后打开的地址', e);
this.chatpageset.id = e.id;
this.chatpageset.chatType = e.chatType;
this.chatpageset.name = decodeURIComponent(e.name);
this.chatpageset.avatar = decodeURIComponent(e.avatar);
this.chatpageset.avatar = this.chatpageset.avatar && this.chatpageset.avatar.startsWith('/') ?
requestUrl.http + this.chatpageset.avatar : this.chatpageset.avatar;
// 是否有跳转字段
this.chatpageset.redirect = e.redirect ? e.redirect : false ;
// 获取群资料
if(this.chatpageset.chatType == 'group'){
this.getgroupinfo();
}else{
// 个人
this.chatpageset.buttonText = '加 为 好 友';
// 获取用户设置信息
this.getUseraSetInfo().then(res=>{
this.chatpageset = res;
console.log('---获取用户设置信息',this.chatpageset);
if(this.chatpageset.redirect){
if(this.chatpageset.isgoodfriend && this.chatpageset.isgoodfriend_status){
this.groupOrSingleChatRedirect('single');
}else{
console.log('非好友或者状态有问题');
if(this.chatpageset.invite_confirm == 0){
console.log('非好友或者状态有问题,但是你可以加他,不用它审核就可以成为朋友');
// 接下来自动完成两步
// 自动加对方为好友
// 加完之后,进入userinfo页面根据聊天设置来判断
this.autoAddFriendAndAgree().then(res=>{
uni.showToast({title:'连线成功',icon:'success'});
// 已是好友关系,直接聊天
setTimeout(()=>{
this.groupOrSingleChatRedirect('single');
},1000);
});
}else if(this.chatpageset.invite_confirm == 1){
console.log('非好友或者状态有问题,但是你可以加他,要他审核');
}
}
}
});
}
}else if(...
# 5-2. 在文件 /pages/setpageInfo/group.js
用到当添加好友设置为:无需我审核的时候,进行自动添加好友并发送websocket消息的接口说明,接口查看:四十、自动添加好友并通知websocket消息
...
export default {
...
methods: {
// 自动加群并同意
async autoAddGroupAndAgree(){
return new Promise((resolve,reject)=>{
console.log('自动加群并同意this.chatpageset',this.chatpageset);
console.log('自动加群并同意this.me',this.me);
// return;
// 交互
uni.$u.http.post(requestUrl.http + `/api/chat/groupInviteUser`,{
group_id: this.chatpageset.id,
user_id: this.me.id,
inviteuser_id: -1,// 小于0代表自己申请进群,没有人拉我进群
addGroupDesc: '当群设置为任何人都可以进入时,用户自主加群群聊',
},{
header:{
token: this.me.token,
}
}).then(res=>{
resolve(res);
});
});
},
// 自动加对方为好友并同意
async autoAddFriendAndAgree(){
return new Promise((resolve,reject)=>{
// 我的信息
let meInfo = uni.getStorageSync('chatuser');
meInfo = meInfo ? JSON.parse(meInfo) : '';
let nickname = ``;
if(meInfo){
nickname = meInfo.nickname || meInfo.username;
nickname += meInfo.role == 'visitor' ? '[游客]' : '[平台注册用户]';
// 交互
uni.$u.http.post(requestUrl.http + `/api/chat/autoAddFriendAndAgree`,{
friend_id: this.chatpageset.id,
nickname: `我是${nickname},系统自动加为你好友的`,
},{
header:{
token: meInfo.token,
}
}).then(res=>{
resolve(res);
});
}
});
},
// 进群|单聊聊天调转
...
// 获取用户设置信息 - 页面初始化就要执行
...
// 获取用户设置信息
...
// 申请加为好友提交数据
...
// 加个人为好友
addUserFriend(){
console.log('加个人为好友', this.chatpageset);
if(this.chatpageset.isgoodfriend && this.chatpageset.isgoodfriend_status){
console.log('是好友了,可以直接聊天了',this.chatpageset);
this.groupOrSingleChatRedirect(chatType = 'single');
return;
}
// 非好友
if(this.chatpageset.invite_confirm == 0){
console.log('非好友, 但可以加他为好友不用他审核');
this.autoAddFriendAndAgree().then(res=>{
uni.showToast({title:'连线成功',icon:'success'});
// 已是好友关系,直接聊天
setTimeout(()=>{
this.groupOrSingleChatRedirect('single');
},1000);
});
}else if(this.chatpageset.invite_confirm == 1){
console.log('先申请,等待对方同意');
this.chatpageset.showAddGroupDesc = true;
this.chatpageset.areaPlaceHolder = `可描述一下加好友的理由,方便对方快速通过`;
this.chatpageset.btnText = `申 请 加 为 好 友`;
}
},
// 通过扫码方式来申请加入群聊
...
// 处理进群的申请
...
// 进群设置
...
// 添加好友进群
...
// 搜索好友
...
// 往群里面加人
...
// 点击群成员
openUserInfo(item,action){
console.log(item);
if(action == 'chatGroup'){
// 进入聊天页 传一下用户的信息过去在页面展示
// const userchat = {
// id: item.id,
// name: item.name,
// avatar: item.avatar,
// chatType: 'group', // 单聊 single 群聊 group
// };
// uni.navigateTo({
// url: `/pages/chat/chat?arg=${encodeURIComponent(JSON.stringify(userchat))}`,
// });
this.groupOrSingleChatRedirect('group', item);
}else if(action == 'deleteGroupUser'){
...
}else if(action == 'addGroupUser'){
...
}else{
...
}
},
// 搜索群成员
...
// 清空搜索
...
// 删除群成员
...
// 加入群聊
addGroupfn(){
if(this.chatpageset.chatType == 'single') return this.addUserFriend();
console.log('加入群聊,看管理员怎么设置的');
console.log('显示到页面的群资料',this.chatpageset);
// 如果你是这个群群成员或者群主
if(this.chatpageset.isGroupUser){
this.groupOrSingleChatRedirect();
return;
}
// 你不是群成员
if(this.chatpageset.invite_confirm == 0){
// 任何人都能进去聊天
...
}else if(this.chatpageset.invite_confirm == 1){
// 要群主同意你才能进群
...
}else if(this.chatpageset.invite_confirm == 2){
// 如果你是游客,则要先登录再来申请进群,然后在等待群主同意
...
}
},
// 解散群或者退群或者删除好友
...
// 获取群资料
// 获取群资料
getgroupinfo(){
return new Promise((resolve,reject)=>{
uni.$u.http.get(requestUrl.http + `/api/chat/groupinfo/${this.chatpageset.id}`, {
header: {
token: this.me.token,
},
}).then(res => {
...
if(groupUsersIds){
if(groupUsersIds.includes(this.me.id)){
// 我是群成员
this.chatpageset.isGroupUser = true;
this.chatpageset.buttonText = '进群聊天';
console.log('我是群成员',this.chatpageset);
if(this.chatpageset.redirect){
// 直接进群聊天
this.groupOrSingleChatRedirect('group');
}
}else{
console.log('我不是群成员',this.chatpageset);
if(this.chatpageset.redirect && this.chatpageset.invite_confirm == 0){
console.log('我不是群成员, 但群任何人都可以进,并且需要自动跳转');
// 自动加群并同意
this.autoAddGroupAndAgree().then(res=>{
uni.showToast({title: '连线成功', icon:'success'});
// 已是群成员,直接聊天
setTimeout(()=>{
this.groupOrSingleChatRedirect('group');
},1000);
});
}
}
}
resolve(this.chatpageset);
}).catch(err =>{
this.navigateBack();
});
});
},
// 修改我在群里面的昵称
...
// 更新群公告
...
// 更新群名称
...
// 更新群信息
...
// 点击开关
...
}
}