|
@@ -1,155 +1,21 @@
|
|
<template>
|
|
<template>
|
|
<div class="cl-chat__wrap">
|
|
<div class="cl-chat__wrap">
|
|
<!-- 聊天窗口 -->
|
|
<!-- 聊天窗口 -->
|
|
- <cl-dialog :visible.sync="visible" v-bind="conf">
|
|
|
|
|
|
+ <cl-dialog
|
|
|
|
+ :visible.sync="visible"
|
|
|
|
+ :title="title"
|
|
|
|
+ :height="height"
|
|
|
|
+ :width="width"
|
|
|
|
+ :props="conf"
|
|
|
|
+ >
|
|
<div class="cl-chat">
|
|
<div class="cl-chat">
|
|
<!-- 会话区域 -->
|
|
<!-- 会话区域 -->
|
|
- <div class="cl-chat__session">
|
|
|
|
- <div class="cl-chat__session-search">
|
|
|
|
- <el-input
|
|
|
|
- v-model="session.keyWord"
|
|
|
|
- placeholder="搜索"
|
|
|
|
- prefix-icon="el-icon-search"
|
|
|
|
- size="small"
|
|
|
|
- clearable
|
|
|
|
- @clear="onSearch"
|
|
|
|
- @keyup.enter.native="onSearch"
|
|
|
|
- ></el-input>
|
|
|
|
- </div>
|
|
|
|
-
|
|
|
|
- <!-- 会话列表 -->
|
|
|
|
- <ul class="cl-chat__session-list scroller1" v-if="sessionList.length > 0">
|
|
|
|
- <li
|
|
|
|
- class="cl-chat__session-item"
|
|
|
|
- v-for="(item, index) in sessionList"
|
|
|
|
- :key="index"
|
|
|
|
- :class="{
|
|
|
|
- 'is-active': session.current ? item.id == session.current.id : false
|
|
|
|
- }"
|
|
|
|
- @click="sessionDetail(item)"
|
|
|
|
- @contextmenu.stop.prevent="openSessionCM($event, item.id, index)"
|
|
|
|
- >
|
|
|
|
- <!-- 头像 -->
|
|
|
|
- <div class="avatar">
|
|
|
|
- <el-badge
|
|
|
|
- :value="item.serviceUnreadCount"
|
|
|
|
- :hidden="item.serviceUnreadCount === 0"
|
|
|
|
- :max="99"
|
|
|
|
- >
|
|
|
|
- <img :src="item.headimgurl" alt="" />
|
|
|
|
- </el-badge>
|
|
|
|
- </div>
|
|
|
|
-
|
|
|
|
- <!-- 昵称,内容 -->
|
|
|
|
- <div class="det">
|
|
|
|
- <p class="name">{{ item.nickname }}</p>
|
|
|
|
- <p class="content">{{ item.lastMessage }}</p>
|
|
|
|
- </div>
|
|
|
|
- </li>
|
|
|
|
- </ul>
|
|
|
|
-
|
|
|
|
- <!-- 空态 -->
|
|
|
|
- <div class="cl-chat__session-empty" v-else>
|
|
|
|
- 没有搜索到内容...
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
|
|
+ <chat-session />
|
|
|
|
|
|
<!-- 会话详情 -->
|
|
<!-- 会话详情 -->
|
|
- <div class="cl-chat__detail">
|
|
|
|
- <template v-if="session.current">
|
|
|
|
- <div
|
|
|
|
- class="cl-chat__detail-container scroller1"
|
|
|
|
- ref="scroller"
|
|
|
|
- v-loading="message.loading"
|
|
|
|
- >
|
|
|
|
- <!-- 加载更多 -->
|
|
|
|
- <div class="cl-chat__detail-more" v-if="message.list.length > 0">
|
|
|
|
- <el-button
|
|
|
|
- round
|
|
|
|
- size="mini"
|
|
|
|
- :loading="message.loading"
|
|
|
|
- @click="onLoadmore"
|
|
|
|
- >加载更多</el-button
|
|
|
|
- >
|
|
|
|
- </div>
|
|
|
|
-
|
|
|
|
- <!-- 消息列表 -->
|
|
|
|
- <message :list="message.list" />
|
|
|
|
- </div>
|
|
|
|
-
|
|
|
|
- <div class="cl-chat__detail-footer">
|
|
|
|
- <!-- 工具栏 -->
|
|
|
|
- <div class="cl-chat__opbar">
|
|
|
|
- <ul>
|
|
|
|
- <!-- 表情 -->
|
|
|
|
- <li>
|
|
|
|
- <el-popover
|
|
|
|
- v-model="emoji.visible"
|
|
|
|
- placement="top-start"
|
|
|
|
- width="470"
|
|
|
|
- trigger="click"
|
|
|
|
- >
|
|
|
|
- <emoji @select="onEmojiSelect" />
|
|
|
|
- <img
|
|
|
|
- slot="reference"
|
|
|
|
- src="../static/images/emoji.png"
|
|
|
|
- alt=""
|
|
|
|
- />
|
|
|
|
- </el-popover>
|
|
|
|
- </li>
|
|
|
|
- <!-- 图片上传 -->
|
|
|
|
- <li hidden>
|
|
|
|
- <cl-upload
|
|
|
|
- accept="image/*"
|
|
|
|
- list-type
|
|
|
|
- :on-success="onImageSelect"
|
|
|
|
- >
|
|
|
|
- <img src="../static/images/image.png" alt="" />
|
|
|
|
- </cl-upload>
|
|
|
|
- </li>
|
|
|
|
- <!-- 视频上传 -->
|
|
|
|
- <li hidden>
|
|
|
|
- <cl-upload
|
|
|
|
- accept="video/*"
|
|
|
|
- list-type
|
|
|
|
- :before-upload="
|
|
|
|
- f => {
|
|
|
|
- onBeforeUpload(f, 'video');
|
|
|
|
- }
|
|
|
|
- "
|
|
|
|
- :on-progress="onUploadProgress"
|
|
|
|
- :on-success="
|
|
|
|
- (r, f) => {
|
|
|
|
- onUploadSuccess(r, f, 'video');
|
|
|
|
- }
|
|
|
|
- "
|
|
|
|
- >
|
|
|
|
- <img src="../static/images/video.png" alt="" />
|
|
|
|
- </cl-upload>
|
|
|
|
- </li>
|
|
|
|
- </ul>
|
|
|
|
- </div>
|
|
|
|
-
|
|
|
|
- <!-- 输入框,发送按钮 -->
|
|
|
|
- <div class="cl-chat__input">
|
|
|
|
- <el-input
|
|
|
|
- v-model="message.value"
|
|
|
|
- placeholder="请描述您想咨询的问题"
|
|
|
|
- type="textarea"
|
|
|
|
- :rows="5"
|
|
|
|
- @keyup.enter.native="onTextSend"
|
|
|
|
- ></el-input>
|
|
|
|
-
|
|
|
|
- <el-button
|
|
|
|
- type="primary"
|
|
|
|
- size="mini"
|
|
|
|
- :disabled="!message.value"
|
|
|
|
- @click="onTextSend"
|
|
|
|
- >发送</el-button
|
|
|
|
- >
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </template>
|
|
|
|
|
|
+ <div class="cl-chat__detail" v-if="session">
|
|
|
|
+ <chat-message />
|
|
|
|
+ <chat-input />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</cl-dialog>
|
|
</cl-dialog>
|
|
@@ -164,22 +30,36 @@
|
|
<script>
|
|
<script>
|
|
import dayjs from "dayjs";
|
|
import dayjs from "dayjs";
|
|
import { mapGetters } from "vuex";
|
|
import { mapGetters } from "vuex";
|
|
-import { isString, debounce } from "cl-admin/utils";
|
|
|
|
|
|
+import { parseContent } from "../utils";
|
|
|
|
+
|
|
import io from "socket.io-client";
|
|
import io from "socket.io-client";
|
|
import { socketUrl } from "@/config/env";
|
|
import { socketUrl } from "@/config/env";
|
|
-import Emoji from "./emoji";
|
|
|
|
|
|
+
|
|
|
|
+import Session from "./session";
|
|
import Message from "./message";
|
|
import Message from "./message";
|
|
-import { parseContent } from "../utils";
|
|
|
|
|
|
+import Input from "./input";
|
|
|
|
+import eventBus from "../utils/event-bus";
|
|
|
|
|
|
// 消息模式
|
|
// 消息模式
|
|
-const MODES = ["text", "image", "emoji", "voice", "video"];
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
name: "cl-chat",
|
|
name: "cl-chat",
|
|
|
|
|
|
components: {
|
|
components: {
|
|
- Message,
|
|
|
|
- Emoji
|
|
|
|
|
|
+ "chat-session": Session,
|
|
|
|
+ "chat-message": Message,
|
|
|
|
+ "chat-input": Input
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ props: {
|
|
|
|
+ height: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: "650px"
|
|
|
|
+ },
|
|
|
|
+ width: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: "1000px"
|
|
|
|
+ }
|
|
},
|
|
},
|
|
|
|
|
|
data() {
|
|
data() {
|
|
@@ -187,55 +67,25 @@ export default {
|
|
visible: false,
|
|
visible: false,
|
|
socket: null,
|
|
socket: null,
|
|
conf: {
|
|
conf: {
|
|
- title: "聊天对话框",
|
|
|
|
- height: "650px",
|
|
|
|
- width: "1000px",
|
|
|
|
- props: {
|
|
|
|
- modal: true,
|
|
|
|
- customClass: "cl-chat__dialog",
|
|
|
|
- "append-to-body": true,
|
|
|
|
- "close-on-click-modal": false
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- message: {
|
|
|
|
- list: [],
|
|
|
|
- pagination: {
|
|
|
|
- page: 1,
|
|
|
|
- size: 20,
|
|
|
|
- total: 0
|
|
|
|
- },
|
|
|
|
- loading: false,
|
|
|
|
- value: ""
|
|
|
|
- },
|
|
|
|
- session: {
|
|
|
|
- list: [],
|
|
|
|
- pagination: {
|
|
|
|
- page: 1,
|
|
|
|
- size: 100,
|
|
|
|
- total: 0
|
|
|
|
- },
|
|
|
|
- current: null,
|
|
|
|
- keyWord: ""
|
|
|
|
- },
|
|
|
|
- emoji: {
|
|
|
|
- visible: false
|
|
|
|
|
|
+ modal: true,
|
|
|
|
+ customClass: "cl-chat__dialog",
|
|
|
|
+ "append-to-body": true,
|
|
|
|
+ "close-on-click-modal": false
|
|
}
|
|
}
|
|
};
|
|
};
|
|
},
|
|
},
|
|
|
|
|
|
|
|
+ provide() {
|
|
|
|
+ return {
|
|
|
|
+ socket: this.socket
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+
|
|
computed: {
|
|
computed: {
|
|
- ...mapGetters(["userInfo", "token"]),
|
|
|
|
-
|
|
|
|
- sessionList() {
|
|
|
|
- return this.session.list
|
|
|
|
- .map(e => {
|
|
|
|
- let { _text } = parseContent(e);
|
|
|
|
- e.lastMessage = _text;
|
|
|
|
- return e;
|
|
|
|
- })
|
|
|
|
- .sort((a, b) => {
|
|
|
|
- return a.updateTime < b.updateTime ? 1 : -1;
|
|
|
|
- });
|
|
|
|
|
|
+ ...mapGetters(["token", "session", "sessionList"]),
|
|
|
|
+
|
|
|
|
+ title() {
|
|
|
|
+ return this.session ? `与 ${this.session.nickname} 聊天中` : "聊天对话框";
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
|
|
@@ -264,227 +114,12 @@ export default {
|
|
methods: {
|
|
methods: {
|
|
open() {
|
|
open() {
|
|
this.visible = true;
|
|
this.visible = true;
|
|
-
|
|
|
|
- this.refreshSession().then(res => {
|
|
|
|
- this.sessionDetail(res.list[0]);
|
|
|
|
- });
|
|
|
|
},
|
|
},
|
|
|
|
|
|
close() {
|
|
close() {
|
|
this.visible = false;
|
|
this.visible = false;
|
|
},
|
|
},
|
|
|
|
|
|
- // 上传前
|
|
|
|
- onBeforeUpload(file, key) {
|
|
|
|
- const data = {
|
|
|
|
- content: {
|
|
|
|
- [`${key}Url`]: ""
|
|
|
|
- },
|
|
|
|
- type: 0,
|
|
|
|
- contentType: MODES.indexOf(key),
|
|
|
|
- uid: file.uid,
|
|
|
|
- loading: true,
|
|
|
|
- progress: "0%"
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- this.append(data);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 上传中
|
|
|
|
- onUploadProgress(e, file) {
|
|
|
|
- let item = this.message.list.find(e => e.uid == file.uid);
|
|
|
|
-
|
|
|
|
- if (item) {
|
|
|
|
- item.progress = e.percent + "%";
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 上传成功
|
|
|
|
- onUploadSuccess(res, file, key) {
|
|
|
|
- let item = this.message.list.find(e => e.uid == file.uid);
|
|
|
|
-
|
|
|
|
- if (item) {
|
|
|
|
- item.loading = false;
|
|
|
|
- item.content[`${key}Url`] = res.data;
|
|
|
|
-
|
|
|
|
- this.sendMessage(item);
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 打开会话列表右键菜单
|
|
|
|
- openSessionCM(e, id, index) {
|
|
|
|
- this.$crud.openContextMenu(e, {
|
|
|
|
- list: [
|
|
|
|
- {
|
|
|
|
- label: "删除",
|
|
|
|
- icon: "el-icon-delete",
|
|
|
|
- callback: (_, done) => {
|
|
|
|
- this.$service.im.session.delete({
|
|
|
|
- ids: id
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- this.session.list.splice(index, 1);
|
|
|
|
-
|
|
|
|
- if (id == this.session.current.id) {
|
|
|
|
- this.sessionDetail();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- done();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- ]
|
|
|
|
- });
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 刷新会话列表
|
|
|
|
- refreshSession(params) {
|
|
|
|
- return this.$service.im.session
|
|
|
|
- .page({
|
|
|
|
- ...this.session.pagination,
|
|
|
|
- keyWord: this.session.keyWord,
|
|
|
|
- params,
|
|
|
|
- order: "updateTime",
|
|
|
|
- sort: "desc"
|
|
|
|
- })
|
|
|
|
- .then(res => {
|
|
|
|
- this.session.list = res.list;
|
|
|
|
- this.session.pagination = res.pagination;
|
|
|
|
-
|
|
|
|
- return res;
|
|
|
|
- });
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 刷新详情
|
|
|
|
- async sessionDetail(item) {
|
|
|
|
- if (item) {
|
|
|
|
- let { id } = this.session.current || {};
|
|
|
|
-
|
|
|
|
- if (id != item.id) {
|
|
|
|
- item.serviceUnreadCount = 0;
|
|
|
|
-
|
|
|
|
- this.conf.title = `与${item.nickname}聊天中`;
|
|
|
|
- this.message.loading = true;
|
|
|
|
- this.message.list = [];
|
|
|
|
- this.session.current = item;
|
|
|
|
-
|
|
|
|
- await this.refreshMessage({ page: 1 });
|
|
|
|
-
|
|
|
|
- this.message.loading = false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- this.scrollToBottom();
|
|
|
|
- } else {
|
|
|
|
- this.conf.title = "聊天对话框";
|
|
|
|
- this.message.list = [];
|
|
|
|
- this.session.current = null;
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 刷新消息列表
|
|
|
|
- refreshMessage(params) {
|
|
|
|
- return this.$service.im.message
|
|
|
|
- .page({
|
|
|
|
- ...this.message.pagination,
|
|
|
|
- ...params,
|
|
|
|
- sessionId: this.session.current.id,
|
|
|
|
- order: "createTime",
|
|
|
|
- sort: "desc"
|
|
|
|
- })
|
|
|
|
- .then(res => {
|
|
|
|
- this.message.pagination = res.pagination;
|
|
|
|
- this.prepend.apply(this, res.list);
|
|
|
|
- });
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 更新会话消息
|
|
|
|
- updateSession(data) {
|
|
|
|
- Object.assign(this.session.current, data);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 搜索关键字
|
|
|
|
- onSearch() {
|
|
|
|
- this.refreshSession({ page: 1 });
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 加载更多
|
|
|
|
- onLoadmore() {
|
|
|
|
- this.refreshMessage({ page: this.message.pagination.page + 1 });
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 滚动到底部
|
|
|
|
- scrollToBottom: debounce(function() {
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
- if (this.$refs["scroller"]) {
|
|
|
|
- this.$refs["scroller"].scrollTo({
|
|
|
|
- top: 99999,
|
|
|
|
- behavior: "smooth"
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- }, 300),
|
|
|
|
-
|
|
|
|
- // 发送文本内容
|
|
|
|
- onTextSend() {
|
|
|
|
- if (this.message.value) {
|
|
|
|
- if (this.message.value.replace(/\n/g, "") !== "") {
|
|
|
|
- const data = {
|
|
|
|
- type: 0,
|
|
|
|
- contentType: 0,
|
|
|
|
- content: {
|
|
|
|
- text: this.message.value
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- this.append(data);
|
|
|
|
- this.sendMessage(data);
|
|
|
|
-
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
- this.message.value = "";
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 图片选择
|
|
|
|
- onImageSelect(res) {
|
|
|
|
- const data = {
|
|
|
|
- content: {
|
|
|
|
- imageUrl: res.data
|
|
|
|
- },
|
|
|
|
- type: 0,
|
|
|
|
- contentType: 1
|
|
|
|
- };
|
|
|
|
- this.append(data);
|
|
|
|
- this.sendMessage(data);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 表情选择
|
|
|
|
- onEmojiSelect(url) {
|
|
|
|
- this.emoji.visible = false;
|
|
|
|
- const data = {
|
|
|
|
- content: {
|
|
|
|
- imageUrl: url
|
|
|
|
- },
|
|
|
|
- type: 0,
|
|
|
|
- contentType: 2
|
|
|
|
- };
|
|
|
|
- this.append(data);
|
|
|
|
- this.sendMessage(data);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 视频选择
|
|
|
|
- onVideoSelect(url) {
|
|
|
|
- const data = {
|
|
|
|
- content: {
|
|
|
|
- videoUrl: url
|
|
|
|
- },
|
|
|
|
- type: 0,
|
|
|
|
- contentType: 4
|
|
|
|
- };
|
|
|
|
- this.append(data);
|
|
|
|
- this.sendMessage(data);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
// 监听消息
|
|
// 监听消息
|
|
onMessage(msg) {
|
|
onMessage(msg) {
|
|
// 回调
|
|
// 回调
|
|
@@ -497,17 +132,17 @@ export default {
|
|
const { contentType, fromId, content, msgId } = JSON.parse(msg);
|
|
const { contentType, fromId, content, msgId } = JSON.parse(msg);
|
|
|
|
|
|
// 是否当前
|
|
// 是否当前
|
|
- const same = this.session.current && this.session.current.userId == fromId;
|
|
|
|
|
|
+ const same = this.session && this.session.userId == fromId;
|
|
|
|
|
|
if (same) {
|
|
if (same) {
|
|
// 更新消息
|
|
// 更新消息
|
|
- this.updateSession({
|
|
|
|
|
|
+ this.$store.commit("UPDATE_SESSION", {
|
|
contentType,
|
|
contentType,
|
|
content
|
|
content
|
|
});
|
|
});
|
|
|
|
|
|
// 追加消息
|
|
// 追加消息
|
|
- this.append({
|
|
|
|
|
|
+ eventBus.$emit("message-append", {
|
|
contentType,
|
|
contentType,
|
|
content: JSON.parse(content),
|
|
content: JSON.parse(content),
|
|
type: 1
|
|
type: 1
|
|
@@ -521,7 +156,7 @@ export default {
|
|
}
|
|
}
|
|
|
|
|
|
// 查找会话
|
|
// 查找会话
|
|
- let item = this.session.list.find(e => e.userId == fromId);
|
|
|
|
|
|
+ const item = this.sessionList.find(e => e.userId == fromId);
|
|
|
|
|
|
if (item) {
|
|
if (item) {
|
|
if (!same) {
|
|
if (!same) {
|
|
@@ -535,7 +170,7 @@ export default {
|
|
});
|
|
});
|
|
} else {
|
|
} else {
|
|
// 刷新会话列表
|
|
// 刷新会话列表
|
|
- this.refreshSession();
|
|
|
|
|
|
+ eventBus.$emit("session-refresh");
|
|
}
|
|
}
|
|
} catch (e) {
|
|
} catch (e) {
|
|
console.error("消息格式异常", e);
|
|
console.error("消息格式异常", e);
|
|
@@ -575,76 +210,6 @@ export default {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- },
|
|
|
|
-
|
|
|
|
- // 发送消息
|
|
|
|
- sendMessage({ contentType, content }) {
|
|
|
|
- const { id, userId } = this.session.current;
|
|
|
|
-
|
|
|
|
- // 更新消息
|
|
|
|
- this.updateSession({
|
|
|
|
- contentType,
|
|
|
|
- content
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- if (this.socket) {
|
|
|
|
- this.socket.emit(`user@${userId}`, {
|
|
|
|
- contentType,
|
|
|
|
- type: 0,
|
|
|
|
- content: JSON.stringify(content),
|
|
|
|
- sessionId: id
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 处理消息数据
|
|
|
|
- * mode: 消息模式
|
|
|
|
- * type: 消息类型 0-回复,1-反馈
|
|
|
|
- * duration: 时常
|
|
|
|
- * videoUrl: 视频地址
|
|
|
|
- * videoCoverUrl: 视频封面
|
|
|
|
- * imageUrl: 图片地址
|
|
|
|
- * avatarUrl: 头像地址
|
|
|
|
- * nickName: 昵称
|
|
|
|
- */
|
|
|
|
- handleMessage(e) {
|
|
|
|
- if (isString(e)) {
|
|
|
|
- e = JSON.parse(e);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (isString(e.content)) {
|
|
|
|
- e.content = JSON.parse(e.content);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 昵称
|
|
|
|
- const nickName = e.type == 0 ? this.userInfo.nickName : this.session.current.nickname;
|
|
|
|
- // 头像
|
|
|
|
- const avatarUrl =
|
|
|
|
- e.type == 0
|
|
|
|
- ? this.userInfo.avatarUrl || require("../static/images/custom-avatar.png")
|
|
|
|
- : this.session.current.headimgurl;
|
|
|
|
-
|
|
|
|
- return {
|
|
|
|
- ...e,
|
|
|
|
- avatarUrl,
|
|
|
|
- nickName,
|
|
|
|
- mode: MODES[e.contentType],
|
|
|
|
- date: dayjs().format("YYYY-MM-DD HH:mm:ss")
|
|
|
|
- };
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 追加数据到开头
|
|
|
|
- prepend(...data) {
|
|
|
|
- data.map(this.handleMessage).forEach(e => {
|
|
|
|
- this.message.list.unshift(e);
|
|
|
|
- });
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- // 追加数据到结尾
|
|
|
|
- append(...data) {
|
|
|
|
- this.message.list.push(...data.map(this.handleMessage));
|
|
|
|
- this.scrollToBottom();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
@@ -671,90 +236,6 @@ export default {
|
|
height: 100%;
|
|
height: 100%;
|
|
background-color: #f7f7f7;
|
|
background-color: #f7f7f7;
|
|
|
|
|
|
- &__session {
|
|
|
|
- height: calc(100% - 10px);
|
|
|
|
- width: 250px;
|
|
|
|
- margin: 5px 0 5px 5px;
|
|
|
|
- border-radius: 5px;
|
|
|
|
- background-color: #fff;
|
|
|
|
-
|
|
|
|
- &-search {
|
|
|
|
- padding: 10px;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &-list {
|
|
|
|
- height: calc(100% - 52px);
|
|
|
|
- overflow: auto;
|
|
|
|
-
|
|
|
|
- li {
|
|
|
|
- display: flex;
|
|
|
|
- list-style: none;
|
|
|
|
- padding: 10px;
|
|
|
|
- border-left: 5px solid #fff;
|
|
|
|
-
|
|
|
|
- .avatar {
|
|
|
|
- margin-right: 12px;
|
|
|
|
-
|
|
|
|
- img {
|
|
|
|
- display: block;
|
|
|
|
- height: 40px;
|
|
|
|
- width: 40px;
|
|
|
|
- border-radius: 3px;
|
|
|
|
- background-color: #eee;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- .el-badge {
|
|
|
|
- &__content {
|
|
|
|
- height: 14px;
|
|
|
|
- line-height: 14px;
|
|
|
|
- padding: 0 4px;
|
|
|
|
- background-color: #fa5151;
|
|
|
|
- border: 0;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- .det {
|
|
|
|
- flex: 1;
|
|
|
|
- .name {
|
|
|
|
- font-size: 13px;
|
|
|
|
- margin-top: 1px;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- .content {
|
|
|
|
- font-size: 12px;
|
|
|
|
- margin-top: 5px;
|
|
|
|
- color: #666;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- .name,
|
|
|
|
- .content {
|
|
|
|
- overflow: hidden;
|
|
|
|
- text-overflow: ellipsis;
|
|
|
|
- display: -webkit-box;
|
|
|
|
- -webkit-box-orient: vertical;
|
|
|
|
- -webkit-line-clamp: 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &.is-active {
|
|
|
|
- background-color: #eee;
|
|
|
|
- border-color: $color-primary;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &:hover {
|
|
|
|
- background-color: #eee;
|
|
|
|
- cursor: pointer;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &-empty {
|
|
|
|
- text-align: center;
|
|
|
|
- margin-top: 10px;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
&__detail {
|
|
&__detail {
|
|
display: flex;
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
@@ -762,63 +243,6 @@ export default {
|
|
height: 100%;
|
|
height: 100%;
|
|
padding: 5px;
|
|
padding: 5px;
|
|
box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
-
|
|
|
|
- &-container {
|
|
|
|
- flex: 1;
|
|
|
|
- border-radius: 5px;
|
|
|
|
- padding: 10px;
|
|
|
|
- overflow: auto;
|
|
|
|
- margin-bottom: 5px;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &-more {
|
|
|
|
- display: flex;
|
|
|
|
- justify-content: center;
|
|
|
|
- margin-bottom: 20px;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &-footer {
|
|
|
|
- background-color: #fff;
|
|
|
|
- padding: 10px;
|
|
|
|
- border-radius: 5px;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &__message {
|
|
|
|
- flex: 1;
|
|
|
|
- border-radius: 5px;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &__opbar {
|
|
|
|
- margin-bottom: 5px;
|
|
|
|
-
|
|
|
|
- ul {
|
|
|
|
- display: flex;
|
|
|
|
- li {
|
|
|
|
- list-style: none;
|
|
|
|
- margin-right: 10px;
|
|
|
|
- cursor: pointer;
|
|
|
|
-
|
|
|
|
- &:hover {
|
|
|
|
- opacity: 0.7;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- img {
|
|
|
|
- height: 26px;
|
|
|
|
- width: 26px;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- &__input {
|
|
|
|
- position: relative;
|
|
|
|
-
|
|
|
|
- .el-button {
|
|
|
|
- position: absolute;
|
|
|
|
- right: 10px;
|
|
|
|
- bottom: 10px;
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
</style>
|