Browse Source

提交修改客服端修改内容

master
[yxf] 3 weeks ago
parent
commit
838de2de3b
  1. 1
      im-platform/src/main/java/com/bx/implatform/service/impl/ImAgentServiceImpl.java
  2. 1
      im-uniapp/App.vue
  3. 3
      im-uniapp/components/chat-message-item/chat-message-item.vue
  4. 19
      im-uniapp/pages/chat/chat-box.vue
  5. 7
      im-web/src/components/account/AccountSwitchMenu.vue
  6. 14
      im-web/src/components/chat/ChatBox.vue
  7. 6
      im-web/src/components/chat/ChatMessageItem.vue
  8. 35
      im-web/src/store/chatStore.js
  9. 41
      im-web/src/store/friendStore.js
  10. 8
      im-web/src/view/Home.vue
  11. 61
      im-web/src/view/Login.vue

1
im-platform/src/main/java/com/bx/implatform/service/impl/ImAgentServiceImpl.java

@ -53,7 +53,6 @@ public class ImAgentServiceImpl extends ServiceImpl<ImAgentMapper, ImAgent> impl
// if(user == null || ObjectUtil.isEmpty(user)){ // if(user == null || ObjectUtil.isEmpty(user)){
// return false; // return false;
// } // }
String token = user.getUniqueToken(); String token = user.getUniqueToken();
if(token == null || ObjectUtil.isEmpty(token)){ if(token == null || ObjectUtil.isEmpty(token)){
return false; return false;

1
im-uniapp/App.vue

@ -42,7 +42,6 @@ export default {
this.configStore.setAppInit(true); this.configStore.setAppInit(true);
} }
}); });
// console.log(cmd, msgInfo);
wsApi.onMessage((cmd, msgInfo) => { wsApi.onMessage((cmd, msgInfo) => {
console.log(cmd, msgInfo); console.log(cmd, msgInfo);
if (cmd == 2) { if (cmd == 2) {

3
im-uniapp/components/chat-message-item/chat-message-item.vue

@ -66,8 +66,7 @@
<view v-if="sending&&(isTextMessage||isAudioMessage)" class="sending"> <view v-if="sending&&(isTextMessage||isAudioMessage)" class="sending">
<custom-loading :size="40" icon-color="#656adf" :mask="false"></custom-loading> <custom-loading :size="40" icon-color="#656adf" :mask="false"></custom-loading>
</view> </view>
<view v-else-if="sendFail" @click="onSendFail" <!-- <view v-else-if="sendFail" @click="onSendFail" class="send-fail iconfont icon-warning-circle-fill"></view> -->
class="send-fail iconfont icon-warning-circle-fill"></view>
</view> </view>
<view class="message-status" v-if="!isAction && msgInfo.selfSend && !msgInfo.groupId"> <view class="message-status" v-if="!isAction && msgInfo.selfSend && !msgInfo.groupId">
<text class="chat-readed" v-if="msgInfo.status == $enums.MESSAGE_STATUS.READED">{{ $t('chat.read') }}</text> <text class="chat-readed" v-if="msgInfo.status == $enums.MESSAGE_STATUS.READED">{{ $t('chat.read') }}</text>

19
im-uniapp/pages/chat/chat-box.vue

@ -664,9 +664,26 @@ export default {
this.$forceUpdate(); this.$forceUpdate();
uni.showToast({ uni.showToast({
title: this.$t('chat.sendFailed'), title: "客服已更换,刷新中...",
icon: "none", icon: "none",
duration: 1500
}); });
setTimeout(() => {
// #ifdef H5
window.location.reload();
// #endif
// #ifdef APP-PLUS
plus.runtime.restart();
// #endif
// #ifdef MP-WEIXIN
uni.reLaunch({
url: '/pages/chat/chat-box?chatIdx=0'
});
// #endif
}, 800);
}); });
} }
} }

7
im-web/src/components/account/AccountSwitchMenu.vue

@ -31,7 +31,7 @@
<div class="divider"></div> <div class="divider"></div>
<div class="other-label"> <div class="other-label">
可切换账号 可切换账号
<span class="account-count">{{ allAccounts.length }}</span> <!-- <span class="account-count">{{ allAccounts.length }}</span> -->
</div> </div>
<div <div
class="account-item" class="account-item"
@ -53,7 +53,6 @@
<div class="account-info"> <div class="account-info">
<div class="nick-name"> <div class="nick-name">
{{ account.nickName }} {{ account.nickName }}
<el-tag type="success" size="mini" class="role-tag">客服</el-tag>
</div> </div>
<div class="account-name">@{{ account.userName }}</div> <div class="account-name">@{{ account.userName }}</div>
<div class="account-id">ID: {{ account.id }}</div> <div class="account-id">ID: {{ account.id }}</div>
@ -509,8 +508,8 @@ export default {
this.$emit('update'); this.$emit('update');
} catch (error) { } catch (error) {
console.error('添加失败:', error); // console.error(':', error);
this.$message.error(error?.response?.data?.message || '添加失败'); // this.$message.error(error?.response?.data?.message || '');
} finally { } finally {
this.adding = false; this.adding = false;
} }

14
im-web/src/components/chat/ChatBox.vue

@ -1474,6 +1474,19 @@ export default {
}, },
immediate: true, immediate: true,
}, },
userInfo: {
handler(newVal) {
if (newVal && newVal.language) {
//
const userLang = newVal.language.toLowerCase();
//
const matchLang = this.countryCodeList.find(item => item.value === userLang);
//
this.countryCode = matchLang ? matchLang.value : "en";
}
},
immediate: true, //
},
messageSize: { messageSize: {
handler(newSize, oldSize) { handler(newSize, oldSize) {
if (newSize > oldSize) { if (newSize > oldSize) {
@ -1607,6 +1620,7 @@ export default {
} }
.side-box { .side-box {
border-left: var(--im-border); border-left: var(--im-border);
overflow: hidden !important;
} }
.user-info-side { .user-info-side {
.user-info-container { .user-info-container {

6
im-web/src/components/chat/ChatMessageItem.vue

@ -55,8 +55,10 @@
<span>{{ msgInfo.content }}</span> <span>{{ msgInfo.content }}</span>
</div> </div>
<div class="message-status" v-if="!isAction && msgInfo.selfSend && !isGroupMessage"> <div class="message-status" v-if="!isAction && msgInfo.selfSend && !isGroupMessage">
<span class="chat-readed" v-if="msgInfo.status == $enums.MESSAGE_STATUS.READED">Read</span> <!-- <span class="chat-readed" v-if="msgInfo.status == $enums.MESSAGE_STATUS.READED">Read</span>
<span class="chat-unread" v-else>Unread</span> <span class="chat-unread" v-else>Unread</span> -->
<span class="chat-readed" v-if="msgInfo.status == $enums.MESSAGE_STATUS.READED">已读</span>
<span class="chat-unread" v-else>未读</span>
</div> </div>
<div class="chat-receipt" v-show="msgInfo.receipt" @click="onShowReadedBox"> <div class="chat-receipt" v-show="msgInfo.receipt" @click="onShowReadedBox">
<span v-if="msgInfo.receiptOk" class="icon iconfont icon-ok" title="全体已读"></span> <span v-if="msgInfo.receiptOk" class="icon iconfont icon-ok" title="全体已读"></span>

35
im-web/src/store/chatStore.js

@ -34,6 +34,41 @@ export default defineStore('chatStore', {
} }
}, },
actions: { actions: {
cleanOfflineChats() {
const friendStore = useFriendStore();
const onlineFriendIds = friendStore.onlineFriendIds || [];
// 获取当前会话列表
let chats = this.findChats();
let removedCount = 0;
// 从后往前遍历,避免删除时索引错乱
for (let idx = chats.length - 1; idx >= 0; idx--) {
const chat = chats[idx];
// 只处理私聊会话
if (chat.type === 'PRIVATE') {
const isOnline = onlineFriendIds.includes(chat.targetId);
if (!isOnline) {
// 标记为删除
chat.delete = true;
chat.stored = false;
removedCount++;
}
}
}
// 清理已删除的会话
this.chats = this.chats.filter(chat => !chat.delete);
// 保存到存储
this.saveToStorage(true);
console.log(`清理完成: 删除了 ${removedCount} 个离线会话,剩余 ${this.chats.length} 个会话`);
return removedCount;
},
initChats(chatsData) { initChats(chatsData) {
this.chats = []; this.chats = [];
this.privateMsgMaxId = chatsData.privateMsgMaxId || 0; this.privateMsgMaxId = chatsData.privateMsgMaxId || 0;

41
im-web/src/store/friendStore.js

@ -50,19 +50,27 @@ export default defineStore('friendStore', {
refreshOnlineStatus() { refreshOnlineStatus() {
let userIds = this.friends.filter((f) => !f.deleted).map((f) => f.id); let userIds = this.friends.filter((f) => !f.deleted).map((f) => f.id);
if (userIds.length == 0) { if (userIds.length == 0) {
return; // 清除定时器
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.refreshOnlineStatus();
}, 30000);
return Promise.resolve(); // 返回 resolved Promise
} }
http({
// 返回 Promise,确保可以等待
return http({
url: '/user/terminal/online?userIds=' + userIds.join(','), url: '/user/terminal/online?userIds=' + userIds.join(','),
method: 'GET' method: 'GET'
}).then((onlineTerminals) => { }).then((onlineTerminals) => {
this.setOnlineStatus(onlineTerminals); this.setOnlineStatus(onlineTerminals);
}) }).finally(() => {
// 30s后重新拉取 // 30s后重新拉取
clearTimeout(this.timer); clearTimeout(this.timer);
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
this.refreshOnlineStatus(); this.refreshOnlineStatus();
}, 30000) }, 30000);
});
}, },
setDnd(id, isDnd) { setDnd(id, isDnd) {
let friend = this.findFriend(id); let friend = this.findFriend(id);
@ -80,20 +88,41 @@ export default defineStore('friendStore', {
method: 'GET' method: 'GET'
}).then(async (friends) => { }).then(async (friends) => {
this.setFriends(friends); this.setFriends(friends);
this.refreshOnlineStatus(); // 等待在线状态刷新完成
await this.refreshOnlineStatus();
resolve(); resolve();
}).catch(e => { }).catch(e => {
reject(e); reject(e);
}) })
}); });
} },
}, },
getters: { getters: {
// 原有的 getters
isFriend: (state) => (userId) => { isFriend: (state) => (userId) => {
return state.friends.filter((f) => !f.deleted).some((f) => f.id == userId); return state.friends.filter((f) => !f.deleted).some((f) => f.id == userId);
}, },
findFriend: (state) => (userId) => { findFriend: (state) => (userId) => {
return state.friends.find((f) => f.id == userId); return state.friends.find((f) => f.id == userId);
},
// 获取在线好友列表
onlineFriends: (state) => {
return state.friends.filter(f => !f.deleted && f.online);
},
// 获取在线好友ID列表
onlineFriendIds: (state) => {
return state.friends
.filter(f => !f.deleted && f.online)
.map(f => f.id);
},
// 获取离线好友ID列表
offlineFriendIds: (state) => {
return state.friends
.filter(f => !f.deleted && !f.online)
.map(f => f.id);
} }
} }
}); });

8
im-web/src/view/Home.vue

@ -506,7 +506,11 @@ export default {
}, },
onSwtichFullScreen() { onSwtichFullScreen() {
this.configStore.setFullScreen(!this.configStore.fullScreen); // this.configStore.setFullScreen(!this.configStore.fullScreen);
const newState = !this.configStore.fullScreen;
this.configStore.setFullScreen(newState);
//
localStorage.setItem('im_full_screen', newState);
}, },
onExit() { onExit() {
@ -583,6 +587,8 @@ export default {
} }
}, },
mounted() { mounted() {
const savedFullScreen = localStorage.getItem('im_full_screen') === 'true';
this.configStore.setFullScreen(savedFullScreen);
this.init(); this.init();
}, },
unmounted() { unmounted() {

61
im-web/src/view/Login.vue

@ -38,6 +38,9 @@
<script> <script>
import Icp from '../components/common/Icp.vue' import Icp from '../components/common/Icp.vue'
import useFriendStore from '../store/friendStore'
import useChatStore from '../store/chatStore'
export default { export default {
name: "login", name: "login",
components: { components: {
@ -55,7 +58,6 @@ export default {
callback(new Error('请输入密码')); callback(new Error('请输入密码'));
} }
callback(); callback();
}; };
return { return {
loginForm: { loginForm: {
@ -76,28 +78,65 @@ export default {
}; };
}, },
methods: { methods: {
submitForm(formName) { async submitForm(formName) {
this.$refs[formName].validate((valid) => { const valid = await this.$refs[formName].validate().catch(() => false);
if (valid) { if (!valid) return;
this.$http({
try {
const data = await this.$http({
url: "/loginCustom", url: "/loginCustom",
method: 'post', method: 'post',
data: this.loginForm data: this.loginForm
}) });
.then((data) => {
// cookie() // cookie
this.setCookie('username', this.loginForm.userName); this.setCookie('username', this.loginForm.userName);
this.setCookie('password', this.loginForm.password); this.setCookie('password', this.loginForm.password);
// token // token
sessionStorage.setItem("accessToken", data.accessToken); sessionStorage.setItem("accessToken", data.accessToken);
sessionStorage.setItem("refreshToken", data.refreshToken); sessionStorage.setItem("refreshToken", data.refreshToken);
this.$message.success("登录成功"); this.$message.success("登录成功");
//
this.$router.push("/home/chat"); this.$router.push("/home/chat");
})
} //
this.$nextTick(() => {
this.initAfterLogin();
}); });
} catch (error) {
console.error('登录失败:', error);
this.$message.error('登录失败');
}
}, },
async initAfterLogin() {
const friendStore = useFriendStore();
const chatStore = useChatStore();
try {
await friendStore.loadFriend();
await chatStore.loadChat();
chatStore.refreshChats();
chatStore.setLoading(false);
const removedCount = chatStore.cleanOfflineChats();
console.log(`=== 初始化完成: 清理了 ${removedCount} 个离线会话 ===`);
} catch (error) {
console.error('初始化失败:', error);
}
},
resetForm(formName) { resetForm(formName) {
this.$refs[formName].resetFields(); this.$refs[formName].resetFields();
}, },
@ -112,11 +151,9 @@ export default {
setCookie(name, value) { setCookie(name, value) {
document.cookie = name + "=" + escape(value); document.cookie = name + "=" + escape(value);
} }
}, },
mounted() { mounted() {
this.loginForm.userName = this.getCookie("username"); this.loginForm.userName = this.getCookie("username");
// cookie便
this.loginForm.password = this.getCookie("password"); this.loginForm.password = this.getCookie("password");
} }
} }

Loading…
Cancel
Save