web/im/src/components/chat/TalkSearchRecord.vue
2022-12-28 10:08:51 +08:00

603 lines
15 KiB
Vue

<template>
<div class="lum-dialog-mask">
<el-container class="lum-dialog-box" :class="{ 'full-screen': fullscreen }">
<el-header height="60px" class="header">
<p>消息管理器</p>
<p class="title">
<span>{{ query.talk_type == 1 ? "好友" : "群" }}{{ title }}</span>
</p>
<p class="tools">
<i
class="iconfont"
style="transform: scale(0.85)"
:class="fullscreen ? 'icon-tuichuquanping' : 'icon-quanping'"
@click="fullscreen = !fullscreen"
/>
<i class="el-icon-close" @click="$emit('close')" />
</p>
</el-header>
<el-header height="38px" class="sub-header">
<i
class="iconfont pointer"
:class="{ 'icon-shouqi2': broadside, 'icon-zhankai': !broadside }"
@click="triggerBroadside"
/>
<div class="search-box no-select">
<i class="el-icon-search" />
<input
v-model="search.keyword"
type="text"
maxlength="30"
placeholder="关键字搜索"
@keyup.enter="searchText($event)"
/>
</div>
</el-header>
<el-container class="full-height ov-hidden">
<el-aside width="200px" class="broadside" v-show="broadside">
<el-container class="full-height">
<el-header height="40px" class="aside-header">
<div
class="item"
:class="{ selected: contacts.show == 'friends' }"
@click="contacts.show = 'friends'"
>
我的好友({{ contacts.friends.length }})
</div>
<div class="item-shuxian">|</div>
<div
class="item"
:class="{ selected: contacts.show == 'groups' }"
@click="contacts.show = 'groups'"
>
我的群组({{ contacts.groups.length }})
</div>
</el-header>
<el-main class="no-padding">
<el-scrollbar class="full-height" tag="section" :native="false">
<div
v-for="item in contacts[contacts.show]"
class="contacts-item pointer"
:class="{
selected:
query.talk_type == item.type &&
query.receiver_id == item.id,
}"
:key="item.id"
@click="triggerMenuItem(item)"
>
<div class="avatar">
<el-avatar :size="20" :src="item.avatar">
<img src="~@/assets/image/detault-avatar.jpg" />
</el-avatar>
</div>
<div class="content" v-text="item.name"></div>
</div>
</el-scrollbar>
</el-main>
</el-container>
</el-aside>
<!-- 聊天记录阅览 -->
<el-main v-show="showBox == 0" class="no-padding">
<el-container class="full-height">
<el-header height="40px" class="type-items">
<span
v-for="tab in tabType"
:class="{ active: query.msg_type == tab.type }"
@click="triggerLoadType(tab.type)"
>{{ tab.name }}
</span>
</el-header>
<el-main
v-if="records.isEmpty"
class="history-record animated fadeIn"
>
<div class="empty-records">
<img src="~@/assets/image/chat-search-no-message.png" />
<p>暂无聊天记录</p>
</div>
</el-main>
<el-main v-else class="history-record">
<el-scrollbar class="full-height" tag="section" :native="false">
<div
v-for="record in records.items"
:key="record.id"
class="message-group"
>
<div class="left-box">
<el-avatar
shape="square"
fit="contain"
:size="30"
:src="record.avatar"
/>
</div>
<div class="right-box">
<div class="msg-header">
<span class="name">
{{
record.nickname_remarks
? record.nickname_remarks
: record.nickname
}}
</span>
<el-divider direction="vertical" />
<span class="time">{{ record.created_at }}</span>
</div>
<!-- 文本消息 -->
<text-message
v-if="record.msg_type == 1"
:content="record.content"
/>
<!-- 文件 - 图片消息 -->
<image-message
v-else-if="
record.msg_type == 2 && record.file.file_type == 1
"
:src="record.file.file_url"
/>
<!-- 文件 - 音频消息 -->
<audio-message
v-else-if="
record.msg_type == 2 && record.file.file_type == 2
"
:src="record.file.file_url"
/>
<!-- 文件 - 视频消息 -->
<video-message
v-else-if="
record.msg_type == 2 && record.file.file_type == 3
"
/>
<!-- 文件 - 其它格式文件 -->
<file-message
v-else-if="
record.msg_type == 2 && record.file.file_type == 4
"
:file="record.file"
:record_id="record.id"
/>
<!-- 会话记录消息 -->
<forward-message
v-else-if="record.msg_type == 3"
:forward="record.forward"
:record_id="record.id"
/>
<!-- 代码块消息 -->
<code-message
v-else-if="record.msg_type == 4"
:code="record.code_block.code"
:lang="record.code_block.code_lang"
/>
<!-- 投票消息 -->
<vote-message
v-else-if="record.msg_type == 5"
:record_id="record.id"
:vote="record.vote"
/>
<div v-else class="other-message">未知消息类型</div>
</div>
</div>
<!-- 数据加载栏 -->
<div v-show="records.loadStatus == 1" class="load-button blue">
<i class="el-icon-loading" />
<span>加载数据中...</span>
</div>
<div v-show="records.loadStatus == 0" class="load-button">
<i class="el-icon-arrow-down" />
<span @click="loadChatRecord">加载更多...</span>
</div>
</el-scrollbar>
</el-main>
</el-container>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import { ServeGetContacts } from "@/api/contacts";
import { ServeFindTalkRecords } from "@/api/chat";
import { formatSize as renderSize, download, imgZoom } from "@/utils/functions";
export default {
name: "TalkSearchRecord",
props: {
params: {
type: Object,
default: () => {
return {
talk_type: 0,
receiver_id: 0,
title: "",
};
},
},
},
data() {
return {
fullscreen: false,
user_id: this.$store.state.user.id,
title: "",
// 侧边栏相关信息
broadside: false,
contacts: {
show: "friends",
friends: [],
groups: [],
},
query: {
talk_type: 0,
receiver_id: 0,
msg_type: 0,
},
// 用户聊天记录
records: {
record_id: 0,
items: [],
isEmpty: false,
loadStatus: 0,
},
showBox: 0,
tabType: [
{ name: "全部", type: 0 },
{ name: "文件", type: 2 },
{ name: "会话记录", type: 3 },
{ name: "代码块", type: 4 },
{ name: "群投票", type: 5 },
],
search: {
keyword: "", // 关键字查询
date: "", // 时间查询
page: 1, // 当前分页
totalPage: 50, // 总分页
items: [], // 数据列表
isShowDate: false,
},
};
},
mounted() {
this.title = this.params.title;
this.query = {
talk_type: this.params.talk_type,
receiver_id: this.params.receiver_id,
msg_type: 0,
};
this.loadChatRecord(0);
},
created() {
this.loadFriends();
},
methods: {
download,
renderSize,
// 获取图片信息
getImgStyle(url) {
return imgZoom(url, 200);
},
// 获取会话记录消息名称
getForwardTitle(item) {
let arr = [...new Set(item.map((v) => v.nickname))];
return arr.join("、") + "的会话记录";
},
// 获取好友列表
loadFriends() {
ServeGetContacts().then(({ code, data }) => {
if (code == 200) {
this.contacts.friends = data.map((item) => {
return {
id: item.id,
type: 1,
avatar: item.avatar,
name: item.friend_remark ? item.friend_remark : item.nickname,
};
});
}
});
},
// 左侧联系人菜单点击事件
triggerMenuItem(item) {
this.title = item.name;
this.query.talk_type = item.type;
this.query.receiver_id = item.id;
this.showBox = 0;
this.triggerLoadType(0);
},
// 加载历史记录
loadChatRecord() {
let data = {
talk_type: this.query.talk_type,
receiver_id: this.query.receiver_id,
record_id: this.records.record_id,
msg_type: this.query.msg_type,
};
if (this.records.loadStatus == 1) return;
this.records.loadStatus = 1;
ServeFindTalkRecords(data)
.then((res) => {
if (res.code != 200) return;
let records = data.record_id == 0 ? [] : this.records.items;
records.push(...res.data.rows);
this.records.items = records;
this.records.loadStatus =
res.data.rows.length < res.data.limit ? 2 : 0;
if (this.records.items.length == 0) {
this.records.isEmpty = true;
} else {
this.records.record_id =
this.records.items[this.records.items.length - 1].id;
}
})
.catch(() => {
this.records.loadStatus = 0;
});
},
triggerLoadType(type) {
this.records.record_id = 0;
this.query.msg_type = type;
this.records.isEmpty = false;
this.records.items = [];
this.loadChatRecord();
},
searchText() {
if (this.search.keyword == "") {
this.showBox = 0;
return false;
}
this.$notify.info({
title: "消息",
message: "查询功能正在开发中...",
});
},
triggerBroadside() {
this.broadside = !this.broadside;
},
},
};
</script>
<style lang="less" scoped>
/deep/.el-scrollbar__wrap {
overflow-x: hidden;
}
.lum-dialog-mask {
z-index: 1;
}
.lum-dialog-box {
width: 100%;
height: 600px;
max-width: 800px;
transition: 1s ease;
&.full-screen {
width: 100%;
height: 100%;
max-width: unset;
margin: 0;
border-radius: 0px;
}
.sub-header {
height: 38px;
line-height: 38px;
font-size: 12px;
border-bottom: 1px solid #f9f4f4;
margin-top: 10px;
padding: 0 10px;
position: relative;
i {
font-size: 22px;
color: #6f6a6a;
}
.search-box {
position: absolute;
width: 230px;
height: 32px;
top: 2px;
right: 10px;
background: #f9f4f4;
border-radius: 5px;
i {
position: absolute;
left: 10px;
top: 8px;
font-size: 16px;
}
input {
position: absolute;
left: 35px;
top: 3px;
height: 25px;
width: 184px;
color: #7d7171;
background: #f9f4f4;
}
}
}
.broadside {
@border: 1px solid #f9f9f9;
border-right: @border;
user-select: none;
transition: 3s ease;
.aside-header {
display: flex;
flex-direction: row;
height: 100%;
border-bottom: @border;
padding: 0;
> div {
text-align: center;
line-height: 40px;
font-size: 13px;
font-weight: 400;
}
.item {
flex: 1;
cursor: pointer;
&.selected {
color: #66b1ff;
}
}
.item-shuxian {
flex-basis: 1px;
flex-shrink: 0;
color: rgb(232 224 224);
}
}
.contacts-item {
height: 35px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding-left: 10px;
position: relative;
.avatar {
flex-basis: 40px;
flex-shrink: 0;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.content {
flex: 1 1;
height: 100%;
line-height: 35px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 13px;
padding-right: 10px;
}
&:hover,
&.selected {
background-color: #f5f5f5;
}
}
}
}
/* first box */
.type-items {
padding: 0 0 0 10px;
line-height: 40px;
user-select: none;
border-bottom: 1px solid #f9f4f4;
.active {
color: #03a9f4;
font-weight: 500;
font-size: 13px;
}
span {
height: 40px;
width: 45px;
text-align: center;
cursor: pointer;
margin: 0 10px;
font-size: 12px;
font-weight: 400;
}
}
.history-record {
padding: 10px 0;
}
.load-button {
width: 100%;
height: 35px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
&.blue {
color: #51b2ff;
}
span {
margin-left: 5px;
font-size: 13px;
cursor: pointer;
user-select: none;
}
}
.empty-records {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
color: #cccccc;
font-weight: 300;
font-size: 14px;
img {
width: 100px;
}
}
@import "~@/assets/css/talk/talk-records.less";
</style>