This commit is contained in:
Vinjor 2025-09-01 17:06:16 +08:00
parent e976da94b7
commit 0a793caf80
16 changed files with 129 additions and 97 deletions

View File

@ -52,14 +52,6 @@ public class ChatController {
public AjaxResult sendMessage(@RequestBody BusiChatItem message) {
return AjaxResult.success(busiChatItemService.sendMessage(message));
}
/**
* 根据租户ID查询会话列表
*/
@GetMapping("/tenant/{tenantId}")
public AjaxResult getByTenantId(@PathVariable String tenantId) {
List<BusiChatMain> sessions = busiChatMainService.selectByTenantId(tenantId);
return AjaxResult.success(sessions);
}
/**
* 查询用户活跃会话
@ -93,7 +85,7 @@ public class ChatController {
*/
@PutMapping("/read/{sessionId}")
public AjaxResult markAsRead(@PathVariable String sessionId, @RequestParam String receiverId) {
boolean success = busiChatItemService.markAsRead(sessionId, receiverId);
return success ? AjaxResult.success() : AjaxResult.error("标记已读失败");
busiChatItemService.markAsRead(sessionId, receiverId);
return AjaxResult.success();
}
}

View File

@ -15,6 +15,7 @@ import com.ruoyi.busi.utils.CommonUtils;
import com.ruoyi.busi.vo.BusiCategoryVO;
import com.ruoyi.busi.vo.SiteMapVO;
import com.ruoyi.busi.vo.WebDetailVO;
import com.ruoyi.common.config.GoogleConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
@ -37,7 +38,6 @@ import java.util.*;
import static com.ruoyi.constant.DictConstants.*;
import static com.ruoyi.constant.DictConstants.CATG_TYPE_WZ;
import static com.ruoyi.constant.StrConstants.UPLOAD_DIR;
/**
* Web 专用Controller
@ -71,6 +71,8 @@ public class WebController extends BaseController {
private ISysDictDataService dictDataService;
@Autowired
private IBaseAppService appService;
@Autowired
private GoogleConfig googleConfig;
/**
* 导航栏接口--所有分类
@ -459,7 +461,7 @@ public class WebController extends BaseController {
public void downloadApk(HttpServletResponse response) {
try {
// APK文件路径
File file = new File(UPLOAD_DIR);
File file = new File(googleConfig.getAppDownload());
// 检查文件是否存在
if (!file.exists()) {

View File

@ -118,7 +118,7 @@ public class BusiChatMainController extends BaseController
}
/**
* 根据客服ID查询会话列表---用到了
* 根据客服ID查询会话列表---只有服务端使用所以挪过来
*/
@GetMapping("/service")
public AjaxResult getByServiceId() {

View File

@ -48,14 +48,6 @@ public interface BusiChatMainMapper extends BaseMapper<BusiChatMain>
List<BusiChatMain> selectLineChart(@Param("tenantId")String tenantId,@Param("startDate")String startDate,@Param("endDate")String endDate);
/**
* 根据租户ID查询会话列表
* @param tenantId 租户ID
* @return 会话列表
*/
List<BusiChatMain> selectByTenantId(@Param("tenantId") String tenantId);
/**
* 根据客服ID查询会话列表
* @param serviceId 客服ID
@ -66,12 +58,10 @@ public interface BusiChatMainMapper extends BaseMapper<BusiChatMain>
/**
* 根据用户标识查询活跃会话
* @param tenantId 租户ID
* @param userIp 用户IP
* @param deviceCode 设备编码
* @return 会话信息
*/
BusiChatMain selectActiveSession(@Param("tenantId") String tenantId,
@Param("userIp") String userIp,
@Param("deviceCode") String deviceCode,
@Param("prodId") String prodId);
}

View File

@ -36,13 +36,6 @@ public interface IBusiChatMainService extends IService<BusiChatMain> {
*/
BusiChatMain createSession(BusiChatMain session);
/**
* 根据租户ID查询会话列表
* @param tenantId 租户ID
* @return 会话列表
*/
List<BusiChatMain> selectByTenantId(String tenantId);
/**
* 根据客服ID查询会话列表
* @param serviceId 客服ID

View File

@ -1,5 +1,6 @@
package com.ruoyi.busi.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ -97,11 +98,6 @@ public class BusiChatMainServiceImpl extends ServiceImpl<BusiChatMainMapper,Busi
return session;
}
@Override
public List<BusiChatMain> selectByTenantId(String tenantId) {
return busiChatMainMapper.selectByTenantId(tenantId);
}
@Override
public List<BusiChatMain> selectByServiceId(Long serviceId) {
// 先查缓存
@ -111,9 +107,13 @@ public class BusiChatMainServiceImpl extends ServiceImpl<BusiChatMainMapper,Busi
if (sessions == null || sessions.isEmpty()) {
// 缓存未命中查数据库
sessions = busiChatMainMapper.selectByServiceId(serviceId);
if(null!= sessions && sessions.size()>0){
// 存入缓存设置较短过期时间避免缓存与数据库不一致
redisCache.setCacheList(cacheKey, sessions);
redisCache.expire(cacheKey, 5, TimeUnit.MINUTES);
}else{
sessions = new ArrayList<>();
}
}
for (BusiChatMain session : sessions) {
session.setUnreadCount(busiChatItemService.selectUnreadCount(session.getId(),DATA_FROM_CUSTOMER));
@ -124,7 +124,7 @@ public class BusiChatMainServiceImpl extends ServiceImpl<BusiChatMainMapper,Busi
@Override
public BusiChatMain selectActiveSession(String tenantId, String userIp, String deviceCode,String prodId) {
// 先查缓存
String cacheKey = "im:active_session:" + tenantId + ":" + userIp + ":" + deviceCode;
String cacheKey = "im:active_session:" + tenantId + ":" + deviceCode;
if(null!=prodId){
cacheKey+=":"+prodId;
}
@ -132,7 +132,7 @@ public class BusiChatMainServiceImpl extends ServiceImpl<BusiChatMainMapper,Busi
if (session == null) {
// 缓存未命中查数据库
session = busiChatMainMapper.selectActiveSession(tenantId, userIp, deviceCode,prodId);
session = busiChatMainMapper.selectActiveSession(tenantId, deviceCode,prodId);
if (session != null) {
// 存入缓存
redisCache.setCacheObject(cacheKey, session, SESSION_CACHE_EXPIRE, TimeUnit.SECONDS);
@ -161,7 +161,10 @@ public class BusiChatMainServiceImpl extends ServiceImpl<BusiChatMainMapper,Busi
String serviceCacheKey = "im:service_sessions:" + session.getUserId();
redisCache.deleteObject(serviceCacheKey);
String activeCacheKey = "im:active_session:" + session.getTenantId() + ":" + session.getId() + ":" + session.getEquipment();
String activeCacheKey = "im:active_session:" + session.getTenantId() + ":" + session.getCusCode();
if(StringUtils.isNotEmpty(session.getProdId())){
activeCacheKey+=":"+session.getProdId();
}
redisCache.deleteObject(activeCacheKey);
}
return rows > 0;

View File

@ -36,8 +36,4 @@ public class StrConstants {
* 国家
*/
public static final String COUNTRY = "country";
/**
* app下载目录
*/
public static final String UPLOAD_DIR = "/app/apk/truck.apk";
}

View File

@ -5,15 +5,15 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源-点亮开发库
master:
url: jdbc:mysql://82.156.161.160:3306/dl_site_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: site
password: 123456
#主库数据源-客户测试服务器
# master:
# url: jdbc:mysql://114.132.197.85:3306/dl_site_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# url: jdbc:mysql://82.156.161.160:3306/dl_site_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: site
# password: 123456
#主库数据源-客户测试服务器
master:
url: jdbc:mysql://127.0.0.1:3306/dl_site_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: site
password: 123456
# 从库数据源
slave:
# 从数据源开关/默认关闭

View File

@ -161,4 +161,6 @@ google:
json-path: /www/wwwroot/nuxt/chengda.json
#月搜索量下限
search-down: 500
#App下载路径
app-download: /www/wwwroot/nuxt/truck.apk

View File

@ -18,7 +18,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectBusiChatItemVo">
select id, main_id, data_from, sender_id,receiver_id,content,is_read, create_time from dl_busi_chat_item
</sql>
<select id="queryListPage" parameterType="BusiChatItem" resultMap="BusiChatItemResult">
<include refid="selectBusiChatItemVo"/>
<where>
@ -55,4 +54,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY
create_time
</select>
<update id="updateReadStatus">
update dl_busi_chat_item
set is_read = 1
where main_id = #{sessionId}
and receiver_id = #{receiverId}
</update>
</mapper>

View File

@ -148,8 +148,7 @@
FROM
dl_busi_chat_main
WHERE
ip = #{userIp}
AND cus_code = #{deviceCode}
cus_code = #{deviceCode}
AND `status` = 1
AND del_flag = '0'
AND tenant_id = #{tenantId}

View File

@ -16,6 +16,8 @@ public class GoogleConfig {
private String developerToken;
private String jsonPath;
private Long searchDown;
/** app下载路径 */
private String appDownload;
}

View File

@ -74,3 +74,17 @@ export function sendMessage(data) {
data: data
})
}
export function markAsRead(id, query) {
return request({
url: '/chat/read/'+id,
method: 'put',
params: query
})
}
export function closeSession(id) {
return request({
url: '/chat/close/'+id,
method: 'put',
})
}

View File

@ -33,9 +33,9 @@
</span>
</el-dialog>
<!--消息列表组件-->
<messageList ref="messageList" @switchSession="switchSession" @addNewMag="addNewMag"/>
<messageList ref="messageList" @switchSession="switchSession" @addNewMag="addNewMag" @closeForm="closeFormMes"/>
<!-- 聊天记录弹出框-->
<chat-form ref="chatFrom"></chat-form>
<chat-form ref="chatFrom" @updateSessionRead="updateSessionRead" @closeForm="closeForm" @closeCurrentSession="closeCurrentSession"></chat-form>
</div>
</template>
@ -105,6 +105,22 @@ export default {
this.getSiteList()
},
methods: {
//
closeCurrentSession(){
this.$refs.messageList.closeCurrentSession()
},
//
closeForm(){
this.$refs.messageList.closeForm()
},
//
closeFormMes(){
this.$refs.chatFrom.open=false
},
//
updateSessionRead(sessionId){
this.$refs.messageList.updateSessionRead(sessionId)
},
//
switchSession(session){
this.$refs.chatFrom.show(session)

View File

@ -32,12 +32,13 @@
@keyup.enter.native="sendToServer"
></el-input>
<el-button type="primary" icon="el-icon-s-promotion" @click="sendToServer"></el-button>
<el-button type="warning" @click="closeCurrentSession">结束会话</el-button>
</div>
</el-dialog>
</template>
<script>
import { getBySessionId ,sendMessage} from "@/api/busi/chatMain";
import { getBySessionId ,sendMessage,markAsRead} from "@/api/busi/chatMain";
import Cookies from "js-cookie";
export default {
name: 'chatForm',
@ -52,8 +53,6 @@ export default {
messages: [],
//
text:'',
//id
chatId:'',
session: null,
}
},
@ -66,13 +65,8 @@ export default {
this.title = "来自"+session.oceania+"-"+session.national+"的客户"
console.log(session)
this.loadMessages(session.id)
this.markAsRead(session.id)
this.open = true
// console.log(row)
// this.chatId = row.id
// if (row.itemJson!=null) {
// this.messages = JSON.parse(row.itemJson)
// this.$store.dispatch('set_message',this.messages);
// }
},
//
loadMessages(sessionId) {
@ -82,6 +76,13 @@ export default {
this.scrollBottom()
})
},
//
markAsRead(sessionId) {
markAsRead(sessionId, {receiverId:this.session.userId}).then(() => {
// ,
this.$emit("updateSessionRead",sessionId)
})
},
scrollBottom(){
//
this.$nextTick(() => {
@ -91,13 +92,6 @@ export default {
}
});
},
// openForm(){
// if (!this.open) {
// this.open = true
// this.messages = this.$store._modules.root.state.websocket.message
// }
// },
/**发送消息*/
sendToServer() {
//
@ -116,13 +110,25 @@ export default {
type: 1,
toUserId: this.session.cusCode,
content: this.text,
sessionId: this.session.id
sessionId: this.session.id,
createTime:new Date()
}
this.$store.dispatch('websocket_send',JSON.stringify(wsMsg));
this.text=''
this.scrollBottom()
})
},
//
closeCurrentSession(){
this.$confirm('确定要结束当前会话吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//
this.$emit("closeCurrentSession")
})
},
//
addNewMsg(msg){
this.messages.push(msg)
@ -130,6 +136,8 @@ export default {
},
close(){
this.open = false;
//
this.$emit("closeForm")
}
}

View File

@ -62,15 +62,35 @@ export default {
(session.lastMessage && session.lastMessage.includes(val))
})
},
currentSessionId(val) {
if (val) {
this.loadMessages(val)
//
this.markAsRead(val)
}
}
},
methods: {
//
closeCurrentSession(){
closeSession(this.currentSessionId).then(() => {
this.$message.success('会话已结束')
//
const wsMsg = {
type: 3,
toUserId: this.currentSession.cusCode,
content: '客服已结束会话',
sessionId: this.currentSessionId
}
this.$store.dispatch('websocket_send',JSON.stringify(wsMsg));
//
this.currentSessionId = null
this.currentSession = {}
this.messages = []
//
this.loadSessions()
//
this.$emit("closeForm")
})
},
//
closeForm(){
this.currentSessionId=null
this.currentSession= {}
},
//
loadSessions() {
getByServiceId(this.serviceId).then(response => {
@ -84,22 +104,12 @@ export default {
this.currentSession = session
this.$emit("switchSession",session)
},
//
loadMessages(sessionId) {
// getBySessionId(sessionId).then(response => {
// this.messages = response.data
// this.scrollToBottom()
// })
},
//
markAsRead(sessionId) {
// markAsRead(sessionId, this.serviceId).then(() => {
// //
// const session = this.sessions.find(s => s.id === sessionId)
// if (session) {
// session.unreadCount = 0
// }
// })
//
updateSessionRead(sessionId){
const session = this.sessions.find(s => s.id === sessionId)
if (session) {
session.unreadCount = 0
}
},
//
formatTime(time) {
@ -134,7 +144,6 @@ export default {
}
//
this.$emit("addNewMag",newMsg)
// this.scrollToBottom()
} else {
//
const session = this.sessions.find(s => s.id === message.sessionId)