51 changed files with 4741 additions and 4730 deletions
@ -1,429 +1,430 @@ |
|||
<script> |
|||
import App from './App' |
|||
import http from './common/request'; |
|||
import * as msgType from './common/messageType'; |
|||
import * as enums from './common/enums'; |
|||
import * as wsApi from './common/wssocket'; |
|||
import UNI_APP from '@/.env.js' |
|||
import App from './App' |
|||
import http from './common/request'; |
|||
import * as msgType from './common/messageType'; |
|||
import * as enums from './common/enums'; |
|||
import * as wsApi from './common/wssocket'; |
|||
import UNI_APP from '@/.env.js' |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
isExit: false, // 是否已退出 |
|||
audioTip: null, |
|||
reconnecting: false // 正在重连标志 |
|||
} |
|||
export default { |
|||
data() { |
|||
return { |
|||
isExit: false, // 是否已退出 |
|||
audioTip: null, |
|||
reconnecting: false // 正在重连标志 |
|||
} |
|||
}, |
|||
methods: { |
|||
init() { |
|||
this.isExit = false; |
|||
// 加载数据 |
|||
this.loadStore().then(() => { |
|||
// 初始化websocket |
|||
this.initWebSocket(); |
|||
}).catch((e) => { |
|||
console.log(e); |
|||
this.exit(); |
|||
}) |
|||
}, |
|||
methods: { |
|||
init() { |
|||
this.isExit = false; |
|||
// 加载数据 |
|||
this.loadStore().then(() => { |
|||
// 初始化websocket |
|||
this.initWebSocket(); |
|||
}).catch((e) => { |
|||
console.log(e); |
|||
this.exit(); |
|||
}) |
|||
}, |
|||
initWebSocket() { |
|||
let loginInfo = uni.getStorageSync("loginInfo") |
|||
wsApi.init(); |
|||
wsApi.connect(UNI_APP.WS_URL, loginInfo.accessToken); |
|||
wsApi.onConnect(() => { |
|||
// 重连成功提示 |
|||
if (this.reconnecting) { |
|||
this.reconnecting = false; |
|||
uni.showToast({ |
|||
title: "已重新连接", |
|||
icon: 'none' |
|||
}) |
|||
} |
|||
// 加载离线消息 |
|||
this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId); |
|||
this.pullGroupOfflineMessage(this.chatStore.groupMsgMaxId); |
|||
}); |
|||
wsApi.onMessage((cmd, msgInfo) => { |
|||
if (cmd == 2) { |
|||
// 异地登录,强制下线 |
|||
uni.showModal({ |
|||
content: '您已在其他地方登陆,将被强制下线', |
|||
showCancel: false, |
|||
}) |
|||
this.exit(); |
|||
} else if (cmd == 3) { |
|||
// 私聊消息 |
|||
this.handlePrivateMessage(msgInfo); |
|||
} else if (cmd == 4) { |
|||
// 群聊消息 |
|||
this.handleGroupMessage(msgInfo); |
|||
} else if (cmd == 5) { |
|||
// 系统消息 |
|||
this.handleSystemMessage(msgInfo); |
|||
} |
|||
}); |
|||
wsApi.onClose((res) => { |
|||
console.log("ws断开", res); |
|||
// 重新连接 |
|||
this.reconnectWs(); |
|||
|
|||
}) |
|||
}, |
|||
loadStore() { |
|||
return this.userStore.loadUser().then(() => { |
|||
const promises = []; |
|||
promises.push(this.friendStore.loadFriend()); |
|||
promises.push(this.groupStore.loadGroup()); |
|||
promises.push(this.chatStore.loadChat()); |
|||
promises.push(this.configStore.loadConfig()); |
|||
return Promise.all(promises); |
|||
}) |
|||
}, |
|||
unloadStore(){ |
|||
this.friendStore.clear(); |
|||
this.groupStore.clear(); |
|||
this.chatStore.clear(); |
|||
this.configStore.clear(); |
|||
this.userStore.clear(); |
|||
}, |
|||
pullPrivateOfflineMessage(minId) { |
|||
this.chatStore.setLoadingPrivateMsg(true) |
|||
http({ |
|||
url: "/message/private/pullOfflineMessage?minId=" + minId, |
|||
method: 'GET' |
|||
}).catch(() => { |
|||
this.chatStore.setLoadingPrivateMsg(false) |
|||
}) |
|||
}, |
|||
pullGroupOfflineMessage(minId) { |
|||
this.chatStore.setLoadingGroupMsg(true) |
|||
http({ |
|||
url: "/message/group/pullOfflineMessage?minId=" + minId, |
|||
method: 'GET' |
|||
}).catch(() => { |
|||
this.chatStore.setLoadingGroupMsg(false) |
|||
}) |
|||
}, |
|||
handlePrivateMessage(msg) { |
|||
// 消息加载标志 |
|||
if (msg.type == enums.MESSAGE_TYPE.LOADING) { |
|||
this.chatStore.setLoadingPrivateMsg(JSON.parse(msg.content)) |
|||
return; |
|||
} |
|||
// 消息已读处理,清空已读数量 |
|||
if (msg.type == enums.MESSAGE_TYPE.READED) { |
|||
this.chatStore.resetUnreadCount({ |
|||
type: 'PRIVATE', |
|||
targetId: msg.recvId |
|||
}) |
|||
return; |
|||
} |
|||
// 消息回执处理,改消息状态为已读 |
|||
if (msg.type == enums.MESSAGE_TYPE.RECEIPT) { |
|||
this.chatStore.readedMessage({ |
|||
friendId: msg.sendId |
|||
initWebSocket() { |
|||
let loginInfo = uni.getStorageSync("loginInfo") |
|||
wsApi.init(); |
|||
wsApi.connect(UNI_APP.WS_URL, loginInfo.accessToken); |
|||
wsApi.onConnect(() => { |
|||
// 重连成功提示 |
|||
if (this.reconnecting) { |
|||
this.reconnecting = false; |
|||
uni.showToast({ |
|||
title: "已重新连接", |
|||
icon: 'none' |
|||
}) |
|||
return; |
|||
} |
|||
// 标记这条消息是不是自己发的 |
|||
msg.selfSend = msg.sendId == this.userStore.userInfo.id; |
|||
// 好友id |
|||
let friendId = msg.selfSend ? msg.recvId : msg.sendId; |
|||
this.loadFriendInfo(friendId, (friend) => { |
|||
this.insertPrivateMessage(friend, msg); |
|||
}) |
|||
}, |
|||
insertPrivateMessage(friend, msg) { |
|||
// 单人视频信令 |
|||
if (msgType.isRtcPrivate(msg.type)) { |
|||
// #ifdef MP-WEIXIN |
|||
// 小程序不支持音视频 |
|||
return; |
|||
// #endif |
|||
// 被呼叫,弹出视频页面 |
|||
let delayTime = 100; |
|||
if (msg.type == enums.MESSAGE_TYPE.RTC_CALL_VOICE || |
|||
msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO) { |
|||
let mode = msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO ? "video" : "voice"; |
|||
let pages = getCurrentPages(); |
|||
let curPage = pages[pages.length - 1].route; |
|||
if (curPage != "pages/chat/chat-private-video") { |
|||
const friendInfo = encodeURIComponent(JSON.stringify(friend)); |
|||
uni.navigateTo({ |
|||
url: `/pages/chat/chat-private-video?mode=${mode}&friend=${friendInfo}&isHost=false` |
|||
}) |
|||
delayTime = 500; |
|||
} |
|||
} |
|||
setTimeout(() => { |
|||
uni.$emit('WS_RTC_PRIVATE', msg); |
|||
}, delayTime) |
|||
return; |
|||
} |
|||
let chatInfo = { |
|||
type: 'PRIVATE', |
|||
targetId: friend.id, |
|||
showName: friend.nickName, |
|||
headImage: friend.headImage |
|||
}; |
|||
// 打开会话 |
|||
this.chatStore.openChat(chatInfo); |
|||
// 插入消息 |
|||
this.chatStore.insertMessage(msg); |
|||
// 播放提示音 |
|||
this.playAudioTip(); |
|||
|
|||
}, |
|||
handleGroupMessage(msg) { |
|||
// 消息加载标志 |
|||
if (msg.type == enums.MESSAGE_TYPE.LOADING) { |
|||
this.chatStore.setLoadingGroupMsg(JSON.parse(msg.content)) |
|||
return; |
|||
} |
|||
// 消息已读处理 |
|||
if (msg.type == enums.MESSAGE_TYPE.READED) { |
|||
// 我已读对方的消息,清空已读数量 |
|||
let chatInfo = { |
|||
type: 'GROUP', |
|||
targetId: msg.groupId |
|||
} |
|||
this.chatStore.resetUnreadCount(chatInfo) |
|||
return; |
|||
} |
|||
// 消息回执处理 |
|||
if (msg.type == enums.MESSAGE_TYPE.RECEIPT) { |
|||
// 更新消息已读人数 |
|||
let msgInfo = { |
|||
id: msg.id, |
|||
groupId: msg.groupId, |
|||
readedCount: msg.readedCount, |
|||
receiptOk: msg.receiptOk |
|||
}; |
|||
this.chatStore.updateMessage(msgInfo) |
|||
return; |
|||
} |
|||
// 标记这条消息是不是自己发的 |
|||
msg.selfSend = msg.sendId == this.userStore.userInfo.id; |
|||
this.loadGroupInfo(msg.groupId, (group) => { |
|||
// 插入群聊消息 |
|||
this.insertGroupMessage(group, msg); |
|||
}) |
|||
}, |
|||
handleSystemMessage(msg) { |
|||
if (msg.type == enums.MESSAGE_TYPE.USER_BANNED) { |
|||
// 用户被封禁 |
|||
wsApi.close(3099); |
|||
// 加载离线消息 |
|||
this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId); |
|||
this.pullGroupOfflineMessage(this.chatStore.groupMsgMaxId); |
|||
}); |
|||
wsApi.onMessage((cmd, msgInfo) => { |
|||
if (cmd == 2) { |
|||
// 异地登录,强制下线 |
|||
uni.showModal({ |
|||
content: '您的账号已被管理员封禁,原因:' + msg.content, |
|||
content: '您已在其他地方登陆,将被强制下线', |
|||
showCancel: false, |
|||
}) |
|||
this.exit(); |
|||
} else if (cmd == 3) { |
|||
// 私聊消息 |
|||
this.handlePrivateMessage(msgInfo); |
|||
} else if (cmd == 4) { |
|||
// 群聊消息 |
|||
this.handleGroupMessage(msgInfo); |
|||
} else if (cmd == 5) { |
|||
// 系统消息 |
|||
this.handleSystemMessage(msgInfo); |
|||
} |
|||
}, |
|||
insertGroupMessage(group, msg) { |
|||
// 群视频信令 |
|||
if (msgType.isRtcGroup(msg.type)) { |
|||
// #ifdef MP-WEIXIN |
|||
// 小程序不支持音视频 |
|||
return; |
|||
// #endif |
|||
// 被呼叫,弹出视频页面 |
|||
let delayTime = 100; |
|||
if (msg.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP) { |
|||
let pages = getCurrentPages(); |
|||
let curPage = pages[pages.length - 1].route; |
|||
if (curPage != "pages/chat/chat-group-video") { |
|||
const userInfos = encodeURIComponent(msg.content); |
|||
const inviterId = msg.sendId; |
|||
const groupId = msg.groupId |
|||
uni.navigateTo({ |
|||
url: `/pages/chat/chat-group-video?groupId=${groupId}&isHost=false |
|||
&inviterId=${inviterId}&userInfos=${userInfos}` |
|||
}) |
|||
delayTime = 500; |
|||
} |
|||
}); |
|||
wsApi.onClose((res) => { |
|||
console.log("ws断开", res); |
|||
// 重新连接 |
|||
this.reconnectWs(); |
|||
|
|||
}) |
|||
}, |
|||
loadStore() { |
|||
return this.userStore.loadUser().then(() => { |
|||
const promises = []; |
|||
promises.push(this.friendStore.loadFriend()); |
|||
promises.push(this.groupStore.loadGroup()); |
|||
promises.push(this.chatStore.loadChat()); |
|||
promises.push(this.configStore.loadConfig()); |
|||
return Promise.all(promises); |
|||
}) |
|||
}, |
|||
unloadStore() { |
|||
this.friendStore.clear(); |
|||
this.groupStore.clear(); |
|||
this.chatStore.clear(); |
|||
this.configStore.clear(); |
|||
this.userStore.clear(); |
|||
}, |
|||
pullPrivateOfflineMessage(minId) { |
|||
this.chatStore.setLoadingPrivateMsg(true) |
|||
http({ |
|||
url: "/message/private/pullOfflineMessage?minId=" + minId, |
|||
method: 'GET' |
|||
}).catch(() => { |
|||
this.chatStore.setLoadingPrivateMsg(false) |
|||
}) |
|||
}, |
|||
pullGroupOfflineMessage(minId) { |
|||
this.chatStore.setLoadingGroupMsg(true) |
|||
http({ |
|||
url: "/message/group/pullOfflineMessage?minId=" + minId, |
|||
method: 'GET' |
|||
}).catch(() => { |
|||
this.chatStore.setLoadingGroupMsg(false) |
|||
}) |
|||
}, |
|||
handlePrivateMessage(msg) { |
|||
// 消息加载标志 |
|||
if (msg.type == enums.MESSAGE_TYPE.LOADING) { |
|||
this.chatStore.setLoadingPrivateMsg(JSON.parse(msg.content)) |
|||
return; |
|||
} |
|||
// 消息已读处理,清空已读数量 |
|||
if (msg.type == enums.MESSAGE_TYPE.READED) { |
|||
this.chatStore.resetUnreadCount({ |
|||
type: 'PRIVATE', |
|||
targetId: msg.recvId |
|||
}) |
|||
return; |
|||
} |
|||
// 消息回执处理,改消息状态为已读 |
|||
if (msg.type == enums.MESSAGE_TYPE.RECEIPT) { |
|||
this.chatStore.readedMessage({ |
|||
friendId: msg.sendId |
|||
}) |
|||
return; |
|||
} |
|||
// 标记这条消息是不是自己发的 |
|||
msg.selfSend = msg.sendId == this.userStore.userInfo.id; |
|||
// 好友id |
|||
let friendId = msg.selfSend ? msg.recvId : msg.sendId; |
|||
this.loadFriendInfo(friendId, (friend) => { |
|||
this.insertPrivateMessage(friend, msg); |
|||
}) |
|||
}, |
|||
insertPrivateMessage(friend, msg) { |
|||
// 单人视频信令 |
|||
if (msgType.isRtcPrivate(msg.type)) { |
|||
// #ifdef MP-WEIXIN |
|||
// 小程序不支持音视频 |
|||
return; |
|||
// #endif |
|||
// 被呼叫,弹出视频页面 |
|||
let delayTime = 100; |
|||
if (msg.type == enums.MESSAGE_TYPE.RTC_CALL_VOICE || |
|||
msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO) { |
|||
let mode = msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO ? "video" : "voice"; |
|||
let pages = getCurrentPages(); |
|||
let curPage = pages[pages.length - 1].route; |
|||
if (curPage != "pages/chat/chat-private-video") { |
|||
const friendInfo = encodeURIComponent(JSON.stringify(friend)); |
|||
uni.navigateTo({ |
|||
url: `/pages/chat/chat-private-video?mode=${mode}&friend=${friendInfo}&isHost=false` |
|||
}) |
|||
delayTime = 500; |
|||
} |
|||
// 消息转发到chat-group-video页面进行处理 |
|||
setTimeout(() => { |
|||
uni.$emit('WS_RTC_GROUP', msg); |
|||
}, delayTime) |
|||
return; |
|||
} |
|||
setTimeout(() => { |
|||
uni.$emit('WS_RTC_PRIVATE', msg); |
|||
}, delayTime) |
|||
return; |
|||
} |
|||
let chatInfo = { |
|||
type: 'PRIVATE', |
|||
targetId: friend.id, |
|||
showName: friend.nickName, |
|||
headImage: friend.headImage |
|||
}; |
|||
// 打开会话 |
|||
this.chatStore.openChat(chatInfo); |
|||
// 插入消息 |
|||
this.chatStore.insertMessage(msg); |
|||
// 播放提示音 |
|||
this.playAudioTip(); |
|||
|
|||
}, |
|||
handleGroupMessage(msg) { |
|||
// 消息加载标志 |
|||
if (msg.type == enums.MESSAGE_TYPE.LOADING) { |
|||
this.chatStore.setLoadingGroupMsg(JSON.parse(msg.content)) |
|||
return; |
|||
} |
|||
// 消息已读处理 |
|||
if (msg.type == enums.MESSAGE_TYPE.READED) { |
|||
// 我已读对方的消息,清空已读数量 |
|||
let chatInfo = { |
|||
type: 'GROUP', |
|||
targetId: group.id, |
|||
showName: group.showGroupName, |
|||
headImage: group.headImageThumb |
|||
}; |
|||
// 打开会话 |
|||
this.chatStore.openChat(chatInfo); |
|||
// 插入消息 |
|||
this.chatStore.insertMessage(msg); |
|||
// 播放提示音 |
|||
this.playAudioTip(); |
|||
}, |
|||
loadFriendInfo(id, callback) { |
|||
let friend = this.friendStore.findFriend(id); |
|||
if (friend) { |
|||
callback(friend); |
|||
} else { |
|||
http({ |
|||
url: `/friend/find/${id}`, |
|||
method: 'GET' |
|||
}).then((friend) => { |
|||
this.friendStore.addFriend(friend); |
|||
callback(friend) |
|||
}) |
|||
} |
|||
}, |
|||
loadGroupInfo(id, callback) { |
|||
let group = this.groupStore.findGroup(id); |
|||
if (group) { |
|||
callback(group); |
|||
} else { |
|||
http({ |
|||
url: `/group/find/${id}`, |
|||
method: 'GET' |
|||
}).then((group) => { |
|||
this.groupStore.addGroup(group); |
|||
callback(group) |
|||
}) |
|||
targetId: msg.groupId |
|||
} |
|||
}, |
|||
exit() { |
|||
console.log("exit"); |
|||
this.isExit = true; |
|||
this.chatStore.resetUnreadCount(chatInfo) |
|||
return; |
|||
} |
|||
// 消息回执处理 |
|||
if (msg.type == enums.MESSAGE_TYPE.RECEIPT) { |
|||
// 更新消息已读人数 |
|||
let msgInfo = { |
|||
id: msg.id, |
|||
groupId: msg.groupId, |
|||
readedCount: msg.readedCount, |
|||
receiptOk: msg.receiptOk |
|||
}; |
|||
this.chatStore.updateMessage(msgInfo) |
|||
return; |
|||
} |
|||
// 标记这条消息是不是自己发的 |
|||
msg.selfSend = msg.sendId == this.userStore.userInfo.id; |
|||
this.loadGroupInfo(msg.groupId, (group) => { |
|||
// 插入群聊消息 |
|||
this.insertGroupMessage(group, msg); |
|||
}) |
|||
}, |
|||
handleSystemMessage(msg) { |
|||
if (msg.type == enums.MESSAGE_TYPE.USER_BANNED) { |
|||
// 用户被封禁 |
|||
wsApi.close(3099); |
|||
uni.removeStorageSync("loginInfo"); |
|||
uni.reLaunch({ |
|||
url: "/pages/login/login" |
|||
uni.showModal({ |
|||
content: '您的账号已被管理员封禁,原因:' + msg.content, |
|||
showCancel: false, |
|||
}) |
|||
this.unloadStore(); |
|||
}, |
|||
playAudioTip() { |
|||
// 音频播放无法成功 |
|||
// this.audioTip = uni.createInnerAudioContext(); |
|||
// this.audioTip.src = "/static/audio/tip.wav"; |
|||
// this.audioTip.play(); |
|||
}, |
|||
refreshToken(loginInfo) { |
|||
return new Promise((resolve, reject) => { |
|||
if (!loginInfo || !loginInfo.refreshToken) { |
|||
reject(); |
|||
return; |
|||
this.exit(); |
|||
} |
|||
}, |
|||
insertGroupMessage(group, msg) { |
|||
// 群视频信令 |
|||
if (msgType.isRtcGroup(msg.type)) { |
|||
// #ifdef MP-WEIXIN |
|||
// 小程序不支持音视频 |
|||
return; |
|||
// #endif |
|||
// 被呼叫,弹出视频页面 |
|||
let delayTime = 100; |
|||
if (msg.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP) { |
|||
let pages = getCurrentPages(); |
|||
let curPage = pages[pages.length - 1].route; |
|||
if (curPage != "pages/chat/chat-group-video") { |
|||
const userInfos = encodeURIComponent(msg.content); |
|||
const inviterId = msg.sendId; |
|||
const groupId = msg.groupId |
|||
uni.navigateTo({ |
|||
url: `/pages/chat/chat-group-video?groupId=${groupId}&isHost=false |
|||
&inviterId=${inviterId}&userInfos=${userInfos}` |
|||
}) |
|||
delayTime = 500; |
|||
} |
|||
http({ |
|||
url: '/refreshToken', |
|||
method: 'PUT', |
|||
header: { |
|||
refreshToken: loginInfo.refreshToken |
|||
} |
|||
}).then((newLoginInfo) => { |
|||
uni.setStorageSync("loginInfo", newLoginInfo) |
|||
resolve() |
|||
}).catch((e) => { |
|||
reject(e) |
|||
}) |
|||
}) |
|||
}, |
|||
reconnectWs() { |
|||
// 已退出则不再重连 |
|||
if (this.isExit) { |
|||
return; |
|||
} |
|||
// 记录标志 |
|||
this.reconnecting = true; |
|||
// 重新加载一次个人信息,目的是为了保证网络已经正常且token有效 |
|||
this.reloadUserInfo().then((userInfo) => { |
|||
uni.showToast({ |
|||
title: '连接已断开,尝试重新连接...', |
|||
icon: 'none', |
|||
}) |
|||
this.userStore.setUserInfo(userInfo); |
|||
// 重新连接 |
|||
let loginInfo = uni.getStorageSync("loginInfo") |
|||
wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken); |
|||
}).catch(() => { |
|||
// 5s后重试 |
|||
setTimeout(() => { |
|||
this.reconnectWs(); |
|||
}, 5000) |
|||
// 消息转发到chat-group-video页面进行处理 |
|||
setTimeout(() => { |
|||
uni.$emit('WS_RTC_GROUP', msg); |
|||
}, delayTime) |
|||
return; |
|||
} |
|||
|
|||
let chatInfo = { |
|||
type: 'GROUP', |
|||
targetId: group.id, |
|||
showName: group.showGroupName, |
|||
headImage: group.headImageThumb |
|||
}; |
|||
// 打开会话 |
|||
this.chatStore.openChat(chatInfo); |
|||
// 插入消息 |
|||
this.chatStore.insertMessage(msg); |
|||
// 播放提示音 |
|||
this.playAudioTip(); |
|||
}, |
|||
loadFriendInfo(id, callback) { |
|||
let friend = this.friendStore.findFriend(id); |
|||
if (friend) { |
|||
callback(friend); |
|||
} else { |
|||
http({ |
|||
url: `/friend/find/${id}`, |
|||
method: 'GET' |
|||
}).then((friend) => { |
|||
this.friendStore.addFriend(friend); |
|||
callback(friend) |
|||
}) |
|||
}, |
|||
reloadUserInfo() { |
|||
return http({ |
|||
url: '/user/self', |
|||
} |
|||
}, |
|||
loadGroupInfo(id, callback) { |
|||
let group = this.groupStore.findGroup(id); |
|||
if (group) { |
|||
callback(group); |
|||
} else { |
|||
http({ |
|||
url: `/group/find/${id}`, |
|||
method: 'GET' |
|||
}).then((group) => { |
|||
this.groupStore.addGroup(group); |
|||
callback(group) |
|||
}) |
|||
} |
|||
}, |
|||
onLaunch() { |
|||
this.$mountStore(); |
|||
// 登录状态校验 |
|||
let loginInfo = uni.getStorageSync("loginInfo") |
|||
this.refreshToken(loginInfo).then(() => { |
|||
// 初始化 |
|||
this.init(); |
|||
// 跳转到聊天页面 |
|||
uni.switchTab({ |
|||
url: "/pages/chat/chat" |
|||
exit() { |
|||
console.log("exit"); |
|||
this.isExit = true; |
|||
wsApi.close(3099); |
|||
uni.removeStorageSync("loginInfo"); |
|||
uni.reLaunch({ |
|||
url: "/pages/login/login" |
|||
}) |
|||
this.unloadStore(); |
|||
}, |
|||
playAudioTip() { |
|||
// 音频播放无法成功 |
|||
// this.audioTip = uni.createInnerAudioContext(); |
|||
// this.audioTip.src = "/static/audio/tip.wav"; |
|||
// this.audioTip.play(); |
|||
}, |
|||
refreshToken(loginInfo) { |
|||
return new Promise((resolve, reject) => { |
|||
if (!loginInfo || !loginInfo.refreshToken) { |
|||
reject(); |
|||
return; |
|||
} |
|||
http({ |
|||
url: '/refreshToken', |
|||
method: 'PUT', |
|||
header: { |
|||
refreshToken: loginInfo.refreshToken |
|||
} |
|||
}).then((newLoginInfo) => { |
|||
uni.setStorageSync("loginInfo", newLoginInfo) |
|||
resolve() |
|||
}).catch((e) => { |
|||
reject(e) |
|||
}) |
|||
}).catch(() => { |
|||
// 跳转到登录页 |
|||
// #ifdef H5 |
|||
uni.navigateTo({ |
|||
url: "/pages/login/login" |
|||
}) |
|||
}, |
|||
reconnectWs() { |
|||
// 已退出则不再重连 |
|||
if (this.isExit) { |
|||
return; |
|||
} |
|||
// 记录标志 |
|||
this.reconnecting = true; |
|||
// 重新加载一次个人信息,目的是为了保证网络已经正常且token有效 |
|||
this.reloadUserInfo().then((userInfo) => { |
|||
uni.showToast({ |
|||
title: '连接已断开,尝试重新连接...', |
|||
icon: 'none', |
|||
}) |
|||
// #endif |
|||
this.userStore.setUserInfo(userInfo); |
|||
// 重新连接 |
|||
let loginInfo = uni.getStorageSync("loginInfo") |
|||
wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken); |
|||
}).catch(() => { |
|||
// 5s后重试 |
|||
setTimeout(() => { |
|||
this.reconnectWs(); |
|||
}, 5000) |
|||
}) |
|||
}, |
|||
reloadUserInfo() { |
|||
return http({ |
|||
url: '/user/self', |
|||
method: 'GET' |
|||
}) |
|||
} |
|||
}, |
|||
onLaunch() { |
|||
this.$mountStore(); |
|||
// 登录状态校验 |
|||
let loginInfo = uni.getStorageSync("loginInfo") |
|||
this.refreshToken(loginInfo).then(() => { |
|||
// 初始化 |
|||
this.init(); |
|||
// 跳转到聊天页面 |
|||
uni.switchTab({ |
|||
url: "/pages/chat/chat" |
|||
}) |
|||
}).catch(() => { |
|||
// 跳转到登录页 |
|||
// #ifdef H5 |
|||
uni.navigateTo({ |
|||
url: "/pages/login/login" |
|||
}) |
|||
// #endif |
|||
}) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
@import "@/uni_modules/uview-plus/index.scss"; |
|||
@import "@/im.scss"; |
|||
@import url('./static/icon/iconfont.css'); |
|||
@import "@/uni_modules/uview-plus/index.scss"; |
|||
@import "@/im.scss"; |
|||
@import url('./static/icon/iconfont.css'); |
|||
|
|||
// #ifdef H5 |
|||
uni-page-head { |
|||
display: none; // h5浏览器本身就有标题 |
|||
} |
|||
// #endif |
|||
// #ifdef H5 |
|||
uni-page-head { |
|||
display: none; // h5浏览器本身就有标题 |
|||
} |
|||
|
|||
.tab-page { |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: column; |
|||
// #ifdef H5 |
|||
height: calc(100vh - 50px - $im-nav-bar-height); // h5平台100vh是包含了底部高度,需要减去 |
|||
top: $im-nav-bar-height; |
|||
// #endif |
|||
// #endif |
|||
|
|||
// #ifndef H5 |
|||
height: calc(100vh - var(--status-bar-height) - $im-nav-bar-height); // app平台还要减去顶部手机状态栏高度 |
|||
top: calc($im-nav-bar-height + var(--status-bar-height)); |
|||
// #endif |
|||
color: $im-text-color; |
|||
background-color: $im-bg; |
|||
font-size: $im-font-size; |
|||
font-family: $font-family; |
|||
} |
|||
.tab-page { |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: column; |
|||
// #ifdef H5 |
|||
height: calc(100vh - 50px - $im-nav-bar-height); // h5平台100vh是包含了底部高度,需要减去 |
|||
top: $im-nav-bar-height; |
|||
// #endif |
|||
|
|||
.page { |
|||
position: relative; |
|||
// #ifdef H5 |
|||
height: calc(100vh - $im-nav-bar-height); // app平台还要减去顶部手机状态栏高度 |
|||
top: $im-nav-bar-height; |
|||
// #endif |
|||
// #ifndef H5 |
|||
height: calc(100vh - var(--status-bar-height) - $im-nav-bar-height); // app平台还要减去顶部手机状态栏高度 |
|||
top: calc($im-nav-bar-height + var(--status-bar-height)); |
|||
// #endif |
|||
color: $im-text-color; |
|||
background-color: $im-bg; |
|||
font-size: $im-font-size; |
|||
font-family: $font-family; |
|||
} |
|||
// #ifndef H5 |
|||
height: calc(100vh - var(--status-bar-height) - $im-nav-bar-height); // app平台还要减去顶部手机状态栏高度 |
|||
top: calc($im-nav-bar-height + var(--status-bar-height)); |
|||
// #endif |
|||
color: $im-text-color; |
|||
background-color: $im-bg; |
|||
font-size: $im-font-size; |
|||
font-family: $font-family; |
|||
} |
|||
|
|||
.page { |
|||
position: relative; |
|||
// #ifdef H5 |
|||
height: calc(100vh - $im-nav-bar-height); // app平台还要减去顶部手机状态栏高度 |
|||
top: $im-nav-bar-height; |
|||
// #endif |
|||
// #ifndef H5 |
|||
height: calc(100vh - var(--status-bar-height) - $im-nav-bar-height); // app平台还要减去顶部手机状态栏高度 |
|||
top: calc($im-nav-bar-height + var(--status-bar-height)); |
|||
// #endif |
|||
color: $im-text-color; |
|||
background-color: $im-bg; |
|||
font-size: $im-font-size; |
|||
font-family: $font-family; |
|||
} |
|||
</style> |
|||
@ -1,39 +1,40 @@ |
|||
<template> |
|||
<view class="arrow-bar"> |
|||
<text class="title">{{title}}</text> |
|||
<text class="title">{{ title }}</text> |
|||
<uni-icons class="arrow" type="right" size="16"></uni-icons> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: "arrow-bar", |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
required: true |
|||
} |
|||
}, |
|||
} |
|||
export default { |
|||
name: "arrow-bar", |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
required: true |
|||
} |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.arrow-bar { |
|||
width: 100%; |
|||
height: 90rpx; |
|||
font-size: 30rpx; |
|||
color: black; |
|||
margin-top: 5rpx; |
|||
background-color: white; |
|||
line-height: 90rpx; |
|||
display: flex; |
|||
.title { |
|||
flex: 1; |
|||
margin-left: 40rpx; |
|||
} |
|||
|
|||
.arrow { |
|||
margin-right: 40rpx; |
|||
} |
|||
.arrow-bar { |
|||
width: 100%; |
|||
height: 90rpx; |
|||
font-size: 30rpx; |
|||
color: black; |
|||
margin-top: 5rpx; |
|||
background-color: white; |
|||
line-height: 90rpx; |
|||
display: flex; |
|||
|
|||
.title { |
|||
flex: 1; |
|||
margin-left: 40rpx; |
|||
} |
|||
|
|||
.arrow { |
|||
margin-right: 40rpx; |
|||
} |
|||
} |
|||
</style> |
|||
@ -1,66 +1,68 @@ |
|||
<template> |
|||
<view class="btn-bar" :style="style"> |
|||
<text v-if="icon" class="icon iconfont" :class="icon"></text> |
|||
<text class="title">{{title}}</text> |
|||
<text class="title">{{ title }}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: "btn-bar", |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
icon: { |
|||
type: String, |
|||
required: false |
|||
}, |
|||
type: { |
|||
type: String, |
|||
default: "normal" |
|||
}, |
|||
color: { |
|||
type: String, |
|||
default: "#000" |
|||
} |
|||
export default { |
|||
name: "btn-bar", |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
icon: { |
|||
type: String, |
|||
required: false |
|||
}, |
|||
type: { |
|||
type: String, |
|||
default: "normal" |
|||
}, |
|||
computed: { |
|||
style() { |
|||
let color = "#000"; |
|||
switch (this.type) { |
|||
case 'danger': |
|||
color = "#f14747"; |
|||
break; |
|||
case 'primary': |
|||
color = "#35567f"; |
|||
break; |
|||
} |
|||
return `color: ${color};` |
|||
color: { |
|||
type: String, |
|||
default: "#000" |
|||
} |
|||
}, |
|||
computed: { |
|||
style() { |
|||
let color = "#000"; |
|||
switch (this.type) { |
|||
case 'danger': |
|||
color = "#f14747"; |
|||
break; |
|||
case 'primary': |
|||
color = "#35567f"; |
|||
break; |
|||
} |
|||
return `color: ${color};` |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.btn-bar { |
|||
width: 100%; |
|||
height: 100rpx; |
|||
margin-top: 5rpx; |
|||
background-color: white; |
|||
line-height: 100rpx; |
|||
text-align: center; |
|||
display: flex; |
|||
justify-content: center; |
|||
.icon { |
|||
font-size: 40rpx; |
|||
font-weight: 600; |
|||
margin-right: 10rpx; |
|||
} |
|||
.title { |
|||
font-size: 32rpx; |
|||
font-weight: 600; |
|||
} |
|||
.btn-bar { |
|||
width: 100%; |
|||
height: 100rpx; |
|||
margin-top: 5rpx; |
|||
background-color: white; |
|||
line-height: 100rpx; |
|||
text-align: center; |
|||
display: flex; |
|||
justify-content: center; |
|||
|
|||
.icon { |
|||
font-size: 40rpx; |
|||
font-weight: 600; |
|||
margin-right: 10rpx; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 32rpx; |
|||
font-weight: 600; |
|||
} |
|||
} |
|||
</style> |
|||
@ -1,61 +1,61 @@ |
|||
<template> |
|||
<view class="switch-bar"> |
|||
<text class="title">{{title}}</text> |
|||
<text class="title">{{ title }}</text> |
|||
<switch class="switch" :checked="checked" color="#18bc37" @change="onChange"></switch> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: "switch-bar", |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
checked: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
export default { |
|||
name: "switch-bar", |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
data() { |
|||
return { |
|||
value: this.checked |
|||
} |
|||
}, |
|||
methods: { |
|||
onChange(e) { |
|||
this.value = true; |
|||
setTimeout(()=>{ |
|||
this.value = false; |
|||
},100) |
|||
//this.value = false; |
|||
|
|||
this.$emit('change', e); |
|||
} |
|||
checked: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
value: this.checked |
|||
} |
|||
}, |
|||
methods: { |
|||
onChange(e) { |
|||
this.value = true; |
|||
setTimeout(() => { |
|||
this.value = false; |
|||
}, 100) |
|||
//this.value = false; |
|||
|
|||
this.$emit('change', e); |
|||
} |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.switch-bar { |
|||
width: 100%; |
|||
height: 100rpx; |
|||
font-size: 34rpx; |
|||
color: black; |
|||
margin-top: 5rpx; |
|||
background-color: white; |
|||
line-height: 100rpx; |
|||
display: flex; |
|||
.switch-bar { |
|||
width: 100%; |
|||
height: 100rpx; |
|||
font-size: 34rpx; |
|||
color: black; |
|||
margin-top: 5rpx; |
|||
background-color: white; |
|||
line-height: 100rpx; |
|||
display: flex; |
|||
|
|||
.title { |
|||
flex: 1; |
|||
margin-left: 40rpx; |
|||
} |
|||
.title { |
|||
flex: 1; |
|||
margin-left: 40rpx; |
|||
} |
|||
|
|||
.switch { |
|||
margin-right: 40rpx; |
|||
} |
|||
.switch { |
|||
margin-right: 40rpx; |
|||
} |
|||
} |
|||
</style> |
|||
@ -1,59 +1,58 @@ |
|||
<template> |
|||
<view class="group-item" @click="showGroupInfo()"> |
|||
<head-image :name="group.showGroupName" |
|||
:url="group.headImage" size="small"></head-image> |
|||
<head-image :name="group.showGroupName" :url="group.headImage" size="small"></head-image> |
|||
<view class="group-name"> |
|||
<view>{{ group.showGroupName}}</view> |
|||
<view>{{ group.showGroupName }}</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: "group-item", |
|||
data() { |
|||
return {} |
|||
export default { |
|||
name: "group-item", |
|||
data() { |
|||
return {} |
|||
}, |
|||
methods: { |
|||
showGroupInfo() { |
|||
uni.navigateTo({ |
|||
url: "/pages/group/group-info?id=" + this.group.id |
|||
}) |
|||
}, |
|||
methods:{ |
|||
showGroupInfo(){ |
|||
uni.navigateTo({ |
|||
url:"/pages/group/group-info?id="+this.group.id |
|||
}) |
|||
}, |
|||
}, |
|||
props: { |
|||
group: { |
|||
type: Object |
|||
} |
|||
}, |
|||
props: { |
|||
group: { |
|||
type: Object |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scope lang="scss"> |
|||
.group-item { |
|||
height: 90rpx; |
|||
display: flex; |
|||
margin-bottom: 2rpx; |
|||
position: relative; |
|||
padding: 18rpx 20rpx; |
|||
align-items: center; |
|||
background-color: white; |
|||
white-space: nowrap; |
|||
.group-item { |
|||
height: 90rpx; |
|||
display: flex; |
|||
margin-bottom: 2rpx; |
|||
position: relative; |
|||
padding: 18rpx 20rpx; |
|||
align-items: center; |
|||
background-color: white; |
|||
white-space: nowrap; |
|||
|
|||
&:hover { |
|||
background-color: $im-bg-active; |
|||
} |
|||
&:hover { |
|||
background-color: $im-bg-active; |
|||
} |
|||
|
|||
&.active { |
|||
background-color: $im-bg-active; |
|||
} |
|||
&.active { |
|||
background-color: $im-bg-active; |
|||
} |
|||
|
|||
.group-name { |
|||
font-size: $im-font-size; |
|||
padding-left: 20rpx; |
|||
text-align: left; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
} |
|||
.group-name { |
|||
font-size: $im-font-size; |
|||
padding-left: 20rpx; |
|||
text-align: left; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
} |
|||
} |
|||
</style> |
|||
|
|||
File diff suppressed because it is too large
@ -1,146 +1,150 @@ |
|||
<template> |
|||
<nav-bar add search @add="onAddNewFriends" @search="showSearch = !showSearch">好友</nav-bar> |
|||
|
|||
<view class="tab-page friend"> |
|||
<nav-bar add search @add="onAddNewFriends" @search="showSearch = !showSearch">好友</nav-bar> |
|||
<view class="nav-bar" v-if="showSearch"> |
|||
<view class="nav-search"> |
|||
<uni-search-bar v-model="searchText" radius="100" cancelButton="none" placeholder="点击搜索好友"></uni-search-bar> |
|||
<uni-search-bar v-model="searchText" radius="100" cancelButton="none" |
|||
placeholder="点击搜索好友"></uni-search-bar> |
|||
</view> |
|||
</view> |
|||
<view class="friend-tip" v-if="friends.length==0"> |
|||
<view class="friend-tip" v-if="friends.length == 0"> |
|||
温馨提示:您现在还没有任何好友,快点击右上方'+'按钮添加好友吧~ |
|||
</view> |
|||
<view class="friend-items" v-else> |
|||
<up-index-list :index-list="friendIdx" > |
|||
<template v-for="(friends,i) in friendGroups"> |
|||
<up-index-list :index-list="friendIdx"> |
|||
<template v-for="(friends, i) in friendGroups"> |
|||
<up-index-item> |
|||
<up-index-anchor :text="friendIdx[i]=='*'?'在线':friendIdx[i]"></up-index-anchor> |
|||
<view v-for="(friend,idx) in friends" :key="idx"> |
|||
<up-index-anchor :text="friendIdx[i] == '*' ? '在线' : friendIdx[i]"></up-index-anchor> |
|||
<view v-for="(friend, idx) in friends" :key="idx"> |
|||
<friend-item :friend="friend"></friend-item> |
|||
</view> |
|||
</up-index-item> |
|||
</template> |
|||
</up-index-list> |
|||
</view> |
|||
|
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { pinyin } from 'pinyin-pro'; |
|||
import { pinyin } from 'pinyin-pro'; |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
showSearch: false, |
|||
searchText: '' |
|||
} |
|||
export default { |
|||
data() { |
|||
return { |
|||
showSearch: false, |
|||
searchText: '' |
|||
} |
|||
}, |
|||
methods: { |
|||
onAddNewFriends() { |
|||
uni.navigateTo({ |
|||
url: "/pages/friend/friend-add" |
|||
}) |
|||
}, |
|||
firstLetter(strText) { |
|||
// 使用pinyin-pro库将中文转换为拼音 |
|||
let pinyinOptions = { |
|||
toneType: 'none', // 无声调 |
|||
type: 'normal' // 普通拼音 |
|||
}; |
|||
let pyText = pinyin(strText, pinyinOptions); |
|||
return pyText[0]; |
|||
}, |
|||
isEnglish(character) { |
|||
return /^[A-Za-z]+$/.test(character); |
|||
} |
|||
}, |
|||
computed: { |
|||
friends() { |
|||
return this.friendStore.friends; |
|||
}, |
|||
friendGroupMap() { |
|||
// 按首字母分组 |
|||
let groupMap = new Map(); |
|||
this.friends.forEach((f) => { |
|||
if (this.searchText && !f.nickName.includes(this.searchText)) { |
|||
return; |
|||
} |
|||
let letter = this.firstLetter(f.nickName).toUpperCase(); |
|||
// 非英文一律为#组 |
|||
if (!this.isEnglish(letter)) { |
|||
letter = "#" |
|||
} |
|||
if (f.online) { |
|||
letter = '*' |
|||
} |
|||
if (groupMap.has(letter)) { |
|||
groupMap.get(letter).push(f); |
|||
} else { |
|||
groupMap.set(letter, [f]); |
|||
} |
|||
}) |
|||
// 排序 |
|||
let arrayObj = Array.from(groupMap); |
|||
arrayObj.sort((a, b) => { |
|||
// #组在最后面 |
|||
if (a[0] == '#' || b[0] == '#') { |
|||
return b[0].localeCompare(a[0]) |
|||
} |
|||
return a[0].localeCompare(b[0]) |
|||
}) |
|||
groupMap = new Map(arrayObj.map(i => [i[0], i[1]])); |
|||
return groupMap; |
|||
}, |
|||
methods: { |
|||
onAddNewFriends() { |
|||
uni.navigateTo({ |
|||
url: "/pages/friend/friend-add" |
|||
}) |
|||
}, |
|||
firstLetter(strText) { |
|||
// 使用pinyin-pro库将中文转换为拼音 |
|||
let pinyinOptions = { |
|||
toneType: 'none', // 无声调 |
|||
type: 'normal' // 普通拼音 |
|||
}; |
|||
let pyText = pinyin(strText, pinyinOptions); |
|||
return pyText[0]; |
|||
}, |
|||
isEnglish(character) { |
|||
return /^[A-Za-z]+$/.test(character); |
|||
} |
|||
friendIdx() { |
|||
return Array.from(this.friendGroupMap.keys()); |
|||
}, |
|||
computed: { |
|||
friends() { |
|||
return this.friendStore.friends; |
|||
}, |
|||
friendGroupMap(){ |
|||
// 按首字母分组 |
|||
let groupMap = new Map(); |
|||
this.friends.forEach((f) => { |
|||
if(this.searchText && !f.nickName.includes(this.searchText)){ |
|||
return; |
|||
} |
|||
let letter = this.firstLetter(f.nickName).toUpperCase(); |
|||
// 非英文一律为#组 |
|||
if (!this.isEnglish(letter)) { |
|||
letter = "#" |
|||
} |
|||
if (f.online) { |
|||
letter = '*' |
|||
} |
|||
if (groupMap.has(letter)) { |
|||
groupMap.get(letter).push(f); |
|||
} else { |
|||
groupMap.set(letter, [f]); |
|||
} |
|||
}) |
|||
// 排序 |
|||
let arrayObj = Array.from(groupMap); |
|||
arrayObj.sort((a, b) => { |
|||
// #组在最后面 |
|||
if (a[0] == '#' || b[0] == '#') { |
|||
return b[0].localeCompare(a[0]) |
|||
} |
|||
return a[0].localeCompare(b[0]) |
|||
}) |
|||
groupMap = new Map(arrayObj.map(i => [i[0], i[1]])); |
|||
return groupMap; |
|||
}, |
|||
friendIdx(){ |
|||
return Array.from(this.friendGroupMap.keys()); |
|||
}, |
|||
friendGroups(){ |
|||
return Array.from(this.friendGroupMap.values()); |
|||
} |
|||
friendGroups() { |
|||
return Array.from(this.friendGroupMap.values()); |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.friend { |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: column; |
|||
.friend { |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
:deep(.u-index-anchor){ |
|||
height: 60rpx !important; |
|||
background-color: unset !important; |
|||
border-bottom: none !important; |
|||
} |
|||
:deep(.u-index-anchor__text){ |
|||
color: $im-text-color !important; |
|||
} |
|||
:deep(.u-index-list__letter__item){ |
|||
width: 48rpx !important; |
|||
height: 48rpx !important; |
|||
} |
|||
:deep(.u-index-list__letter__item__index){ |
|||
font-size: $im-font-size-small !important; |
|||
} |
|||
:deep(.u-index-anchor) { |
|||
height: 60rpx !important; |
|||
background-color: unset !important; |
|||
border-bottom: none !important; |
|||
} |
|||
|
|||
.friend-tip { |
|||
position: absolute; |
|||
top: 400rpx; |
|||
padding: 50rpx; |
|||
text-align: center; |
|||
line-height: 50rpx; |
|||
color: $im-text-color-lighter; |
|||
} |
|||
:deep(.u-index-anchor__text) { |
|||
color: $im-text-color !important; |
|||
} |
|||
|
|||
:deep(.u-index-list__letter__item) { |
|||
width: 48rpx !important; |
|||
height: 48rpx !important; |
|||
} |
|||
|
|||
:deep(.u-index-list__letter__item__index) { |
|||
font-size: $im-font-size-small !important; |
|||
} |
|||
|
|||
.friend-tip { |
|||
position: absolute; |
|||
top: 400rpx; |
|||
padding: 50rpx; |
|||
text-align: center; |
|||
line-height: 50rpx; |
|||
color: $im-text-color-lighter; |
|||
} |
|||
|
|||
.friend-items { |
|||
flex: 1; |
|||
padding: 0; |
|||
overflow: hidden; |
|||
position: relative; |
|||
|
|||
.friend-items { |
|||
flex: 1; |
|||
padding: 0; |
|||
overflow: hidden; |
|||
position: relative; |
|||
|
|||
.scroll-bar { |
|||
height: 100%; |
|||
} |
|||
.scroll-bar { |
|||
height: 100%; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -1,156 +1,157 @@ |
|||
<template> |
|||
<nav-bar back>修改群资料</nav-bar> |
|||
<view v-if="userStore.userInfo.type == 1" class="page group-edit"> |
|||
<uni-card :is-shadow="false" is-full :border="false"> |
|||
<uni-forms ref="form" :modelValue="group" :rules="rules" validate-trigger="bind" label-position="top" |
|||
label-width="100%"> |
|||
<uni-forms-item name="headImage" class="avatar"> |
|||
<image-upload v-if="isOwner" :onSuccess="onUnloadImageSuccess"> |
|||
<image :src="group.headImageThumb" class="group-image"></image> |
|||
</image-upload> |
|||
<head-image v-if="!isOwner" :name="group.showGroupName" |
|||
:url="group.headImageThumb" :size="200"></head-image> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="群聊名称" name="name" :required="true"> |
|||
<uni-easyinput type="text" v-model="group.name" :disabled="!isOwner" placeholder="请输入群聊名称" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="群聊备注" name="remarkGroupName"> |
|||
<uni-easyinput v-model="group.remarkGroupName" type="text" :placeholder="group.name" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="我在本群的昵称" name="remarkNickName"> |
|||
<uni-easyinput v-model="group.remarkNickName" type="text" :placeholder="userStore.userInfo.nickName" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="群公告" name="notice"> |
|||
<uni-easyinput type="textarea" v-model="group.notice" :disabled="!isOwner" placeholder="请输入群公告" /> |
|||
</uni-forms-item> |
|||
</uni-forms> |
|||
</uni-card> |
|||
<button class="bottom-btn" type="primary" @click="submit()">提交</button> |
|||
</view> |
|||
<view v-if="userStore.userInfo.type == 1" class="page group-edit"> |
|||
<nav-bar back>修改群资料</nav-bar> |
|||
<uni-card :is-shadow="false" is-full :border="false"> |
|||
<uni-forms ref="form" :modelValue="group" :rules="rules" validate-trigger="bind" label-position="top" |
|||
label-width="100%"> |
|||
<uni-forms-item name="headImage" class="avatar"> |
|||
<image-upload v-if="isOwner" :onSuccess="onUnloadImageSuccess"> |
|||
<image :src="group.headImageThumb" class="group-image"></image> |
|||
</image-upload> |
|||
<head-image v-if="!isOwner" :name="group.showGroupName" :url="group.headImageThumb" |
|||
:size="200"></head-image> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="群聊名称" name="name" :required="true"> |
|||
<uni-easyinput type="text" v-model="group.name" :disabled="!isOwner" placeholder="请输入群聊名称" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="群聊备注" name="remarkGroupName"> |
|||
<uni-easyinput v-model="group.remarkGroupName" type="text" :placeholder="group.name" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="我在本群的昵称" name="remarkNickName"> |
|||
<uni-easyinput v-model="group.remarkNickName" type="text" |
|||
:placeholder="userStore.userInfo.nickName" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="群公告" name="notice"> |
|||
<uni-easyinput type="textarea" v-model="group.notice" :disabled="!isOwner" placeholder="请输入群公告" /> |
|||
</uni-forms-item> |
|||
</uni-forms> |
|||
</uni-card> |
|||
<button class="bottom-btn" type="primary" @click="submit()">提交</button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
group: {}, |
|||
rules: { |
|||
name: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '请输入群聊名称', |
|||
}] |
|||
} |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
group: {}, |
|||
rules: { |
|||
name: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '请输入群聊名称', |
|||
}] |
|||
} |
|||
|
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
submit() { |
|||
if (this.group.id) { |
|||
this.modifyGroup(); |
|||
} else { |
|||
this.createNewGroup(); |
|||
} |
|||
}, |
|||
onUnloadImageSuccess(file, res) { |
|||
this.group.headImage = res.data.originUrl; |
|||
this.group.headImageThumb = res.data.thumbUrl; |
|||
}, |
|||
modifyGroup() { |
|||
this.$http({ |
|||
url: "/group/modify", |
|||
method: "PUT", |
|||
data: this.group |
|||
}).then((group) => { |
|||
this.groupStore.updateGroup(group); |
|||
uni.showToast({ |
|||
title: "修改群聊信息成功", |
|||
icon: 'none' |
|||
}); |
|||
setTimeout(() => { |
|||
let pages = getCurrentPages(); |
|||
let prevPage = pages[pages.length - 2]; |
|||
prevPage.$vm.loadGroupInfo(); |
|||
uni.navigateBack(); |
|||
}, 1000); |
|||
|
|||
methods: { |
|||
submit() { |
|||
if (this.group.id) { |
|||
this.modifyGroup(); |
|||
} else { |
|||
this.createNewGroup(); |
|||
} |
|||
}, |
|||
onUnloadImageSuccess(file, res) { |
|||
this.group.headImage = res.data.originUrl; |
|||
this.group.headImageThumb = res.data.thumbUrl; |
|||
}, |
|||
modifyGroup() { |
|||
this.$http({ |
|||
url: "/group/modify", |
|||
method: "PUT", |
|||
data: this.group |
|||
}).then((group) => { |
|||
this.groupStore.updateGroup(group); |
|||
uni.showToast({ |
|||
title: "修改群聊信息成功", |
|||
icon: 'none' |
|||
}); |
|||
setTimeout(() => { |
|||
let pages = getCurrentPages(); |
|||
let prevPage = pages[pages.length - 2]; |
|||
prevPage.$vm.loadGroupInfo(); |
|||
uni.navigateBack(); |
|||
}, 1000); |
|||
|
|||
}) |
|||
}, |
|||
createNewGroup() { |
|||
this.$http({ |
|||
url: "/group/create", |
|||
method: 'POST', |
|||
data: this.group |
|||
}).then((group) => { |
|||
this.groupStore.addGroup(group); |
|||
uni.showToast({ |
|||
title: `群聊创建成功,快邀请小伙伴进群吧`, |
|||
icon: 'none', |
|||
duration: 1500 |
|||
}) |
|||
}, |
|||
createNewGroup() { |
|||
this.$http({ |
|||
url: "/group/create", |
|||
method: 'POST', |
|||
data: this.group |
|||
}).then((group) => { |
|||
this.groupStore.addGroup(group); |
|||
uni.showToast({ |
|||
title: `群聊创建成功,快邀请小伙伴进群吧`, |
|||
icon: 'none', |
|||
duration: 1500 |
|||
}); |
|||
setTimeout(() => { |
|||
uni.navigateTo({ |
|||
url: "/pages/group/group-info?id=" + group.id |
|||
}); |
|||
setTimeout(() => { |
|||
uni.navigateTo({ |
|||
url: "/pages/group/group-info?id=" + group.id |
|||
}); |
|||
}, 1500) |
|||
|
|||
}) |
|||
}, |
|||
loadGroupInfo(id) { |
|||
this.$http({ |
|||
url: `/group/find/${id}`, |
|||
method: 'GET' |
|||
}).then((group) => { |
|||
this.group = group; |
|||
// 更新聊天页面的群聊信息 |
|||
this.chatStore.updateChatFromGroup(group); |
|||
// 更新聊天列表的群聊信息 |
|||
this.groupStore.updateGroup(group); |
|||
}, 1500) |
|||
|
|||
}); |
|||
}, |
|||
initNewGroup() { |
|||
let userInfo = this.userStore.userInfo; |
|||
this.group = { |
|||
name: `${userInfo.userName}创建的群聊`, |
|||
headImage: userInfo.headImage, |
|||
headImageThumb: userInfo.headImageThumb, |
|||
ownerId: this.userStore.userInfo.id |
|||
} |
|||
} |
|||
}) |
|||
}, |
|||
computed: { |
|||
isOwner() { |
|||
return this.userStore.userInfo.id == this.group.ownerId |
|||
} |
|||
loadGroupInfo(id) { |
|||
this.$http({ |
|||
url: `/group/find/${id}`, |
|||
method: 'GET' |
|||
}).then((group) => { |
|||
this.group = group; |
|||
// 更新聊天页面的群聊信息 |
|||
this.chatStore.updateChatFromGroup(group); |
|||
// 更新聊天列表的群聊信息 |
|||
this.groupStore.updateGroup(group); |
|||
|
|||
}); |
|||
}, |
|||
onLoad(options) { |
|||
if (options.id) { |
|||
// 修改群聊 |
|||
this.loadGroupInfo(options.id); |
|||
} else { |
|||
// 创建群聊 |
|||
this.initNewGroup(); |
|||
initNewGroup() { |
|||
let userInfo = this.userStore.userInfo; |
|||
this.group = { |
|||
name: `${userInfo.userName}创建的群聊`, |
|||
headImage: userInfo.headImage, |
|||
headImageThumb: userInfo.headImageThumb, |
|||
ownerId: this.userStore.userInfo.id |
|||
} |
|||
|
|||
} |
|||
}, |
|||
computed: { |
|||
isOwner() { |
|||
return this.userStore.userInfo.id == this.group.ownerId |
|||
} |
|||
}, |
|||
onLoad(options) { |
|||
if (options.id) { |
|||
// 修改群聊 |
|||
this.loadGroupInfo(options.id); |
|||
} else { |
|||
// 创建群聊 |
|||
this.initNewGroup(); |
|||
} |
|||
|
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.group-edit { |
|||
//padding: 20rpx; |
|||
.group-edit { |
|||
//padding: 20rpx; |
|||
|
|||
.group-image { |
|||
width: 200rpx; |
|||
height: 200rpx; |
|||
border: 1px solid #ccc; |
|||
border-radius: 5%; |
|||
} |
|||
.group-image { |
|||
width: 200rpx; |
|||
height: 200rpx; |
|||
border: 1px solid #ccc; |
|||
border-radius: 5%; |
|||
} |
|||
.avatar { |
|||
margin-top: -30px; |
|||
} |
|||
} |
|||
|
|||
.avatar { |
|||
margin-top: -30px; |
|||
} |
|||
</style> |
|||
|
|||
@ -1,166 +1,165 @@ |
|||
<template> |
|||
<view class="page group-invite"> |
|||
<view class="nav-bar"> |
|||
<view class="nav-search"> |
|||
<uni-search-bar v-model="searchText" radius="100" cancelButton="none" placeholder="输入好友昵称搜索"></uni-search-bar> |
|||
</view> |
|||
</view> |
|||
<view class="nav-bar"> |
|||
<view class="nav-search"> |
|||
<uni-search-bar v-model="searchText" radius="100" cancelButton="none" |
|||
placeholder="输入好友昵称搜索"></uni-search-bar> |
|||
</view> |
|||
</view> |
|||
<view class="friend-items"> |
|||
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> |
|||
<view v-for="friend in friendItems" v-show="!searchText || friend.nickName.includes(searchText)" |
|||
:key="friend.id"> |
|||
<view class="friend-item" @click="onSwitchChecked(friend)" :class="{checked: friend.checked, disabled: friend.disabled}"> |
|||
<head-image :name="friend.nickName" |
|||
:online="friend.online" :url="friend.headImage"></head-image> |
|||
|
|||
<view class="friend-name">{{ friend.nickName}}</view> |
|||
<!-- <view class="friend-checked">--> |
|||
<!-- <radio :checked="friend.checked" :disabled="friend.disabled" @click.stop="onSwitchChecked(friend)"/>--> |
|||
<!-- </view>--> |
|||
<view class="friend-item" @click="onSwitchChecked(friend)" |
|||
:class="{ checked: friend.checked, disabled: friend.disabled }"> |
|||
<head-image :name="friend.nickName" :online="friend.online" |
|||
:url="friend.headImage"></head-image> |
|||
<view class="friend-name">{{ friend.nickName }}</view> |
|||
</view> |
|||
</view> |
|||
</scroll-view> |
|||
</view> |
|||
<button class="bottom-btn" type="primary" :disabled="inviteSize==0" @click="onInviteFriends()">邀请({{inviteSize}}) </button> |
|||
<button class="bottom-btn" type="primary" :disabled="inviteSize == 0" |
|||
@click="onInviteFriends()">邀请({{ inviteSize }}) </button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
groupId: null, |
|||
searchText: "", |
|||
groupMembers: [], |
|||
friendItems: [] |
|||
export default { |
|||
data() { |
|||
return { |
|||
groupId: null, |
|||
searchText: "", |
|||
groupMembers: [], |
|||
friendItems: [] |
|||
} |
|||
}, |
|||
methods: { |
|||
onInviteFriends() { |
|||
let inviteVo = { |
|||
groupId: this.groupId, |
|||
friendIds: [] |
|||
} |
|||
}, |
|||
methods: { |
|||
onInviteFriends() { |
|||
let inviteVo = { |
|||
groupId: this.groupId, |
|||
friendIds: [] |
|||
} |
|||
this.friendItems.forEach((f) => { |
|||
if (f.checked && !f.disabled) { |
|||
inviteVo.friendIds.push(f.id); |
|||
} |
|||
}) |
|||
if (inviteVo.friendIds.length > 0) { |
|||
this.$http({ |
|||
url: "/group/invite", |
|||
method: 'POST', |
|||
data: inviteVo |
|||
}).then(() => { |
|||
uni.showToast({ |
|||
title: "邀请成功", |
|||
icon: 'none' |
|||
}) |
|||
setTimeout(() => { |
|||
// 回退并刷新 |
|||
let pages = getCurrentPages(); |
|||
let prevPage = pages[pages.length - 2]; |
|||
prevPage.$vm.loadGroupMembers(); |
|||
uni.navigateBack(); |
|||
}, 1000); |
|||
|
|||
}) |
|||
this.friendItems.forEach((f) => { |
|||
if (f.checked && !f.disabled) { |
|||
inviteVo.friendIds.push(f.id); |
|||
} |
|||
}, |
|||
onShowUserInfo(userId) { |
|||
uni.navigateTo({ |
|||
url: "/pages/common/user-info?id=" + userId |
|||
}) |
|||
}, |
|||
onSwitchChecked(friend) { |
|||
if (!friend.disabled) { |
|||
friend.checked = !friend.checked; |
|||
} |
|||
}, |
|||
initFriendItems() { |
|||
this.friendItems = []; |
|||
let friends = this.friendStore.friends; |
|||
friends.forEach((f => { |
|||
let item = { |
|||
id: f.id, |
|||
headImage: f.headImage, |
|||
nickName: f.nickName, |
|||
online: f.online |
|||
} |
|||
item.disabled = this.isGroupMember(f.id); |
|||
item.checked = item.disabled; |
|||
this.friendItems.push(item); |
|||
})) |
|||
}, |
|||
loadGroupMembers(id) { |
|||
}) |
|||
if (inviteVo.friendIds.length > 0) { |
|||
this.$http({ |
|||
url: `/group/members/${id}`, |
|||
method: "GET" |
|||
}).then((members) => { |
|||
this.groupMembers = members.filter(m => !m.quit); |
|||
this.initFriendItems(); |
|||
}) |
|||
}, |
|||
url: "/group/invite", |
|||
method: 'POST', |
|||
data: inviteVo |
|||
}).then(() => { |
|||
uni.showToast({ |
|||
title: "邀请成功", |
|||
icon: 'none' |
|||
}) |
|||
setTimeout(() => { |
|||
// 回退并刷新 |
|||
let pages = getCurrentPages(); |
|||
let prevPage = pages[pages.length - 2]; |
|||
prevPage.$vm.loadGroupMembers(); |
|||
uni.navigateBack(); |
|||
}, 1000); |
|||
|
|||
isGroupMember(id) { |
|||
return this.groupMembers.some(m => m.userId == id); |
|||
}) |
|||
} |
|||
}, |
|||
computed: { |
|||
inviteSize() { |
|||
return this.friendItems.filter(f => !f.disabled && f.checked).length; |
|||
onShowUserInfo(userId) { |
|||
uni.navigateTo({ |
|||
url: "/pages/common/user-info?id=" + userId |
|||
}) |
|||
}, |
|||
onSwitchChecked(friend) { |
|||
if (!friend.disabled) { |
|||
friend.checked = !friend.checked; |
|||
} |
|||
}, |
|||
onLoad(options) { |
|||
this.groupId = options.id; |
|||
this.loadGroupMembers(options.id); |
|||
initFriendItems() { |
|||
this.friendItems = []; |
|||
let friends = this.friendStore.friends; |
|||
friends.forEach((f => { |
|||
let item = { |
|||
id: f.id, |
|||
headImage: f.headImage, |
|||
nickName: f.nickName, |
|||
online: f.online |
|||
} |
|||
item.disabled = this.isGroupMember(f.id); |
|||
item.checked = item.disabled; |
|||
this.friendItems.push(item); |
|||
})) |
|||
}, |
|||
loadGroupMembers(id) { |
|||
this.$http({ |
|||
url: `/group/members/${id}`, |
|||
method: "GET" |
|||
}).then((members) => { |
|||
this.groupMembers = members.filter(m => !m.quit); |
|||
this.initFriendItems(); |
|||
}) |
|||
}, |
|||
|
|||
isGroupMember(id) { |
|||
return this.groupMembers.some(m => m.userId == id); |
|||
} |
|||
}, |
|||
computed: { |
|||
inviteSize() { |
|||
return this.friendItems.filter(f => !f.disabled && f.checked).length; |
|||
} |
|||
}, |
|||
onLoad(options) { |
|||
this.groupId = options.id; |
|||
this.loadGroupMembers(options.id); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.group-invite { |
|||
.group-invite { |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.friend-items { |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: column; |
|||
flex: 1; |
|||
overflow: hidden; |
|||
|
|||
.friend-items { |
|||
.friend-item { |
|||
height: 120rpx; |
|||
display: flex; |
|||
margin-bottom: 1rpx; |
|||
position: relative; |
|||
flex: 1; |
|||
overflow: hidden; |
|||
|
|||
.friend-item { |
|||
height: 120rpx; |
|||
display: flex; |
|||
margin-bottom: 1rpx; |
|||
position: relative; |
|||
padding: 0 30rpx ; |
|||
align-items: center; |
|||
background-color: white; |
|||
white-space: nowrap; |
|||
padding: 0 30rpx; |
|||
align-items: center; |
|||
background-color: white; |
|||
white-space: nowrap; |
|||
|
|||
&.disabled { |
|||
background-color: $im-bg-active !important; |
|||
} |
|||
|
|||
&.checked { |
|||
background-color: $im-color-primary-light-9; |
|||
} |
|||
&.disabled { |
|||
background-color: $im-bg-active !important; |
|||
} |
|||
|
|||
.friend-name { |
|||
flex:1; |
|||
padding-left: 20rpx; |
|||
font-size: 30rpx; |
|||
font-weight: 600; |
|||
line-height: 60rpx; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
} |
|||
&.checked { |
|||
background-color: $im-color-primary-light-9; |
|||
} |
|||
|
|||
.scroll-bar { |
|||
height: 100%; |
|||
|
|||
.friend-name { |
|||
flex: 1; |
|||
padding-left: 20rpx; |
|||
font-size: 30rpx; |
|||
font-weight: 600; |
|||
line-height: 60rpx; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
} |
|||
} |
|||
|
|||
.scroll-bar { |
|||
height: 100%; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -1,81 +1,81 @@ |
|||
<template> |
|||
<view class="page mine-edit"> |
|||
<nav-bar back>修改我的信息</nav-bar> |
|||
<uni-card :is-shadow="false" is-full :border="false"> |
|||
<uni-forms ref="form" :modelValue="userInfo" label-position="top" |
|||
label-width="100%"> |
|||
<uni-forms-item name="headImage" class="avatar"> |
|||
<image-upload :onSuccess="onUnloadImageSuccess"> |
|||
<image :src="userInfo.headImageThumb" class="head-image"></image> |
|||
</image-upload> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="用户名" name="userName"> |
|||
<uni-easyinput type="text" v-model="userInfo.userName" :disabled="true" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="昵称" name="nickName"> |
|||
<uni-easyinput v-model="userInfo.nickName" type="text" :placeholder="userInfo.userName" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="性别" name="sex"> |
|||
<uni-data-checkbox v-model="userInfo.sex" :localdata="[{text: '男', value: 0}, {text: '女', value: 1}]"></uni-data-checkbox> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="签名" name="signature"> |
|||
<uni-easyinput type="textarea" v-model="userInfo.signature" placeholder="编辑个性标签,展示我的独特态度" /> |
|||
</uni-forms-item> |
|||
</uni-forms> |
|||
</uni-card> |
|||
<nav-bar back>修改我的信息</nav-bar> |
|||
<uni-card :is-shadow="false" is-full :border="false"> |
|||
<uni-forms ref="form" :modelValue="userInfo" label-position="top" label-width="100%"> |
|||
<uni-forms-item name="headImage" class="avatar"> |
|||
<image-upload :onSuccess="onUnloadImageSuccess"> |
|||
<image :src="userInfo.headImageThumb" class="head-image"></image> |
|||
</image-upload> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="用户名" name="userName"> |
|||
<uni-easyinput type="text" v-model="userInfo.userName" :disabled="true" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="昵称" name="nickName"> |
|||
<uni-easyinput v-model="userInfo.nickName" type="text" :placeholder="userInfo.userName" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="性别" name="sex"> |
|||
<uni-data-checkbox v-model="userInfo.sex" |
|||
:localdata="[{ text: '男', value: 0 }, { text: '女', value: 1 }]"></uni-data-checkbox> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="签名" name="signature"> |
|||
<uni-easyinput type="textarea" v-model="userInfo.signature" placeholder="编辑个性标签,展示我的独特态度" /> |
|||
</uni-forms-item> |
|||
</uni-forms> |
|||
</uni-card> |
|||
<button type="primary" class="bottom-btn" @click="onSubmit()">提交</button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
userInfo: {} |
|||
} |
|||
export default { |
|||
data() { |
|||
return { |
|||
userInfo: {} |
|||
} |
|||
}, |
|||
methods: { |
|||
onSexchange(e) { |
|||
this.userInfo.sex = e.detail.value; |
|||
}, |
|||
methods:{ |
|||
onSexchange(e){ |
|||
this.userInfo.sex=e.detail.value; |
|||
}, |
|||
onUnloadImageSuccess(file, res) { |
|||
this.userInfo.headImage = res.data.originUrl; |
|||
this.userInfo.headImageThumb = res.data.thumbUrl; |
|||
}, |
|||
onSubmit(){ |
|||
this.$http({ |
|||
url: "/user/update", |
|||
method: "PUT", |
|||
data: this.userInfo |
|||
}).then(()=>{ |
|||
this.userStore.setUserInfo(this.userInfo); |
|||
uni.showToast({ |
|||
title:"修改成功", |
|||
icon: 'none' |
|||
}); |
|||
setTimeout(()=>{ |
|||
uni.navigateBack(); |
|||
},1000); |
|||
}) |
|||
} |
|||
onUnloadImageSuccess(file, res) { |
|||
this.userInfo.headImage = res.data.originUrl; |
|||
this.userInfo.headImageThumb = res.data.thumbUrl; |
|||
}, |
|||
onLoad() { |
|||
// 深拷贝一份数据 |
|||
let mine = this.userStore.userInfo; |
|||
this.userInfo = JSON.parse(JSON.stringify(mine)); |
|||
onSubmit() { |
|||
this.$http({ |
|||
url: "/user/update", |
|||
method: "PUT", |
|||
data: this.userInfo |
|||
}).then(() => { |
|||
this.userStore.setUserInfo(this.userInfo); |
|||
uni.showToast({ |
|||
title: "修改成功", |
|||
icon: 'none' |
|||
}); |
|||
setTimeout(() => { |
|||
uni.navigateBack(); |
|||
}, 1000); |
|||
}) |
|||
} |
|||
}, |
|||
onLoad() { |
|||
// 深拷贝一份数据 |
|||
let mine = this.userStore.userInfo; |
|||
this.userInfo = JSON.parse(JSON.stringify(mine)); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped lang="scss"> |
|||
.mine-edit { |
|||
.head-image { |
|||
width: 200rpx; |
|||
height: 200rpx; |
|||
} |
|||
.mine-edit { |
|||
.head-image { |
|||
width: 200rpx; |
|||
height: 200rpx; |
|||
} |
|||
} |
|||
|
|||
.avatar { |
|||
margin-top: -30px; |
|||
} |
|||
.avatar { |
|||
margin-top: -30px; |
|||
} |
|||
</style> |
|||
|
|||
@ -1,102 +1,101 @@ |
|||
<template> |
|||
<view class="page mine-password"> |
|||
<nav-bar back>修改密码</nav-bar> |
|||
<uni-card :is-shadow="false" is-full :border="false"> |
|||
<uni-forms ref="form" :modelValue="formData" label-position="top" label-width="100%" > |
|||
<uni-forms-item label="原密码" name="oldPassword"> |
|||
<uni-easyinput type="password" v-model="formData.oldPassword" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="新密码" name="newPassword"> |
|||
<uni-easyinput type="password" v-model="formData.newPassword" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="确认密码" name="confirmPassword"> |
|||
<uni-easyinput type="password" v-model="formData.confirmPassword" /> |
|||
</uni-forms-item> |
|||
</uni-forms> |
|||
</uni-card> |
|||
<button class="bottom-btn" type="primary" @click="onSubmit()">提交</button> |
|||
<nav-bar back>修改密码</nav-bar> |
|||
<uni-card :is-shadow="false" is-full :border="false"> |
|||
<uni-forms ref="form" :modelValue="formData" label-position="top" label-width="100%"> |
|||
<uni-forms-item label="原密码" name="oldPassword"> |
|||
<uni-easyinput type="password" v-model="formData.oldPassword" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="新密码" name="newPassword"> |
|||
<uni-easyinput type="password" v-model="formData.newPassword" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="确认密码" name="confirmPassword"> |
|||
<uni-easyinput type="password" v-model="formData.confirmPassword" /> |
|||
</uni-forms-item> |
|||
</uni-forms> |
|||
</uni-card> |
|||
<button class="bottom-btn" type="primary" @click="onSubmit()">提交</button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
formData: { |
|||
oldPassword: "", |
|||
newPassword: "", |
|||
confirmPassword: "" |
|||
export default { |
|||
data() { |
|||
return { |
|||
formData: { |
|||
oldPassword: "", |
|||
newPassword: "", |
|||
confirmPassword: "" |
|||
}, |
|||
rules: { |
|||
oldPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '请输入原密码', |
|||
}] |
|||
}, |
|||
rules: { |
|||
oldPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '请输入原密码', |
|||
}] |
|||
}, |
|||
newPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '请输入新密码', |
|||
}, { |
|||
validateFunction: function(rule, value, data, callback) { |
|||
if (data.confirmPassword != data.newPassword) { |
|||
callback("两次输入的密码不一致"); |
|||
} |
|||
if (data.newPassword == data.oldPassword) { |
|||
callback("新密码不能和原密码一致"); |
|||
} |
|||
return true; |
|||
newPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '请输入新密码', |
|||
}, { |
|||
validateFunction: function (rule, value, data, callback) { |
|||
if (data.confirmPassword != data.newPassword) { |
|||
callback("两次输入的密码不一致"); |
|||
} |
|||
}] |
|||
}, |
|||
confirmPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '请输入确认密码', |
|||
}, { |
|||
validateFunction: function(rule, value, data, callback) { |
|||
if (data.confirmPassword != data.newPassword) { |
|||
callback("两次输入的密码不一致"); |
|||
} |
|||
|
|||
return true; |
|||
if (data.newPassword == data.oldPassword) { |
|||
callback("新密码不能和原密码一致"); |
|||
} |
|||
return true; |
|||
} |
|||
}] |
|||
}, |
|||
confirmPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '请输入确认密码', |
|||
}, { |
|||
validateFunction: function (rule, value, data, callback) { |
|||
if (data.confirmPassword != data.newPassword) { |
|||
callback("两次输入的密码不一致"); |
|||
} |
|||
}] |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
}] |
|||
} |
|||
|
|||
} |
|||
}, |
|||
methods: { |
|||
onSubmit() { |
|||
this.$refs.form.validate().then(res => { |
|||
this.$http({ |
|||
url: "/modifyPwd", |
|||
method: "PUT", |
|||
data: this.formData |
|||
}).then((res) => { |
|||
uni.showToast({ |
|||
title: "修改密码成功", |
|||
icon: 'none' |
|||
}) |
|||
setTimeout(()=>{ |
|||
uni.navigateBack(); |
|||
},1000); |
|||
} |
|||
}, |
|||
methods: { |
|||
onSubmit() { |
|||
this.$refs.form.validate().then(res => { |
|||
this.$http({ |
|||
url: "/modifyPwd", |
|||
method: "PUT", |
|||
data: this.formData |
|||
}).then((res) => { |
|||
uni.showToast({ |
|||
title: "修改密码成功", |
|||
icon: 'none' |
|||
}) |
|||
}).catch(err => { |
|||
console.log('表单错误信息:', err); |
|||
setTimeout(() => { |
|||
uni.navigateBack(); |
|||
}, 1000); |
|||
}) |
|||
}).catch(err => { |
|||
console.log('表单错误信息:', err); |
|||
}) |
|||
|
|||
} |
|||
}, |
|||
onReady() { |
|||
// 需要在onReady中设置规则 |
|||
this.$refs.form.setRules(this.rules) |
|||
} |
|||
|
|||
}, |
|||
onReady() { |
|||
// 需要在onReady中设置规则 |
|||
this.$refs.form.setRules(this.rules) |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style scoped lang="scss"> |
|||
</style> |
|||
<style scoped lang="scss"></style> |
|||
Loading…
Reference in new issue