feat: 会话列表对接

feature/task1.0.0__0514__ch
向文可 3 years ago
parent 4c92155014
commit 78628cc8a7

@ -16,12 +16,17 @@
</template> </template>
<script setup> <script setup>
import LayoutMain from './components/main.vue';
import LayoutAside from './components/aside.vue'; import LayoutAside from './components/aside.vue';
import LayoutMenu from './components/menu.vue'; import LayoutFooter from './components/footer.vue';
import LayoutHeader from './components/header.vue'; import LayoutHeader from './components/header.vue';
import LayoutMain from './components/main.vue';
import LayoutMenu from './components/menu.vue';
import LayoutTabs from './components/tabs.vue'; import LayoutTabs from './components/tabs.vue';
import LayoutFooter from './components/footer.vue'; const store = useStore();
store.dispatch(
'chat/connect',
'eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjQwNzA4ODAwMDAsImlkIjoyfQ.NlKpMH_bjVHlbj_GfAf196W4GUhpqmHY3efw7W_1F8WQeovw1ZgEeYo_oY24Q38z_yh6WIplq730ohoU5SLkLxdIxC60T9SoHwgmxOdd8w_Mo0ksOcsQs3xLytJca1KVvOfAT_flTjgOe0q5iSJeNCblTY4hsP6dn1aE69pqcng'
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

@ -0,0 +1,127 @@
import { ElMessage } from '@/plugins/element-plus';
import { UUID } from '@/utils/chat';
const state = () => ({
socket: null,
heart: null,
queue: [],
task: [],
sessionData: {},
});
const getters = {};
const mutations = {
setSocket: (state, data) => (state.socket = data),
setHeart: (state, data) => (state.heart = data),
setTask: (state, data) => (state.task = data),
addTask: (state, data) => state.task.push(data),
delTask: (state, data) => state.task.splice(data, 1),
receive: (state, { code, traceType, content }) => {
if (code === 200) {
switch (traceType) {
case 27:
state.sessionData = content;
break;
default:
break;
}
}
},
};
const actions = {
/**
* 创建连接
*/
connect: ({ state, commit, dispatch }, token) => {
return new Promise((resolve, reject) => {
if (window.WebSocket) {
const socket = new WebSocket('ws://192.168.10.93:8090/ws?client=' + token);
socket.onmessage = ({ data }) => {
data = JSON.parse(data);
if (data.traceType !== 0) {
let index = state.task.findIndex((item) => item.traceId === data.traceId);
if (index !== -1) {
commit('delTask', index);
commit('receive', data);
console.info('[chat] msg', data);
} else {
console.info('[chat] deprecated', data);
}
}
};
socket.onopen = () => {
commit(
'setHeart',
setInterval(() => {
dispatch('heart');
}, 3000)
);
console.info('[chat] open');
resolve(socket);
};
socket.onclose = () => {
clearInterval(state.heart);
console.info('[chat] close');
};
socket.onerror = (e) => {
clearInterval(state.heart);
console.info('[chat] error', e);
reject(e);
};
commit('setSocket', socket);
} else {
ElMessage.error('当前浏览器不支持 WebSocket');
reject('not support websocket');
}
});
},
/**
* 发送心跳任务监测
*/
heart: ({ state, dispatch }) => {
dispatch('send', {
traceType: 26,
content: { storeId: 1 },
});
console.info('[chat] heart');
state.task.forEach((item) => {
dispatch('send', item);
});
},
/**
* 执行任务
*/
invoke: ({ commit, dispatch }, data) => {
data.traceId = UUID();
commit('addTask', data);
dispatch('send', data);
},
/**
* 发送数据
*/
send: ({ state }, data) => {
if (window.WebSocket) {
if (state.socket?.readyState === WebSocket.OPEN) {
data.traceId = data.traceId || UUID();
state.socket.send(JSON.stringify(data));
if (data.traceType !== 26) {
console.info('[chat] send', data);
}
}
}
},
/**
* 查询回话列表
*/
querySession: ({ dispatch }) => {
dispatch('invoke', {
traceType: 27,
content: { storeId: 1 },
});
},
};
export default {
state,
getters,
mutations,
actions,
};

@ -310,6 +310,15 @@ export const emojiData = [
], ],
}, },
]; ];
//生成UUID
export function UUID() {
let d = _.now();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + _.random(16)) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
});
}
//emoji表情编码 //emoji表情编码
export function utf16toEntities(str) { export function utf16toEntities(str) {
const patt = /[\ud800-\udbff][\udc00-\udfff]/g; // 检测utf16字符正则 const patt = /[\ud800-\udbff][\udc00-\udfff]/g; // 检测utf16字符正则

@ -1,5 +1,6 @@
<template> <template>
<div class="chat-container" @click="emojiVisible = false"> <div class="chat-container" @click="emojiVisible = false">
{{ $store.state.chat }}
<div class="header"> <div class="header">
<p>当前客服小爱</p> <p>当前客服小爱</p>
<el-button type="text" @click="summaryVisible = !summaryVisible"> <el-button type="text" @click="summaryVisible = !summaryVisible">
@ -25,16 +26,21 @@
:class="{ active: state.currentIndex === index }" :class="{ active: state.currentIndex === index }"
@click="handleChangeSession(index)" @click="handleChangeSession(index)"
> >
<el-badge class="session-count" :hidden="item.count === 0" :max="99" :value="item.count"> <el-badge
<el-avatar circle :src="item.avatar" /> class="session-count"
:hidden="item.unreadCount === 0"
:max="99"
:value="item.unreadCount"
>
<el-avatar circle :src="item.fromAvatar" />
</el-badge> </el-badge>
<div class="session-info"> <div class="session-info">
<div class="row"> <div class="row">
<div class="session-name">{{ item.name }}</div> <div class="session-name">{{ item.fromNickname }}</div>
<div class="session-time">{{ item.time }}</div> <div class="session-time">{{ parseTime(item.lastMessage.createTimeStamp) }}</div>
</div> </div>
<div class="row"> <div class="row">
<div class="session-content">{{ item.content }}</div> <div class="session-content">{{ parseContent(item.lastMessage.payload) }}</div>
</div> </div>
</div> </div>
</li> </li>
@ -44,7 +50,7 @@
<div class="content-header"> <div class="content-header">
<div class="content-header-left"> <div class="content-header-left">
<div class="name sex-1"> <div class="name sex-1">
{{ currentSession.name }} {{ currentSession?.name }}
</div> </div>
</div> </div>
<div class="content-header-right"> <div class="content-header-right">
@ -103,9 +109,11 @@
</template> </template>
<script setup> <script setup>
import { emojiData, entitiestoUtf16 } from '@/utils/emoji.js'; import { emojiData, entitiestoUtf16 } from '@/utils/chat.js';
import MessageItem from './message.vue'; import MessageItem from './message.vue';
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const store = useStore();
store.dispatch('chat/querySession');
// //
const summaryVisible = ref(true); const summaryVisible = ref(true);
@ -121,32 +129,24 @@
currentIndex: 0, currentIndex: 0,
message: '', message: '',
}); });
const sessionList = reactive([ const sessionList = computed(() => {
{ return store.state.chat.sessionData?.sessionVOS || [];
name: '小可爱', });
avatar: 'https://placem.at/people',
count: 1,
time: '2019-12-12',
content: '你好,请问这个能有优惠吗?',
},
{
name: '小可爱',
avatar: 'https://placem.at/people',
count: 0,
time: '2019-12-12',
content: '你好,请问这个能有优惠吗?',
},
{
name: '小可爱',
avatar: 'https://placem.at/people',
count: 0,
time: '2019-12-12',
content: '你好,请问这个能有优惠吗?',
},
]);
const currentSession = computed(() => { const currentSession = computed(() => {
return sessionList[state.currentIndex]; return sessionList[state.currentIndex];
}); });
//
const parseTime = (timestamp) => dayjs(new Date(timestamp)).format('MM-DD HH:mm:ss');
const parseContent = (payload) => {
payload = JSON.parse(payload);
if ('text' in payload) {
payload = payload.text;
} else {
payload = '[未知消息]';
}
return payload;
};
const sessionMessageList = reactive([ const sessionMessageList = reactive([
{ {
type: 'text', type: 'text',

Loading…
Cancel
Save