From 4700bc995a9dbe9cd50b1ba18b8352435e91884d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AD=A6=E4=B9=A0=E5=BE=88=E5=B7=AE=E5=95=A6?=
<17633066053@163.com>
Date: Wed, 1 Mar 2023 14:59:54 +0800
Subject: [PATCH 1/6] =?UTF-8?q?feat:=20:sparkles:=20=E4=BC=98=E5=8C=96im?=
=?UTF-8?q?=20=E6=8E=A5=E5=8F=A3403=E5=88=A4=E5=AE=9A=EF=BC=8C=E6=96=B0?=
=?UTF-8?q?=E5=A2=9E=E4=BB=8E=E4=B9=B0=E5=AE=B6=E7=AB=AF=E4=BB=A5=E5=8F=8A?=
=?UTF-8?q?=E5=8D=96=E5=AE=B6=E7=AB=AF=E8=BF=9B=E8=A1=8C=E8=B7=B3=E8=BD=AC?=
=?UTF-8?q?im=E6=9D=83=E9=99=90=E5=88=A4=E5=AE=9A=EF=BC=8C=E6=96=B0?=
=?UTF-8?q?=E5=A2=9Eim=E6=8E=89=E7=BA=BF=E9=87=8D=E8=BF=9E=E4=BB=A5?=
=?UTF-8?q?=E5=8F=8A=E9=87=8D=E8=BF=9E=E6=88=90=E5=8A=9F=E6=8F=90=E9=86=92?=
=?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=8F=91=E9=80=81=E7=9A=84=E6=B6=88?=
=?UTF-8?q?=E6=81=AF=E6=96=AD=E7=BA=BF=E5=B0=86=E4=BC=9A=E8=BF=9B=E8=A1=8C?=
=?UTF-8?q?=E9=87=8D=E6=96=B0=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF=E6=8F=90?=
=?UTF-8?q?=E7=A4=BA=EF=BC=8C=E4=BC=98=E5=8C=96=E6=9C=80=E8=BF=91=E6=B5=8F?=
=?UTF-8?q?=E8=A7=88=20=E8=AE=A2=E5=8D=95=E5=88=97=E8=A1=A8=E7=A9=BA?=
=?UTF-8?q?=E5=B1=95=E7=A4=BA=E3=80=82=E6=B3=A8=E9=87=8A=E9=83=A8=E5=88=86?=
=?UTF-8?q?im=E6=89=93=E5=8D=B0=E7=9A=84=E6=97=A5=E5=BF=97=E4=BF=A1?=
=?UTF-8?q?=E6=81=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
buyer/src/components/mixes/talkIm.vue | 43 +++++++
buyer/src/pages/GoodsDetail.vue | 46 +------
buyer/src/pages/Merchant.vue | 32 +----
im/src/components/chat/panel/TalkPanel.vue | 74 ++++++++---
.../chat/panel/template/footPrint.vue | 62 +++++++--
im/src/components/editor/MeEditor.vue | 1 -
im/src/components/face.vue | 8 +-
im/src/core/lazy-use.js | 3 +-
im/src/plugins/ws-socket.js | 121 +++++++++++++-----
im/src/store/modules/dialogue.js | 8 +-
im/src/store/modules/talk.js | 1 +
im/src/store/modules/user.js | 1 -
im/src/store/state.js | 2 -
im/src/utils/request.js | 11 +-
im/src/views/message/index.vue | 4 +-
seller/src/views/home/home.vue | 24 +++-
16 files changed, 288 insertions(+), 153 deletions(-)
create mode 100644 buyer/src/components/mixes/talkIm.vue
diff --git a/buyer/src/components/mixes/talkIm.vue b/buyer/src/components/mixes/talkIm.vue
new file mode 100644
index 00000000..a51c1ad4
--- /dev/null
+++ b/buyer/src/components/mixes/talkIm.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
diff --git a/buyer/src/pages/GoodsDetail.vue b/buyer/src/pages/GoodsDetail.vue
index 929db852..949eb115 100644
--- a/buyer/src/pages/GoodsDetail.vue
+++ b/buyer/src/pages/GoodsDetail.vue
@@ -50,8 +50,7 @@ import {
getGoodsDistribution,
} from "@/api/member";
import { getDetailById } from "@/api/shopentry";
-import { getIMDetail } from "@/api/common";
-import Storage from "../plugins/storage";
+import imTalk from '@/components/mixes/talkIm'
export default {
name: "GoodsDetail",
beforeRouteEnter (to, from, next) {
@@ -61,6 +60,7 @@ export default {
created () {
this.getGoodsDetail();
},
+ mixins: [imTalk],
data () {
return {
goodsMsg: {}, // 商品信息
@@ -68,49 +68,11 @@ export default {
categoryBar: [], // 分类
storeCollected: false, // 商品收藏
storeMsg: {}, // 店铺信息
- IMLink: "",
+
};
},
methods: {
- // 跳转im客服
- async IMService () {
- // 获取访问Token
- let accessToken = Storage.getItem("accessToken");
- await this.getIMDetailMethods();
- if (!accessToken) {
- this.$Message.error("请登录后再联系客服");
- return;
- }
- window.open(
- this.IMLink +
- "?token=" +
- accessToken +
- "&id=" +
- this.goodsMsg.data.storeId +
- "&goodsId=" +
- this.goodsMsg.data.goodsId +
- "&skuId=" +
- this.goodsMsg.data.id
- );
- // window.open(
- // 'http://192.168.0.139:8000/' +
- // "?token=" +
- // accessToken +
- // "&id=" +
- // this.goodsMsg.data.storeId +
- // "&goodsId=" +
- // this.goodsMsg.data.goodsId +
- // "&skuId=" +
- // this.goodsMsg.data.id
- // );
- },
- // 获取im信息
- async getIMDetailMethods () {
- let res = await getIMDetail();
- if (res.success) {
- this.IMLink = res.result;
- }
- },
+
// 点击规格
targetClickSku (val) {
this.getGoodsDetail(val);
diff --git a/buyer/src/pages/Merchant.vue b/buyer/src/pages/Merchant.vue
index e99caeef..b76609c0 100644
--- a/buyer/src/pages/Merchant.vue
+++ b/buyer/src/pages/Merchant.vue
@@ -106,8 +106,7 @@
\ No newline at end of file
diff --git a/im/src/components/editor/MeEditor.vue b/im/src/components/editor/MeEditor.vue
index 345297ba..0c301fed 100644
--- a/im/src/components/editor/MeEditor.vue
+++ b/im/src/components/editor/MeEditor.vue
@@ -173,7 +173,6 @@ export default {
methods: {
// 读取对话编辑草稿信息 并赋值给当前富文本
getDraftText (index_name) {
- console.log("findTalk(index_name)", findTalk(index_name));
return findTalk(index_name)?.draft_text || "";
},
diff --git a/im/src/components/face.vue b/im/src/components/face.vue
index 9f4d6709..2ef80ab3 100644
--- a/im/src/components/face.vue
+++ b/im/src/components/face.vue
@@ -1,5 +1,5 @@
-
+
diff --git a/im/src/core/lazy-use.js b/im/src/core/lazy-use.js
index 43a07afd..38ea74d0 100644
--- a/im/src/core/lazy-use.js
+++ b/im/src/core/lazy-use.js
@@ -85,5 +85,4 @@ Vue.prototype.$alert = MessageBox.alert
import Contextmenu from 'vue-contextmenujs'
Vue.use(Contextmenu)
-process.env.NODE_ENV !== 'production' &&
- console.warn('[Lumen-IM] NOTICE: element-ui use lazy-load.')
+
diff --git a/im/src/plugins/ws-socket.js b/im/src/plugins/ws-socket.js
index 69a3ac8b..234b6329 100644
--- a/im/src/plugins/ws-socket.js
+++ b/im/src/plugins/ws-socket.js
@@ -1,3 +1,6 @@
+import { Notification, MessageBox } from "element-ui";
+let wsSignIn; // ws 是否是掉线状态
+import store from "@/store";
class WsSocket {
/**
* Websocket 连接
@@ -25,7 +28,7 @@ class WsSocket {
reconnect: {
lockReconnect: false,
setTimeout: null, // 计时器对象
- time: 5000, // 重连间隔时间
+ time: 1000, // 重连间隔时间
number: 1000, // 重连次数
},
};
@@ -49,9 +52,9 @@ class WsSocket {
// 定义 WebSocket 原生方法
this.events = Object.assign(
{
- onError: (evt) => { },
- onOpen: (evt) => { },
- onClose: (evt) => { },
+ onError: (evt) => {},
+ onOpen: (evt) => {},
+ onClose: (evt) => {},
},
events
);
@@ -63,7 +66,7 @@ class WsSocket {
* @param {String} event 事件名
* @param {Function} callBack 回调方法
*/
- on (event, callBack) {
+ on(event, callBack) {
// 对应 socket-instance.js
this.onCallBacks[event] = callBack;
return this;
@@ -72,7 +75,23 @@ class WsSocket {
/**
* 加载 WebSocket
*/
- loadSocket () {
+ loadSocket() {
+ /**
+ * 判断当前如果是掉线提示
+ * 重连成功后关闭掉线提示,新增重连提示
+ */
+ if (wsSignIn) {
+ store.commit('SET_WS_STATUS',true);
+ wsSignIn.close();
+
+ Notification({
+ title: "成功",
+ message: "重连成功",
+ type: "success",
+ position: "top-right",
+ duration: 1000,
+ });
+ }
// 判断当前是否已经连接
if (this.connect != null) {
this.connect.close();
@@ -85,41 +104,72 @@ class WsSocket {
connect.onopen = this.onOpen.bind(this);
connect.onmessage = this.onMessage.bind(this);
connect.onclose = this.onClose.bind(this);
-
this.connect = connect;
}
/**
* 连接 Websocket
*/
- connection () {
+ connection() {
this.loadSocket();
}
/**
* 掉线重连 Websocket
*/
- reconnect () {
- console.log("掉线重连接");
+ reconnect() {
+
+ /**
+ * 长时间挂载页面中并且重连次数为空的时候进行提示
+ */
+ if (this.config.reconnect.number == 0) {
+ MessageBox("当前对话链接已失效,请从关闭重新进入。", "提示", {
+ confirmButtonText: "确定",
+ cancelButtonText: "取消",
+ closeOnPressEscape: false,
+ closeOnClickModal: false,
+ type: "warning",
+ })
+ .then(() => {
+ window.close();
+ Notification({
+ title: "对话链接已失效提示",
+ message: "请手动关闭当前页面",
+ type: "error",
+ position: "top-right",
+ });
+ })
+ .catch(() => {
+ Notification({
+ title: "对话链接已失效提示",
+ message: "请手动关闭当前页面",
+ type: "error",
+ position: "top-right",
+ });
+ });
+ return false;
+ }
+ // 掉线重连提示
+ wsSignIn = Notification({
+ title: "掉线重连接提示",
+ message: `网络连接已断开,正在尝试重新连接......`,
+ type: "error",
+ position: "top-right",
+ duration: 0,
+ });
+ // 掉线更改消息状态
+ store.commit('SET_WS_STATUS',true);
let reconnect = this.config.reconnect;
if (reconnect.lockReconnect || reconnect.number == 0) {
return;
}
-
this.config.reconnect.lockReconnect = true;
-
// 没连接上会一直重连,设置延迟避免请求过多
reconnect.setTimeout && clearTimeout(reconnect.setTimeout);
-
this.config.reconnect.setTimeout = setTimeout(() => {
this.connection();
-
this.config.reconnect.lockReconnect = false;
this.config.reconnect.number--;
-
- console.log(
- `网络连接已断开,正在尝试重新连接(${this.config.reconnect.number})...`
- );
}, reconnect.time);
}
@@ -128,8 +178,7 @@ class WsSocket {
*
* @param {Object} evt Websocket 消息
*/
- onParse (evt) {
-
+ onParse(evt) {
const res = JSON.parse(evt.data).result;
//如果创建时间是时间戳类型则转换为 日期类型,否则新压入栈的消息的创建时间和从数据库读取出来的创建时间格式对不上,处理的时候会出异常。
@@ -145,7 +194,7 @@ class WsSocket {
* @param format 转换格式
* @returns {*|string}
*/
- unixToDate (unix, format) {
+ unixToDate(unix, format) {
if (!unix) return unix;
let _format = format || "yyyy-MM-dd hh:mm:ss";
const d = new Date(unix);
@@ -179,7 +228,7 @@ class WsSocket {
*
* @param {Object} evt Websocket 消息
*/
- onOpen (evt) {
+ onOpen(evt) {
this.events.onOpen(evt);
if (this.config.heartbeat.enabled) {
@@ -192,7 +241,7 @@ class WsSocket {
*
* @param {Object} evt Websocket 消息
*/
- onClose (evt) {
+ onClose(evt) {
console.log("关闭连接", evt);
if (this.config.heartbeat.enabled) {
clearInterval(this.config.heartbeat.setInterval);
@@ -211,7 +260,7 @@ class WsSocket {
*
* @param {Object} evt Websocket 消息
*/
- onError (evt) {
+ onError(evt) {
this.events.onError(evt);
}
@@ -220,28 +269,30 @@ class WsSocket {
*
* @param {Object} evt Websocket 消息
*/
- onMessage (evt) {
+ onMessage(evt) {
let result = this.onParse(evt);
- if (this.onParse(evt).text.includes('goodsName') || this.onParse(evt).text.includes('groupName')) {
+ if (
+ this.onParse(evt).text.includes("goodsName") ||
+ this.onParse(evt).text.includes("groupName")
+ ) {
let params = {
...this.onParse(evt),
- text: JSON.parse(this.onParse(evt).text)
- }
+ text: JSON.parse(this.onParse(evt).text),
+ };
this.onCallBacks["event_talk"](params);
} else {
let params = {
...this.onParse(evt),
- text: this.onParse(evt).text
- }
+ text: this.onParse(evt).text,
+ };
this.onCallBacks["event_talk"](params);
}
// 指定推送消息
-
}
/**
* WebSocket心跳检测
*/
- heartbeat () {
+ heartbeat() {
console.log("WebSocket心跳检测");
this.config.heartbeat.setInterval = setInterval(() => {
this.connect.send("PING");
@@ -253,14 +304,14 @@ class WsSocket {
*
* @param {Object} message
*/
- send (message) {
+ send(message) {
this.connect.send(JSON.stringify(message));
}
/**
* 关闭连接
*/
- close () {
+ close() {
this.connect.close();
}
@@ -270,7 +321,7 @@ class WsSocket {
* @param {String} event 事件名
* @param {Object} data 数据
*/
- emit (event, data) {
+ emit(event, data) {
if (this.connect && this.connect.readyState === 1) {
this.connect.send(JSON.stringify(data));
} else {
diff --git a/im/src/store/modules/dialogue.js b/im/src/store/modules/dialogue.js
index 8876b364..259612e3 100644
--- a/im/src/store/modules/dialogue.js
+++ b/im/src/store/modules/dialogue.js
@@ -21,11 +21,15 @@ export default {
float: "",
},
],
-
+ webSocketWithOut:false, // ws 是否是掉线 无输出状态
// 对话索引(聊天对话的唯一索引)
index_name: null,
},
mutations: {
+ // 设置ws状态
+ SET_WS_STATUS: (state,resource) =>{
+ state.webSocketWithOut = resource
+ },
// 更新对话
UPDATE_DIALOGUE_MESSAGE (state, resource) {
state.records = [];
@@ -56,6 +60,8 @@ export default {
// 推送对话记录
PUSH_DIALOGUE (state, record) {
+ record = {...record,webSocketStatus:state.webSocketWithOut}
+ console.log("推送对话",)
state.records.push(record);
},
diff --git a/im/src/store/modules/talk.js b/im/src/store/modules/talk.js
index d52847d4..e7770c6f 100644
--- a/im/src/store/modules/talk.js
+++ b/im/src/store/modules/talk.js
@@ -37,6 +37,7 @@ const Talk = {
talkNum: (state) => state.items.length,
},
mutations: {
+
// 设置对话列表
SET_TALK_ITEMS (state, resource) {
Vue.set(state, 'items', resource.items)
diff --git a/im/src/store/modules/user.js b/im/src/store/modules/user.js
index 995c4566..507a2f96 100644
--- a/im/src/store/modules/user.js
+++ b/im/src/store/modules/user.js
@@ -19,7 +19,6 @@ let state = {
// 判断用户是否登录
if (getToken()) {
let userInfo = getUserInfo();
- console.error(userInfo)
state.name = userInfo.name;
state.id = userInfo.id;
state.face = userInfo.face ? userInfo.face : state.avatar;
diff --git a/im/src/store/state.js b/im/src/store/state.js
index e571ecaf..64c8f811 100644
--- a/im/src/store/state.js
+++ b/im/src/store/state.js
@@ -4,8 +4,6 @@ const defaultAvatar = require('@/assets/image/detault-avatar.jpg')
const state = {
socketStatus: false,
website_name: process.env.VUE_APP_WEBSITE_NAME,
- copyright: `©2020 - 2021 ${process.env.VUE_APP_WEBSITE_NAME} 在线聊天 Github源码`,
-
// 头像加载失败后的默认头像
defaultAvatar: "this.src='" + defaultAvatar + "'",
}
diff --git a/im/src/utils/request.js b/im/src/utils/request.js
index 517b9d59..eedb8d92 100644
--- a/im/src/utils/request.js
+++ b/im/src/utils/request.js
@@ -14,6 +14,7 @@ const request = axios.create({
timeout: 20000,
});
+let isRefreshing = false
/**
* 异常拦截处理器
*
@@ -27,10 +28,12 @@ const errorHandler = (error) => {
removeAll();
location.reload();
} else if (error.response.status == 403) {
+ if(!isRefreshing){
+
/**
* 403提示将重新从商家移动端进入当前页面
*/
- MessageBox("当前登录已失效,请从商家管理后台重新登录。", "提示", {
+ MessageBox("当前登录已失效,请从关闭重新进入。", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnPressEscape: false,
@@ -38,6 +41,7 @@ const errorHandler = (error) => {
type: "warning",
})
.then(() => {
+ isRefreshing = true
window.close();
Notification({
title:"登录失效提示",
@@ -45,9 +49,10 @@ const errorHandler = (error) => {
type:"error",
position: "top-right",
});
+
})
.catch(() => {
-
+ isRefreshing = true
Notification({
title:"登录失效提示",
message: "请手动关闭当前页面",
@@ -55,6 +60,8 @@ const errorHandler = (error) => {
position: "top-right",
});
});
+ isRefreshing = false
+ }
} else if(error.response.status == 400){
Notification({
message: error.response.data.message,
diff --git a/im/src/views/message/index.vue b/im/src/views/message/index.vue
index ba327c57..7b65757f 100644
--- a/im/src/views/message/index.vue
+++ b/im/src/views/message/index.vue
@@ -9,7 +9,7 @@