Browse Source

将用户语言信息保存到数据库

master
[yxf] 4 weeks ago
parent
commit
4c4a84c40f
  1. 46
      im-platform/src/main/java/com/bx/implatform/controller/UserController.java
  2. 6
      im-platform/src/main/java/com/bx/implatform/entity/User.java
  3. 4
      im-platform/src/main/java/com/bx/implatform/vo/UserVO.java
  4. 56
      im-uniapp/pages/chat/chat-box.vue
  5. 4
      im-uniapp/store/chatStore.js
  6. 21
      im-web/src/components/chat/ChatBox.vue

46
im-platform/src/main/java/com/bx/implatform/controller/UserController.java

@ -68,7 +68,7 @@ public class UserController {
@Operation(summary = "保存用户分组", description = "单个分组,保存到 group_ids 字段")
public Result<?> saveGroup(@RequestBody JSONObject jsonObject) {
Long userId = jsonObject.getLong("userId");
String groupId = jsonObject.getStr("groupIds"); // 前端传分组ID
String groupId = jsonObject.getStr("groupIds");
userService.saveUserGroup(userId, groupId);
return ResultUtils.success();
@ -104,6 +104,27 @@ public class UserController {
return ResultUtils.success();
}
@PostMapping("/updateLanguage")
@Operation(summary = "更新用户语言", description = "更新当前用户的语言设置:zh/en/jp/kor等")
public Result<?> updateLanguage(@RequestBody JSONObject jsonObject) {
String language = jsonObject.getStr("language");
if (StrUtil.isBlank(language)) {
return ResultUtils.error(ResultCode.XSS_PARAM_ERROR, "语言不能为空");
}
UserSession session = SessionContext.getSession();
Long userId = session.getUserId();
User user = userService.getById(userId);
if (user == null) {
return ResultUtils.error(ResultCode.XSS_PARAM_ERROR, "用户不存在");
}
user.setLanguage(language);
boolean success = userService.updateById(user);
return success ? ResultUtils.success("语言更新成功") : ResultUtils.error(ResultCode.XSS_PARAM_ERROR, "更新失败");
}
@GetMapping("/findByName")
@Operation(summary = "查找用户", description = "根据用户名或昵称查找用户")
public Result<List<UserVO>> findByName(@RequestParam String name) {
@ -113,18 +134,15 @@ public class UserController {
@PostMapping("/getEnableChangeCustomer")
@Operation(summary = "获取可转接的客服", description = "转接客服")
public Result<List<Map<String, Object>>> getEnableChangeCustomer() {
// 获取当前客服id、转接客服id、转接用户id
UserSession session = SessionContext.getSession();
Long userId = session.getUserId();
if(ObjectUtil.isNull(userId)){
return ResultUtils.error(XSS_PARAM_ERROR);
}
List<User> list = userService.getEnableChangeCustomerList(userId);
//使用Map返回id、昵称
List<Map<String, Object>> result = list.stream().map(user -> {
Map<String, Object> map = new HashMap<>();
map.put("id", user.getId());
@ -152,7 +170,6 @@ public class UserController {
return ResultUtils.error(XSS_PARAM_ERROR);
}
// 获取当前用户信息
User currentUser = userService.getById(userId);
if (currentUser == null) {
return ResultUtils.error(XSS_PARAM_ERROR);
@ -160,7 +177,6 @@ public class UserController {
Map<String, Object> result = new HashMap<>();
// 获取可切换的账号ID列表(逗号分隔的字符串,如 "13,14")
String switchableIdsStr = currentUser.getSwitchableAccountIds();
List<Map<String, Object>> switchableUsers = new ArrayList<>();
@ -173,7 +189,6 @@ public class UserController {
if (!ids.isEmpty()) {
List<User> users = userService.listByIds(ids);
// 过滤掉被封禁的账号
users = users.stream()
.filter(u -> !Boolean.TRUE.equals(u.getIsBanned()))
.collect(Collectors.toList());
@ -192,27 +207,21 @@ public class UserController {
result.put("switchableUsers", switchableUsers);
// 获取当前用户的 unique_token
String currentUserUniqueToken = currentUser.getUniqueToken();
// 构建查询条件
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
.eq(User::getIsCustomer, 2)
.ne(User::getId, userId)
.eq(User::getIsBanned, 0);
// 添加 unique_token 条件
if (StrUtil.isNotBlank(currentUserUniqueToken)) {
// 当前用户有 unique_token,只查询相同 unique_token 的客服
queryWrapper.eq(User::getUniqueToken, currentUserUniqueToken);
} else {
// 当前用户没有 unique_token,只查询也没有 unique_token 的客服
queryWrapper.isNull(User::getUniqueToken).or().eq(User::getUniqueToken, "");
}
List<User> availableUsers = userService.list(queryWrapper);
// 获取已添加的ID集合
Set<Long> existingIds = new HashSet<>();
if (StrUtil.isNotBlank(switchableIdsStr)) {
Arrays.stream(switchableIdsStr.split(","))
@ -221,14 +230,12 @@ public class UserController {
.forEach(existingIds::add);
}
// 标记是否已添加
List<Map<String, Object>> availableUsersList = availableUsers.stream().map(user -> {
Map<String, Object> map = new HashMap<>();
map.put("id", user.getId());
map.put("userName", user.getUserName());
map.put("nickName", user.getNickName());
map.put("headImage", user.getHeadImage());
// map.put("headImageThumb", user.getHeadImageThumb());
map.put("isAdded", existingIds.contains(user.getId()));
return map;
}).collect(Collectors.toList());
@ -244,7 +251,6 @@ public class UserController {
UserSession session = SessionContext.getSession();
// 获取当前客服id、转接客服id、转接用户id
Long customerId = session.getUserId();
Long targetId = jsonObject.getLong("targetId");
Long userId = jsonObject.getLong("userId");
@ -267,22 +273,18 @@ public class UserController {
Long targetUserId = jsonObject.getLong("targetUserId");
Integer terminal = jsonObject.getInt("terminal");
// 获取当前登录用户
UserSession currentSession = SessionContext.getSession();
User currentUser = userService.getById(currentSession.getUserId());
// 权限校验:只有客服才能切换账号
if (currentUser.getIsCustomer() != 2) {
return ResultUtils.error(XSS_PARAM_ERROR, "无权限切换账号");
}
// 获取目标用户信息
User targetUser = userService.getById(targetUserId);
if (ObjectUtil.isNull(targetUser)) {
return ResultUtils.error(ResultCode.XSS_PARAM_ERROR, "目标用户不存在");
}
// 生成新的token
UserSession newSession = BeanUtils.copyProperties(targetUser, UserSession.class);
newSession.setUserId(targetUser.getId());
newSession.setTerminal(terminal);
@ -299,8 +301,6 @@ public class UserController {
vo.setRefreshTokenExpiresIn(jwtProperties.getRefreshTokenExpireIn());
vo.setUser(targetUser);
// log.info("账号切换:从用户 {} 切换到用户 {}", currentSession.getUserId(), targetUserId);
return ResultUtils.success(vo);
}
@ -319,7 +319,6 @@ public class UserController {
return ResultUtils.error(XSS_PARAM_ERROR);
}
// 取出可切换账号并移除目标ID
String switchableIdsStr = currentUser.getSwitchableAccountIds();
if (StrUtil.isBlank(switchableIdsStr)) {
return ResultUtils.success("移除成功");
@ -333,7 +332,6 @@ public class UserController {
String newIds = idList.stream().map(String::valueOf).collect(Collectors.joining(","));
// 更新到数据库
currentUser.setSwitchableAccountIds(newIds);
userService.updateById(currentUser);

6
im-platform/src/main/java/com/bx/implatform/entity/User.java

@ -134,6 +134,8 @@ public class User {
*/
private String switchableAccountIds;
/**
* 语言
*/
private String language;
}

4
im-platform/src/main/java/com/bx/implatform/vo/UserVO.java

@ -78,6 +78,8 @@ public class UserVO {
// 修改为完整的UserGroup列表
private List<UserLabelVO> labelList; // 完整的分组信息列表
private String platformName; // 新增:平台名称
private String platformName;
private String language;
}

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

@ -268,8 +268,8 @@ export default {
isFileOpen: false,
isPasting: false,
hasPasteListener: false,
currentLang: 'zh',
showLangModal: false, //
currentLang: uni.getStorageSync("app_language") || "zh",
langList: [
{ label: "中文", value: "zh" },
{ label: "English", value: "en" },
@ -285,17 +285,25 @@ export default {
};
},
methods: {
//
selectLang(lang) {
this.currentLang = lang;
this.$i18n.locale = lang;
uni.setStorageSync("app_language", lang);
this.showLangDrop = false;
//
this.$http({
url: "/user/updateLanguage",
method: "POST",
data: { language: lang }
}).then(() => {
console.log("语言保存成功");
}).finally(() => {
this.$i18n.locale = lang;
uni.setStorageSync("app_language", lang);
setTimeout(() => {
window.location.reload(); // H5
window.location.reload();
}, 100);
});
},
loadCommonQuestions(userId) {
this.$http({
@ -1257,13 +1265,18 @@ export default {
this.chatStore.updateChatFromUser(this.userInfo);
}
},
loadFriend(friendId) {
async loadFriend(friendId) {
return new Promise((resolve) => {
this.$http({
url: `/user/find/${friendId}`,
method: "GET",
}).then((userInfo) => {
this.userInfo = userInfo;
this.updateFriendInfo();
resolve(); // then
}).catch(() => {
resolve();
});
});
},
rpxTopx(rpx) {
@ -1648,7 +1661,9 @@ export default {
}
this.readedMessage();
this.loadFriend(targetId);
// this.loadFriend(targetId);
await this.loadFriend(targetId);
this.loadReaded(targetId);
this.loadCommonQuestions(targetId);
@ -1659,23 +1674,7 @@ export default {
await this.getSetting();
this.$nextTick(() => this.scrollToBottom());
this.$socket.on('customer_transfer', (data) => {
/**
* data后端返回格式
* { oldKfId: 旧客服ID, newKfId: 新客服ID }
*/
const { oldKfId, newKfId } = data;
if (!oldKfId || !newKfId) return;
// chatStore
this.chatStore.mergeOldCustomerToNew(oldKfId, newKfId);
console.log(data);
//
this.currentTargetId = newKfId;
this.$nextTick(() => {
this.scrollToBottom();
});
})
} catch (err) {
console.error("错误:", err);
} finally {
@ -1696,11 +1695,10 @@ export default {
</script>
<style lang="scss">
/* ========== 右上角语言按钮 ========== */
.lang-wrap {
position: fixed;
top: var(--status-bar-height);
right: 40rpx; /* 按钮靠右距离,美观不贴边 */
right: 40rpx;
z-index: 9999 !important;
height: $im-nav-bar-height;
display: flex;
@ -1718,11 +1716,10 @@ export default {
cursor: pointer;
}
/* ========== 自定义下拉面板(向左展开!永远不裁切) ========== */
.lang-drop-panel {
position: absolute;
top: 100%;
right: 0; /* 面板右边缘和按钮右边缘对齐,**向左展开** */
right: 0;
min-width: 180rpx;
background: #fff;
border-radius: 12rpx;
@ -1732,7 +1729,6 @@ export default {
z-index: 10000;
}
/* 下拉每一个语言选项 */
.lang-drop-item {
padding: 24rpx 30rpx;
font-size: 28rpx;
@ -1751,7 +1747,6 @@ export default {
}
}
/* ========== 全局遮罩(点击空白关闭下拉) ========== */
.lang-mask {
position: fixed;
top: 0;
@ -1761,7 +1756,6 @@ export default {
z-index: 9998;
}
/* 原有标题样式不动 */
.nav-title-wrapper {
width: 100%;
text-align: center;

4
im-uniapp/store/chatStore.js

@ -209,8 +209,6 @@ export default defineStore('chatStore', {
this.saveToStorage();
return;
}
// ====================== 多语言消息类型 ======================
if (msgInfo.type == MESSAGE_TYPE.IMAGE) {
chat.lastContent = t('chat.image');
} else if (msgInfo.type == MESSAGE_TYPE.FILE) {
@ -226,7 +224,6 @@ export default defineStore('chatStore', {
msgInfo.type == MESSAGE_TYPE.TIP_TEXT) {
chat.lastContent = msgInfo.content;
}
// ============================================================
chat.lastSendTime = msgInfo.sendTime;
chat.sendNickName = msgInfo.sendNickName;
@ -323,6 +320,7 @@ export default defineStore('chatStore', {
chat.stored = false;
this.saveToStorage(isColdMessage);
},
updateChatFromFriend(friend) {
let chat = this.findChatByFriend(friend.id)
if (chat && (chat.headImage != friend.headImage ||

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

@ -165,6 +165,10 @@
<div class="info-label">来源地址</div>
<div class="info-value">{{ userInfo.platformName }}</div>
</div>
<div class="info-item">
<div class="info-label">用户语言</div>
<div class="info-value">{{ getLanguageText(userInfo.language) }}</div>
</div>
<div class="info-item">
<div class="info-label">标签</div>
<div class="info-value">
@ -340,6 +344,7 @@ export default {
maxTmpId: 0,
countryCode: "en",
countryCodeList: [
{ label: "中文", value: "zh" },
{ label: "英语", value: "en" },
{ label: "日语", value: "jp" },
{ label: "韩语", value: "kor" },
@ -353,6 +358,22 @@ export default {
};
},
methods: {
getLanguageText(lang) {
if (!lang) return '未知';
const langMap = {
'zh': '中文',
'en': '英语',
'jp': '日语',
'kor': '韩语',
'vie': '越南语',
'ru': '俄语',
'de': '德语',
'fra': '法语',
'pt': '葡萄牙语',
'ara': '阿拉伯语',
};
return langMap[lang.toLowerCase()] || lang;
},
moveChatToTop() {
let chatIdx = this.chatStore.findChatIdx(this.chat);
this.chatStore.moveTop(chatIdx);

Loading…
Cancel
Save