Merge branch 'fix/im-vue3-migration'

This commit is contained in:
田香琪
2026-07-22 18:10:04 +08:00
55 changed files with 672 additions and 378 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,29 +15,53 @@ 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")) {
// 获取访问Token this.promptLogin();
let accessToken = Storage.getItem("accessToken"); return;
await this.getIMDetailMethods();
const userInfo = await getMemberMsg();
if (userInfo.success) {
//携带商品Id,在IM可以发送商品信息
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 { try {
Message.error("请登录后再联系客服"); await this.getIMDetailMethods();
const userInfo = await getMemberMsg();
if (!userInfo.success) {
this.promptLogin();
return; return;
} }
const accessToken = Storage.getItem("accessToken");
const storeId = id || this.storeMsg?.storeId;
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信息
async getIMDetailMethods() { async getIMDetailMethods() {

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

@@ -0,0 +1,81 @@
const fs = require("fs");
const path = require("path");
const root = path.join(__dirname, "../src");
const pairs = [
[/<i class="el-icon-close"/g, '<legacy-el-icon name="el-icon-close"'],
[/<i class="close-btn el-icon-close"/g, '<legacy-el-icon name="el-icon-close" class="close-btn"'],
[/<i class="el-icon-loading"/g, '<legacy-el-icon name="el-icon-loading"'],
[/<i class="el-icon-bottom"/g, '<legacy-el-icon name="el-icon-bottom"'],
[/<i class="el-icon-chat-dot-round"/g, '<legacy-el-icon name="el-icon-chat-dot-round"'],
[/<i class="el-icon-search"/g, '<legacy-el-icon name="el-icon-search"'],
[/<i class="el-icon-top"/g, '<legacy-el-icon name="el-icon-top"'],
[/<i class="el-icon-arrow-down"/g, '<legacy-el-icon name="el-icon-arrow-down"'],
[/<i class="el-icon-time"/g, '<legacy-el-icon name="el-icon-time"'],
[/<i class="el-icon-setting"/g, '<legacy-el-icon name="el-icon-setting"'],
[/<i class="el-icon-circle-close"/g, '<legacy-el-icon name="el-icon-circle-close"'],
[/<i class="el-icon-position"/g, '<legacy-el-icon name="el-icon-position"'],
[/<i class="el-icon-delete"/g, '<legacy-el-icon name="el-icon-delete"'],
[/<i class="el-icon-picture"/g, '<legacy-el-icon name="el-icon-picture"'],
[/<i class="el-icon-caret-left"/g, '<legacy-el-icon name="el-icon-caret-left"'],
[/<i class="el-icon-caret-right"/g, '<legacy-el-icon name="el-icon-caret-right"'],
[/<i class="el-icon-plus"><\/i>/g, '<legacy-el-icon name="el-icon-plus" />'],
[/<i class="el-icon-headset"/g, '<legacy-el-icon name="el-icon-headset"'],
[/<i class="el-icon-picture-outline-round"/g, '<legacy-el-icon name="el-icon-picture-outline-round"'],
[/<i class="el-icon-folder"/g, '<legacy-el-icon name="el-icon-folder"'],
[/<i class="el-icon-folder-opened"/g, '<legacy-el-icon name="el-icon-folder-opened"'],
[/<i class="el-icon-s-data"/g, '<legacy-el-icon name="el-icon-s-data"'],
[/<i class="el-icon-chat-line-round"/g, '<legacy-el-icon name="el-icon-chat-line-round"'],
[/<i class="el-icon-video-pause"/g, '<legacy-el-icon name="el-icon-video-pause"'],
[/<i class="el-icon-video-play"/g, '<legacy-el-icon name="el-icon-video-play"'],
[/<i class="el-icon-service"/g, '<legacy-el-icon name="el-icon-service"'],
[/<p class="tools"><i class="el-icon-close"/g, '<p class="tools"><legacy-el-icon name="el-icon-close"'],
[/<i class="el-icon-close close-btn"/g, '<legacy-el-icon name="el-icon-close" class="close-btn"'],
[/<i class="el-icon-plus" \/> 加好友/g, '<legacy-el-icon name="el-icon-plus" /> 加好友'],
[/<i class="el-icon-plus"><\/i> 添加选项/g, '<legacy-el-icon name="el-icon-plus" /> 添加选项'],
[
/<i @click="againSendMessage\(item\)" v-if="item.webSocketStatus" class="el-icon-refresh-left again main-color"><\/i>/g,
'<legacy-el-icon name="el-icon-refresh-left" class="again main-color" @click="againSendMessage(item)" v-if="item.webSocketStatus" />',
],
[
/<i class="el-icon-success" :class="\{ selected: verifyMultiSelect\(item.id\) \}"\s*@click="triggerMultiSelect\(item.id\)" \/>/g,
'<legacy-el-icon name="el-icon-success" :class="{ selected: verifyMultiSelect(item.id) }" @click="triggerMultiSelect(item.id)" />',
],
[/icon="el-icon-microphone"/g, ":icon=\"$legacyIcon('el-icon-microphone')\""],
[/icon="el-icon-video-pause"/g, ":icon=\"$legacyIcon('el-icon-video-pause')\""],
[/icon="el-icon-video-play"/g, ":icon=\"$legacyIcon('el-icon-video-play')\""],
[/icon="el-icon-upload"/g, ":icon=\"$legacyIcon('el-icon-upload')\""],
[/icon="el-icon-refresh"/g, ":icon=\"$legacyIcon('el-icon-refresh')\""],
[/icon="el-icon-refresh-left"/g, ":icon=\"$legacyIcon('el-icon-refresh-left')\""],
[/icon="el-icon-refresh-right"/g, ":icon=\"$legacyIcon('el-icon-refresh-right')\""],
[/prefix-icon="el-icon-search"/g, ":prefix-icon=\"$legacyIcon('el-icon-search')\""],
[/size="mini"/g, 'size="small"'],
[/size='mini'/g, "size='small'"],
[/size="medium"/g, 'size="default"'],
];
function walk(dir, files = []) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) walk(full, files);
else if (full.endsWith(".vue")) files.push(full);
}
return files;
}
let changed = 0;
for (const file of walk(root)) {
let content = fs.readFileSync(file, "utf8");
let next = content;
for (const [pattern, replacement] of pairs) {
next = next.replace(pattern, replacement);
}
if (next !== content) {
fs.writeFileSync(file, next);
console.log("updated:", path.relative(root, file));
changed++;
}
}
console.log("files changed:", changed);

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
);
}; };

5
im/src/assets/images.js Normal file
View File

@@ -0,0 +1,5 @@
import defaultAvatar from "@/assets/image/detault-avatar.jpg";
import defaultUserBanner from "@/assets/image/default-user-banner.png";
import noOncallImage from "@/assets/image/no-oncall.6b776fcf.png";
export { defaultAvatar, defaultUserBanner, noOncallImage };

View File

@@ -5,11 +5,11 @@
<el-header class="header no-padding" height="50px"> <el-header class="header no-padding" height="50px">
<div class="tools"> <div class="tools">
<span>选择编程语言:&nbsp;&nbsp;</span> <span>选择编程语言:&nbsp;&nbsp;</span>
<el-select v-model="language" size="mini" filterable placeholder="语言类型" :disabled="!editMode"> <el-select v-model="language" size="small" filterable placeholder="语言类型" :disabled="!editMode">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </div>
<i class="el-icon-close close-btn" @click="close" /> <legacy-el-icon name="el-icon-close" class="close-btn" @click="close" />
<i class="iconfont icon-full-screen" :class="{ <i class="iconfont icon-full-screen" :class="{
'icon-tuichuquanping': isFullScreen, 'icon-tuichuquanping': isFullScreen,
'icon-quanping ': !isFullScreen, 'icon-quanping ': !isFullScreen,

View File

@@ -4,7 +4,7 @@
<el-header class="no-padding header" height="60px"> <el-header class="no-padding header" height="60px">
<p>会话记录 ({{ records.length }})</p> <p>会话记录 ({{ records.length }})</p>
<p class="tools"> <p class="tools">
<i class="el-icon-close" @click="close" /> <legacy-el-icon name="el-icon-close" @click="close" />
</p> </p>
</el-header> </el-header>
<el-main class="no-padding main" v-loading="loading"> <el-main class="no-padding main" v-loading="loading">

View File

@@ -13,7 +13,7 @@
:class="fullscreen ? 'icon-tuichuquanping' : 'icon-quanping'" :class="fullscreen ? 'icon-tuichuquanping' : 'icon-quanping'"
@click="fullscreen = !fullscreen" @click="fullscreen = !fullscreen"
/> />
<i class="el-icon-close" @click="$emit('close')" /> <legacy-el-icon name="el-icon-close" @click="$emit('close')" />
</p> </p>
</el-header> </el-header>
@@ -24,7 +24,7 @@
@click="triggerBroadside" @click="triggerBroadside"
/> />
<div class="search-box no-select"> <div class="search-box no-select">
<i class="el-icon-search" /> <legacy-el-icon name="el-icon-search" />
<input <input
v-model="search.keyword" v-model="search.keyword"
type="text" type="text"
@@ -196,11 +196,11 @@
<!-- 数据加载栏 --> <!-- 数据加载栏 -->
<div v-show="records.loadStatus == 1" class="load-button blue"> <div v-show="records.loadStatus == 1" class="load-button blue">
<i class="el-icon-loading" /> <legacy-el-icon name="el-icon-loading" />
<span>加载数据中...</span> <span>加载数据中...</span>
</div> </div>
<div v-show="records.loadStatus == 0" class="load-button"> <div v-show="records.loadStatus == 0" class="load-button">
<i class="el-icon-arrow-down" /> <legacy-el-icon name="el-icon-arrow-down" />
<span @click="loadChatRecord">加载更多...</span> <span @click="loadChatRecord">加载更多...</span>
</div> </div>
</el-scrollbar> </el-scrollbar>

View File

@@ -2,9 +2,9 @@
<div class="audio-message"> <div class="audio-message">
<div class="videodisc"> <div class="videodisc">
<div class="disc" :class="{ play: isPlay }" @click="toPlay"> <div class="disc" :class="{ play: isPlay }" @click="toPlay">
<i v-if="loading" class="el-icon-loading" /> <legacy-el-icon v-if="loading" name="el-icon-loading" />
<i v-else-if="isPlay" class="el-icon-video-pause" /> <legacy-el-icon v-else-if="isPlay" name="el-icon-video-pause" />
<i v-else class="el-icon-video-play" /> <legacy-el-icon v-else name="el-icon-video-play" />
<audio <audio
ref="audio" ref="audio"
type="audio/mp3" type="audio/mp3"
@@ -17,7 +17,7 @@
</div> </div>
<div class="detail"> <div class="detail">
<div class="text"> <div class="text">
<i class="el-icon-service" /> <legacy-el-icon name="el-icon-service" />
<span>{{ getCurrDuration }} / {{ getTotalDuration }}</span> <span>{{ getCurrDuration }} / {{ getTotalDuration }}</span>
</div> </div>
<div class="process"> <div class="process">

View File

@@ -7,10 +7,14 @@
'full-screen': fullscreen, 'full-screen': fullscreen,
}" }"
> >
<legacy-el-icon
v-if="fullscreen"
name="el-icon-close"
@click="fullscreen = !fullscreen"
/>
<i <i
:class=" v-else
fullscreen ? 'el-icon-close' : 'iconfont icon-tubiao_chakangongyi' class="iconfont icon-tubiao_chakangongyi"
"
@click="fullscreen = !fullscreen" @click="fullscreen = !fullscreen"
/> />
<pre class="lum-scrollbar" v-html="formatCode(code, lang)" /> <pre class="lum-scrollbar" v-html="formatCode(code, lang)" />

View File

@@ -9,7 +9,7 @@
</div> </div>
<div class="tools flex-center"> <div class="tools flex-center">
<span class="flex-center pointer"> <span class="flex-center pointer">
<i class="el-icon-plus" /> 加好友 <legacy-el-icon name="el-icon-plus" /> 加好友
</span> </span>
</div> </div>
</div> </div>

View File

@@ -5,16 +5,13 @@
<div class="vheader"> <div class="vheader">
<p> <p>
{{ answer_mode == 1 ? "[多选投票]" : "[单选投票]" }} {{ answer_mode == 1 ? "[多选投票]" : "[单选投票]" }}
<i <legacy-el-icon
v-show="is_vote" v-show="is_vote"
class="pointer" class="pointer"
:class="{ :name="refresh ? 'el-icon-loading' : 'el-icon-refresh'"
'el-icon-loading': refresh,
'el-icon-refresh': !refresh,
}"
title="刷新投票结果" title="刷新投票结果"
@click="loadRefresh" @click="loadRefresh"
></i> />
</p> </p>
<p>{{ title }}</p> <p>{{ title }}</p>
</div> </div>

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.getMemberDetail()
// }
this.getFootPrint()
if (this.goodsParams && this.toUser.storeFlag == true) {
this.getGoodsDetail()
} }
this.getFootPrint();
if (this.goodsParams && this.toUser.storeFlag) {
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: {
syncStoreFlagCache() {
localStorage.setItem(
"storeFlag",
this.isBuyerImMode ? "true" : "false"
);
},
resetSidePanelData() {
this.footPrintList = [];
this.orderPrintList = [];
this.footPrintParams.pageNumber = 1;
},
getStoreDetail() { getStoreDetail() {
ServeGetStoreDetail(this.toUser.userId).then(res => { ServeGetStoreDetail(this.toUser.userId, SIDE_REQUEST_OPTIONS)
.then((res) => {
if (res.success) { if (res.success) {
this.storeInfo = res.result this.storeInfo = res.result;
} }
}) })
.catch(() => {});
}, },
loadMoreFootPrint (e) { loadMoreFootPrint() {
//触底再次调接口 this.footPrintParams.pageNumber++;
this.footPrintParams.pageNumber++ this.getFootPrint();
this.getFootPrint()
}, },
handleClick() {}, handleClick() {},
// getMemberDetail () {
// ServeGetUserDetail(this.toUser.userId).then(res => {
// if (res.success) {
// this.memberInfo = res.result
// }
// })
// },
getGoodsDetail() { 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;
this.fetchBuyerSideData();
} else { } else {
item.btnHide = 1 this.footPrintParams.memberId = this.toUser.userId;
} this.footPrintParams.storeId = this.id;
if (item.goodsId === this.goodsParams.goodsId) { this.fetchStoreSideData();
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 {
this.footPrintParams.memberId = this.toUser.userId
this.footPrintParams.storeId = this.id
ServeStoreGetFootPrint(this.footPrintParams).then(res => {
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)
.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) { 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,11 +248,10 @@ 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) {
@@ -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

@@ -23,7 +23,7 @@
<div class="module right-module" > <div class="module right-module" >
<el-tooltip content="历史消息" placement="top"> <el-tooltip content="历史消息" placement="top">
<p v-show="params.is_robot == 0"> <p v-show="params.is_robot == 0">
<i class="el-icon-time" @click="triggerEvent('history')" /> <legacy-el-icon name="el-icon-time" @click="triggerEvent('history')" />
</p> </p>
</el-tooltip> </el-tooltip>
<el-tooltip content="群公告" placement="top"> <el-tooltip content="群公告" placement="top">
@@ -33,7 +33,7 @@
</el-tooltip> </el-tooltip>
<el-tooltip content="群设置" placement="top"> <el-tooltip content="群设置" placement="top">
<p v-show="params.talk_type == 2"> <p v-show="params.talk_type == 2">
<i class="el-icon-setting" @click="triggerEvent('setting')" /> <legacy-el-icon name="el-icon-setting" @click="triggerEvent('setting')" />
</p> </p>
</el-tooltip> </el-tooltip>
</div> </div>

View File

@@ -9,25 +9,25 @@
class="multi-icon pointer" class="multi-icon pointer"
@click="$emit('event', 'merge_forward')" @click="$emit('event', 'merge_forward')"
> >
<i class="el-icon-position" /> <legacy-el-icon name="el-icon-position" />
</div> </div>
<p>合并转发</p> <p>合并转发</p>
</div> </div>
<div class="btn-group"> <div class="btn-group">
<div class="multi-icon pointer" @click="$emit('event', 'forward')"> <div class="multi-icon pointer" @click="$emit('event', 'forward')">
<i class="el-icon-position" /> <legacy-el-icon name="el-icon-position" />
</div> </div>
<p>逐条转发</p> <p>逐条转发</p>
</div> </div>
<div class="btn-group"> <div class="btn-group">
<div class="multi-icon pointer" @click="$emit('event', 'delete')"> <div class="multi-icon pointer" @click="$emit('event', 'delete')">
<i class="el-icon-delete" /> <legacy-el-icon name="el-icon-delete" />
</div> </div>
<p>批量删除</p> <p>批量删除</p>
</div> </div>
<div class="btn-group"> <div class="btn-group">
<div class="multi-icon pointer" @click="$emit('event', 'close')"> <div class="multi-icon pointer" @click="$emit('event', 'close')">
<i class="el-icon-close" /> <legacy-el-icon name="el-icon-close" />
</div> </div>
<p>关闭</p> <p>关闭</p>
</div> </div>

View File

@@ -9,10 +9,10 @@
<!-- 数据加载状态栏 --> <!-- 数据加载状态栏 -->
<div class="loading-toolbar"> <div class="loading-toolbar">
<span v-if="loadRecord.status == 0" class="color-blue"> <span v-if="loadRecord.status == 0" class="color-blue">
<i class="el-icon-loading" /> 正在加载数据中... <legacy-el-icon name="el-icon-loading" /> 正在加载数据中...
</span> </span>
<span v-if="loadRecord.status == 1" class="pointer color-blue" @click="loadChatRecords"> <span v-if="loadRecord.status == 1" class="pointer color-blue" @click="loadChatRecords">
<i class="el-icon-bottom" /> 查看更多消息... <legacy-el-icon name="el-icon-bottom" /> 查看更多消息...
</span> </span>
<span v-if="loadRecord.status == 2"> 没有更多消息了... </span> <span v-if="loadRecord.status == 2"> 没有更多消息了... </span>
</div> </div>
@@ -39,8 +39,7 @@
'checkbox-border': multiSelect.isOpen === true, 'checkbox-border': multiSelect.isOpen === true,
}"> }">
<aside v-show="multiSelect.isOpen" class="checkbox-column"> <aside v-show="multiSelect.isOpen" class="checkbox-column">
<i class="el-icon-success" :class="{ selected: verifyMultiSelect(item.id) }" <legacy-el-icon name="el-icon-success" :class="{ selected: verifyMultiSelect(item.id) }" @click="triggerMultiSelect(item.id)" />
@click="triggerMultiSelect(item.id)" />
</aside> </aside>
<aside class="avatar-column"> <aside class="avatar-column">
<div class="avatar-box" v-if="item.float == 'right'"> <div class="avatar-box" v-if="item.float == 'right'">
@@ -59,7 +58,7 @@
{{ unixToDate(item.createTime, "MM月dd日 hh:mm") }} {{ unixToDate(item.createTime, "MM月dd日 hh:mm") }}
</span> </span>
<div class="flex flex-a-c"> <div class="flex flex-a-c">
<i @click="againSendMessage(item)" v-if="item.webSocketStatus" class="el-icon-refresh-left again main-color"></i> <legacy-el-icon name="el-icon-refresh-left" class="again main-color" @click="againSendMessage(item)" v-if="item.webSocketStatus" />
<!-- 文本消息 --> <!-- 文本消息 -->
<div v-if="item.messageType == 'MESSAGE'" style="background-color: #d0e9ff;color: black;" <div v-if="item.messageType == 'MESSAGE'" style="background-color: #d0e9ff;color: black;"
class="text-message" :class="{ class="text-message" :class="{
@@ -122,7 +121,7 @@
</span> </span>
<div class="order-status"> <div class="order-status">
<el-tag <el-tag
size="mini" size="small"
:type="item.text.orderStatus == 'CANCELLED' || item.text.orderStatus == 'UNPAID' || item.text.orderStatus == ' TAKE' ? 'info' : 'danger'">{{ :type="item.text.orderStatus == 'CANCELLED' || item.text.orderStatus == 'UNPAID' || item.text.orderStatus == ' TAKE' ? 'info' : 'danger'">{{
item.text.orderStatus == 'CANCELLED' ? '已取消' : item.text.orderStatus == 'UNPAID' ? '未付款' : item.text.orderStatus == 'CANCELLED' ? '已取消' : item.text.orderStatus == 'UNPAID' ? '未付款' :
item.text.orderStatus == item.text.orderStatus ==
@@ -156,7 +155,7 @@
<!-- 新消息气泡 --> <!-- 新消息气泡 -->
<div v-show="tipsBoard && unreadMessage.num" class="talk-bubble pointer no-select" <div v-show="tipsBoard && unreadMessage.num" class="talk-bubble pointer no-select"
@click="talkPanelScrollBottom"> @click="talkPanelScrollBottom">
<i class="el-icon-chat-dot-round" /> <legacy-el-icon name="el-icon-chat-dot-round" />
<span>新消息({{ unreadMessage.num }})</span> <span>新消息({{ unreadMessage.num }})</span>
<span> <span>
&nbsp;#{{ unreadMessage.nickname }}# &nbsp;#{{ unreadMessage.nickname }}#
@@ -285,6 +284,9 @@ export default {
// 置底按钮是否显示 // 置底按钮是否显示
tipsBoard: false, tipsBoard: false,
// 防止并发请求导致 loading 状态错乱
recordsRequestId: 0,
}; };
}, },
@@ -302,21 +304,14 @@ export default {
}), }),
}, },
watch: { watch: {
// 监听面板传递参数 // 监听面板传递参数(含首次挂载)
params () { params: {
this.loadRecord.minRecord = 0; handler () {
this.tipsBoard = false; this.resetRecordState();
this.multiSelect = {
isOpen: false,
items: [],
mode: 0,
};
this.loadChatRecords(); this.loadChatRecords();
}, },
immediate: true,
}, },
mounted () {
this.loadChatRecords();
}, },
methods: { methods: {
parseTime, parseTime,
@@ -497,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";
@@ -525,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

@@ -4,7 +4,7 @@
<el-tabs v-model="activeName" @tab-click="handleClick" :stretch=true> <el-tabs v-model="activeName" @tab-click="handleClick" :stretch=true>
<el-tab-pane label="最近浏览" name="goods"> <el-tab-pane label="最近浏览" name="goods">
<dl v-if='list.length' class='base-list'> <dl v-if='list.length' class='base-list'>
<dd :key="index" @click="linkToGoods(item.goodsId, item.id)" v-for="(item,index) in list" v-infinite-scroll="loadMore"> <dd :key="index" @click="linkToGoods(item.goodsId, item.id)" v-for="(item,index) in list">
<div class="base"> <div class="base">
<div> <div>
<img style="width: 60px; height: 60px;margin-left:20px;box-sizing: border-box;" :src="item.thumbnail" <img style="width: 60px; height: 60px;margin-left:20px;box-sizing: border-box;" :src="item.thumbnail"
@@ -21,7 +21,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="review"> <el-button v-if="item.btnHide == 1 && toUser.storeFlag" size="mini" <div class="review"> <el-button v-if="item.btnHide == 1 && toUser.storeFlag" size="small"
@click.stop="submitSendGoodsMessage(item)" plain>发送</el-button></div> @click.stop="submitSendGoodsMessage(item)" plain>发送</el-button></div>
</div> </div>
</dd> </dd>
@@ -33,7 +33,7 @@
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="订单列表" name="orders"> <el-tab-pane label="订单列表" name="orders">
<dl class='base-order-list' v-if='orderList.length'> <dl class='base-order-list' v-if='orderList.length'>
<dd v-for="(item, index) in orderList" v-infinite-scroll="loadMore" :key="index"> <dd v-for="(item, index) in orderList" :key="index">
<div class="order-list"> <div class="order-list">
<div class="order-top order-padding"> <div class="order-top order-padding">
<span class="order-sn" @click="linkToOrders(item.sn)">订单号:{{ item.sn }}</span> <span class="order-sn" @click="linkToOrders(item.sn)">订单号:{{ item.sn }}</span>
@@ -48,12 +48,12 @@
<div class="order-btn "> <div class="order-btn ">
<el-button class="store-button" v-if="item.btnHide == 1 && toUser.storeFlag" <el-button class="store-button" v-if="item.btnHide == 1 && toUser.storeFlag"
size="mini" @click="submitSendOrderMessage(item, index)" plain>发送</el-button> size="small" @click="submitSendOrderMessage(item, index)" plain>发送</el-button>
</div> </div>
</div> </div>
<div class="order-footer order-padding"> <div class="order-footer order-padding">
<span></span> <span></span>
<el-tag size='mini' :type="col[item.orderStatus]">{{ <el-tag size="small" :type="col[item.orderStatus]">{{
item.orderStatus == 'STAY_PICKED_UP' ? '待自提' item.orderStatus == 'STAY_PICKED_UP' ? '待自提'
: item.orderStatus == 'CANCELLED' ? '已取消' : item.orderStatus == 'UNPAID' ? '未付款' : item.orderStatus : item.orderStatus == 'CANCELLED' ? '已取消' : item.orderStatus == 'UNPAID' ? '未付款' : item.orderStatus
== ==
@@ -108,12 +108,6 @@ export default {
toUser: (state) => state.user.toUser, toUser: (state) => state.user.toUser,
}), }),
}, },
components: {
"el-tag": Tag,
"el-button": button,
"el-tabs": Tabs,
"el-tab-pane": TabPane,
},
methods: { methods: {
//跳转订单列表 //跳转订单列表
@@ -179,11 +173,11 @@ export default {
props: { props: {
list: { list: {
type: Array, type: Array,
default: [], default: () => [],
}, },
orderList: { orderList: {
type: Array, type: Array,
default: [] default: () => [],
}, },
}, },
mounted () { mounted () {

View File

@@ -11,7 +11,7 @@
<span style="color: red;">{{ $filters.unitPrice(goodsDetail.price, '¥') }}</span> <span style="color: red;">{{ $filters.unitPrice(goodsDetail.price, '¥') }}</span>
</div> </div>
<div v-if="hide"> <div v-if="hide">
<el-button class="store-button" type="danger" v-if="btnHide == 1 && toUser.storeFlag" size="mini" <el-button class="store-button" type="danger" v-if="btnHide == 1 && toUser.storeFlag" size="small"
@click="submitSendMessage()" plain>发送</el-button> @click="submitSendMessage()" plain>发送</el-button>
</div> </div>
</div> </div>

View File

@@ -8,14 +8,14 @@
<div> <div>
<div class="div-zoom"> <div class="div-zoom">
<span class="title_left_name"> 店铺名称:</span> <span class="title_right_name">{{ storeInfo.storeName }}</span> <span class="title_left_name"> 店铺名称:</span> <span class="title_right_name">{{ storeInfo.storeName }}</span>
<el-tag style="margin-left: 10px;" type="danger" v-if="storeInfo.selfOperated" size="mini">自营</el-tag> <el-tag style="margin-left: 10px;" type="danger" v-if="storeInfo.selfOperated" size="small">自营</el-tag>
</div> </div>
<div> <div>
<span class="title_left_name"> 联系方式:</span> <span class="title_right_name">{{ storeInfo.memberName }}</span> <span class="title_left_name"> 联系方式:</span> <span class="title_right_name">{{ storeInfo.memberName }}</span>
</div> </div>
</div> </div>
<div> <div>
<el-button class="store-button" @click="linkToStore(storeInfo.id)" size="mini" <el-button class="store-button" @click="linkToStore(storeInfo.id)" size="small"
plain>进入店铺</el-button> plain>进入店铺</el-button>
</div> </div>
</div> </div>

View File

@@ -18,24 +18,24 @@
<p class="tip-title">代码片段</p> <p class="tip-title">代码片段</p>
</li> </li>
<li @click="recorder = true"> <li @click="recorder = true">
<i class="el-icon-headset" /> <legacy-el-icon name="el-icon-headset" />
<p class="tip-title">语音消息</p> <p class="tip-title">语音消息</p>
</li> --> </li> -->
<!-- #TODO 发图片功能暂时隐藏 此处会涉及到token过期 --> <!-- #TODO 发图片功能暂时隐藏 此处会涉及到token过期 -->
<!-- <li @click="$refs.restFile.click()"> <!-- <li @click="$refs.restFile.click()">
<i class="el-icon-picture-outline-round" /> <legacy-el-icon name="el-icon-picture-outline-round" />
<p class="tip-title">图片</p> <p class="tip-title">图片</p>
</li> --> </li> -->
<!-- <li @click="$refs.restFile2.click()"> <!-- <li @click="$refs.restFile2.click()">
<i class="el-icon-folder" /> <legacy-el-icon name="el-icon-folder" />
<p class="tip-title">附件</p> <p class="tip-title">附件</p>
</li> </li>
<li @click="filesManager.isShow = true"> <li @click="filesManager.isShow = true">
<i class="el-icon-folder-opened" /> <legacy-el-icon name="el-icon-folder-opened" />
<p class="tip-title">上传管理</p> <p class="tip-title">上传管理</p>
</li> </li>
<li v-show="isGroupTalk" @click="vote.isShow = true"> <li v-show="isGroupTalk" @click="vote.isShow = true">
<i class="el-icon-s-data" /> <legacy-el-icon name="el-icon-s-data" />
<p class="tip-title">发起投票</p> <p class="tip-title">发起投票</p>
</li> --> </li> -->
@@ -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

@@ -43,7 +43,7 @@
class="emoji-item custom-emoji" class="emoji-item custom-emoji"
@click="$refs.fileCustomEmoji.click()" @click="$refs.fileCustomEmoji.click()"
> >
<i class="el-icon-picture" /> <legacy-el-icon name="el-icon-picture" />
<span>自定义</span> <span>自定义</span>
</div> </div>
<div <div
@@ -64,7 +64,7 @@
class="toolbar-item prev-page" class="toolbar-item prev-page"
@click="turnPage(1)" @click="turnPage(1)"
> >
<i class="el-icon-caret-left" /> <legacy-el-icon name="el-icon-caret-left" />
</div> </div>
<div <div
v-for="(item, index) in showItems" v-for="(item, index) in showItems"
@@ -80,7 +80,7 @@
class="toolbar-item next-page" class="toolbar-item next-page"
@click="turnPage(2)" @click="turnPage(2)"
> >
<i class="el-icon-caret-right" /> <legacy-el-icon name="el-icon-caret-right" />
</div> </div>
</div> </div>
</el-footer> --> </el-footer> -->

View File

@@ -8,7 +8,7 @@
<p> <p>
上传管理 <span v-show="total">({{ successNum }}/{{ total }})</span> 上传管理 <span v-show="total">({{ successNum }}/{{ total }})</span>
</p> </p>
<i class="close-btn el-icon-close" @click="closeBox" /> <legacy-el-icon name="el-icon-close" class="close-btn" @click="closeBox" />
</el-header> </el-header>
<el-main class="no-padding mian lum-scrollbar"> <el-main class="no-padding mian lum-scrollbar">

View File

@@ -4,7 +4,7 @@
<el-header class="no-padding header" height="50px"> <el-header class="no-padding header" height="50px">
<p>发送图片</p> <p>发送图片</p>
<p class="tools"> <p class="tools">
<i class="el-icon-close" @click="closeBox" /> <legacy-el-icon name="el-icon-close" @click="closeBox" />
</p> </p>
</el-header> </el-header>
@@ -21,7 +21,7 @@
<el-button <el-button
class="btn" class="btn"
type="primary" type="primary"
size="medium" size="default"
:loading="loading" :loading="loading"
@click="uploadImage" @click="uploadImage"
>立即发送 >立即发送

View File

@@ -3,7 +3,7 @@
<el-container class="lum-dialog-box"> <el-container class="lum-dialog-box">
<el-header class="no-padding header no-select" height="50px"> <el-header class="no-padding header no-select" height="50px">
<p>语音消息</p> <p>语音消息</p>
<p class="tools"><i class="el-icon-close" @click="closeBox" /></p> <p class="tools"><legacy-el-icon name="el-icon-close" @click="closeBox" /></p>
</el-header> </el-header>
<el-main class="no-padding mian"> <el-main class="no-padding mian">
@@ -52,45 +52,45 @@
<el-button <el-button
v-show="recorderStatus == 0" v-show="recorderStatus == 0"
type="primary" type="primary"
size="mini" size="small"
round round
icon="el-icon-microphone" :icon="$legacyIcon('el-icon-microphone')"
@click="startRecorder" @click="startRecorder"
>开始录音 >开始录音
</el-button> </el-button>
<el-button <el-button
v-show="recorderStatus == 1" v-show="recorderStatus == 1"
type="primary" type="primary"
size="mini" size="small"
round round
icon="el-icon-video-pause" :icon="$legacyIcon('el-icon-video-pause')"
@click="pauseRecorder" @click="pauseRecorder"
>暂停录音 >暂停录音
</el-button> </el-button>
<el-button <el-button
v-show="recorderStatus == 2" v-show="recorderStatus == 2"
type="primary" type="primary"
size="mini" size="small"
round round
icon="el-icon-microphone" :icon="$legacyIcon('el-icon-microphone')"
@click="resumeRecorder" @click="resumeRecorder"
>继续录音 >继续录音
</el-button> </el-button>
<el-button <el-button
v-show="recorderStatus == 2" v-show="recorderStatus == 2"
type="primary" type="primary"
size="mini" size="small"
round round
icon="el-icon-microphone" :icon="$legacyIcon('el-icon-microphone')"
@click="stopRecorder" @click="stopRecorder"
>结束录音 >结束录音
</el-button> </el-button>
<el-button <el-button
v-show="recorderStatus == 3 || recorderStatus == 6" v-show="recorderStatus == 3 || recorderStatus == 6"
type="primary" type="primary"
size="mini" size="small"
round round
icon="el-icon-video-play" :icon="$legacyIcon('el-icon-video-play')"
@click="playRecorder" @click="playRecorder"
>播放录音 >播放录音
</el-button> </el-button>
@@ -100,9 +100,9 @@
recorderStatus == 3 || recorderStatus == 5 || recorderStatus == 6 recorderStatus == 3 || recorderStatus == 5 || recorderStatus == 6
" "
type="primary" type="primary"
size="mini" size="small"
round round
icon="el-icon-video-play" :icon="$legacyIcon('el-icon-video-play')"
@click="startRecorder" @click="startRecorder"
>重新录音 >重新录音
</el-button> </el-button>
@@ -110,18 +110,18 @@
<el-button <el-button
v-show="recorderStatus == 4" v-show="recorderStatus == 4"
type="primary" type="primary"
size="mini" size="small"
round round
icon="el-icon-video-pause" :icon="$legacyIcon('el-icon-video-pause')"
@click="pausePlayRecorder" @click="pausePlayRecorder"
>暂停播放 >暂停播放
</el-button> </el-button>
<el-button <el-button
v-show="recorderStatus == 5" v-show="recorderStatus == 5"
type="primary" type="primary"
size="mini" size="small"
round round
icon="el-icon-video-play" :icon="$legacyIcon('el-icon-video-play')"
@click="resumePlayRecorder" @click="resumePlayRecorder"
>继续播放 >继续播放
</el-button> </el-button>
@@ -131,7 +131,7 @@
recorderStatus == 3 || recorderStatus == 5 || recorderStatus == 6 recorderStatus == 3 || recorderStatus == 5 || recorderStatus == 6
" "
type="primary" type="primary"
size="mini" size="small"
round round
@click="submit" @click="submit"
>立即发送 >立即发送

View File

@@ -4,7 +4,7 @@
<el-header class="no-padding header" height="50px"> <el-header class="no-padding header" height="50px">
<p>系统表情</p> <p>系统表情</p>
<p class="tools"> <p class="tools">
<i class="el-icon-close" @click="closeBox" /> <legacy-el-icon name="el-icon-close" @click="closeBox" />
</p> </p>
</el-header> </el-header>
@@ -31,7 +31,7 @@
</el-main> </el-main>
<el-footer class="footer" height="50px"> <el-footer class="footer" height="50px">
<el-button type="primary" size="medium" class="btn" @click="closeBox"> <el-button type="primary" size="default" class="btn" @click="closeBox">
关闭窗口 关闭窗口
</el-button> </el-button>
</el-footer> </el-footer>

View File

@@ -4,7 +4,7 @@
<el-header class="header no-select" height="60px"> <el-header class="header no-select" height="60px">
<p>发起投票</p> <p>发起投票</p>
<p class="tools"> <p class="tools">
<i class="el-icon-close" @click="$emit('close')" /> <legacy-el-icon name="el-icon-close" @click="$emit('close')" />
</p> </p>
</el-header> </el-header>
<el-main class="main no-padding vote-from"> <el-main class="main no-padding vote-from">
@@ -18,7 +18,7 @@
<div class="vote-title">投票主题</div> <div class="vote-title">投票主题</div>
<div> <div>
<el-input <el-input
size="medium" size="default"
clear="vote-input" clear="vote-input"
v-model.trim="title" v-model.trim="title"
placeholder="请输入投票主题最多50字" placeholder="请输入投票主题最多50字"
@@ -31,7 +31,7 @@
<div class="vote-options" v-for="(option, index) in options"> <div class="vote-options" v-for="(option, index) in options">
<div class="lbox"> <div class="lbox">
<el-input <el-input
size="medium" size="default"
clear="vote-input" clear="vote-input"
v-model.trim="option.value" v-model.trim="option.value"
placeholder="请输入选项内容" placeholder="请输入选项内容"
@@ -46,12 +46,12 @@
</el-input> </el-input>
</div> </div>
<div class="rbox"> <div class="rbox">
<i class="el-icon-close" @click="removeOption(index)"></i> <legacy-el-icon name="el-icon-close" @click="removeOption(index)" />
</div> </div>
</div> </div>
<h6 class="pointer add-option" @click="addOption"> <h6 class="pointer add-option" @click="addOption">
<i class="el-icon-plus"></i> 添加选项 <legacy-el-icon name="el-icon-plus" /> 添加选项
</h6> </h6>
</div> </div>
</el-main> </el-main>

View File

@@ -8,6 +8,8 @@
</template> </template>
<script> <script>
import { noOncallImage } from "@/assets/images";
export default { export default {
name: 'Empty', name: 'Empty',
props: { props: {
@@ -17,7 +19,7 @@ export default {
}, },
src: { src: {
type: String, type: String,
default: require('@/assets/image/no-oncall.6b776fcf.png'), default: noOncallImage,
}, },
}, },
data() { data() {

View File

@@ -0,0 +1,25 @@
<template>
<el-icon v-bind="$attrs">
<component :is="iconComponent" v-if="iconComponent" />
</el-icon>
</template>
<script>
import { resolveLegacyIcon } from "@/core/legacy-icon-map";
export default {
name: "LegacyElIcon",
inheritAttrs: false,
props: {
name: {
type: String,
default: "",
},
},
computed: {
iconComponent() {
return resolveLegacyIcon(this.name);
},
},
};
</script>

View File

@@ -2,7 +2,7 @@
<div> <div>
<div class="abs-module" v-show="isShow"> <div class="abs-module" v-show="isShow">
<div class="abs-box"> <div class="abs-box">
<i class="el-icon-circle-close" @click="close" /> <legacy-el-icon name="el-icon-circle-close" @click="close" />
<a href="https://www.aliyun.com/minisite/goods?userCode=kqyyppx2"> <a href="https://www.aliyun.com/minisite/goods?userCode=kqyyppx2">
<img src="~@/assets/image/aliyun-abs.jpg" width="300" /> <img src="~@/assets/image/aliyun-abs.jpg" width="300" />
</a> </a>

View File

@@ -4,7 +4,7 @@
<el-header class="header" height="50px"> <el-header class="header" height="50px">
<p>选择头像</p> <p>选择头像</p>
<p class="tools"> <p class="tools">
<i class="el-icon-close" @click="$emit('close', 0)" /> <legacy-el-icon name="el-icon-close" @click="$emit('close', 0)" />
</p> </p>
</el-header> </el-header>
<el-main class="main"> <el-main class="main">
@@ -45,28 +45,28 @@
<el-button <el-button
size="small" size="small"
plain plain
icon="el-icon-upload" :icon="$legacyIcon('el-icon-upload')"
@click="clickUpload" @click="clickUpload"
>上传图片 >上传图片
</el-button> </el-button>
<el-button <el-button
size="small" size="small"
plain plain
icon="el-icon-refresh" :icon="$legacyIcon('el-icon-refresh')"
@click="refreshCrop" @click="refreshCrop"
>刷新 >刷新
</el-button> </el-button>
<el-button <el-button
size="small" size="small"
plain plain
icon="el-icon-refresh-left" :icon="$legacyIcon('el-icon-refresh-left')"
@click="rotateLeft" @click="rotateLeft"
>左转 >左转
</el-button> </el-button>
<el-button <el-button
size="small" size="small"
plain plain
icon="el-icon-refresh-right" :icon="$legacyIcon('el-icon-refresh-right')"
@click="rotateRight" @click="rotateRight"
>右转 >右转
</el-button> </el-button>

View File

@@ -3,7 +3,7 @@
<div class="reward" v-show="isShow"> <div class="reward" v-show="isShow">
<div class="title"> <div class="title">
<span>Donate</span> <span>Donate</span>
<i class="el-icon-circle-close" @click="close" /> <legacy-el-icon name="el-icon-circle-close" @click="close" />
</div> </div>
<div class="main"> <div class="main">
<div class="pay-box"> <div class="pay-box">

View File

@@ -2,7 +2,7 @@
<!-- 新消息提示组件 --> <!-- 新消息提示组件 -->
<div class="notify-box"> <div class="notify-box">
<div class="lbox"> <div class="lbox">
<el-avatar size="medium" :src="avatar" /> <el-avatar size="default" :src="avatar" />
</div> </div>
<div class="rbox"> <div class="rbox">
<div class="xheader"> <div class="xheader">

View File

@@ -2,14 +2,14 @@
<!-- 新消息提示组件 --> <!-- 新消息提示组件 -->
<div class="notify-box pointer"> <div class="notify-box pointer">
<div class="lbox"> <div class="lbox">
<el-avatar size="medium" shape="square" :src="avatar" /> <el-avatar size="default" shape="square" :src="avatar" />
</div> </div>
<div class="rbox"> <div class="rbox">
<div class="xheader"> <div class="xheader">
<p class="title"> <p class="title">
{{ talk_type == 1 ? '私信消息通知' : '群聊消息通知' }} {{ talk_type == 1 ? '私信消息通知' : '群聊消息通知' }}
</p> </p>
<p class="time"><i class="el-icon-time" /> {{ formatTime(datetime) }}</p> <p class="time"><legacy-el-icon name="el-icon-time" /> {{ formatTime(datetime) }}</p>
</div> </div>
<div class="xbody"> <div class="xbody">
<p>@{{ nickname }}</p> <p>@{{ nickname }}</p>

View File

@@ -5,7 +5,7 @@
<el-header class="header" height="50px"> <el-header class="header" height="50px">
<p>添加好友</p> <p>添加好友</p>
<p class="tools"> <p class="tools">
<i class="el-icon-close" @click="close" /> <legacy-el-icon name="el-icon-close" @click="close" />
</p> </p>
</el-header> </el-header>
<el-main class="main"> <el-main class="main">
@@ -13,7 +13,7 @@
v-model="mobile" v-model="mobile"
id="serach-mobile" id="serach-mobile"
class="input" class="input"
prefix-icon="el-icon-search" :prefix-icon="$legacyIcon('el-icon-search')"
placeholder="请输入对方手机号(精确查找)" placeholder="请输入对方手机号(精确查找)"
clearable clearable
@keyup.enter="onSubmit" @keyup.enter="onSubmit"

View File

@@ -2,7 +2,7 @@
<div class="lum-dialog-mask animated fadeIn"> <div class="lum-dialog-mask animated fadeIn">
<el-container class="container" v-outside="close"> <el-container class="container" v-outside="close">
<el-header class="no-padding header" height="180px"> <el-header class="no-padding header" height="180px">
<i class="close el-icon-error pointer" @click="close" /> <legacy-el-icon name="el-icon-error" class="close pointer" @click="close" />
<div class="img-banner"> <div class="img-banner">
<img :src="detail.bag" class="img-banner" /> <img :src="detail.bag" class="img-banner" />
</div> </div>
@@ -55,9 +55,9 @@
@keyup.enter="editRemarkSubmit" @keyup.enter="editRemarkSubmit"
/> />
</span> </span>
<i <legacy-el-icon
v-show="!editRemark.isShow" v-show="!editRemark.isShow"
class="el-icon-edit-outline" name="el-icon-edit-outline"
@click="clickEditRemark" @click="clickEditRemark"
/> />
</div> </div>
@@ -76,7 +76,7 @@
v-if="detail.friend_status == 1 && detail.friend_apply == 0" v-if="detail.friend_status == 1 && detail.friend_apply == 0"
type="primary" type="primary"
size="small" size="small"
icon="el-icon-circle-plus-outline" :icon="$legacyIcon('el-icon-circle-plus-outline')"
@click="apply.isShow = true" @click="apply.isShow = true"
>添加好友 >添加好友
</el-button> </el-button>
@@ -90,7 +90,7 @@
v-else-if="detail.friend_status == 2" v-else-if="detail.friend_status == 2"
type="primary" type="primary"
size="small" size="small"
icon="el-icon-s-promotion" :icon="$legacyIcon('el-icon-s-promotion')"
@click="sendMessage(detail)" @click="sendMessage(detail)"
>发消息 >发消息
</el-button> </el-button>
@@ -125,6 +125,7 @@
// import { ServeSearchUser } from "@/api/user"; // import { ServeSearchUser } from "@/api/user";
import { ServeCreateContact, ServeEditContactRemark } from "@/api/contacts"; import { ServeCreateContact, ServeEditContactRemark } from "@/api/contacts";
import { toTalk } from "@/utils/talk"; import { toTalk } from "@/utils/talk";
import { defaultUserBanner } from "@/assets/images";
export default { export default {
name: "UserCardDetail", name: "UserCardDetail",
@@ -144,7 +145,7 @@ export default {
friend_status: 0, friend_status: 0,
friend_apply: 0, friend_apply: 0,
nickname_remark: "", nickname_remark: "",
bag: require("@/assets/image/default-user-banner.png"), bag: defaultUserBanner,
gender: 0, gender: 0,
}, },
@@ -425,7 +426,7 @@ export default {
padding-right: 5px; padding-right: 5px;
} }
.el-icon-edit-outline { .legacy-el-icon {
margin-left: 3px !important; margin-left: 3px !important;
} }
} }

View File

@@ -5,6 +5,8 @@ import store from "@/store";
import { setupElementPlus } from "@/plugins/element"; import { setupElementPlus } from "@/plugins/element";
import { setupLegacyMessage } from "@/utils/message"; import { setupLegacyMessage } from "@/utils/message";
import { registerDirectives } from "@/core/directives"; import { registerDirectives } from "@/core/directives";
import LegacyElIcon from "@/components/global/LegacyElIcon.vue";
import { resolveLegacyIcon } from "@/core/legacy-icon-map";
export default { export default {
install(app) { install(app) {
@@ -30,6 +32,8 @@ export default {
setupElementPlus(cardApp); setupElementPlus(cardApp);
setupLegacyMessage(cardApp); setupLegacyMessage(cardApp);
registerDirectives(cardApp); registerDirectives(cardApp);
cardApp.component("legacy-el-icon", LegacyElIcon);
cardApp.config.globalProperties.$legacyIcon = resolveLegacyIcon;
cardApp.use(router); cardApp.use(router);
cardApp.use(store); cardApp.use(store);
cardApp.mount(container); cardApp.mount(container);

View File

@@ -16,6 +16,8 @@ import {
LoginMessage, LoginMessage,
} from "@/components/chat/messaege"; } from "@/components/chat/messaege";
import UserCard from "@/components/user/user-card/index"; import UserCard from "@/components/user/user-card/index";
import LegacyElIcon from "@/components/global/LegacyElIcon.vue";
import { resolveLegacyIcon } from "@/core/legacy-icon-map";
const messageComponents = [ const messageComponents = [
AudioMessage, AudioMessage,
@@ -39,5 +41,7 @@ export function registerGlobalComponents(app) {
messageComponents.forEach((component) => { messageComponents.forEach((component) => {
app.component(component.name, component); app.component(component.name, component);
}); });
app.component("legacy-el-icon", LegacyElIcon);
app.config.globalProperties.$legacyIcon = resolveLegacyIcon;
app.use(UserCard); app.use(UserCard);
} }

View File

@@ -0,0 +1,96 @@
import {
ArrowDown,
ArrowLeft,
ArrowRight,
Bell,
Bottom,
ChatDotRound,
ChatLineRound,
CircleCheck,
CircleClose,
CircleCloseFilled,
CirclePlus,
Clock,
Close,
Connection,
DataLine,
Delete,
DocumentCopy,
Edit,
Flag,
Folder,
FolderOpened,
Headset,
Loading,
Microphone,
MuteNotification,
Picture,
PictureRounded,
Plus,
Promotion,
Refresh,
RefreshLeft,
RefreshRight,
Remove,
Search,
Select,
Service,
Setting,
Top,
Upload,
User,
VideoPause,
VideoPlay,
} from "@element-plus/icons-vue";
/** Element UI `el-icon-*` class names → Element Plus icon components */
export const LEGACY_ICON_MAP = {
"el-icon-arrow-down": ArrowDown,
"el-icon-bell": Bell,
"el-icon-bottom": Bottom,
"el-icon-caret-left": ArrowLeft,
"el-icon-caret-right": ArrowRight,
"el-icon-chat-dot-round": ChatDotRound,
"el-icon-chat-line-round": ChatLineRound,
"el-icon-circle-close": CircleClose,
"el-icon-circle-plus-outline": CirclePlus,
"el-icon-close": Close,
"el-icon-close-notification": MuteNotification,
"el-icon-connection": Connection,
"el-icon-delete": Delete,
"el-icon-document-copy": DocumentCopy,
"el-icon-edit-outline": Edit,
"el-icon-error": CircleCloseFilled,
"el-icon-finished": Select,
"el-icon-folder": Folder,
"el-icon-folder-opened": FolderOpened,
"el-icon-headset": Headset,
"el-icon-loading": Loading,
"el-icon-microphone": Microphone,
"el-icon-picture": Picture,
"el-icon-picture-outline-round": PictureRounded,
"el-icon-plus": Plus,
"el-icon-position": Promotion,
"el-icon-refresh": Refresh,
"el-icon-refresh-left": RefreshLeft,
"el-icon-refresh-right": RefreshRight,
"el-icon-remove-outline": Remove,
"el-icon-s-data": DataLine,
"el-icon-s-flag": Flag,
"el-icon-s-promotion": Promotion,
"el-icon-search": Search,
"el-icon-service": Service,
"el-icon-setting": Setting,
"el-icon-success": CircleCheck,
"el-icon-time": Clock,
"el-icon-top": Top,
"el-icon-upload": Upload,
"el-icon-user": User,
"el-icon-video-pause": VideoPause,
"el-icon-video-play": VideoPlay,
};
export function resolveLegacyIcon(name) {
if (!name) return null;
return LEGACY_ICON_MAP[name] || null;
}

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) {
if (typeof this.createTalk === "function") {
await this.createTalk(this.$route.query.id); 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,
}); });
//获取店铺聊天列表 //获取店铺聊天列表
if (typeof this.loadStoreChatList === "function") {
await this.loadStoreChatList() 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

@@ -1,4 +1,5 @@
import { createApp, h, onMounted, onUnmounted } from "vue"; import { createApp, h, onMounted, onUnmounted } from "vue";
import LegacyElIcon from "@/components/global/LegacyElIcon.vue";
let activeMenu = null; let activeMenu = null;
@@ -99,7 +100,7 @@ function renderMenuItem(item, close) {
}, },
}, },
[ [
item.icon ? h("i", { class: item.icon }) : null, item.icon ? h(LegacyElIcon, { name: item.icon }) : null,
h("span", item.label), h("span", item.label),
] ]
); );

View File

@@ -1,4 +1,5 @@
import { setUserInfo, getUserInfo, getToken } from "@/utils/auth"; import { setUserInfo, getUserInfo, getToken } from "@/utils/auth";
import { defaultAvatar, defaultUserBanner } from "@/assets/images";
// import { ServeLogout } from "@/api/user"; // import { ServeLogout } from "@/api/user";
@@ -8,9 +9,9 @@ let state = {
// 用户昵称 // 用户昵称
name: "", name: "",
// 个性头像 // 个性头像
face: require("@/assets/image/detault-avatar.jpg"), face: defaultAvatar,
// 名片背景 // 名片背景
visitCardBag: require("@/assets/image/default-user-banner.png"), visitCardBag: defaultUserBanner,
// 当前登录状态 // 当前登录状态
loginStatus: false, loginStatus: false,
toUser:"" toUser:""

View File

@@ -1,4 +1,4 @@
const defaultAvatar = require('@/assets/image/detault-avatar.jpg') import { defaultAvatar } from "@/assets/images";
// 根级别的 state // 根级别的 state
const state = { const state = {

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

@@ -18,7 +18,7 @@
<el-tooltip content="我的消息" placement="right" :visible-arrow="false"> <el-tooltip content="我的消息" placement="right" :visible-arrow="false">
<router-link to="/message"> <router-link to="/message">
<div class="menu-items" :class="{ active: idx == 0 }"> <div class="menu-items" :class="{ active: idx == 0 }">
<i class="el-icon-chat-line-round" /> <legacy-el-icon name="el-icon-chat-line-round" />
<span v-show="unreadNum" class="notify"></span> <span v-show="unreadNum" class="notify"></span>
</div> </div>
</router-link> </router-link>

View File

@@ -20,7 +20,7 @@
</el-header> </el-header>
<el-header height="60px" class="header"> <el-header height="60px" class="header">
<div class="from-search"> <div class="from-search">
<el-input v-model="input" prefix-icon="el-icon-search" placeholder="搜索好友" size="small" /> <el-input v-model="input" :prefix-icon="$legacyIcon('el-icon-search')" placeholder="搜索好友" size="small" />
</div> </div>
</el-header> </el-header>
<!-- <el-header height="118px" class="logo-header"> <!-- <el-header height="118px" class="logo-header">
@@ -48,10 +48,10 @@
</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">
<i class="el-icon-loading" /> 数据加载中... <legacy-el-icon name="el-icon-loading" /> 数据加载中...
</p> </p>
<p v-show="loadStatus === 1 && talkNum === 0" class="empty-data"> <p v-show="loadStatus === 1 && talkNum === 0" class="empty-data">
@@ -61,7 +61,7 @@
<p v-show="loadStatus === 1 && talkNum > 0" class="main-menu"> <p v-show="loadStatus === 1 && talkNum > 0" class="main-menu">
<span class="title">对话记录({{ talkNum }})</span> <span class="title">对话记录({{ talkNum }})</span>
<!-- <el-tag size="mini" type="danger" v-if="myUnreadNum" <!-- <el-tag size="small" type="danger" v-if="myUnreadNum"
>未读{{ myUnreadNum }}</el-tag >未读{{ myUnreadNum }}</el-tag
> --> > -->
</p> </p>
@@ -78,7 +78,7 @@
<face :text="item.face" v-if="item.face"></face> <face :text="item.face" v-if="item.face"></face>
<face-null :text="item.name" v-else></face-null> <face-null :text="item.name" v-else></face-null>
<div v-show="item.is_top == 0" class="top-mask" @click.stop="topChatItem(item)"> <div v-show="item.is_top == 0" class="top-mask" @click.stop="topChatItem(item)">
<i class="el-icon-top" /> <legacy-el-icon name="el-icon-top" />
</div> </div>
</div> </div>
<div class="card-box"> <div class="card-box">
@@ -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
}; };