添加通知弹窗、音效,具有防抖

This commit is contained in:
peak 2025-06-12 18:43:40 +08:00
parent d8f71b14cb
commit 8114f48e70
9 changed files with 9346 additions and 7592 deletions

View File

@ -5,7 +5,8 @@ VITE_DEV=true
# 请求路径
VITE_BASE_URL='https://zysc.fjptzykj.com'
# VITE_BASE_URL='http://192.168.1.12:6127'
# VITE_BASE_URL='http://192.168.10.75:6127'
# VITE_BASE_URL='http://127.0.0.1:6127'
# 文件上传类型server - 后端上传, client - 前端直连上传,仅支持 S3 服务
VITE_UPLOAD_TYPE=server

View File

@ -62,7 +62,7 @@
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[typescriptreact]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,9 @@ import { useAppStore } from '@/store/modules/app'
import { useDesign } from '@/hooks/web/useDesign'
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
import routerSearch from '@/components/RouterSearch/index.vue'
import EventBus from '@/utils/eventBus'
import { debounce } from 'lodash'
import { ElNotification } from 'element-plus'
defineOptions({ name: 'APP' })
const { getPrefixCls } = useDesign()
@ -23,6 +25,17 @@ const setDefaultTheme = () => {
appStore.setIsDark(isDarkTheme)
}
setDefaultTheme()
const debounceNotify = debounce((msg) => {
alert(msg)
ElNotification.info({
title: "新消息",
message: msg,
duration: 3000,
})
}, 600);
onMounted(() => {
EventBus.on('show-notification', debounceNotify);
})
</script>
<template>
<ConfigGlobal :size="currentSize">

View File

@ -5,6 +5,9 @@ import { Backtop } from '@/components/Backtop'
import { Setting } from '@/layout/components/Setting'
import { useRenderLayout } from './components/useRenderLayout'
import { useDesign } from '@/hooks/web/useDesign'
import EventBus from '@/utils/eventBus'
import { debounce } from 'lodash'
import { ElNotification } from 'element-plus'
const { getPrefixCls } = useDesign()
@ -42,7 +45,14 @@ const renderLayout = () => {
break
}
}
const debounceNotify = debounce((msg) => {
ElNotification.info({
title: "新消息",
message: msg,
duration: 3000,
})
}, 600);
EventBus.on('notification', debounceNotify);
export default defineComponent({
name: 'Layout',
setup() {

View File

@ -0,0 +1,2 @@
import mitt from 'mitt';
export default mitt();

View File

@ -7,14 +7,13 @@
<div style="width:100%;height:68px;background-color:#3c80ff;">
<el-row>
<el-col :span="6">
<el-input @input="findNameInput" v-model="findName"
style="width: 80%;margin-top: 20px;margin-left:23px;"
:suffix-icon="Search"/>
<el-input @input="findNameInput" v-model="findName" style="width: 80%;margin-top: 20px;margin-left:23px;"
:suffix-icon="Search" />
</el-col>
<el-col :span="1">
<el-avatar style=" margin-top: 15px;" :src="pic"/>
<!-- <span style="display: flex; margin-top: 15px;">
<el-avatar style=" margin-top: 15px;" :src="pic" />
<!-- <span style="display: flex; margin-top: 15px;">
<span style="margin-left:5px;margin-top: 9px;">{{name}}</span>
<el-switch
@ -23,31 +22,29 @@
inactive-text="下线" @change="handleSwitchChange"/>
</span> -->
</el-col>
<el-col :span="7">
<span style="display: flex; margin-top: 15px;">
<!-- <el-avatar :src="pic"/> -->
<span style="margin-left:5px;margin-top: 9px;">{{name}}</span>
<el-switch
style="margin-top: 4px;--el-switch-on-color: #13ce66; --el-switch-off-color: #b6bac1;"
v-model="lineStatus" class="ml-2" width="60" inline-prompt active-text="在线"
inactive-text="下线" @change="handleSwitchChange"/>
</span>
</el-col>
<el-col :span="7">
<span style="display: flex; margin-top: 15px;">
<!-- <el-avatar :src="pic"/> -->
<span style="margin-left:5px;margin-top: 9px;">{{ name }}</span>
<el-switch style="margin-top: 4px;--el-switch-on-color: #13ce66; --el-switch-off-color: #b6bac1;"
v-model="lineStatus" class="ml-2" width="60" inline-prompt active-text="在线" inactive-text="下线"
@change="handleSwitchChange" />
</span>
</el-col>
<el-col :span="4">
<el-button @click="out" size="small" round
style="margin-top:23px;margin-left:72%">退出
<el-button @click="out" size="small" round style="margin-top:23px;margin-left:72%">退出
</el-button>
</el-col>
<el-col :span="6">
<el-menu background-color="#3c80ff" text-color="white" active-text-color="white"
style="width:100%;display: flex;">
style="width:100%;display: flex;">
<el-menu-item @click="userInfo" style="width:33%;height:70px" index="1">客户信息
</el-menu-item>
<el-menu-item @click="jiaoyi" style="width:33%;height:70px" index="3">交易订单
</el-menu-item>
<el-menu-item @click="jiaoyi" style="width:33%;height:70px" index="3">交易订单
</el-menu-item>
<el-menu-item @click="zuoji" style="width:33%;height:70px" index="2">商品信息
</el-menu-item>
<!-- <el-menu-item style="width:34%;height:70px" index="3">商品信息</el-menu-item> -->
@ -65,84 +62,84 @@
<!-- 会话列表 -->
<el-col :span="6">
<ContentWrap>
<KeFuConversationList ref="keFuConversationRef" @change="handleChange"/>
<KeFuConversationList ref="keFuConversationRef" @change="handleChange" />
</ContentWrap>
</el-col>
<!-- 会话详情选中会话的消息列表 -->
<el-col :span="12">
<KeFuMessageList ref="keFuChatBoxRef" @change="getConversationList"/>
<KeFuMessageList ref="keFuChatBoxRef" @change="getConversationList" />
</el-col>
<!-- 会员足迹选中会话的会员足迹 -->
<el-col :span="6">
<ContentWrap v-show="chick == '1' && clickUser == 2">
<div style="height: 522px ;">
<div>
<span style="display: flex;">
<el-avatar style="border: 1px solid #f8f9ee;" :src="user.avatar"/>
<span style="margin-left:5px;margin-top: 9px;">{{user.nickname}}</span>
</span>
<span style="display: flex;">
<el-avatar style="border: 1px solid #f8f9ee;" :src="user.avatar" />
<span style="margin-left:5px;margin-top: 9px;">{{ user.nickname }}</span>
</span>
</div>
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;"/>
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
<div>
<span style="color: #5d5d59;font-size: 13px ;">手机号</span><span
style="margin-left: 47px;font-size: 14px ;">{{user.mobile}}</span>
style="margin-left: 47px;font-size: 14px ;">{{ user.mobile }}</span>
</div>
<div style="margin-top: 5px;">
<span style="color: #5d5d59;font-size: 13px ;">分组</span><span
style="margin-left: 60px;font-size: 14px ;">{{user.groupName}}</span>
style="margin-left: 60px;font-size: 14px ;">{{ user.groupName }}</span>
</div>
<div style="margin-top: 5px;">
<span style="color: #5d5d59;font-size: 13px ;">用户标签</span><span
style="margin-left: 33px;font-size: 14px ;">客户</span>
style="margin-left: 33px;font-size: 14px ;">客户</span>
</div>
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;"/>
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
<div>
<span style="color: #5d5d59;font-size: 13px ;">用户等级</span><span
style="margin-left: 35px;font-size: 14px ;">{{user.levelName}}</span>
style="margin-left: 35px;font-size: 14px ;">{{ user.levelName }}</span>
</div>
<div style="margin-top: 5px;">
<span style="color: #5d5d59;font-size: 13px ;">推荐人</span><span
style="margin-left: 47px;font-size: 14px ;">客户</span>
style="margin-left: 47px;font-size: 14px ;">客户</span>
</div>
<!-- <div style="margin-top: 5px;">
<!-- <div style="margin-top: 5px;">
<span style="color: #5d5d59;font-size: 13px ;">用户类型</span><span
style="margin-left: 33px;font-size: 14px ;">小客户</span>
</div> -->
<div style="margin-top: 5px;">
<span style="color: #5d5d59;font-size: 13px ;">积分</span><span
style="margin-left: 60px;font-size: 14px ;">{{user.point}}</span>
style="margin-left: 60px;font-size: 14px ;">{{ user.point }}</span>
</div>
<div style="margin-top: 5px;">
<span style="color: #5d5d59;font-size: 13px ;">推广员</span><span
style="margin-left: 47px;font-size: 14px ;">客户</span>
style="margin-left: 47px;font-size: 14px ;">客户</span>
</div>
<div style="margin-top: 5px;">
<span style="color: #5d5d59;font-size: 13px ;">生日</span><span
style="margin-left: 60px;font-size: 14px ;">{{user.birthday}}</span>
style="margin-left: 60px;font-size: 14px ;">{{ user.birthday }}</span>
</div>
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;"/>
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
</div>
</ContentWrap>
<ContentWrap v-show="chick == '1' && clickUser == 1">
<el-empty description="请选择左侧的一个会话后开始" />
</ContentWrap>
<ContentWrap v-show="chick == '2'">
<MemberBrowsingHistory ref="memberBrowsingHistoryRef"/>
<ContentWrap v-show="chick == '1' && clickUser == 1">
<el-empty description="请选择左侧的一个会话后开始" />
</ContentWrap>
<ContentWrap v-show="chick == '3'">
<MemberBrowsingHistorys ref="memberBrowsingHistorysRef"/>
</ContentWrap>
<ContentWrap v-show="chick == '2'">
<MemberBrowsingHistory ref="memberBrowsingHistoryRef" />
</ContentWrap>
<ContentWrap v-show="chick == '3'">
<MemberBrowsingHistorys ref="memberBrowsingHistorysRef" />
</ContentWrap>
</el-col>
</el-row>
</div>
@ -150,235 +147,245 @@
<script lang="ts" setup>
import {
KeFuConversationList,
KeFuMessageList,
MemberBrowsingHistorys,
MemberBrowsingHistory
} from './components'
import {WebSocketMessageTypeConstants} from './components/tools/constants'
import { KeFuMessageApi, KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
import {KeFuConversationRespVO} from '@/api/mall/promotion/kefu/conversation'
import {getRefreshToken, getAccessToken} from '@/utils/auth'
import {useWebSocket} from '@vueuse/core'
import {Search} from '@element-plus/icons-vue'
import * as UserApi from '@/api/member/user'
import {SupportStaffApi, SupportStaffVO} from '@/api/mall/promotion/supportstaff'
import {string} from 'vue-types'
import {
KeFuConversationList,
KeFuMessageList,
MemberBrowsingHistorys,
MemberBrowsingHistory
} from './components'
import { WebSocketMessageTypeConstants } from './components/tools/constants'
import { KeFuMessageApi, KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
import { getRefreshToken, getAccessToken } from '@/utils/auth'
import { useWebSocket } from '@vueuse/core'
import { Search } from '@element-plus/icons-vue'
import * as UserApi from '@/api/member/user'
import { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportstaff'
import { string } from 'vue-types'
import EventBus from '@/utils/eventBus';
import bgm from './xm3463.mp3'
import type { TabsPaneContext } from 'element-plus'
const findName = ref('')
import { ElNotification } from 'element-plus'
const findName = ref('')
const audio = new Audio(bgm)
defineOptions({ name: 'KeFu' })
defineOptions({name: 'KeFu'})
const lineStatus = ref(true)
const lineStatus = ref(true)
const clickUser = ref(1)
const clickUser = ref(1)
const message = useMessage() //
const params = new URLSearchParams(window.location.search);
const name = params.get('name');
const pic = params.get('pic');
const kefuId = params.get('id')
const conversations = ref<KeFuConversationRespVO[]>([])
// const userInfoRef = ref<InstanceType<typeof UserInfo>>()
const user = ref<UserApi.UserVO>({} as UserApi.UserVO)
const userId = ref(0)
const stat = ref(false)
const message = useMessage() //
// ======================= WebSocket start =======================
const server = ref(
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
'?token=' + getRefreshToken()
// getAccessToken()
// 使 getRefreshToken() 使 getAccessToken() WebSocket 便访
) // WebSocket
const params = new URLSearchParams(window.location.search);
const name = params.get('name');
const pic = params.get('pic');
const kefuId = params.get('id')
const conversations = ref<KeFuConversationRespVO[]>([])
// const userInfoRef = ref<InstanceType<typeof UserInfo>>()
const user = ref<UserApi.UserVO>({} as UserApi.UserVO)
const userId = ref(0)
const stat = ref(false)
const handleSwitchChange = async (value) => {
console.log('11111:', value)
let a = 0;
// ======================= WebSocket start =======================
const server = ref(
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
'?token=' + getAccessToken()
// getAccessToken()
// 使 getRefreshToken() 使 getAccessToken() WebSocket 便访
) // WebSocket
if (value == true) {
a = 1;
await SupportStaffApi.updateLineStatus(kefuId, a)
message.success('已上线')
} else {
a = 2;
await SupportStaffApi.updateLineStatus(kefuId, a)
message.success('已下线')
}
}
const shangxian = async () => {
await SupportStaffApi.updateLineStatus(kefuId, 1)
}
const xiaxian = async () => {
await SupportStaffApi.updateLineStatus(kefuId, 2)
}
const handleSwitchChange = async (value) => {
console.log('11111:', value)
let a = 0;
const {status, data, send, open, close} = useWebSocket(server.value, {
onConnected: function (ws) {
shangxian(); //线
console.log('websocket 连接成功!', ws);
},
onDisconnected: function (ws, event) {
xiaxian(); //线
console.log('WebSocket 连接断开', event);
},
// onError: function (ws, event) {
// console.error('WebSocket :', event);
// if (event instanceof ErrorEvent) {
// console.error(':', event.message);
// } else {
// console.error(':', event);
// }
// },
onMessage: function (ws, event) {
// console.log(' WebSocket :', event.data);
if (value == true) {
a = 1;
await SupportStaffApi.updateLineStatus(kefuId, a)
message.success('已上线')
} else {
a = 2;
await SupportStaffApi.updateLineStatus(kefuId, a)
message.success('已下线')
}
a = a + 1;
if (a == 2) {
getConversationList()
if(userId.value != 0){
getBySenderIdStat()
if(stat.value){
keFuChatBoxRef.value?.refreshMessageList()
}
}
a = 0;
}
const shangxian = async () => {
await SupportStaffApi.updateLineStatus(kefuId, 1)
}
const xiaxian = async () => {
await SupportStaffApi.updateLineStatus(kefuId, 2)
}
let a = 0;
const { status, data, send, open, close } = useWebSocket(server.value, {
onConnected: function (ws) {
shangxian(); //线
console.log('websocket 连接成功!', ws);
},
onDisconnected: function (ws, event) {
xiaxian(); //线
console.log('WebSocket 连接断开', event);
},
// onError: function (ws, event) {
// console.error('WebSocket :', event);
// if (event instanceof ErrorEvent) {
// console.error(':', event.message);
// } else {
// console.error(':', event);
// }
// },
onMessage: function (ws, event) {
a = a + 1;
if (a == 2) {
getConversationList()
if (userId.value != 0) {
getBySenderIdStat()
if (stat.value) {
keFuChatBoxRef.value?.refreshMessageList()
}
}
a = 0;
}
},
autoReconnect: true, //
heartbeat: true
});
},
autoReconnect: true, //
heartbeat: true
});
// const { data, close, open } = useWebSocket(server.value, {
// autoReconnect: true,
// heartbeat: true
// })
/** 监听 WebSocket 数据 */
watchEffect(() => {
console.log('连接服务器得到消息:', data.value)
if (!data.value) {
/** 监听 WebSocket 数据 */
watchEffect(() => {
if (!data.value) {
return
}
try {
// 1.
if (data.value === 'pong') {
return
}
try {
// 1.
if (data.value === 'pong') {
return
}
// 2.1 type
const jsonMessage = JSON.parse(data.value)
const type = jsonMessage.type
// 2.1 type
const jsonMessage = JSON.parse(data.value)
const type = jsonMessage.type
if (!type) {
message.error('未知的消息类型:' + data.value)
return
}
// 2.2 KEFU_MESSAGE_TYPE
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
console.log('来自用户发送的消息:', JSON.parse(jsonMessage.content))
//
// TODO @puhui999 update
getConversationList()
//
keFuChatBoxRef.value?.refreshMessageList(JSON.parse(jsonMessage.content))
return
}
// 2.3 KEFU_MESSAGE_ADMIN_READ
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ) {
//
// TODO @puhui999 update
getConversationList()
}
} catch (error) {
console.error(error)
if (!type) {
message.error('未知的消息类型:' + data.value)
return
}
})
// 2.2 KEFU_MESSAGE_TYPE
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
console.log('来自用户发送的消息:', JSON.parse(jsonMessage.content))
const message = JSON.parse(jsonMessage.content)
if (message.senderType == 1) {
audio.play()
EventBus.emit('notification', message.content)
// Notification.requestPermission().then(permission => {
// if (permission === 'granted') {
// console.log('');
// }
// });
// if (Notification.permission === 'granted') {
// console.warn('');
// new Notification(":"+message.content);
// } else {
// console.warn('');
// }
}
//
// TODO @puhui999 update
getConversationList()
//
keFuChatBoxRef.value?.refreshMessageList(JSON.parse(jsonMessage.content))
return
}
// 2.3 KEFU_MESSAGE_ADMIN_READ
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ) {
//
// TODO @puhui999 update
getConversationList()
}
} catch (error) {
console.error(error)
}
})
// ======================= WebSocket end =======================
/** 加载会话列表 */
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
const getConversationList = () => {
keFuConversationRef.value?.getConversationList(findName.value)
// ======================= WebSocket end =======================
/** 加载会话列表 */
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
const getConversationList = () => {
keFuConversationRef.value?.getConversationList(findName.value)
}
/** 加载指定会话的消息列表 */
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
const memberBrowsingHistoryRef = ref<InstanceType<typeof MemberBrowsingHistory>>()
const memberBrowsingHistorysRef = ref<InstanceType<typeof MemberBrowsingHistorys>>()
const handleChange = async (conversation: KeFuConversationRespVO) => {
conversations.value = conversation
// chick.value = '1'
clickUser.value = 2
userId.value = conversation.userId
userInfo()
keFuChatBoxRef.value?.getNewMessageList(conversation)
memberBrowsingHistoryRef.value?.initHistory(conversation)
memberBrowsingHistorysRef.value?.initHistory(conversation)
}
const out = async () => {
// await SupportStaffApi.updateLineStatus(kefuId, 2)
window.close();
// window.location.href = '/kefu/support-staff';
}
const getBySenderIdStat = async () => {
stat.value = await KeFuMessageApi.getBySenderIdStat(userId.value)
}
const chick = ref('1')
const userInfo = async () => {
chick.value = '1'
if (clickUser.value == 2) {
user.value = await UserApi.getUserInfo(userId.value)
}
/** 加载指定会话的消息列表 */
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
const memberBrowsingHistoryRef = ref<InstanceType<typeof MemberBrowsingHistory>>()
const memberBrowsingHistorysRef = ref<InstanceType<typeof MemberBrowsingHistorys>>()
const handleChange = async (conversation: KeFuConversationRespVO) => {
conversations.value = conversation
// chick.value = '1'
clickUser.value = 2
userId.value = conversation.userId
userInfo()
keFuChatBoxRef.value?.getNewMessageList(conversation)
memberBrowsingHistoryRef.value?.initHistory(conversation)
memberBrowsingHistorysRef.value?.initHistory(conversation)
}
const out = async () => {
// await SupportStaffApi.updateLineStatus(kefuId, 2)
window.close();
// window.location.href = '/kefu/support-staff';
}
const getBySenderIdStat = async () => {
stat.value = await KeFuMessageApi.getBySenderIdStat(userId.value)
}
}
const zuoji = () => {
chick.value = '2'
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
memberBrowsingHistoryRef.value?.initHistory(conversations.value)
}
const jiaoyi = () => {
chick.value = '3'
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
// memberBrowsingHistoryRef.value?.initHistory(conversations.value)
}
const chick = ref('1')
const userInfo = async () => {
chick.value = '1'
if(clickUser.value == 2){
user.value = await UserApi.getUserInfo(userId.value)
}
}
const zuoji = () => {
chick.value = '2'
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
memberBrowsingHistoryRef.value?.initHistory(conversations.value)
}
const jiaoyi = () => {
chick.value = '3'
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
// memberBrowsingHistoryRef.value?.initHistory(conversations.value)
}
const findNameInput = () => {
keFuConversationRef.value?.getConversationList(findName.value)
}
const findNameInput = () => {
keFuConversationRef.value?.getConversationList(findName.value)
}
/** 初始化 */
onMounted(() => {
getConversationList()
// websocket
open()
console.log('WebSocket 已初始化');
})
/** 初始化 */
onMounted(() => {
getConversationList()
// websocket
open()
console.log('WebSocket 已初始化');
})
// /** */
// /** */
// onBeforeUnmount(() => {
// // websocket
// close()
@ -387,32 +394,32 @@ import type { TabsPaneContext } from 'element-plus'
</script>
<style lang="scss">
.kefu {
height: calc(100vh - 165px);
overflow: auto;
/* 确保内容可滚动 */
.kefu {
height: calc(100vh - 165px);
overflow: auto;
/* 确保内容可滚动 */
}
}
/* 定义滚动条样式 */
::-webkit-scrollbar {
width: 10px;
height: 6px;
}
/* 定义滚动条样式 */
::-webkit-scrollbar {
width: 10px;
height: 6px;
}
/* 定义滚动条轨道 内阴影+圆角 */
::-webkit-scrollbar-track {
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
border-radius: 10px;
background-color: #fff;
}
/* 定义滚动条轨道 内阴影+圆角 */
::-webkit-scrollbar-track {
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
border-radius: 10px;
background-color: #fff;
}
/* 定义滑块 内阴影+圆角 */
::-webkit-scrollbar-thumb {
/* 定义滑块 内阴影+圆角 */
::-webkit-scrollbar-thumb {
border-radius: 10px;
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
background-color: rgba(240, 240, 240, 0.5);
border-radius: 10px;
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
background-color: rgba(240, 240, 240, 0.5);
}
}
</style>

View File

@ -169,6 +169,8 @@ import { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportsta
import SupportStaffForm from './SupportStaffForm.vue'
import { setStaffToken} from '@/utils/auth'
import { createImageViewer } from '@/components/ImageViewer'
import { useRouter } from 'vue-router'
const router = useRouter()
/** 客服人员 列表 */
defineOptions({ name: 'SupportStaff' })
@ -247,8 +249,10 @@ const handleDelete = async (id: number) => {
/** 客服进入工作台 */
const handleEnterConsole = async (id: number,name: string,pic: string) => {
setStaffToken(id);
const url = `${window.location.origin}/kefu/kefu?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}&pic=${encodeURIComponent(pic)}`;
const url = `${window.location.origin}/kefu/chat?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}&pic=${encodeURIComponent(pic)}`;
window.open(url, '_blank');
// const url = `/kefu/chat?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}&pic=${encodeURIComponent(pic)}`;
// router.push(url);
}
/** 导出按钮操作 */
const handleExport = async () => {