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)){
// return false;
// }
String token = user.getUniqueToken();
if(token == null || ObjectUtil.isEmpty(token)){
return false;

1
im-uniapp/App.vue

@ -42,7 +42,6 @@ export default {
this.configStore.setAppInit(true);
}
});
// console.log(cmd, msgInfo);
wsApi.onMessage((cmd, msgInfo) => {
console.log(cmd, msgInfo);
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">
<custom-loading :size="40" icon-color="#656adf" :mask="false"></custom-loading>
</view>
<view v-else-if="sendFail" @click="onSendFail"
class="send-fail iconfont icon-warning-circle-fill"></view>
<!-- <view v-else-if="sendFail" @click="onSendFail" class="send-fail iconfont icon-warning-circle-fill"></view> -->
</view>
<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>

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

@ -664,9 +664,26 @@ export default {
this.$forceUpdate();
uni.showToast({
title: this.$t('chat.sendFailed'),
title: "客服已更换,刷新中...",
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="other-label">
可切换账号
<span class="account-count">{{ allAccounts.length }}</span>
<!-- <span class="account-count">{{ allAccounts.length }}</span> -->
</div>
<div
class="account-item"
@ -53,7 +53,6 @@
<div class="account-info">
<div class="nick-name">
{{ account.nickName }}
<el-tag type="success" size="mini" class="role-tag">客服</el-tag>
</div>
<div class="account-name">@{{ account.userName }}</div>
<div class="account-id">ID: {{ account.id }}</div>
@ -509,8 +508,8 @@ export default {
this.$emit('update');
} catch (error) {
console.error('添加失败:', error);
this.$message.error(error?.response?.data?.message || '添加失败');
// console.error(':', error);
// this.$message.error(error?.response?.data?.message || '');
} finally {
this.adding = false;
}

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

@ -1474,6 +1474,19 @@ export default {
},
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: {
handler(newSize, oldSize) {
if (newSize > oldSize) {
@ -1607,6 +1620,7 @@ export default {
}
.side-box {
border-left: var(--im-border);
overflow: hidden !important;
}
.user-info-side {
.user-info-container {

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

@ -55,8 +55,10 @@
<span>{{ msgInfo.content }}</span>
</div>
<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-unread" v-else>Unread</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-readed" v-if="msgInfo.status == $enums.MESSAGE_STATUS.READED">已读</span>
<span class="chat-unread" v-else>未读</span>
</div>
<div class="chat-receipt" v-show="msgInfo.receipt" @click="onShowReadedBox">
<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: {
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) {
this.chats = [];
this.privateMsgMaxId = chatsData.privateMsgMaxId || 0;

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

@ -50,19 +50,27 @@ export default defineStore('friendStore', {
refreshOnlineStatus() {
let userIds = this.friends.filter((f) => !f.deleted).map((f) => f.id);
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(','),
method: 'GET'
}).then((onlineTerminals) => {
this.setOnlineStatus(onlineTerminals);
})
}).finally(() => {
// 30s后重新拉取
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.refreshOnlineStatus();
}, 30000)
}, 30000);
});
},
setDnd(id, isDnd) {
let friend = this.findFriend(id);
@ -80,20 +88,41 @@ export default defineStore('friendStore', {
method: 'GET'
}).then(async (friends) => {
this.setFriends(friends);
this.refreshOnlineStatus();
// 等待在线状态刷新完成
await this.refreshOnlineStatus();
resolve();
}).catch(e => {
reject(e);
})
});
}
},
},
getters: {
// 原有的 getters
isFriend: (state) => (userId) => {
return state.friends.filter((f) => !f.deleted).some((f) => f.id == userId);
},
findFriend: (state) => (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() {
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() {
@ -583,6 +587,8 @@ export default {
}
},
mounted() {
const savedFullScreen = localStorage.getItem('im_full_screen') === 'true';
this.configStore.setFullScreen(savedFullScreen);
this.init();
},
unmounted() {

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

@ -38,6 +38,9 @@
<script>
import Icp from '../components/common/Icp.vue'
import useFriendStore from '../store/friendStore'
import useChatStore from '../store/chatStore'
export default {
name: "login",
components: {
@ -55,7 +58,6 @@ export default {
callback(new Error('请输入密码'));
}
callback();
};
return {
loginForm: {
@ -76,28 +78,65 @@ export default {
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$http({
async submitForm(formName) {
const valid = await this.$refs[formName].validate().catch(() => false);
if (!valid) return;
try {
const data = await this.$http({
url: "/loginCustom",
method: 'post',
data: this.loginForm
})
.then((data) => {
// cookie()
});
// cookie
this.setCookie('username', this.loginForm.userName);
this.setCookie('password', this.loginForm.password);
// token
sessionStorage.setItem("accessToken", data.accessToken);
sessionStorage.setItem("refreshToken", data.refreshToken);
this.$message.success("登录成功");
//
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) {
this.$refs[formName].resetFields();
},
@ -112,11 +151,9 @@ export default {
setCookie(name, value) {
document.cookie = name + "=" + escape(value);
}
},
mounted() {
this.loginForm.userName = this.getCookie("username");
// cookie便
this.loginForm.password = this.getCookie("password");
}
}

Loading…
Cancel
Save