Commit 452addc8 by Sixong.Zhu

eslint

parent a5b8ff29
<template> <template>
<div class="chat-container" :class="{'is-in-page': isInPage}"> <div class="chat-container" :class="{ 'is-in-page': isInPage }">
<div class="search-wrap" v-if="!modelName">
<div class="search-wrap" v-if="!modelName"> <el-input
<el-input class="keyword-input"
class="keyword-input" placeholder="会话标题"
placeholder="会话标题" prefix-icon="el-icon-search"
prefix-icon="el-icon-search" v-model="searchKeyword"
v-model="searchKeyword" v-on:keyup.enter.native="search"
v-on:keyup.enter.native="search" clearable
clearable @clear="search"
@clear="search" ></el-input>
></el-input> <i
<i v-if="!isInPage" class="close-btn el-icon-close" @click="$emit('close')"></i> v-if="!isInPage"
class="close-btn el-icon-close"
@click="$emit('close')"
></i>
</div>
<chat-list
v-if="!modelName"
ref="chatListComp"
@list-count-update="$emit('list-count-update', $event)"
/>
<chat-list-model
v-if="modelName"
@list-count-update="$emit('list-count-update', $event)"
ref="chatListModel"
:modelName="modelName"
:listName="listName"
/>
<div class="chat-content-wrap" v-if="chatVisible && onShow">
<chat
:modelName="modelName"
@updateActive="$emit('updateActive', $event)"
/>
</div>
</div> </div>
<chat-list v-if="!modelName" ref="chatListComp" @list-count-update="$emit('list-count-update', $event)" />
<chat-list-model v-if="modelName" @list-count-update="$emit('list-count-update', $event)" ref="chatListModel" :modelName="modelName" :listName="listName" />
<div class="chat-content-wrap" v-if="chatVisible && onShow" >
<chat :modelName="modelName" @updateActive="$emit('updateActive', $event)" />
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
...@@ -29,91 +45,94 @@ import chat from "@/customer-service/chat.vue"; ...@@ -29,91 +45,94 @@ import chat from "@/customer-service/chat.vue";
import { ChatStore, chatStore } from "@/customer-service/store/model"; import { ChatStore, chatStore } from "@/customer-service/store/model";
@Component({ @Component({
name: "ChatContainer", name: "ChatContainer",
components: { components: {
chat, chat,
ChatList, ChatList,
ChatListModel ChatListModel,
} },
}) })
export default class ChatContainer extends Vue { export default class ChatContainer extends Vue {
@Prop(Boolean) isInPage: boolean; @Prop(Boolean) isInPage: boolean;
@Prop(String) modelName: string; @Prop(String) modelName: string;
@Prop(String) listName: string; @Prop(String) listName: string;
@Prop(String) activeName: string; @Prop(String) activeName: string;
@Prop(Boolean) isActive: boolean; @Prop(Boolean) isActive: boolean;
private onShow = false; private onShow = false;
@chatStore.State(ChatStore.STATE_CHAT_DIALOG_VISIBLE) @chatStore.State(ChatStore.STATE_CHAT_DIALOG_VISIBLE)
private readonly chatVisible!: ChatStore.STATE_CHAT_DIALOG_VISIBLE; private readonly chatVisible!: ChatStore.STATE_CHAT_DIALOG_VISIBLE;
@chatStore.Mutation(ChatStore.MUTATION_HIDE_CHAT) @chatStore.Mutation(ChatStore.MUTATION_HIDE_CHAT)
private readonly hideChat: ChatStore.MUTATION_HIDE_CHAT private readonly hideChat: ChatStore.MUTATION_HIDE_CHAT;
@Ref("chatListComp") chatListComp: ChatList; @Ref("chatListComp") chatListComp: ChatList;
private searchKeyword = ""; private searchKeyword = "";
@Ref("chatListModel") chatListModel: ChatListModel; @Ref("chatListModel") chatListModel: ChatListModel;
private search() { private search() {
this.chatListComp.search(this.searchKeyword) this.chatListComp.search(this.searchKeyword);
} }
@Watch("isActive", {immediate: true}) isActiveUpdate() { @Watch("isActive", { immediate: true }) isActiveUpdate() {
this.onShow = this.isActive; this.onShow = this.isActive;
if (!this.onShow && this.activeName !== "my_receiving" || this.onShow && this.listName) { if (
this.chatListModel && this.chatListModel.clearActiveId(); (!this.onShow && this.activeName !== "my_receiving") ||
(this.onShow && this.listName)
) {
this.chatListModel && this.chatListModel.clearActiveId();
}
} }
}
private onChatDrawerClose(){ private onChatDrawerClose() {
this.hideChat() this.hideChat();
} }
} }
</script> </script>
<style lang="less"> <style lang="less">
.chat-container { .chat-container {
height: 70vh; height: 70vh;
&.is-in-page { &.is-in-page {
height: 100%; height: 100%;
} }
} }
.keyword-input { .keyword-input {
width: 300px; width: 300px;
margin: 15px 0 14px 20px; margin: 15px 0 14px 20px;
/deep/ .el-input__inner { /deep/ .el-input__inner {
font-size: 13px; font-size: 13px;
height: 30px; height: 30px;
line-height: 28px; line-height: 28px;
border-radius: 15px; border-radius: 15px;
padding-right: 15px; padding-right: 15px;
} }
/deep/ .el-icon-time { /deep/ .el-icon-time {
background: transparent; background: transparent;
} }
/deep/ .el-input__icon { /deep/ .el-input__icon {
line-height: 32px; line-height: 32px;
} }
} }
.search-wrap { .search-wrap {
height: 59px; height: 59px;
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;
} }
.close-btn { .close-btn {
float: right; float: right;
font-size: 20px; font-size: 20px;
color: #aaa; color: #aaa;
padding: 5px; padding: 5px;
cursor: pointer; cursor: pointer;
margin: 15px 10px 0; margin: 15px 10px 0;
} }
.chat-content-wrap { .chat-content-wrap {
display: inline-block; display: inline-block;
width: 75%; width: 75%;
height: calc(100% - 60px); height: calc(100% - 60px);
box-sizing: border-box; box-sizing: border-box;
vertical-align: top; vertical-align: top;
} }
</style> </style>
\ No newline at end of file
...@@ -26,14 +26,16 @@ ...@@ -26,14 +26,16 @@
:title="item.customer_name" :title="item.customer_name"
class="chat-name flex-fill text-dot-dot-dot" class="chat-name flex-fill text-dot-dot-dot"
> >
<span>{{ item.title || item.chat_id }}</span> <span>{{
item.title || item.chat_id
}}</span>
</div> </div>
<div v-if="item.last_msg_ts" class="chat-time"> <div v-if="item.last_msg_ts" class="chat-time">
{{ formatTimestamp(item.last_msg_ts) }} {{ formatTimestamp(item.last_msg_ts) }}
</div> </div>
</div> </div>
<div class="chat-msg text-dot-dot-dot"> <div class="chat-msg text-dot-dot-dot">
{{userNames[item.last_msg_sender] ? userNames[item.last_msg_sender] + ": " : ""}}{{ parseMesage(item) }} {{ buildLastMessage(item) }}
</div> </div>
</div> </div>
</div> </div>
...@@ -52,63 +54,15 @@ ...@@ -52,63 +54,15 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Ref, Vue } from "vue-property-decorator"; import { Component, Prop, Ref, Vue } from "vue-property-decorator";
import avatar from "@/customer-service/components/avatar.vue"; import avatar from "@/customer-service/components/avatar.vue";
import { chatStore, ChatStore } from "@/customer-service/store/model"; import { ChatStore } from "@/customer-service/store/model";
import { formatTime, TimeFormatRule } from "@/customer-service/utils/time";
import { Chat as ChatType } from "@/customer-service/xim/models/chat"; import { Chat as ChatType } from "@/customer-service/xim/models/chat";
import { EVENTS } from "@/EventConsts" import { EVENTS } from "@/EventConsts";
import Controller from "./controller/chat-list";
export function parserMessage(type: string, rawMsg: string) {
if (!type) return "";
if (!rawMsg) return "";
const msg = JSON.parse(rawMsg);
if (type === "text") {
return msg.text;
} else if (type === "image") {
return `[图片]`;
} else if (type === "file") {
return `[文件]`;
} else {
return `[系统自动回复]`;
}
}
@Component({ components: { avatar } }) @Component({ components: { avatar } })
export default class ChatList extends Vue { export default class ChatList extends Controller {
private searchKeyword = ""; private searchKeyword = "";
@chatStore.Action(ChatStore.ACTION_GET_MY_CHAT_LIST)
private readonly getMyChatList!: ChatStore.ACTION_GET_MY_CHAT_LIST;
@chatStore.State(ChatStore.STATE_CHAT_CURRENT_CHAT_ID)
private readonly chatId!: ChatStore.STATE_CHAT_CURRENT_CHAT_ID;
@chatStore.State(ChatStore.STATE_MY_CHAT_ROOM_LIST)
private readonly chatList!: ChatStore.STATE_MY_CHAT_ROOM_LIST;
@chatStore.State(ChatStore.STATE_CHAT_USERNAME)
private readonly userNames!: ChatStore.STATE_CHAT_USERNAME;
@chatStore.Action(ChatStore.ACTION_SAVE_CURRENT_CHAT_ID_VERSION)
private readonly saveChatId!: ChatStore.ACTION_SAVE_CURRENT_CHAT_ID_VERSION;
@chatStore.Mutation(ChatStore.MUTATION_SAVE_MYSELF_ID)
private readonly saveMyId!: ChatStore.MUTATION_SAVE_MYSELF_ID;
@chatStore.Mutation(ChatStore.MUTATION_SAVE_USERNAME)
private readonly updateUserName!: ChatStore.MUTATION_SAVE_USERNAME;
@chatStore.Mutation(ChatStore.MUTATION_SET_CHAT_SOURCE)
private readonly setSource!: ChatStore.MUTATION_SET_CHAT_SOURCE;
@chatStore.Mutation(ChatStore.MUTATION_SAVE_CHAT_TITLE)
private readonly saveChatTitle!: ChatStore.MUTATION_SAVE_CHAT_TITLE;
@chatStore.Mutation(ChatStore.MUTATION_SHOW_CHAT)
private readonly showChat: ChatStore.MUTATION_SHOW_CHAT;
@chatStore.Mutation(ChatStore.MUTATION_HIDE_CHAT)
private readonly hideChat: ChatStore.MUTATION_HIDE_CHAT;
@Prop({ type: Number, default: -1 }) @Prop({ type: Number, default: -1 })
private selected!: number; private selected!: number;
...@@ -118,11 +72,14 @@ export default class ChatList extends Vue { ...@@ -118,11 +72,14 @@ export default class ChatList extends Vue {
private unReadMsgCount = 0; private unReadMsgCount = 0;
private get chatRooms() { private get chatRooms() {
const list = this.chatList?.list.filter(chat => chat.title.indexOf(this.searchKeyword) > -1) || []; const list =
this.chatList?.list.filter(
(chat) => chat.title.indexOf(this.searchKeyword) > -1
) || [];
let unReadMsgCount = 0; let unReadMsgCount = 0;
list.filter(chat => chat.unread_msg_count > 0).forEach(chat => { list.filter((chat) => chat.unread_msg_count > 0).forEach((chat) => {
unReadMsgCount += chat.unread_msg_count unReadMsgCount += chat.unread_msg_count;
}) });
this.unReadMsgCount = unReadMsgCount; this.unReadMsgCount = unReadMsgCount;
this.$emit("list-count-update", this.unReadMsgCount); this.$emit("list-count-update", this.unReadMsgCount);
this.$eventHub.$emit(EVENTS.NewMsg, this.unReadMsgCount); this.$eventHub.$emit(EVENTS.NewMsg, this.unReadMsgCount);
...@@ -159,7 +116,7 @@ export default class ChatList extends Vue { ...@@ -159,7 +116,7 @@ export default class ChatList extends Vue {
this.showChat(); this.showChat();
this.close(); this.close();
if (data.unread_msg_count > 0) { if (data.unread_msg_count > 0) {
data.unread_msg_count = 0; data.unread_msg_count = 0;
} }
...@@ -169,23 +126,6 @@ export default class ChatList extends Vue { ...@@ -169,23 +126,6 @@ export default class ChatList extends Vue {
this.$emit("change"); this.$emit("change");
} }
private parseMesage(data: ChatType) {
if (data.last_msg_sender && data.last_msg_sender != "0") {
if (this.userNames[data.last_msg_sender] === undefined) {
this.updateUserName({id: data.last_msg_sender, name: ""});
this.sdk.model("user").detail(data.last_msg_sender).query().then(userInfo => {
this.updateUserName({id: data.last_msg_sender, name: userInfo.row.first_name.display as string});
})
}
}
if (data.last_msg_content === "") return "[暂无消息]";
return parserMessage(data.last_msg_type, data.last_msg_content);
}
private formatTimestamp(v: number) {
return formatTime(v, { short: true, rule: TimeFormatRule.Hour12 });
}
private close() { private close() {
this.$emit("close"); this.$emit("close");
} }
......
<template> <template>
<div class="chat-room-con h-100 pos-rel"> <div class="chat-room-con h-100 pos-rel">
<div class="chat-panel"> <div class="chat-panel">
<div class="chat-area h-100" ref="chatBox"> <div class="chat-area h-100 d-flex flex-column" ref="chatBox">
<div ref="top" class="chat-messages pos-rel" :class="{'is-not-chat-member': !isChatMember}"> <div
ref="top"
class="chat-messages pos-rel flex-fill"
:class="{ 'is-not-chat-member': !isChatMember }"
>
<div <div
v-if="getCurrentInputingPeople.length" v-if="getCurrentInputingPeople.length"
class="someone-inputing" class="someone-inputing"
...@@ -11,7 +15,13 @@ ...@@ -11,7 +15,13 @@
</div> </div>
<messages /> <messages />
</div> </div>
<div class="resize" title="收缩侧边栏" ref="resize" @mousedown="dragControllerDiv" v-if="isChatMember"></div> <div
class="resize"
title="收缩侧边栏"
ref="resize"
@mousedown="dragControllerDiv"
v-if="isChatMember"
></div>
<div ref="bottom" class="chat-input" v-if="isChatMember"> <div ref="bottom" class="chat-input" v-if="isChatMember">
<message-input @error="onError" /> <message-input @error="onError" />
</div> </div>
...@@ -20,7 +30,14 @@ ...@@ -20,7 +30,14 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Provide, Vue, Watch, Ref } from "vue-property-decorator"; import {
Component,
Prop,
Provide,
Vue,
Watch,
Ref,
} from "vue-property-decorator";
import MessageInput from "@/customer-service/components/message-input.vue"; import MessageInput from "@/customer-service/components/message-input.vue";
import messages from "@/customer-service/components/message-list.vue"; import messages from "@/customer-service/components/message-list.vue";
...@@ -106,7 +123,7 @@ export default class ChatRoom extends Vue { ...@@ -106,7 +123,7 @@ export default class ChatRoom extends Vue {
this.$message.error(msg); this.$message.error(msg);
} }
private dragControllerDiv(e:MouseEvent) { private dragControllerDiv(e: MouseEvent) {
let resize = this.refResize as any; let resize = this.refResize as any;
let top = this.refTop as HTMLElement; let top = this.refTop as HTMLElement;
let bottom = this.refBottom as HTMLElement; let bottom = this.refBottom as HTMLElement;
...@@ -126,9 +143,9 @@ export default class ChatRoom extends Vue { ...@@ -126,9 +143,9 @@ export default class ChatRoom extends Vue {
} }
let bottomHeight = box.clientHeight - moveLen; let bottomHeight = box.clientHeight - moveLen;
resize.style.top = moveLen + 'px'; // 设置左侧区域的宽度 resize.style.top = moveLen + "px"; // 设置左侧区域的宽度
top.style.height = moveLen + 'px'; top.style.height = moveLen + "px";
bottom.style.height = bottomHeight + 'px'; bottom.style.height = bottomHeight + "px";
}; };
// 鼠标松开事件 // 鼠标松开事件
document.onmouseup = function (evt) { document.onmouseup = function (evt) {
......
...@@ -14,21 +14,36 @@ ...@@ -14,21 +14,36 @@
<div v-else class="chat-status">接待中</div> <div v-else class="chat-status">接待中</div>
</template> </template>
</div> </div>
<div class="title-buttons"> <div class="title-buttons d-flex align-items-center">
<el-button
<el-button class="button" @click="startReception" round v-if="!isChatMember" class="button"
@click="startReception"
round
v-if="!isChatMember"
>我要接待</el-button >我要接待</el-button
> >
<el-button class="button" @click="exitChat" round v-if="isChatMember" <el-button
class="button"
@click="exitChat"
round
v-if="isChatMember"
>退出会话</el-button >退出会话</el-button
> >
<el-button class="button" @click="finishReception" round v-if="isChatMember && operatorType > 25" <el-button
class="button"
@click="finishReception"
round
v-if="isChatMember && operatorType > 25"
>结束接待</el-button >结束接待</el-button
> >
<el-button class="button" @click="showAddMember" round <el-button class="button" @click="showAddMember" round
>添加客服</el-button >添加客服</el-button
> >
<i v-if="close && isSingleChat" @click="close" class="title-close el-icon-close" /> <i
v-if="close && isSingleChat"
@click="close"
class="title-close el-icon-close"
/>
</div> </div>
<ChatCreator <ChatCreator
v-if="visible" v-if="visible"
...@@ -115,9 +130,9 @@ export default class ChatTitle extends Vue { ...@@ -115,9 +130,9 @@ export default class ChatTitle extends Vue {
private async exitChat() { private async exitChat() {
try { try {
if (this.operatorType == '25') { if (this.operatorType == "25") {
await this._userExitChat(); await this._userExitChat();
} else if (+this.operatorType > 25){ } else if (+this.operatorType > 25) {
await this._csExitChat(); await this._csExitChat();
} }
this.hideChat(); this.hideChat();
...@@ -129,18 +144,22 @@ export default class ChatTitle extends Vue { ...@@ -129,18 +144,22 @@ export default class ChatTitle extends Vue {
private async startReception() { private async startReception() {
try { try {
await this._startReception(); await this._startReception();
this.$emit("updateActive", "my_receiving") this.$emit("updateActive", "my_receiving");
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
} }
private async finishReception() { private async finishReception() {
await this.$confirm("确定要结束接待吗?结束接待将会终止客服会话", "提示", { await this.$confirm(
confirmButtonText: "确定", "确定要结束接待吗?结束接待将会终止客服会话",
cancelButtonText: "取消", "提示",
type: "warning", {
}) confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
);
await this._finishReception(); await this._finishReception();
this.hideChat(); this.hideChat();
} }
...@@ -167,7 +186,7 @@ export default class ChatTitle extends Vue { ...@@ -167,7 +186,7 @@ export default class ChatTitle extends Vue {
.title-close { .title-close {
color: #8d959d; color: #8d959d;
cursor: pointer; cursor: pointer;
margin-left:30px; margin-left: 30px;
} }
} }
</style> </style>
import { Component, Vue } from "vue-property-decorator";
import { chatStore, ChatStore } from "@/customer-service/store/model";
import { parserMessage } from ".";
import { Chat as ChatItem } from "@/customer-service/xim/models/chat";
import { formatTime, TimeFormatRule } from "@/customer-service/utils/time";
@Component({ components: {} })
export default class ChatList extends Vue {
@chatStore.Action(ChatStore.ACTION_GET_MY_CHAT_LIST)
protected readonly getMyChatList!: ChatStore.ACTION_GET_MY_CHAT_LIST;
@chatStore.State(ChatStore.STATE_CHAT_CURRENT_CHAT_ID)
protected readonly chatId!: ChatStore.STATE_CHAT_CURRENT_CHAT_ID;
@chatStore.State(ChatStore.STATE_MY_CHAT_ROOM_LIST)
protected readonly chatList!: ChatStore.STATE_MY_CHAT_ROOM_LIST;
@chatStore.State(ChatStore.STATE_CHAT_USERNAME)
protected readonly userNames!: ChatStore.STATE_CHAT_USERNAME;
@chatStore.Action(ChatStore.ACTION_SAVE_CURRENT_CHAT_ID_VERSION)
protected readonly saveChatId!: ChatStore.ACTION_SAVE_CURRENT_CHAT_ID_VERSION;
@chatStore.Mutation(ChatStore.MUTATION_SAVE_MYSELF_ID)
protected readonly saveMyId!: ChatStore.MUTATION_SAVE_MYSELF_ID;
@chatStore.Mutation(ChatStore.MUTATION_SAVE_USERNAME)
protected readonly updateUserName!: ChatStore.MUTATION_SAVE_USERNAME;
@chatStore.Mutation(ChatStore.MUTATION_SET_CHAT_SOURCE)
protected readonly setSource!: ChatStore.MUTATION_SET_CHAT_SOURCE;
@chatStore.Mutation(ChatStore.MUTATION_SAVE_CHAT_TITLE)
protected readonly saveChatTitle!: ChatStore.MUTATION_SAVE_CHAT_TITLE;
@chatStore.Mutation(ChatStore.MUTATION_SHOW_CHAT)
protected readonly showChat: ChatStore.MUTATION_SHOW_CHAT;
@chatStore.Mutation(ChatStore.MUTATION_HIDE_CHAT)
protected readonly hideChat: ChatStore.MUTATION_HIDE_CHAT;
protected parseMesage(data: ChatItem) {
if (data.last_msg_sender && data.last_msg_sender != "0") {
if (this.userNames[data.last_msg_sender] === undefined) {
this.updateUserName({ id: data.last_msg_sender, name: "" });
this.sdk
.model("user")
.detail(data.last_msg_sender)
.query()
.then((userInfo) => {
this.updateUserName({
id: data.last_msg_sender,
name: userInfo.row.first_name.display as string,
});
});
}
}
if (data.last_msg_content === "") {
return "[暂无消息]";
}
return parserMessage(data.last_msg_type, data.last_msg_content);
}
protected formatTimestamp(v: number) {
return formatTime(v, { short: true, rule: TimeFormatRule.Hour12 });
}
protected buildLastMessage(item: ChatItem) {
const sender = this.userNames[item.last_msg_sender];
if (sender) {
return `${sender}: ${this.parseMesage(item)}`;
}
return this.parseMesage(item);
}
}
export function parserMessage(type: string, rawMsg: string) {
if (!type) return "";
if (!rawMsg) return "";
const msg = JSON.parse(rawMsg);
if (type === "text") {
return msg.text;
} else if (type === "image") {
return `[图片]`;
} else if (type === "file") {
return `[文件]`;
} else {
return `[系统自动回复]`;
}
}
...@@ -35,8 +35,8 @@ class Chat { ...@@ -35,8 +35,8 @@ class Chat {
EmojiService.raiseOnReady(this.token); EmojiService.raiseOnReady(this.token);
option.sdk().events.addTokenChanged(token => { option.sdk().events.addTokenChanged((token) => {
this.setToken(() => new Promise(resolve => resolve(token))); this.setToken(() => new Promise((resolve) => resolve(token)));
}); });
return this.initChatSdk(option.webSocketUri); return this.initChatSdk(option.webSocketUri);
...@@ -49,7 +49,7 @@ class Chat { ...@@ -49,7 +49,7 @@ class Chat {
public getSdk = () => { public getSdk = () => {
if (this._sdk == null) { if (this._sdk == null) {
throw new Error("sdk shouldn't undefined"); throw new Error("sdk shouldn't undefined");
}; }
return this._sdk(); return this._sdk();
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment