From 7bfb2df8de9d8744994bebf93b466aaff03f035b Mon Sep 17 00:00:00 2001 From: wxl <727869402@qq.com> Date: Sun, 12 Jan 2025 01:54:15 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=B7=E6=B1=82=E8=81=8A=E5=A4=A9=E6=80=BB?= =?UTF-8?q?=E6=95=B0=20=E8=AE=BE=E7=BD=AE=E5=B7=B2=E8=AF=BB=E6=94=B9?= =?UTF-8?q?=E4=B8=BAwebsocket=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/controller/ChatController.java | 29 +- .../business/chat/domain/AuthorParam.java | 12 + .../business/chat/mapper/xml/ChatMapper.xml | 88 ++-- .../operationLog/domain/OperationLogVo.java | 4 + .../handler/GetReadCoutMessageHandler.java | 26 ++ .../webSocket/handler/ReadMessageHandler.java | 27 ++ web/.env.development | 3 +- web/.env.production | 5 +- web/src/api/business/chat/chat.js | 21 + web/src/api/websocket.js | 14 + web/src/assets/logo.png | Bin 6853 -> 3809 bytes web/src/layout/components/Navbar.vue | 52 ++- web/src/layout/index.vue | 44 ++ web/src/utils/request.js | 12 +- .../operationLog/operationLogList.vue | 51 +-- web/src/views/common/Im.vue | 82 +++- .../views/dashboard/components/BarChart.vue | 102 +++++ .../views/dashboard/components/PieChart.vue | 79 ++++ .../dashboard/components/RaddarChart.vue | 116 +++++ .../dashboard/components/mixins/resize.js | 55 +++ web/src/views/dashboard/index.vue | 417 +++++++++++++++++- web/src/views/login/login.vue | 6 +- 22 files changed, 1107 insertions(+), 138 deletions(-) create mode 100644 src/main/java/com/dd/admin/business/chat/domain/AuthorParam.java create mode 100644 src/main/java/com/dd/admin/business/webSocket/handler/GetReadCoutMessageHandler.java create mode 100644 src/main/java/com/dd/admin/business/webSocket/handler/ReadMessageHandler.java create mode 100644 web/src/views/dashboard/components/BarChart.vue create mode 100644 web/src/views/dashboard/components/PieChart.vue create mode 100644 web/src/views/dashboard/components/RaddarChart.vue create mode 100644 web/src/views/dashboard/components/mixins/resize.js diff --git a/src/main/java/com/dd/admin/business/chat/controller/ChatController.java b/src/main/java/com/dd/admin/business/chat/controller/ChatController.java index 6c61768..5842149 100644 --- a/src/main/java/com/dd/admin/business/chat/controller/ChatController.java +++ b/src/main/java/com/dd/admin/business/chat/controller/ChatController.java @@ -3,8 +3,10 @@ package com.dd.admin.business.chat.controller; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.extra.pinyin.PinyinUtil; -import com.dd.admin.business.chat.domain.AuthorChat; -import com.dd.admin.business.chat.domain.MessageBean; +import com.dd.admin.business.api.domain.UnReadCountBean; +import com.dd.admin.business.chat.domain.*; +import com.dd.admin.common.aop.operationLog.aop.OperLog; +import com.dd.admin.common.aop.operationLog.aop.OperType; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import org.springframework.web.bind.annotation.*; import io.swagger.annotations.Api; @@ -16,8 +18,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.NotBlank; import com.dd.admin.business.chat.entity.Chat; -import com.dd.admin.business.chat.domain.ChatVo; -import com.dd.admin.business.chat.domain.ChatDto; import com.dd.admin.business.chat.service.ChatService; import java.util.*; @@ -52,6 +52,16 @@ public class ChatController { return calendar.getTimeInMillis(); } + + @ApiOperation(value = "查询客服未读消息数量") + @ApiOperationSupport(order = 1) + @GetMapping("/admin/chat/getUnReadCount") + @OperLog(operModule = "查询客服未读消息数量",operType = OperType.OTHER,operDesc = "查询客服未读消息数量") + public ResultBean getUnReadCount() { + Integer chatUnReadCount = chatService.selectUnReadCount("8"); + return ResultBean.success(chatUnReadCount); + }; + @ApiOperation(value = "作者列表") @ApiOperationSupport(order = 2) @GetMapping("/admin/chat/authorList") @@ -98,6 +108,17 @@ public class ChatController { } + + @ApiOperation(value = "读取聊天消息") + @ApiOperationSupport(order = 4) + @PostMapping("/admin/chat/readAuthorMessage") + @OperLog(operModule = "读取回复消息", operType = OperType.OTHER, operDesc = "读取聊天消息") + public ResultBean readReplyMessage(@RequestBody AuthorParam authorParam) { + chatService.readMessage(authorParam.getAuthorId(),"8"); + return ResultBean.success("noAlert"); + } + + @ApiOperation(value = "-分页列表") @ApiOperationSupport(order = 1) @GetMapping("/admin/chat/page") diff --git a/src/main/java/com/dd/admin/business/chat/domain/AuthorParam.java b/src/main/java/com/dd/admin/business/chat/domain/AuthorParam.java new file mode 100644 index 0000000..a9fb76d --- /dev/null +++ b/src/main/java/com/dd/admin/business/chat/domain/AuthorParam.java @@ -0,0 +1,12 @@ +package com.dd.admin.business.chat.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class AuthorParam { + private String authorId; +} diff --git a/src/main/java/com/dd/admin/business/chat/mapper/xml/ChatMapper.xml b/src/main/java/com/dd/admin/business/chat/mapper/xml/ChatMapper.xml index 9da0f69..77e3406 100644 --- a/src/main/java/com/dd/admin/business/chat/mapper/xml/ChatMapper.xml +++ b/src/main/java/com/dd/admin/business/chat/mapper/xml/ChatMapper.xml @@ -113,58 +113,52 @@ diff --git a/src/main/java/com/dd/admin/business/operationLog/domain/OperationLogVo.java b/src/main/java/com/dd/admin/business/operationLog/domain/OperationLogVo.java index d6d4546..f457847 100644 --- a/src/main/java/com/dd/admin/business/operationLog/domain/OperationLogVo.java +++ b/src/main/java/com/dd/admin/business/operationLog/domain/OperationLogVo.java @@ -27,6 +27,10 @@ public class OperationLogVo { @ApiModelProperty(value = "日志id") private String operId; + @ApiModelProperty(value = "操作ip") + @TableField("OPER_IP_ADDRESS") + private String operIpAddress; + @ApiModelProperty(value = "请求模块") private String operModule; diff --git a/src/main/java/com/dd/admin/business/webSocket/handler/GetReadCoutMessageHandler.java b/src/main/java/com/dd/admin/business/webSocket/handler/GetReadCoutMessageHandler.java new file mode 100644 index 0000000..c4f1010 --- /dev/null +++ b/src/main/java/com/dd/admin/business/webSocket/handler/GetReadCoutMessageHandler.java @@ -0,0 +1,26 @@ +package com.dd.admin.business.webSocket.handler; + +import com.dd.admin.business.chat.service.ChatService; +import com.dd.admin.business.webSocket.MsgHandlerInterface; +import com.dd.admin.business.webSocket.util.TioUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.tio.core.ChannelContext; + +import java.util.Map; + + +@Slf4j +@Service("8") +public class GetReadCoutMessageHandler implements MsgHandlerInterface { + @Autowired + ChatService chatService; + @Override + public Object handler(Map map, ChannelContext context) { + String authorId = String.valueOf(map.get("authorId")); + Integer unReadCount = chatService.selectUnReadCount(authorId); + TioUtil.sendChatMessageToUser(context.getGroupContext(),authorId,"8",unReadCount); + return null; + } +} diff --git a/src/main/java/com/dd/admin/business/webSocket/handler/ReadMessageHandler.java b/src/main/java/com/dd/admin/business/webSocket/handler/ReadMessageHandler.java new file mode 100644 index 0000000..916cf68 --- /dev/null +++ b/src/main/java/com/dd/admin/business/webSocket/handler/ReadMessageHandler.java @@ -0,0 +1,27 @@ +package com.dd.admin.business.webSocket.handler; + +import com.dd.admin.business.chat.service.ChatService; +import com.dd.admin.business.webSocket.MsgHandlerInterface; +import com.dd.admin.business.webSocket.util.TioUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.tio.core.ChannelContext; + +import java.util.Map; + + +@Slf4j +@Service("7") +public class ReadMessageHandler implements MsgHandlerInterface { + @Autowired + ChatService chatService; + @Override + public Object handler(Map map, ChannelContext context) { + String authorId = String.valueOf(map.get("authorId")); + String loginId = String.valueOf(map.get("loginId")); + chatService.readMessage(authorId,loginId); + return null; + } +} diff --git a/web/.env.development b/web/.env.development index 3e6d80b..a593222 100644 --- a/web/.env.development +++ b/web/.env.development @@ -3,8 +3,9 @@ ENV = 'development' # base api VUE_APP_BASE_API = 'http://127.0.0.1:8080' +VUE_APP_WEBSOCKET_API = 'ws://192.168.10.98:9326' # system name -VUE_APP_SYSTEM_NAME = 'DD ADMIN' +VUE_APP_SYSTEM_NAME = '小红书社区后台管理系统' VUE_APP_SYSTEM_LOGO = 'logo.png' diff --git a/web/.env.production b/web/.env.production index b740e3a..7a5cbce 100644 --- a/web/.env.production +++ b/web/.env.production @@ -3,8 +3,9 @@ ENV = 'production' # base api VUE_APP_BASE_API = 'http://8.146.211.120:8080' -VUE_APP_WEBSOCKET_API = 'ws://8.146.211.120:9326/' +VUE_APP_WEBSOCKET_API = 'ws://8.146.211.120:9326' # system name -VUE_APP_SYSTEM_NAME = 'DD STORE' +VUE_APP_SYSTEM_NAME = '小红书社区后台管理系统' +VUE_APP_SYSTEM_LOGO = 'logo.png' diff --git a/web/src/api/business/chat/chat.js b/web/src/api/business/chat/chat.js index 1ab7247..985ebb2 100644 --- a/web/src/api/business/chat/chat.js +++ b/web/src/api/business/chat/chat.js @@ -54,3 +54,24 @@ export function getAuthorChat(params) { params }) } + + +export function getUnReadCount() { + return request({ + url: '/admin/chat/getUnReadCount', + method: 'get', + }) +} + + + +export function readAuthorMessage(data) { + return request({ + url: '/admin/chat/readAuthorMessage', + method: 'post', + data: data, + noLoading:true + }) +} + + diff --git a/web/src/api/websocket.js b/web/src/api/websocket.js index e3489ef..24457c1 100644 --- a/web/src/api/websocket.js +++ b/web/src/api/websocket.js @@ -1,3 +1,5 @@ +import {error} from "@/utils"; + class WebSocketManager { constructor() { this.webSocketInstance = null; // WebSocket实例对象,使用更清晰的命名 @@ -32,6 +34,16 @@ class WebSocketManager { } console.log("连接WebSocket"); this.webSocketInstance = new WebSocket(url); + + const timeoutTimer = setTimeout(() => { + console.log(this.isConnected) + if (!this.isConnected) { + error("WebSocket连接超时") + } + clearTimeout(timeoutTimer) + }, 5000); + + this.webSocketInstance.onmessage = (event) => { const data = event.data; if (data === 'pong') { @@ -53,6 +65,8 @@ class WebSocketManager { console.log("WebSocket连接成功"); this.isConnected = true; this.heartbeatCheck.start(); + + this.onConnectCallback && this.onConnectCallback(); }; // 连接发生错误的回调方法 diff --git a/web/src/assets/logo.png b/web/src/assets/logo.png index 8bd7972ab196cfe6642318a278f83241a5815418..c828d68b2e34b04276fe2236d96c4e1b382b5f7c 100644 GIT binary patch literal 3809 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 diff --git a/web/src/layout/components/Navbar.vue b/web/src/layout/components/Navbar.vue index 0bb8386..1a955b8 100644 --- a/web/src/layout/components/Navbar.vue +++ b/web/src/layout/components/Navbar.vue @@ -4,9 +4,6 @@ - - -
@@ -39,14 +36,21 @@
- + + 客服消息 +
- + + +
@@ -56,13 +60,16 @@ import Breadcrumb from '@/components/Breadcrumb' import Hamburger from '@/components/Hamburger' import UpdatePassword from '@/views/common/system/UpdatePassword' import Im from "@/views/common/Im"; +import {getUnReadCount} from "@/api/business/chat/chat"; +import webSocketManager from "@/api/websocket"; +import {isNotEmpty} from "@/utils"; export default { components: { UpdatePassword, Breadcrumb, Hamburger, - Im + Im, }, computed: { ...mapGetters([ @@ -71,6 +78,37 @@ export default { 'avatar' ]) }, + data() { + return { + unReadCount:0 + } + }, + mounted() { + // 设置收到消息回调函数 + webSocketManager.onMessage((data) => { + console.log('我是Navbar的mounted') + console.log(data.handlerType) + if(data.handlerType == '6'){ + console.log(JSON.stringify(data.body)) + const {IMUI} = this.$refs.im.$refs; + try { + IMUI.appendMessage(data.body); + IMUI.messageViewToBottom() + const contactId = this.$refs.im.contact.id + if(isNotEmpty(contactId)&&contactId==data.body.toContactId){ + console.log('当前在该用户聊天框 设置为已读') + } + }catch (e) { + } + + //请求总数 + this.$refs.im.getUnReadCount() + } + if(data.handlerType == '8'){ + this.unReadCount = data.body + } + }); + }, methods: { updatePassword(){ this.$refs.updatePass.open() @@ -117,7 +155,7 @@ export default { .top-icon{ text-align: center; height: 50px; - width: 50px; + width: 150px; line-height: 50px; cursor: pointer; color: #606266; diff --git a/web/src/layout/index.vue b/web/src/layout/index.vue index 31da694..f70896b 100644 --- a/web/src/layout/index.vue +++ b/web/src/layout/index.vue @@ -8,6 +8,18 @@
+ +
+ + + + + + + + + +
@@ -94,4 +106,36 @@ export default { } + .floating-component { + position: fixed; /* 固定位置 */ + bottom: 5%; /* 下边距 */ + right: 1%; /* 右边距 */ + padding: 0; + border-radius: 50%; /* 圆角 */ + z-index: 10000; /* 设置 z-index 确保悬浮在顶层 */ + } + .but { + font-size: larger; + color: rgb(0,119,216); + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2); /* 阴影 */ + } + .butto { + border: 0; + padding: 10px; + margin: 0; + } + + .too.el-tooltip__popper.is-light { + border: none !important; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2); + padding: 5px + } + /* 修改箭头边框 这里方位是left,所以 x-placement^="left" 并且是设置 border-right-color 的颜色*/ + .too.el-tooltip__popper.is-light[x-placement^="left"] .popper__arrow { + border-left-color: #eaeaea !important; + } + .too.el-tooltip__popper[x-placement^="left"] .popper__arrow { + border-left-color: #eaeaea !important; + } + diff --git a/web/src/utils/request.js b/web/src/utils/request.js index f9c774a..47b741a 100644 --- a/web/src/utils/request.js +++ b/web/src/utils/request.js @@ -18,7 +18,10 @@ service.interceptors.request.use( // do something before request is sent if(config.method == 'post'){ - showLoading() + console.log(config) + if(!config.noLoading){ + showLoading() + } } if (store.getters.token) { @@ -79,7 +82,12 @@ service.interceptors.response.use( return Promise.reject(new Error(res.message || 'Error')) } else { if(response.config.method == 'post'){ - success('提交成功') + console.log(response) + + if(response.data.data=='noAlert'){ + return res + } + success('请求成功') } return res } diff --git a/web/src/views/business/operationLog/operationLogList.vue b/web/src/views/business/operationLog/operationLogList.vue index 8b7c587..6209ab4 100644 --- a/web/src/views/business/operationLog/operationLogList.vue +++ b/web/src/views/business/operationLog/operationLogList.vue @@ -73,6 +73,16 @@ + + + + - - - - - - - - @@ -185,25 +175,6 @@ - - - - - - -
@@ -24,8 +26,8 @@ diff --git a/web/src/views/dashboard/components/PieChart.vue b/web/src/views/dashboard/components/PieChart.vue new file mode 100644 index 0000000..c556d49 --- /dev/null +++ b/web/src/views/dashboard/components/PieChart.vue @@ -0,0 +1,79 @@ + + + diff --git a/web/src/views/dashboard/components/RaddarChart.vue b/web/src/views/dashboard/components/RaddarChart.vue new file mode 100644 index 0000000..9c10333 --- /dev/null +++ b/web/src/views/dashboard/components/RaddarChart.vue @@ -0,0 +1,116 @@ + + + diff --git a/web/src/views/dashboard/components/mixins/resize.js b/web/src/views/dashboard/components/mixins/resize.js new file mode 100644 index 0000000..234953b --- /dev/null +++ b/web/src/views/dashboard/components/mixins/resize.js @@ -0,0 +1,55 @@ +import { debounce } from '@/utils' + +export default { + data() { + return { + $_sidebarElm: null, + $_resizeHandler: null + } + }, + mounted() { + this.$_resizeHandler = debounce(() => { + if (this.chart) { + this.chart.resize() + } + }, 100) + this.$_initResizeEvent() + this.$_initSidebarResizeEvent() + }, + beforeDestroy() { + this.$_destroyResizeEvent() + this.$_destroySidebarResizeEvent() + }, + // to fixed bug when cached by keep-alive + // https://github.com/PanJiaChen/vue-element-admin/issues/2116 + activated() { + this.$_initResizeEvent() + this.$_initSidebarResizeEvent() + }, + deactivated() { + this.$_destroyResizeEvent() + this.$_destroySidebarResizeEvent() + }, + methods: { + // use $_ for mixins properties + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential + $_initResizeEvent() { + window.addEventListener('resize', this.$_resizeHandler) + }, + $_destroyResizeEvent() { + window.removeEventListener('resize', this.$_resizeHandler) + }, + $_sidebarResizeHandler(e) { + if (e.propertyName === 'width') { + this.$_resizeHandler() + } + }, + $_initSidebarResizeEvent() { + this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0] + this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler) + }, + $_destroySidebarResizeEvent() { + this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler) + } + } +} diff --git a/web/src/views/dashboard/index.vue b/web/src/views/dashboard/index.vue index c39721e..739a193 100644 --- a/web/src/views/dashboard/index.vue +++ b/web/src/views/dashboard/index.vue @@ -1,23 +1,416 @@ + diff --git a/web/src/views/login/login.vue b/web/src/views/login/login.vue index 2e7e6a7..b7ac697 100644 --- a/web/src/views/login/login.vue +++ b/web/src/views/login/login.vue @@ -38,7 +38,7 @@ z-0 ">
-
小红书社区后台管理系统
+
{{title}}
    @@ -269,7 +269,8 @@ export default { loading: false, passwordType: 'password', redirect: undefined, - logoShow:false + logoShow:false, + title:'' } }, watch: { @@ -282,6 +283,7 @@ export default { }, mounted() { this.loginLogo = require('@/assets/' + process.env.VUE_APP_SYSTEM_LOGO) + this.title = process.env.VUE_APP_SYSTEM_NAME }, methods: { showPwd() {