fix(buyer): 未登录联系客服时提示登录

- 将登录提示由 Message 改为 Modal
- 新增 promptLogin 方法处理登录跳转
- IMService 增加 accessToken 校验,未登录时提示登录
- 改进用户信息获取的错误处理
- 重构 IM 链接 URL 拼接,提升可读性
This commit is contained in:
田香琪
2026-07-22 18:08:42 +08:00
parent 4bcaf14bad
commit c0ca9672a1
19 changed files with 343 additions and 263 deletions

View File

@@ -3,7 +3,7 @@
</template> </template>
<script> <script>
import { Message } from "@/utils/message"; import { Modal } from "@/utils/message";
import { getIMDetail } from "@/api/common"; import { getIMDetail } from "@/api/common";
import Storage from "@/plugins/storage"; import Storage from "@/plugins/storage";
import { getMemberMsg } from "@/api/login"; import { getMemberMsg } from "@/api/login";
@@ -15,28 +15,52 @@ export default {
}; };
}, },
methods: { methods: {
promptLogin() {
Modal.confirm({
title: "温馨提示",
content: "请登录后执行此操作",
okText: "立即登录",
cancelText: "取消",
onOk: () => {
this.$router.push({
path: "/login",
query: {
rePath: this.$route.path,
query: JSON.stringify(this.$route.query || {}),
},
});
},
});
},
// 跳转im客服 // 跳转im客服
async IMService(id, goodsId, skuId) { async IMService(id, goodsId, skuId) {
if (!Storage.getItem("accessToken")) {
this.promptLogin();
return;
}
// 获取访问Token try {
let accessToken = Storage.getItem("accessToken"); await this.getIMDetailMethods();
await this.getIMDetailMethods(); const userInfo = await getMemberMsg();
const userInfo = await getMemberMsg(); if (!userInfo.success) {
if (userInfo.success) { this.promptLogin();
//携带商品Id,在IM可以发送商品信息 return;
if(goodsId && skuId){
window.open(
this.IMLink + "?token=" + accessToken + "&id=" + (id || this.storeMsg.storeId) + "&goodsId=" + goodsId + "&skuId=" + skuId
);
}else{
window.open(
this.IMLink + "?token=" + accessToken + "&id=" + (id || this.storeMsg.storeId)
);
} }
} else { const accessToken = Storage.getItem("accessToken");
Message.error("请登录后再联系客服"); const storeId = id || this.storeMsg?.storeId;
return; const baseUrl = `${this.IMLink}?token=${accessToken}&id=${storeId}`;
if (goodsId && skuId) {
window.open(`${baseUrl}&goodsId=${goodsId}&skuId=${skuId}`);
} else {
window.open(baseUrl);
}
} catch {
// token 过期等场景由 request 拦截器处理;未登录时避免未捕获异常
if (!Storage.getItem("accessToken")) {
this.promptLogin();
}
} }
}, },
// 获取im信息 // 获取im信息

View File

@@ -284,7 +284,7 @@ export default {
// 跳转店铺首页 // 跳转店铺首页
goShopPage(id) { goShopPage(id) {
let routeUrl = this.$router.resolve({ let routeUrl = this.$router.resolve({
path: "/Merchant", path: "/merchant",
query: { id }, query: { id },
}); });
window.open(routeUrl.href, "_blank"); window.open(routeUrl.href, "_blank");

View File

@@ -177,7 +177,7 @@ export default {
let url let url
if (this.params.type === 'STORE') { if (this.params.type === 'STORE') {
url = this.$router.resolve({ url = this.$router.resolve({
path: '/Merchant', path: '/merchant',
query: { 'id': storeId } query: { 'id': storeId }
}) })
} else { } else {

View File

@@ -198,7 +198,7 @@ export default {
// 跳转店铺首页 // 跳转店铺首页
shopPage(id) { shopPage(id) {
let routeUrl = this.$router.resolve({ let routeUrl = this.$router.resolve({
path: '/Merchant', path: '/merchant',
query: {id: id} query: {id: id}
}); });
window.open(routeUrl.href, '_blank'); window.open(routeUrl.href, '_blank');

View File

@@ -265,7 +265,7 @@ export default {
// 跳转店铺首页 // 跳转店铺首页
shopPage (id) { shopPage (id) {
let routeUrl = this.$router.resolve({ let routeUrl = this.$router.resolve({
path: '/Merchant', path: '/merchant',
query: { id: id } query: { id: id }
}); });
window.open(routeUrl.href, '_blank'); window.open(routeUrl.href, '_blank');

View File

@@ -424,7 +424,7 @@ export default {
// 跳转店铺首页 // 跳转店铺首页
shopPage(id) { shopPage(id) {
let routeUrl = this.$router.resolve({ let routeUrl = this.$router.resolve({
path: "/Merchant", path: "/merchant",
query: { id: id }, query: { id: id },
}); });
window.open(routeUrl.href, "_blank"); window.open(routeUrl.href, "_blank");

View File

@@ -71,7 +71,7 @@ export default {
// 跳转店铺首页 // 跳转店铺首页
shopPage(id) { shopPage(id) {
let routeUrl = this.$router.resolve({ let routeUrl = this.$router.resolve({
path: "/Merchant", path: "/merchant",
query: { id: id }, query: { id: id },
}); });
window.open(routeUrl.href, "_blank"); window.open(routeUrl.href, "_blank");

View File

@@ -794,7 +794,7 @@ export default {
// 跳转店铺首页 // 跳转店铺首页
goShopPage(id) { goShopPage(id) {
let routeUrl = this.$router.resolve({ let routeUrl = this.$router.resolve({
path: "/Merchant", path: "/merchant",
query: { id: id }, query: { id: id },
}); });
window.open(routeUrl.href, "_blank"); window.open(routeUrl.href, "_blank");

View File

@@ -17,31 +17,35 @@ export const ServeGetUserDetail = (memberId) => {
}; };
// 获取店铺相关设置信息 // 获取店铺相关设置信息
export const ServeGetStoreDetail = (storeId) => { export const ServeGetStoreDetail = (storeId, options = {}) => {
return get(`${config.BASE_BUYER}/buyer/store/store/store/${storeId}`); return get(`${config.BASE_BUYER}/buyer/store/store/store/${storeId}`, {}, options);
}; };
// 获取用户历史足迹 // 获取用户历史足迹
export const ServeGetFootPrint = (params) => { export const ServeGetFootPrint = (params, options = {}) => {
return get(`${config.BASE_BUYER}/buyer/member/footprint`, params); return get(`${config.BASE_BUYER}/buyer/member/footprint`, params, options);
}; };
// 商家获取用户历史足迹 // 商家获取用户历史足迹
export const ServeStoreGetFootPrint = (params) => { export const ServeStoreGetFootPrint = (params, options = {}) => {
return get(`${config.BASE_SELLER}/store/member/footprint`, params); return get(`${config.BASE_SELLER}/store/member/footprint`, params, options);
}; };
// 获取用户订单列表信息 // 获取用户订单列表信息
export const ServeGetOrderPrint = (params) => { export const ServeGetOrderPrint = (params, options = {}) => {
return get(`${config.BASE_BUYER}/buyer/order/order`, params); return get(`${config.BASE_BUYER}/buyer/order/order`, params, options);
}; };
// 商家获取用户订单列表信息 // 商家获取用户订单列表信息
export const ServeStoreGetOrderPrint = (params) => { export const ServeStoreGetOrderPrint = (params, options = {}) => {
return get(`${config.BASE_SELLER}/store/order/order`, params); return get(`${config.BASE_SELLER}/store/order/order`, params, options);
}; };
// 获取商品信息 // 获取商品信息
export const ServeGetGoodsDetail = (data) => { export const ServeGetGoodsDetail = (data, options = {}) => {
return get(`${config.BASE_BUYER}/buyer/goods/goods/sku/${data.goodsId}/${data.skuId}`); return get(
`${config.BASE_BUYER}/buyer/goods/goods/sku/${data.goodsId}/${data.skuId}`,
{},
options
);
}; };

View File

@@ -17,17 +17,29 @@
</template> </template>
<script> <script>
import { ServeGetStoreDetail, ServeGetUserDetail, ServeGetFootPrint, ServeGetOrderPrint, ServeGetGoodsDetail, ServeStoreGetFootPrint,ServeStoreGetOrderPrint } from '@/api/user' import {
ServeGetStoreDetail,
ServeGetFootPrint,
ServeGetOrderPrint,
ServeGetGoodsDetail,
ServeStoreGetFootPrint,
ServeStoreGetOrderPrint,
} from "@/api/user";
import StoreDetail from "@/components/chat/panel/template/storeDetail.vue"; import StoreDetail from "@/components/chat/panel/template/storeDetail.vue";
import FootPrint from "@/components/chat/panel/template/footPrint.vue"; import FootPrint from "@/components/chat/panel/template/footPrint.vue";
import GoodsLink from "@/components/chat/panel/template/goodsLink.vue"; import GoodsLink from "@/components/chat/panel/template/goodsLink.vue";
import SocketInstance from "@/im-server/socket-instance"; import SocketInstance from "@/im-server/socket-instance";
import { mapState, mapGetters } from "vuex"; import { mapState, mapGetters } from "vuex";
import { getToken } from "@/utils/auth";
import { isBuyerImMode } from "@/utils/im-mode";
const SIDE_REQUEST_OPTIONS = { skipAuthDialog: true };
export default { export default {
components: { components: {
StoreDetail, StoreDetail,
FootPrint, FootPrint,
GoodsLink GoodsLink,
}, },
props: { props: {
toUser: { toUser: {
@@ -36,7 +48,7 @@ export default {
}, },
id: { id: {
type: String, type: String,
default: '', default: "",
}, },
goodsParams: { goodsParams: {
type: Object, type: Object,
@@ -48,167 +60,173 @@ export default {
...mapState({ ...mapState({
index_name: (state) => state.dialogue.index_name, index_name: (state) => state.dialogue.index_name,
}), }),
isBuyerImMode() {
return isBuyerImMode(this.$route);
},
}, },
watch:{ watch: {
toUser(){ toUser() {
localStorage.setItem('storeFlag', this.toUser.storeFlag) this.syncStoreFlagCache();
this.footPrintList = [] this.resetSidePanelData();
this.orderPrintList = []
this.footPrintParams.pageNumber = 1
if (this.toUser.storeFlag) { if (this.toUser.storeFlag) {
this.getStoreDetail() this.getStoreDetail();
} }
// else { this.getFootPrint();
// this.getMemberDetail() if (this.goodsParams && this.toUser.storeFlag) {
// } this.getGoodsDetail();
this.getFootPrint()
if (this.goodsParams && this.toUser.storeFlag == true) {
this.getGoodsDetail()
} }
} },
}, },
data () { data() {
return { return {
activeName: 'history', activeName: "history",
storeInfo: {}, //店铺信息 storeInfo: {},
memberInfo: {}, //会员信息 memberInfo: {},
footPrintParams: { footPrintParams: {
pageSize: 20, pageSize: 20,
pageNumber: 1, pageNumber: 1,
memberId: '', memberId: "",
storeId: '', storeId: "",
}, },
goodsDetail: {}, goodsDetail: {},
footPrintList: [], // 商品 footPrintList: [],
orderPrintList: []// 订单 orderPrintList: [],
} };
}, },
mounted () { mounted() {
localStorage.setItem('storeFlag', this.toUser.storeFlag) this.syncStoreFlagCache();
if (this.toUser.storeFlag) { if (this.toUser.storeFlag) {
this.getStoreDetail() this.getStoreDetail();
} }
// else { this.getFootPrint();
// this.getMemberDetail() if (this.goodsParams && this.toUser.storeFlag) {
// } this.getGoodsDetail();
this.getFootPrint()
if (this.goodsParams && this.toUser.storeFlag == true) {
this.getGoodsDetail()
} }
}, },
methods: { methods: {
getStoreDetail () { syncStoreFlagCache() {
ServeGetStoreDetail(this.toUser.userId).then(res => { localStorage.setItem(
if (res.success) { "storeFlag",
this.storeInfo = res.result this.isBuyerImMode ? "true" : "false"
} );
})
}, },
loadMoreFootPrint (e) { resetSidePanelData() {
//触底再次调接口 this.footPrintList = [];
this.footPrintParams.pageNumber++ this.orderPrintList = [];
this.getFootPrint() this.footPrintParams.pageNumber = 1;
}, },
handleClick () { }, getStoreDetail() {
// getMemberDetail () { ServeGetStoreDetail(this.toUser.userId, SIDE_REQUEST_OPTIONS)
// ServeGetUserDetail(this.toUser.userId).then(res => { .then((res) => {
// if (res.success) { if (res.success) {
// this.memberInfo = res.result this.storeInfo = res.result;
// } }
// }) })
// }, .catch(() => {});
getGoodsDetail () { },
// 检查必要参数是否存在 loadMoreFootPrint() {
this.footPrintParams.pageNumber++;
this.getFootPrint();
},
handleClick() {},
getGoodsDetail() {
if (!this.toUser.storeFlag) { if (!this.toUser.storeFlag) {
return return;
} }
if (!this.goodsParams || !this.goodsParams.goodsId) { if (!this.goodsParams || !this.goodsParams.goodsId) {
console.warn('getGoodsDetail: goodsParams 或 goodsId 参数缺失') return;
return
} }
ServeGetGoodsDetail(this.goodsParams, SIDE_REQUEST_OPTIONS)
ServeGetGoodsDetail(this.goodsParams).then(res => { .then((res) => {
if (res.success) { if (res.success) {
this.goodsDetail = res.result.data this.goodsDetail = res.result.data;
} }
}).catch(error => { })
console.error('获取商品详情失败:', error) .catch(() => {});
}) },
normalizeFootPrintRecords(records = []) {
const goodsId = this.goodsParams?.goodsId;
return records
.filter((item) => item != null)
.filter((item) => !goodsId || item.goodsId !== goodsId)
.map((item) => ({
...item,
btnHide: localStorage.getItem(item.goodsId) ? 0 : 1,
}));
},
normalizeOrderRecords(records = []) {
return records.map((item) => ({
...item,
btnHide: 1,
}));
}, },
getFootPrint() { getFootPrint() {
if (this.toUser.storeFlag) { if (!getToken()) {
this.footPrintParams.memberId = this.id return;
this.footPrintParams.storeId = this.toUser.userId }
ServeGetFootPrint(this.footPrintParams).then(res => { if (!this.toUser?.userId || !this.id) {
res.result.records=res.result.records.filter((item)=>{ return;
return item!=null }
})
res.result.records.forEach((item, index) => { if (this.isBuyerImMode) {
if (localStorage.getItem(item.goodsId)) { this.footPrintParams.memberId = this.id;
item.btnHide = 0 this.footPrintParams.storeId = this.toUser.userId;
} else { this.fetchBuyerSideData();
item.btnHide = 1
}
if (item.goodsId === this.goodsParams.goodsId) {
res.result.records.splice(index, 1)
}
});
this.footPrintList.push(...res.result.records)
})
// 订单列表
ServeGetOrderPrint(this.footPrintParams).then((res) => {
if (res.code == 200) {
res.result.records.forEach((item) => {
this.orderPrintList.push({
...item,
btnHide: 1
})
})
}
})
} else { } else {
this.footPrintParams.memberId = this.toUser.userId this.footPrintParams.memberId = this.toUser.userId;
this.footPrintParams.storeId = this.id this.footPrintParams.storeId = this.id;
ServeStoreGetFootPrint(this.footPrintParams).then(res => { this.fetchStoreSideData();
res.result.records=res.result.records.filter((item)=>{
return item!=null
})
res.result.records.forEach((item, index) => {
if (localStorage.getItem(item.goodsId)) {
item.btnHide = 0
} else {
item.btnHide = 1
}
if (item.goodsId === this.goodsParams.goodsId) {
res.result.records.splice(index, 1)
}
});
this.footPrintList.push(...res.result.records)
})
ServeStoreGetOrderPrint(this.footPrintParams).then((res) => {
if (res.code == 200) {
res.result.records.forEach((item) => {
this.orderPrintList.push({
...item,
btnHide: 1
})
})
}
})
} }
}, },
fetchBuyerSideData() {
ServeGetFootPrint(this.footPrintParams, SIDE_REQUEST_OPTIONS)
.then((res) => {
if (res?.result?.records) {
this.footPrintList.push(
...this.normalizeFootPrintRecords(res.result.records)
);
}
})
.catch(() => {});
// 发送消息回调事件 ServeGetOrderPrint(this.footPrintParams, SIDE_REQUEST_OPTIONS)
submitSendMessage (record, context, messageType) { .then((res) => {
if (res?.code === 200 && res?.result?.records) {
this.orderPrintList.push(
...this.normalizeOrderRecords(res.result.records)
);
}
})
.catch(() => {});
},
fetchStoreSideData() {
ServeStoreGetFootPrint(this.footPrintParams, SIDE_REQUEST_OPTIONS)
.then((res) => {
if (res?.result?.records) {
this.footPrintList.push(
...this.normalizeFootPrintRecords(res.result.records)
);
}
})
.catch(() => {});
ServeStoreGetOrderPrint(this.footPrintParams, SIDE_REQUEST_OPTIONS)
.then((res) => {
if (res?.code === 200 && res?.result?.records) {
this.orderPrintList.push(
...this.normalizeOrderRecords(res.result.records)
);
}
})
.catch(() => {});
},
submitSendMessage(record, context, messageType) {
SocketInstance.emit("event_talk", record); SocketInstance.emit("event_talk", record);
this.$store.commit("UPDATE_TALK_ITEM", { this.$store.commit("UPDATE_TALK_ITEM", {
index_name: this.index_name, index_name: this.index_name,
draft_text: "", draft_text: "",
}); });
/**
* 插入数据
*/
const insterChat = { const insterChat = {
createTime: this.formateDateAndTimeToString(new Date()), createTime: this.formateDateAndTimeToString(new Date()),
fromUser: this.id, fromUser: this.id,
@@ -219,11 +237,8 @@ export default {
float: "right", float: "right",
}; };
// 插入对话记录
this.$store.commit("PUSH_DIALOGUE", insterChat); this.$store.commit("PUSH_DIALOGUE", insterChat);
// 获取聊天面板元素节点
let el = document.getElementById("lumenChatPanel"); let el = document.getElementById("lumenChatPanel");
// 判断的滚动条是否在底部
let isBottom = let isBottom =
Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight; Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight;
@@ -233,14 +248,13 @@ export default {
}); });
} else { } else {
this.$store.commit("SET_TLAK_UNREAD_MESSAGE", { this.$store.commit("SET_TLAK_UNREAD_MESSAGE", {
content: content, content: context,
nickname: record.name, nickname: record.name,
}); });
} }
}, },
formateDateAndTimeToString (date) { formateDateAndTimeToString(date) {
var hours = date.getHours(); var hours = date.getHours();
var mins = date.getMinutes(); var mins = date.getMinutes();
var secs = date.getSeconds(); var secs = date.getSeconds();
@@ -254,7 +268,7 @@ export default {
); );
}, },
formatDateToString (date) { formatDateToString(date) {
var year = date.getFullYear(); var year = date.getFullYear();
var month = date.getMonth() + 1; var month = date.getMonth() + 1;
var day = date.getDate(); var day = date.getDate();
@@ -262,15 +276,11 @@ export default {
if (day < 10) day = "0" + day; if (day < 10) day = "0" + day;
return year + "-" + month + "-" + day; return year + "-" + month + "-" + day;
}, },
} },
} };
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
// :deep(.el-tabs__nav.is-top ) {
// }
:deep(.el-tabs__nav ) { :deep(.el-tabs__nav ) {
height: 60px; height: 60px;
line-height: 60px; line-height: 60px;

View File

@@ -284,6 +284,9 @@ export default {
// 置底按钮是否显示 // 置底按钮是否显示
tipsBoard: false, tipsBoard: false,
// 防止并发请求导致 loading 状态错乱
recordsRequestId: 0,
}; };
}, },
@@ -301,22 +304,15 @@ export default {
}), }),
}, },
watch: { watch: {
// 监听面板传递参数 // 监听面板传递参数(含首次挂载)
params () { params: {
this.loadRecord.minRecord = 0; handler () {
this.tipsBoard = false; this.resetRecordState();
this.multiSelect = { this.loadChatRecords();
isOpen: false, },
items: [], immediate: true,
mode: 0,
};
this.loadChatRecords();
}, },
}, },
mounted () {
this.loadChatRecords();
},
methods: { methods: {
parseTime, parseTime,
sendTime: formatTime, sendTime: formatTime,
@@ -496,27 +492,49 @@ export default {
resetRecordState () {
this.loadRecord.minRecord = 0;
this.loadRecord.pageNumber = 0;
this.tipsBoard = false;
this.multiSelect = {
isOpen: false,
items: [],
mode: 0,
};
},
// 加载用户聊天详情信息 // 加载用户聊天详情信息
loadChatRecords () { loadChatRecords () {
if (this.loadRecord.pageNumber === 0 || this.params.clickFlag) { if (!this.params.talkId) {
this.loadRecord.pageNumber = 1 this.loadRecord.status = 2;
this.params.clickFlag = false return;
} else {
this.loadRecord.pageNumber = this.loadRecord.pageNumber + 1
} }
const isFirstPage = this.loadRecord.pageNumber === 0;
if (isFirstPage) {
this.loadRecord.pageNumber = 1;
} else {
this.loadRecord.pageNumber = this.loadRecord.pageNumber + 1;
}
const user_id = this.id; const user_id = this.id;
const data = { const data = {
pageNumber: this.loadRecord.pageNumber, pageNumber: this.loadRecord.pageNumber,
pageSize: this.loadChatRecords.pageSize, pageSize: this.loadRecord.pageSize,
talkId: this.params.talkId, talkId: this.params.talkId,
}; };
this.loadRecord.status = 0; this.loadRecord.status = 0;
let el = document.getElementById('lumenChatPanel') const requestId = ++this.recordsRequestId;
let scrollHeight = el.scrollHeight let el = document.getElementById('lumenChatPanel');
let scrollHeight = el ? el.scrollHeight : 0;
ServeTalkRecords(data).then((res) => { ServeTalkRecords(data).then((res) => {
// 防止点击切换过快消息返回延迟,导致信息错误 if (requestId !== this.recordsRequestId) return;
// console.log("读取历史数据", res); if (res.code !== 200 || !Array.isArray(res.result)) {
this.loadRecord.status = 2;
return;
}
const records = res.result.map((item) => { const records = res.result.map((item) => {
let key = new Date().getTime(); let key = new Date().getTime();
item.float = "center"; item.float = "center";
@@ -524,28 +542,26 @@ export default {
item.float = item.fromUser == user_id ? "right" : "left"; item.float = item.fromUser == user_id ? "right" : "left";
} }
if (item.messageType == 'GOODS') { if (item.messageType == 'GOODS') {
item.text = JSON.parse(item.text) item.text = JSON.parse(item.text);
} }
// if (item.messageType == 'MESSAGE"') {
// item.text = this.textReplaceEmoji(item.text)
// }
if (item.messageType == 'ORDER') { if (item.messageType == 'ORDER') {
item.text = JSON.parse(item.text) item.text = JSON.parse(item.text);
} }
return { ...item, [key]: key }; return { ...item, [key]: key };
}); });
this.$store.commit("UNSHIFT_DIALOGUE", records); this.$store.commit("UNSHIFT_DIALOGUE", records);
records.length this.loadRecord.status = records.length ? 1 : 2;
? (this.loadRecord.status = 1)
: (this.loadRecord.status = 2);
this.$nextTick(() => { this.$nextTick(() => {
// if (data.record_id == 0 || !data.record_id) { if (!el) return;
if (data.record_id == 0 || data.pageNumber == 1) { if (isFirstPage) {
el.scrollTop = el.scrollHeight el.scrollTop = el.scrollHeight;
} else { } else {
el.scrollTop = el.scrollHeight - scrollHeight el.scrollTop = el.scrollHeight - scrollHeight;
} }
}) });
}).catch(() => {
if (requestId !== this.recordsRequestId) return;
this.loadRecord.status = 2;
}); });
}, },

View File

@@ -87,7 +87,7 @@
@confirm="confirmCodeBlock" /> @confirm="confirmCodeBlock" />
<!-- 文件上传管理器 --> <!-- 文件上传管理器 -->
<MeEditorFileManage ref="filesManager" v-model:show="filesManager.isShow" /> <MeEditorFileManage ref="fileManageRef" v-model:show="filesManager.isShow" />
<MeEditorVote v-if="vote.isShow" @close=" <MeEditorVote v-if="vote.isShow" @close="
() => { () => {
@@ -133,7 +133,7 @@ export default {
}, },
watch: { watch: {
talkUser (n_index_name) { talkUser (n_index_name) {
this.$refs.filesManager.clear(); this.$refs.fileManageRef?.clear();
this.editorText = this.getDraftText(n_index_name); this.editorText = this.getDraftText(n_index_name);
}, },
}, },
@@ -251,7 +251,7 @@ export default {
this.filesManager.isShow = true; this.filesManager.isShow = true;
this.$refs.restFile2.value = null; this.$refs.restFile2.value = null;
this.$refs.filesManager.upload(file); this.$refs.fileManageRef?.upload(file);
}, },
// 打开图片查看器 // 打开图片查看器

View File

@@ -48,7 +48,7 @@ app.config.globalProperties.linkToGoods = function (goodsId, skuId) {
); );
}; };
app.config.globalProperties.linkToStore = function (storeId) { app.config.globalProperties.linkToStore = function (storeId) {
window.open(`${config.PC_URL}/Merchant?id=${storeId}`, "_blank"); window.open(`${config.PC_URL}merchant?id=${storeId}`, "_blank");
}; };
app.config.globalProperties.linkToOrders = function (sn) { app.config.globalProperties.linkToOrders = function (sn) {
if (localStorage.getItem("storeFlag") == "false") { if (localStorage.getItem("storeFlag") == "false") {

View File

@@ -20,7 +20,7 @@ export default {
//标识没有值,获取用户信息 //标识没有值,获取用户信息
if(this.$route.query.id){ if(this.$route.query.id){
ServeGetUserSetting().then(async ({ code, result }) => { return ServeGetUserSetting().then(async ({ code, result }) => {
// 如果result有值说明用户创建成功 // 如果result有值说明用户创建成功
if (result) { if (result) {
store.commit("UPDATE_USER_INFO", { store.commit("UPDATE_USER_INFO", {
@@ -28,15 +28,17 @@ export default {
face: result.face, face: result.face,
name: result.nickName, name: result.nickName,
}); });
console.log(result.nickName)
/** /**
* 用户像商家进行聊天,商家进行刷新好友列表 * 用户像商家进行聊天,商家进行刷新好友列表
*/ */
// 判断如果是有id说明是 用户像商家进行聊天。
if (this.$route.query.id) { if (this.$route.query.id) {
await this.createTalk(this.$route.query.id); if (typeof this.createTalk === "function") {
await this.createTalk(this.$route.query.id);
} else if (typeof this.loadChatList === "function") {
await this.loadChatList();
}
} }
if(this.$route.query.goodsId && this.$route.query.skuId){ if(this.$route.query.goodsId && this.$route.query.skuId && this.goodsParams){
this.goodsParams.goodsId = this.$route.query.goodsId this.goodsParams.goodsId = this.$route.query.goodsId
this.goodsParams.skuId = this.$route.query.skuId this.goodsParams.skuId = this.$route.query.skuId
} }
@@ -48,7 +50,7 @@ export default {
}); });
}else{ }else{
//标识有值代表是店铺 //标识有值代表是店铺
ServeGetStoreSetting().then(async ({ code, result }) => { return ServeGetStoreSetting().then(async ({ code, result }) => {
if (result) { if (result) {
store.commit("UPDATE_USER_INFO", { store.commit("UPDATE_USER_INFO", {
id: result.id, id: result.id,
@@ -56,7 +58,9 @@ export default {
name: result.storeName, name: result.storeName,
}); });
//获取店铺聊天列表 //获取店铺聊天列表
await this.loadStoreChatList() if (typeof this.loadStoreChatList === "function") {
await this.loadStoreChatList()
}
}else if (code === 200 && !result) { }else if (code === 200 && !result) {
setTimeout(() => { setTimeout(() => {
this.loadUserSetting(); this.loadUserSetting();
@@ -91,8 +95,8 @@ export default {
//获取商家聊天记录 //获取商家聊天记录
loadStoreChatList() { loadStoreChatList() {
this.loadStatus = this.talkNum == 0 ? 0 : 1; this.loadStatus = this.talkNum == 0 ? 0 : 1;
ServeGetStoreTalkList().then(({ code, result }) => { return ServeGetStoreTalkList().then(({ code, result }) => {
if (code !== 200) return false; if (code !== 200 || !Array.isArray(result)) return false;
this.$store.commit("SET_UNREAD_NUM", 0); this.$store.commit("SET_UNREAD_NUM", 0);
this.$store.commit("SET_TALK_ITEMS", { this.$store.commit("SET_TALK_ITEMS", {
items: result.map((item) => formatTalkItem(item)), items: result.map((item) => formatTalkItem(item)),
@@ -101,7 +105,6 @@ export default {
// 判断 // 判断
if (this.$route.query.id) { if (this.$route.query.id) {
let takeData, takeIndex; let takeData, takeIndex;
console.log(result)
result.forEach((take, index) => { result.forEach((take, index) => {
if (take.id == this.$route.query.id) { if (take.id == this.$route.query.id) {
takeData = take; takeData = take;

View File

@@ -10,6 +10,9 @@ const USER_SETTING = 'LILI-SETTING'
* @param {String} token * @param {String} token
*/ */
export function setToken (token) { export function setToken (token) {
if (token == null || token === '' || token === 'undefined' || token === 'null') {
return
}
return localStorage.setItem( return localStorage.setItem(
USER_TOKEN, USER_TOKEN,
token token

19
im/src/utils/im-mode.js Normal file
View File

@@ -0,0 +1,19 @@
/**
* IM 身份判断(与 main-mixin.loadUserSetting 一致)
* - 买家从商城「联系客服」进入URL 带 ?id=店铺ID
* - 商家从商家后台进入URL 无 id
*/
export function isBuyerImMode(route) {
return !!route?.query?.id;
}
export function isStoreImMode(route) {
return !isBuyerImMode(route);
}
export function syncImTokenFromRoute(route, setTokenFn) {
const token = route?.query?.token;
if (token) {
setTokenFn(token);
}
}

View File

@@ -28,6 +28,9 @@ const errorHandler = (error) => {
removeAll(); removeAll();
location.reload(); location.reload();
} else if (error.response.status == 403) { } else if (error.response.status == 403) {
if (error.config?.skipAuthDialog) {
return Promise.reject(error);
}
if(!isRefreshing){ if(!isRefreshing){
/** /**
@@ -80,8 +83,8 @@ request.interceptors.request.use((config) => {
if (token) { if (token) {
config.headers["accessToken"] = `${token}`; config.headers["accessToken"] = `${token}`;
return config;
} }
return config;
}, errorHandler); }, errorHandler);
// 响应拦截器 // 响应拦截器

View File

@@ -46,6 +46,8 @@ export function formatTalkItem (params) {
}; };
Object.assign(options, params); Object.assign(options, params);
options.talk_type = options.talk_type || 1;
options.receiver_id = options.receiver_id || options.userId;
options.index_name = `${options.talk_type}_${options.receiver_id}`; options.index_name = `${options.talk_type}_${options.receiver_id}`;
return options; return options;

View File

@@ -48,9 +48,9 @@
</el-header> </el-header>
<!-- 对话列表栏 --> <!-- 对话列表栏 -->
<el-scrollbar tag="section" ref="menusScrollbar" class="full-height" :native="false"> <el-scrollbar tag="section" ref="menusScrollbar" class="full-height" :native="false" @scroll="onMenusScroll">
<el-main class="main"> <el-main class="main">
<p v-show="loadStatus === 0" class="empty-data"> <p v-show="loadStatus === 0 && userTalkItem.length === 0" class="empty-data">
<legacy-el-icon name="el-icon-loading" /> 数据加载中... <legacy-el-icon name="el-icon-loading" /> 数据加载中...
</p> </p>
@@ -168,6 +168,7 @@ import { ServeDeleteContact, ServeEditContactRemark } from "@/api/contacts";
import { beautifyTime } from "@/utils/functions"; import { beautifyTime } from "@/utils/functions";
import { formatTalkItem, findTalkIndex, getCacheIndexName } from "@/utils/talk"; import { formatTalkItem, findTalkIndex, getCacheIndexName } from "@/utils/talk";
import { setToken } from "@/utils/auth"; import { setToken } from "@/utils/auth";
import { syncImTokenFromRoute } from "@/utils/im-mode";
const title = document.title; const title = document.title;
@@ -286,6 +287,7 @@ export default {
}, },
beforeRouteUpdate (to, from, next) { beforeRouteUpdate (to, from, next) {
syncImTokenFromRoute(to, setToken);
let index_name = getCacheIndexName(); let index_name = getCacheIndexName();
if (index_name) this.clickTab(index_name); if (index_name) this.clickTab(index_name);
// 更新商品参数 // 更新商品参数
@@ -293,7 +295,7 @@ export default {
next(); next();
}, },
beforeCreate () { beforeCreate () {
setToken(this.$route.query.token); syncImTokenFromRoute(this.$route, setToken);
}, },
async created () { async created () {
await this.initialize(); await this.initialize();
@@ -308,9 +310,6 @@ export default {
}, },
mounted () {
this.scrollEvent();
},
beforeUnmount () { beforeUnmount () {
document.title = title; document.title = title;
clearInterval(this.interval); clearInterval(this.interval);
@@ -368,40 +367,34 @@ export default {
} }
}, },
// 监听自定义滚动条事件 // 左侧会话列表滚动时,控制置顶栏阴影
scrollEvent () { onMenusScroll ({ scrollTop }) {
let scrollbarEl = this.$refs.menusScrollbar.wrap; this.subHeaderShadow = scrollTop > 0;
scrollbarEl.onscroll = () => {
this.subHeaderShadow = scrollbarEl.scrollTop > 0;
};
}, },
// 获取用户对话列表 // 获取用户对话列表
loadChatList () { loadChatList () {
this.loadStatus = this.talkNum == 0 ? 0 : 1; this.loadStatus = this.talkNum == 0 ? 0 : 1;
ServeGetTalkList() return ServeGetTalkList()
.then(({ code, result }) => { .then(({ code, result }) => {
if (code !== 200) return false; if (code !== 200 || !Array.isArray(result)) return false;
this.$store.commit("SET_UNREAD_NUM", 0); this.$store.commit("SET_UNREAD_NUM", 0);
this.$store.commit("SET_TALK_ITEMS", { this.$store.commit("SET_TALK_ITEMS", {
items: result.map((item) => formatTalkItem(item)), items: result.map((item) => formatTalkItem(item)),
}); });
// 判断
if (this.$route.query.id) { if (this.$route.query.id) {
let takeData, takeIndex; const targetId = this.$route.query.id;
console.log("用户result", result) const takeIndex = this.talkItems.findIndex(
this.talkItems.forEach((take, index) => { (take) => take.userId == targetId
if (take.userId == this.$route.query.id) {
takeData = take;
takeIndex = index;
}
});
this.$nextTick(() =>
this.clickTab(this.$route.query.id, takeData, takeIndex)
); );
const takeData = takeIndex >= 0 ? this.talkItems[takeIndex] : null;
if (takeData) {
this.clickTab(targetId, takeData, takeIndex);
}
} }
}) })
.catch(() => {})
.finally(() => { .finally(() => {
this.loadStatus = 1; this.loadStatus = 1;
}); });
@@ -414,18 +407,21 @@ export default {
let item = let item =
this.talks.find((item) => { this.talks.find((item) => {
return item.userId == id; return item.userId == id;
}) || {}; }) || val || {};
// 点击当前栏目存储当前用户的信息 // 点击当前栏目存储当前用户的信息
this.$store.state.user.toUser = val; this.$store.state.user.toUser = val || item;
let nickname = item.name; let nickname = item.name;
const talkId = item.id || val?.id;
if (!talkId) return;
this.params = { this.params = {
talk_type: 1, talk_type: 1,
receiver_id: item.userId, receiver_id: item.userId || id,
nickname, nickname,
is_robot: item.is_robot, is_robot: item.is_robot,
talkId: item.id, //聊天对话的id talkId,
clickFlag: true clickFlag: true
}; };