Commit 03c9c8d6 by panjiangyi

格式化代码

parent 342401e1
......@@ -71,25 +71,26 @@
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from "vue-property-decorator"
import { chatStore, ChatStore } from "@/customer-service/store/model"
import buttonThrottle from "@/utils/button-throttle";
import { Component, Prop, Vue } from "vue-property-decorator";
import { chatStore, ChatStore } from "@/customer-service/store/model";
// import { popupService } from "@/views/common-module/component/element-upgrades/fast-service-popup";
import buttonThrottle from "@/utils/button-throttle"
import Chat from "@/customer-service/xim"
import { formatTime, TimeFormatRule } from "@/customer-service/utils/time"
import { formatTime, TimeFormatRule } from "@/customer-service/utils/time";
import Chat from "@/customer-service/xim";
export function parserMessage(type: string, rawMsg: string) {
if (!type) return ""
if (!rawMsg) return ""
const msg = JSON.parse(rawMsg)
if (!type) return "";
if (!rawMsg) return "";
const msg = JSON.parse(rawMsg);
if (type === "text") {
return msg.text
return msg.text;
} else if (type === "image") {
return `[图片]`
return `[图片]`;
} else if (type === "file") {
return `[文件]`
return `[文件]`;
} else {
;`[不支持的消息格式]`
return `[不支持的消息格式]`;
}
}
type Chat = ChatStore.STATE_MY_CHAT_ROOM_LIST["list"][number]
......@@ -101,8 +102,10 @@ export default class ChatList extends Vue {
@chatStore.State(ChatStore.STATE_CHAT_CURRENT_CHAT_ID)
private readonly chatId!: ChatStore.STATE_CHAT_CURRENT_CHAT_ID
@chatStore.State(ChatStore.STATE_CHAT_CURRENT_CHAT_UNIPLAT_ID)
private readonly currentChatUniplatId!: ChatStore.STATE_CHAT_CURRENT_CHAT_UNIPLAT_ID
@chatStore.State(ChatStore.STATE_CHAT_CURRENT_CHAT_VERSION)
private readonly uniplatVersion!: ChatStore.STATE_CHAT_CURRENT_CHAT_VERSION
......@@ -127,58 +130,58 @@ export default class ChatList extends Vue {
private searchKeyword = ""
private get chatRooms() {
return this.chatList?.list || []
return this.chatList?.list || [];
}
private isSelected(item: Chat) {
if (this.currentChatUniplatId) {
return item.uniplatId === this.currentChatUniplatId
return item.uniplatId === this.currentChatUniplatId;
}
return this.selected === item.uniplatId
return this.selected === item.uniplatId;
}
async created() {
await this.getMyChatList()
this.setSource(ChatStore.StateChatSourceDirection.Server)
this.selectFirstChat()
await this.getMyChatList();
this.setSource(ChatStore.StateChatSourceDirection.Server);
this.selectFirstChat();
}
mounted() {
this.saveMyId()
this.goToOnlyRoom()
this.saveMyId();
this.goToOnlyRoom();
}
private goToOnlyRoom() {
if (this.chatRooms.length === 1) {
const wantedChat = this.chatRooms[0]
this.goToChatRoom(wantedChat)
const wantedChat = this.chatRooms[0];
this.goToChatRoom(wantedChat);
}
}
private selectFirstChat() {
if (this.chatId != null) return
if (!this.chatRooms.length) return
const { chat_id, uniplat_version, uniplatId } = this.chatRooms[0]
if (this.chatId != null) return;
if (!this.chatRooms.length) return;
const { chat_id, uniplat_version, uniplatId } = this.chatRooms[0];
this.saveChatId({
chatId: chat_id,
v: uniplat_version,
uniplatId,
})
});
}
@buttonThrottle()
private async search() {
this.searchKeyword = this.searchKeyword.trim()
this.searchKeyword = this.searchKeyword.trim();
if (!this.searchKeyword) {
await this.getMyChatList()
await this.getMyChatList();
} else {
await this.getMyChatList(this.searchKeyword)
await this.getMyChatList(this.searchKeyword);
}
}
private goToChatRoom(data: Chat) {
if (this.currentChatUniplatId === data.uniplatId) {
return
return;
}
this.saveChatId({
......@@ -186,21 +189,21 @@ export default class ChatList extends Vue {
.chat_id,
v: data.uniplat_version,
uniplatId: data.uniplatId,
}).finally(this.raiseChatIdChanged)
}).finally(this.raiseChatIdChanged);
this.saveChatTitle(data.uniplatId)
this.saveChatTitle(data.uniplatId);
}
private raiseChatIdChanged() {
this.$emit("change")
this.$emit("change");
}
private parseMesage(data: Chat) {
return parserMessage(data.msg_type, data.msg)
return parserMessage(data.msg_type, data.msg);
}
private formatTimestamp(v: number) {
return formatTime(v, { short: true, rule: TimeFormatRule.Hour12 })
return formatTime(v, { short: true, rule: TimeFormatRule.Hour12 });
}
}
</script>
......
......@@ -86,17 +86,18 @@
<script lang="ts">
import {
Component,
Watch,
Vue,
Ref,
Provide,
Prop,
} from "vue-property-decorator"
import MessageInput from "@/customer-service/message-input.vue"
import messages from "@/customer-service/message-list.vue"
Provide,
Ref,
Vue,
Watch,
} from "vue-property-decorator";
import MessageInput from "@/customer-service/message-input.vue";
import messages from "@/customer-service/message-list.vue";
// import CusomterInfo from "./customer-info.vue"
// import OrderInfo from "./order-info.vue"
import { ChatStore, chatStore } from "@/customer-service/store/model"
import { ChatStore, chatStore } from "@/customer-service/store/model";
type RoomInfoTab = "customer" | "order"
......@@ -114,25 +115,31 @@ export default class ChatRoom extends Vue {
@chatStore.Mutation(ChatStore.MUTATION_CLEAR_CURRENT_CHAT_MEMBERS)
private readonly clearChatMembers!: ChatStore.MUTATION_CLEAR_CURRENT_CHAT_MEMBERS
@chatStore.State(ChatStore.STATE_CURRENT_CHAT_TITLE)
private readonly chatTitle!: ChatStore.STATE_CURRENT_CHAT_TITLE
@chatStore.State(ChatStore.STATE_CURRENT_CHAT_INPUTING)
private readonly currentInputPeople!: ChatStore.STATE_CURRENT_CHAT_INPUTING
@chatStore.State(ChatStore.STATE_CHAT_CURRENT_CHAT_UNIPLAT_ID)
private readonly currentChatUniplatId!: ChatStore.STATE_CHAT_CURRENT_CHAT_UNIPLAT_ID
@chatStore.State(ChatStore.STATE_MY_CHAT_ROOM_LIST)
private readonly myChatList!: ChatStore.STATE_MY_CHAT_ROOM_LIST
private allChatList = { list: [] }
@Prop({ type: Function })
private close?: () => void
@Provide() showReadSummary = true
@Watch("currentChatUniplatId")
private whenCurrentChatIdChanged(newValue: string, oldValue: string) {
if (Number(oldValue) === Number(newValue)) return
this.hideMembers()
this.clearChatMembers()
if (Number(oldValue) === Number(newValue)) return;
this.hideMembers();
this.clearChatMembers();
}
private activeTab: RoomInfoTab = "customer"
......@@ -141,38 +148,41 @@ export default class ChatRoom extends Vue {
private get getCurrentInputingPeople() {
return this.currentInputPeople
.map((k) => "" /* this.userInfo[k].name */)
.join("、")
.join("、");
}
private get currentChat() {
const chatId = this.currentChatUniplatId
let result = this.myChatList.list.find((k) => k.uniplatId === chatId)
if (result) return result
result = this.allChatList.list.find((k) => k.uniplatId === chatId)
return result ?? {}
const chatId = this.currentChatUniplatId;
let result = this.myChatList.list.find((k) => k.uniplatId === chatId);
if (result) return result;
result = this.allChatList.list.find((k) => k.uniplatId === chatId);
return result ?? {};
}
private get notOnlyCheck(): boolean {
return true
return true;
}
private get customerInfoTabShow() {
return this.activeTab === "customer"
return this.activeTab === "customer";
}
private get orderInfoTabShow() {
return this.activeTab === "order"
return this.activeTab === "order";
}
private showMembers() {
this.membersPanelVisibility = !this.membersPanelVisibility
this.membersPanelVisibility = !this.membersPanelVisibility;
}
private hideMembers() {
this.membersPanelVisibility = false
this.membersPanelVisibility = false;
}
private onError(msg: string) {
console.error(msg)
this.$message.error(msg)
// eslint-disable-next-line no-console
console.error(msg);
this.$message.error(msg);
}
}
</script>
......
......@@ -19,11 +19,13 @@
</el-dialog>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator"
import MessageList from "./message-list.vue"
import ChatRoom from "./chat-room.vue"
import ChatList from "./chat-list.vue"
import { ChatStore, chatStore } from "@/customer-service/store/model"
import { Component, Vue } from "vue-property-decorator";
import ChatList from "./chat-list.vue";
import ChatRoom from "./chat-room.vue";
import MessageList from "./message-list.vue";
import { ChatStore, chatStore } from "@/customer-service/store/model";
@Component({ components: { MessageList, ChatRoom, ChatList } })
export default class Chat extends Vue {
......@@ -32,13 +34,15 @@ export default class Chat extends Vue {
@chatStore.State(ChatStore.STATE_CHAT_DIALOG_VISIBLE)
private readonly visible: ChatStore.STATE_CHAT_DIALOG_VISIBLE
@chatStore.Mutation(ChatStore.MUTATION_HIDE_CHAT)
private readonly hide: ChatStore.MUTATION_HIDE_CHAT
@chatStore.Action(ChatStore.ACTION_TERINATE_CHAT)
private readonly _terminate: ChatStore.ACTION_TERINATE_CHAT
private terminate() {
this._terminate()
this._terminate();
}
}
</script>
......
......@@ -3,9 +3,10 @@
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator"
import { Model } from "vue-property-decorator"
import { FileType, getSvg } from "./file-controller"
import { Component, Model, Vue } from "vue-property-decorator"
;
import { FileType, getSvg } from "./file-controller";
@Component({ components: {} })
export default class FileIcon extends Vue {
......@@ -13,55 +14,55 @@ export default class FileIcon extends Vue {
private value!: FileType
private get audio() {
return this.value === FileType.Audio
return this.value === FileType.Audio;
}
private get excel() {
return this.value === FileType.Excel
return this.value === FileType.Excel;
}
private get image() {
return this.value === FileType.Image
return this.value === FileType.Image;
}
private get others() {
return this.value === FileType.Others
return this.value === FileType.Others;
}
private get pdf() {
return this.value === FileType.Pdf
return this.value === FileType.Pdf;
}
private get ppt() {
return this.value === FileType.Ppt
return this.value === FileType.Ppt;
}
private get rp() {
return this.value === FileType.Rp
return this.value === FileType.Rp;
}
private get txt() {
return this.value === FileType.Txt
return this.value === FileType.Txt;
}
private get video() {
return this.value === FileType.Video
return this.value === FileType.Video;
}
private get word() {
return this.value === FileType.Word
return this.value === FileType.Word;
}
private get xmid() {
return this.value === FileType.Xmind
return this.value === FileType.Xmind;
}
private get zip() {
return this.value === FileType.Zip
return this.value === FileType.Zip;
}
private get html() {
return getSvg(this.value)
return getSvg(this.value);
}
}
</script>
......
......@@ -31,7 +31,7 @@
</template>
<script lang="ts">
import { Component, Vue, Model, Prop } from "vue-property-decorator"
import { Component, Model, Prop, Vue } from "vue-property-decorator";
@Component({ components: {} })
export default class ImagePreview extends Vue {
......@@ -42,8 +42,8 @@ export default class ImagePreview extends Vue {
private file!: { name: string; url: string }
private style: {
"max-height": number | string
"max-width": number | string
"max-height": number | string;
"max-width": number | string;
} = {
"max-height": "300px",
"max-width": "600px",
......@@ -54,19 +54,19 @@ export default class ImagePreview extends Vue {
() =>
(this.style = { "max-height": "300px", "max-width": "600px" }),
300
)
this.$emit("update", false)
);
this.$emit("update", false);
}
private set2Default() {
this.style = { "max-height": "1600px", "max-width": "1600px" }
this.style = { "max-height": "1600px", "max-width": "1600px" };
}
private get getAttachment() {
if (this.file) {
return this.file.name
return this.file.name;
}
return "文件下载"
return "文件下载";
}
}
</script>
......
......@@ -142,25 +142,28 @@
</template>
<script lang="ts">
import { Component, Vue, Prop, Ref, Inject } from "vue-property-decorator"
import * as dto from "../model"
import chat from "./../xim"
import { chatStore, ChatStore } from "@/customer-service/store/model"
import FileIcon from "./file-icon.vue"
import { Component, Inject, Prop, Ref, Vue } from "vue-property-decorator";
import * as dto from "../model";
import { isAccessibleUrl } from "../service/tools";
import { replaceText2Link } from "../utils";
import chat from "./../xim";
import {
FileType,
getFileType,
isAudio,
isImage,
isVideo,
MAX_FILE_SIZE,
MAX_IMAGE_SIZE,
isImage,
} from "./file-controller"
import VoiceIcon from "./voice.vue"
import WhoReadList from "./who-read-list.vue"
import VideoPlayerIcon from "./video-player-icon.vue"
import { replaceText2Link } from "../utils"
import { isAccessibleUrl } from "../service/tools"
} from "./file-controller";
import FileIcon from "./file-icon.vue";
import VideoPlayerIcon from "./video-player-icon.vue";
import VoiceIcon from "./voice.vue";
import WhoReadList from "./who-read-list.vue";
import { chatStore, ChatStore } from "@/customer-service/store/model";
@Component({
components: { FileIcon, VoiceIcon, WhoReadList, VideoPlayerIcon },
......@@ -168,6 +171,7 @@ import { isAccessibleUrl } from "../service/tools"
export default class Message extends Vue {
@chatStore.State(ChatStore.STATE_CHAT_MY_ID)
private readonly chatMyId!: ChatStore.STATE_CHAT_MY_ID
@chatStore.Getter(ChatStore.GETTER_CURRENT_CHAT_PRESENT_MEMBERS)
private readonly chatMembers!: ChatStore.GETTER_CURRENT_CHAT_PRESENT_MEMBERS
......@@ -211,127 +215,127 @@ export default class Message extends Vue {
private org = ""
private get isAllRead() {
return this.data.read_count >= this.data.total_read_count
return this.data.read_count >= this.data.total_read_count;
}
private get messageBody(): { eid?: string; oid?: string; msg: any } {
if (this.data) {
try {
return { ...this.data, msg: JSON.parse(this.data.msg) }
return { ...this.data, msg: JSON.parse(this.data.msg) };
} catch {
return {
...this.data,
msg: JSON.parse(this.data.msg.replace(/\n/g, "\\n")),
}
};
}
}
return { msg: { text: "" } }
return { msg: { text: "" } };
}
private get getAttachment() {
if (this.messageBody) {
return this.messageBody.msg.name
return this.messageBody.msg.name;
}
return "文件下载"
return "文件下载";
}
private get isMyMessage() {
if (this.isSendingMessage) {
return true
return true;
}
if (this.messageBody) {
const msg = this.messageBody
const msg = this.messageBody;
if (this.chatSource) {
const source = msg.msg.source
const source = msg.msg.source;
if (source) {
return (
source === this.chatSource &&
this.messageBody.eid === this.chatMyId
)
);
}
if (this.org && this.messageBody.oid) {
return (
this.messageBody.oid === this.org &&
this.messageBody.eid === this.chatMyId
)
);
}
return false
return false;
}
return this.messageBody.eid === this.chatMyId
return this.messageBody.eid === this.chatMyId;
}
return false
return false;
}
private get username() {
const avatar = chat.getUserMapping()
if (this.data == null) return ""
if (avatar == null) return this.data.id
const value = avatar[this.data.eid]
if (value == null) return ""
if (value.name == null) return ""
return value.name
const avatar = chat.getUserMapping();
if (this.data == null) return "";
if (avatar == null) return this.data.id;
const value = avatar[this.data.eid];
if (value == null) return "";
if (value.name == null) return "";
return value.name;
}
private get avatar() {
const avatar = chat.getUserMapping()
const avatar = chat.getUserMapping();
if (this.isSendingMessage) {
if (avatar && this.chatMyId) {
const user = avatar[this.chatMyId]
const user = avatar[this.chatMyId];
if (user && user.avatar) {
return user.avatar
return user.avatar;
}
}
}
if (avatar && this.data) {
const value = avatar[this.data.eid]
const value = avatar[this.data.eid];
if (value && value.avatar) {
return value.avatar
return value.avatar;
}
}
return ""
return "";
}
private get fileIcon() {
if (this.data) {
return getFileType(this.messageBody.msg.name)
return getFileType(this.messageBody.msg.name);
}
return FileType.Others
return FileType.Others;
}
private get messageType() {
const type = this.data?.type
const type = this.data?.type;
if (type === "file") {
const name = this.messageBody?.msg.name
const name = this.messageBody?.msg.name;
if (name) {
const size = this.messageBody?.msg.size
const size = this.messageBody?.msg.size;
if (size) {
const outImageSize = size > MAX_IMAGE_SIZE
const outImageSize = size > MAX_IMAGE_SIZE;
if (!outImageSize && isImage(name)) {
return "image"
return "image";
}
const outSize = size > MAX_FILE_SIZE
const outSize = size > MAX_FILE_SIZE;
if (!outSize) {
if (isAudio(name)) {
return "voice"
return "voice";
}
if (isVideo(name)) {
return "video"
return "video";
}
}
}
}
}
return this.data?.type
return this.data?.type;
}
// 图片的样式设置,通过js偶尔会有高度计算不准确, 直接通过css的处理目前看可以达到对应效果
......@@ -347,45 +351,45 @@ export default class Message extends Vue {
// }
private get duration() {
const v = this.messageBody.msg.duration as number
return v || 0
const v = this.messageBody.msg.duration as number;
return v || 0;
}
private get durationInSecond() {
return Math.round(this.duration / 1000)
return Math.round(this.duration / 1000);
}
private get getVoiceMessageWidth() {
if (this.fileFailed2Load) {
return 35
return 35;
}
const d = this.duration / 1000
const d = this.duration / 1000;
if (d <= 3) {
return 60
return 60;
}
if (d >= 60) {
return 200
return 200;
}
return 60 + d
return 60 + d;
}
private isCustomer() {
return !this.showReadSummary
return !this.showReadSummary;
}
private buildMessageUrl() {
if (this.messageRealUrl || this.loadingRealUrl) {
return
return;
}
const url = this.messageBody.msg.url as string
const url = this.messageBody.msg.url as string;
if (url) {
// const service = XimService.getInstance()
if (isAccessibleUrl(url)) {
return (this.messageRealUrl = url)
return (this.messageRealUrl = url);
}
this.loadingRealUrl = true
this.loadingRealUrl = true;
// service
// .getFileUrlById(url, this.chatId || 0, this.isCustomer())
// .then((data) => {
......@@ -398,43 +402,43 @@ export default class Message extends Vue {
// .catch(() => (this.fileFailed2Load = true))
// .finally(() => (this.loadingRealUrl = false))
} else {
this.fileFailed2Load = true
this.fileFailed2Load = true;
}
}
private openFile() {
if (this.isSendingMessage) {
return
return;
}
if (this.failed || this.fileFailed2Load) {
return
return;
}
const copy = { ...this.messageBody.msg }
const copy = { ...this.messageBody.msg };
if (this.messageRealUrl) {
copy.url = this.messageRealUrl
copy.url = this.messageRealUrl;
}
this.$emit("open", { type: this.messageType, msg: copy })
this.$emit("open", { type: this.messageType, msg: copy });
}
private play() {
if (this.audioRef?.paused) {
this.audioRef?.load()
this.audioRef?.play()
this.audioRef?.load();
this.audioRef?.play();
} else {
this.audioRef?.pause()
this.audioRef?.pause();
}
}
private onPlay() {
this.playing = true
this.playing = true;
}
private onPause() {
this.playing = false
this.playing = false;
}
private format2Link(text: string) {
return replaceText2Link(text)
return replaceText2Link(text);
}
}
</script>
......
......@@ -30,7 +30,7 @@
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator"
import { Component, Vue } from "vue-property-decorator";
@Component({ components: {} })
export default class VideoPlayerIcon extends Vue {}
......
......@@ -37,7 +37,7 @@
</template>
<script lang="ts">
import { Component, Vue, Model, Prop, Ref, Watch } from "vue-property-decorator"
import { Component, Model, Prop, Ref, Vue, Watch } from "vue-property-decorator";
@Component({ components: {} })
export default class VideoPreview extends Vue {
......@@ -51,8 +51,8 @@ export default class VideoPreview extends Vue {
private video!: HTMLVideoElement
private style: {
"max-height": number | string
"max-width": number | string
"max-height": number | string;
"max-width": number | string;
} = {
"max-height": "800px",
"max-width": "800px",
......@@ -63,28 +63,28 @@ export default class VideoPreview extends Vue {
() =>
(this.style = { "max-height": "300px", "max-width": "600px" }),
300
)
this.$emit("update", false)
);
this.$emit("update", false);
}
private set2Default() {
this.style = { "max-height": "1600px", "max-width": "1600px" }
this.style = { "max-height": "1600px", "max-width": "1600px" };
}
private get getAttachment() {
if (this.file) {
return this.file.name
return this.file.name;
}
return "视频下载"
return "视频下载";
}
@Watch("value")
private onOpen() {
if (this.value) {
this.video?.load()
setTimeout(() => this.video?.play(), 100)
this.video?.load();
setTimeout(() => this.video?.play(), 100);
} else {
this.video?.pause()
this.video?.pause();
}
}
}
......
......@@ -32,9 +32,9 @@
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator"
import { Prop } from "vue-property-decorator"
import { Watch } from "vue-property-decorator"
import { Component, Prop, Vue, Watch } from "vue-property-decorator"
;
@Component({ components: {} })
export default class VoiceIcon extends Vue {
......@@ -51,21 +51,21 @@ export default class VoiceIcon extends Vue {
private onLoadingChanged() {
if (this.loading) {
this.interval = window.setInterval(() => {
const v = this.status + 1
const v = this.status + 1;
if (v > 3) {
this.status = 0
this.status = 0;
} else {
this.status = v
this.status = v;
}
}, 500)
}, 500);
} else {
clearInterval(this.interval)
this.status = 0
clearInterval(this.interval);
this.status = 0;
}
}
beforeDestroy() {
clearInterval(this.interval)
clearInterval(this.interval);
}
}
</script>
......@@ -41,19 +41,21 @@
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Ref } from "vue-property-decorator"
import { namespace } from "vuex-class"
import { ChatStore } from "@/customer-service/store/model"
import xim from "@/customer-service/xim/xim"
import { unique } from "../utils"
import chat from "../xim"
import * as dto from "../model"
import { Component, Prop, Ref, Vue } from "vue-property-decorator";
import { namespace } from "vuex-class";
const chatStoreNamespace = namespace("chatStore")
import * as dto from "../model";
import { unique } from "../utils";
import { ChatStore } from "@/customer-service/store/model";
import xim from "@/customer-service/xim/xim";
const chatStoreNamespace = namespace("chatStore");
@Component({ components: {} })
export default class WhoReadList extends Vue {
@chatStoreNamespace.State(ChatStore.STATE_CHAT_CURRENT_CHAT_ID)
private readonly chatId!: ChatStore.STATE_CHAT_CURRENT_CHAT_ID
@chatStoreNamespace.State(ChatStore.STATE_CHAT_MY_ID)
private readonly chatMyId!: ChatStore.STATE_CHAT_MY_ID
......@@ -61,6 +63,7 @@ export default class WhoReadList extends Vue {
type: Number,
})
private msgId!: number
@Ref("list-con")
private listCon!: HTMLElement
......@@ -70,74 +73,79 @@ export default class WhoReadList extends Vue {
private unreadlist: { name: string; avatar: string }[] = []
private loading = false
private startLoading() {
this.loading = true
this.loading = true;
}
private endLoading() {
this.loading = false
this.loading = false;
}
public async created() {
this.startLoading()
await this.getReader()
this.endLoading()
this.startLoading();
await this.getReader();
this.endLoading();
}
public mounted() {
this.enableBlur()
this.enableBlur();
const { top, left } = (
this.listCon.parentNode as HTMLElement
).getBoundingClientRect()
this.top = top
this.left = left
).getBoundingClientRect();
this.top = top;
this.left = left;
}
private enableBlur() {
this.listCon.setAttribute("tabindex", "-1")
this.listCon.focus()
this.listCon.setAttribute("tabindex", "-1");
this.listCon.focus();
}
private async getUserNameByid(eid: string) {
const data = await this.sdk.model("user").detail(eid).query()
return data.row.first_name.value as string
const data = await this.sdk.model("user").detail(eid).query();
return data.row.first_name.value as string;
}
private async getReader() {
if (this.chatId == null) return
if (this.msgId == null) return
const userInfo = chat.getUserMapping()
const data = await xim.fetchMsgInBox(this.chatId, this.msgId)
if (this.chatId == null) return;
if (this.msgId == null) return;
const data = await xim.fetchMsgInBox(this.chatId, this.msgId);
const readerlist = this.uniqueReaderList(
data.args[0] as dto.OneWhoReadMessage[]
)
);
this.readlist = await Promise.all(
readerlist
.filter((k) => k.is_read)
.filter((k) => k.eid !== this.chatMyId)
.map(async (k) => {
const eid = k.eid
const name = await this.getUserNameByid(eid)
const eid = k.eid;
const name = await this.getUserNameByid(eid);
return {
eid,
name,
avatar: "",
}
};
})
)
);
this.unreadlist = await Promise.all(
readerlist
.filter((k) => !k.is_read)
.filter((k) => k.eid !== this.chatMyId)
.map(async (k) => {
const eid = k.eid
const name = await this.getUserNameByid(eid)
const eid = k.eid;
const name = await this.getUserNameByid(eid);
return {
eid,
name,
avatar: "",
}
};
})
)
);
}
private uniqueReaderList(data: dto.OneWhoReadMessage[]) {
return unique(data, function (item, all) {
return all.findIndex((k) => k.eid === item.eid)
})
return all.findIndex((k) => k.eid === item.eid);
});
}
}
</script>
......
......@@ -237,7 +237,7 @@ export default class Input extends Vue {
}
} else {
promiseArr.push(
new Promise<void>((reslove) => {
new Promise<void>((resolve) => {
const contentType = items[i].type;
items[i].getAsString((k) => {
/*
......@@ -267,7 +267,7 @@ export default class Input extends Vue {
}
} while (result);
}
reslove();
resolve();
});
})
);
......@@ -514,10 +514,6 @@ export default class Input extends Vue {
this.emojiPanelVisibility = false;
}
private noop() {
}
private setupEmoji() {
EmojiService.onReady(() => {
const service = new EmojiService();
......
......@@ -9,23 +9,26 @@
</div>
</template>
<script lang="ts">
import { Component, Ref, Vue, Watch } from "vue-property-decorator"
import { Component, Ref, Vue, Watch } from "vue-property-decorator";
import ChatInput, {
FILE_INFO_CLASS,
isImageOrFile,
} from "./hybrid-input/index.vue"
import { ChatStore, chatStore } from "@/customer-service/store/model"
import { ChatLoggerService } from "./xim/logger"
import xim from "./xim/xim"
import { Message } from "./model"
import { uploadFile } from "./service/upload"
} from "./hybrid-input/index.vue";
import { Message } from "./model";
import { uploadFile } from "./service/upload";
import { ChatLoggerService } from "./xim/logger";
import xim from "./xim/xim";
import { ChatStore, chatStore } from "@/customer-service/store/model";
let sendingMessageIndex = 1
let sendingMessageIndex = 1;
@Component({ components: { ChatInput } })
export default class MessageInput extends Vue {
@chatStore.State(ChatStore.STATE_CHAT_DIALOG_VISIBLE)
private readonly chatRoomVisible: ChatStore.STATE_CHAT_DIALOG_VISIBLE
@chatStore.Action(ChatStore.ACTION_SEND_MESSAGE)
private readonly sendMsg!: ChatStore.ACTION_SEND_MESSAGE
......@@ -55,44 +58,45 @@ export default class MessageInput extends Vue {
@Watch("chatRoomVisible")
private whenChatRoomShow() {
if (!this.chatRoomVisible) return
this.chatInput.focus()
if (!this.chatRoomVisible) return;
this.chatInput.focus();
}
private async sendMessage(msg: ChildNode[], done: () => void) {
if (this.chatIniting) {
return
return;
}
for (const item of msg) {
if (isImageOrFile(item)) {
if ((item as Element).classList.contains(FILE_INFO_CLASS)) {
this.sendFile(item, "file")
this.sendFile(item, "file");
} else {
this.sendFile(item, "image")
this.sendFile(item, "image");
}
continue
continue;
}
if (item.textContent) {
this.sendText(item.textContent)
this.sendText(item.textContent);
}
}
ChatLoggerService.logger?.debug("all messages sent")
done()
this.$emit("sent")
ChatLoggerService.logger?.debug("all messages sent");
done();
this.$emit("sent");
}
private async onInput() {
if (this.chatId == null) return
await xim.inputing(this.chatId)
if (this.chatId == null) return;
await xim.inputing(this.chatId);
}
private sendText(text: string) {
if (text && text.trim()) {
const msg = { text: text.trim() }
const msg = { text: text.trim() };
if (this.source) {
Object.assign(msg, { source: this.source })
Object.assign(msg, { source: this.source });
}
this.sendMsg({ msgType: "text", msg: JSON.stringify(msg) })
this.sendMsg({ msgType: "text", msg: JSON.stringify(msg) });
}
}
......@@ -100,24 +104,24 @@ export default class MessageInput extends Vue {
const src = JSON.parse(
file.attributes[`data-${type}`]?.value || ""
) as {
url: string
name: string
size: number
}
url: string;
name: string;
size: number;
};
if (src) {
const index = this.sendSendingMessage(type, src)
const file = await this.readBlobUrl2Base64(src.url, src.name)
const index = this.sendSendingMessage(type, src);
const file = await this.readBlobUrl2Base64(src.url, src.name);
if (file) {
let w = 0
let h = 0
let w = 0;
let h = 0;
if (type === "image") {
const img = new Image()
img.src = src.url
const img = new Image();
img.src = src.url;
img.onload = function () {
w = img.naturalWidth
h = img.naturalHeight
}
img.remove()
w = img.naturalWidth;
h = img.naturalHeight;
};
img.remove();
}
uploadFile(file, this.chatId || 0, w, h)
.then((r) => {
......@@ -126,42 +130,43 @@ export default class MessageInput extends Vue {
url: r,
name: file.name,
size: file.size,
}
};
if (this.source) {
Object.assign(msg, { source: this.source })
Object.assign(msg, { source: this.source });
}
if (w && h) {
Object.assign(msg, { w, h })
Object.assign(msg, { w, h });
}
this.sendMsg({
msgType: type,
msg: JSON.stringify(msg),
})
this.removeSendingMessages(index)
URL.revokeObjectURL(src.url)
});
this.removeSendingMessages(index);
URL.revokeObjectURL(src.url);
} else {
this.setMsg2Failed(index)
this.setMsg2Failed(index);
}
})
.catch((e) => {
console.error(e)
// eslint-disable-next-line no-console
console.error(e);
this.setMsg2Failed(index)
})
this.setMsg2Failed(index);
});
}
}
}
private setMsg2Failed(index: number) {
this.failedSendingMessage(index)
this.failedSendingMessage(index);
}
private sendSendingMessage(type: string, msg: any) {
const index = sendingMessageIndex++
const index = sendingMessageIndex++;
if (this.source) {
Object.assign(msg, { source: this.source, eid: this.chatMyId })
Object.assign(msg, { source: this.source, eid: this.chatMyId });
}
if (this.chatId) {
this.appendSendingMessages({
......@@ -170,20 +175,20 @@ export default class MessageInput extends Vue {
ts: Date.now(),
type,
msg: JSON.stringify(msg),
} as Message)
return -index
} as Message);
return -index;
}
return 0
return 0;
}
private readBlobUrl2Base64(url: string, name: string) {
return fetch(url)
.then((r) => r.blob())
.then((blob) => new File([blob], name))
.then((blob) => new File([blob], name));
}
private onError(e: any) {
this.$emit("error", e.message || e)
this.$emit("error", e.message || e);
}
}
</script>
......@@ -43,14 +43,16 @@
</template>
<script lang="ts">
import { Component, Vue, Ref, Prop, Watch } from "vue-property-decorator"
import message from "./components/message.vue"
import { ChatStore, chatStore } from "@/customer-service/store/model"
import { throttle } from "./utils"
import { formatTime } from "./utils/time"
import { Message } from "./model"
import ImagePreview from "./components/image-preview.vue"
import VideoPreview from "./components/video-preview.vue"
import { Component, Prop, Ref, Vue, Watch } from "vue-property-decorator";
import ImagePreview from "./components/image-preview.vue";
import message from "./components/message.vue";
import VideoPreview from "./components/video-preview.vue";
import { Message } from "./model";
import { throttle } from "./utils";
import { formatTime } from "./utils/time";
import { ChatStore, chatStore } from "@/customer-service/store/model";
@Component({ components: { message, ImagePreview, VideoPreview } })
export default class MessageList extends Vue {
......@@ -89,16 +91,16 @@ export default class MessageList extends Vue {
if (this.sendingMessages) {
return [...this.historyMessage, ...this.sendingMessages].filter(
(i) => i.chat_id === this.chatId
)
);
}
return this.historyMessage
return this.historyMessage;
}
if (this.sendingMessages) {
return this.sendingMessages.filter((i) => i.chat_id === this.chatId)
return this.sendingMessages.filter((i) => i.chat_id === this.chatId);
}
return []
return [];
}
// 添加时间戳的最大间隔消息数
......@@ -114,37 +116,39 @@ export default class MessageList extends Vue {
@Ref("message-scrollbar")
private scollbarElement!: Vue & {
update: () => void
update: () => void;
}
private get scollWrapper(): HTMLElement | null {
return this.scollbarElement?.$el?.firstChild as HTMLElement
return this.scollbarElement?.$el?.firstChild as HTMLElement;
}
@Watch("messages")
private whenHasMessages() {
this.$nextTick(() => this.scollbarElement.update())
this.$nextTick(() => this.scollbarElement.update());
}
@Watch("preview")
private onPreviewChanged() {
if (!this.preview) {
this.raiseFileOpen(false)
this.raiseFileOpen(false);
}
}
@Watch("previewVideo")
private onVideoPreviewChanged() {
if (!this.previewVideo) {
this.raiseFileOpen(false)
this.raiseFileOpen(false);
}
}
private raiseFileOpen(value: boolean) {
this.$emit("file-open", value)
this.$emit("file-open", value);
}
private get messageTimestampDictionary() {
const dic = {} as { [prop: number]: boolean }
let count = 0
const dic = {} as { [prop: number]: boolean };
let count = 0;
if (this.historyMessage) {
this.historyMessage.forEach((message, index, array) => {
......@@ -153,15 +157,15 @@ export default class MessageList extends Vue {
this.whetherShowTime(array[index - 1], message) ||
count === this.timeLimit - 1
) {
dic[message.id] = true
count = 0
dic[message.id] = true;
count = 0;
} else {
count++
count++;
}
})
});
}
return dic
return dic;
}
private loading = false
......@@ -169,163 +173,167 @@ export default class MessageList extends Vue {
private loadingNew = false
public created() {
this.handleScrollWrapper()
this.handleScrollWrapper();
}
public mounted() {
this.scollWrapper &&
this.scollWrapper.addEventListener("scroll", this.handleScroll)
this.saveScrollToBottomFunc(this.scrollToNewMsg)
this.scollWrapper.addEventListener("scroll", this.handleScroll);
this.saveScrollToBottomFunc(this.scrollToNewMsg);
}
public beforeDestroy() {
this.scollWrapper &&
this.scollWrapper.removeEventListener("scroll", this.handleScroll)
this.clearScrollToBottomFunc()
this.clearChatId()
this.scollWrapper.removeEventListener("scroll", this.handleScroll);
this.clearScrollToBottomFunc();
this.clearChatId();
}
public scroll2End(delay?: number) {
this.$nextTick(() => {
const wrap = this.scollbarElement?.$el.querySelector(
".el-scrollbar__wrap"
) as HTMLElement
) as HTMLElement;
if (wrap) {
if (delay) {
setTimeout(() => {
wrap.scrollTop = 10000
}, delay)
return
wrap.scrollTop = 10000;
}, delay);
return;
}
wrap.scrollTop = 10000
wrap.scrollTop = 10000;
}
})
});
}
private startLoading() {
this.loading = true
this.loading = true;
}
private endLoading() {
this.loading = false
this.loading = false;
}
private startLoadingOld() {
this.startLoading()
this.loadingOld = true
this.startLoading();
this.loadingOld = true;
}
private endLoadingOld() {
this.endLoading()
this.loadingOld = false
this.endLoading();
this.loadingOld = false;
}
private startLoadingNew() {
this.startLoading()
this.loadingNew = true
this.startLoading();
this.loadingNew = true;
}
private endLoadingNew() {
this.endLoading()
this.loadingNew = false
this.endLoading();
this.loadingNew = false;
}
private handleScroll!: () => void
private handleScrollWrapper() {
let oldScrollTop = 0
let oldScrollTop = 0;
this.handleScroll = () => {
const wrapper = this.scollWrapper
const gap = 150
if (wrapper == null) return
const view = wrapper.firstChild as HTMLElement
const wrapperH = wrapper.getBoundingClientRect().height
const viewH = view.getBoundingClientRect().height
let scrollUp = false
let scrollDown = false
const wrapper = this.scollWrapper;
const gap = 150;
if (wrapper == null) return;
const view = wrapper.firstChild as HTMLElement;
const wrapperH = wrapper.getBoundingClientRect().height;
const viewH = view.getBoundingClientRect().height;
let scrollUp = false;
let scrollDown = false;
if (oldScrollTop > wrapper.scrollTop) {
scrollUp = true
scrollDown = false
scrollUp = true;
scrollDown = false;
} else if (oldScrollTop < wrapper.scrollTop) {
scrollUp = false
scrollDown = true
scrollUp = false;
scrollDown = true;
}
this.forbidScrollTopToZero(wrapper)
this.forbidScrollTopToZero(wrapper);
if (wrapper.scrollTop <= gap) {
scrollUp && this.fetchOldMsg()
scrollUp && this.fetchOldMsg();
}
if (wrapper.scrollTop - 40 - (viewH - wrapperH) >= -gap) {
scrollDown && this.fetchNewMsg()
scrollDown && this.fetchNewMsg();
}
oldScrollTop = wrapper.scrollTop
}
oldScrollTop = wrapper.scrollTop;
};
}
/* scrollTop为0时,新加载的消息后,滚动条也会保持在0的位置 */
private forbidScrollTopToZero(ele: HTMLElement) {
if (ele.scrollTop <= 10) {
ele.scrollTop = 10
ele.scrollTop = 10;
}
}
private scrollToNewMsg() {
this.$nextTick(() => {
if (this.loading) return
this.scroll2End()
})
if (this.loading) return;
this.scroll2End();
});
}
@throttle()
private async fetchOldMsg() {
if (this.loading) return
const msg = this.historyMessage
if (msg == null) return
if (msg.length === 0) return
this.startLoadingOld()
const msgId = msg[0].id
const data = await this.getLastPageMsg(msgId)
if (this.loading) return;
const msg = this.historyMessage;
if (msg == null) return;
if (msg.length === 0) return;
this.startLoadingOld();
const msgId = msg[0].id;
const data = await this.getLastPageMsg(msgId);
if (data.length === 0) {
console.log("没有更多老消息了")
// eslint-disable-next-line no-console
console.log("没有更多老消息了");
}
this.$emit("last-page", msgId)
this.endLoadingOld()
this.$emit("last-page", msgId);
this.endLoadingOld();
}
@throttle()
private async fetchNewMsg() {
if (this.loading) return
const msg = this.historyMessage
if (msg == null) return
if (msg.length === 0) return
this.startLoadingNew()
const msgId = msg[msg.length - 1].id
const data = await this.getNextPageMsg(msgId)
if (this.loading) return;
const msg = this.historyMessage;
if (msg == null) return;
if (msg.length === 0) return;
this.startLoadingNew();
const msgId = msg[msg.length - 1].id;
const data = await this.getNextPageMsg(msgId);
if (data.length === 0) {
console.log("没有更多新消息了")
// eslint-disable-next-line no-console
console.log("没有更多新消息了");
}
this.$emit("next-page", msgId)
this.endLoadingNew()
this.$emit("next-page", msgId);
this.endLoadingNew();
}
private format2Time(time: number) {
return formatTime(time)
return formatTime(time);
}
private whetherShowTime(previous: Message, current: Message) {
return current.ts - previous.ts > 180
return current.ts - previous.ts > 180;
}
private open(file: {
type: string
msg: { url: string; name: string; size: number }
type: string;
msg: { url: string; name: string; size: number };
}) {
if (file.type === "image") {
this.imagePreview = file.msg
this.preview = true
return this.raiseFileOpen(true)
this.imagePreview = file.msg;
this.preview = true;
return this.raiseFileOpen(true);
}
if (file.type === "video") {
this.videoPreview = file.msg
this.previewVideo = true
return this.raiseFileOpen(true)
this.videoPreview = file.msg;
this.previewVideo = true;
return this.raiseFileOpen(true);
}
}
......@@ -333,14 +341,14 @@ export default class MessageList extends Vue {
* 获取当期消息列表头尾消息的id
*/
public getStart2EndMessageIds() {
const v: { start: number; end: number } = { start: 0, end: 0 }
const v: { start: number; end: number } = { start: 0, end: 0 };
if (this.historyMessage && this.historyMessage.length) {
const start = this.historyMessage[0]
v.start = start.id
const end = this.historyMessage[this.historyMessage.length - 1]
v.end = end.id
const start = this.historyMessage[0];
v.start = start.id;
const end = this.historyMessage[this.historyMessage.length - 1];
v.end = end.id;
}
return v
return v;
}
}
</script>
......
import { RootStoreState } from "@/store/model";
import { Module } from "vuex";
import { ChatMember } from "../model";
......@@ -5,28 +6,25 @@ import { isAccessibleUrl } from "../service/tools";
import { unique } from "../utils";
import { decode } from "../utils/jwt";
import Chat from "../xim";
import chat from "../xim/";
import chatType from "../xim/chat-type";
import xim, { ChatNotifyListener } from "../xim/xim";
import { ChatMemberType, ChatStatus, ChatStore, ChatStoreState } from "./model";
import { RootStoreState } from "@/store/model";
export const ns = ChatStore.ns;
const sdk = chat.getSdk;
const sdk = Chat.getSdk;
const UniplatChatModelName = "UniplatChat";
const model = () => sdk().model(UniplatChatModelName);
const orgId = chat.getOrgId;
const getMyinfo = (function () {
let data;
return async () => {
if (data != null) return data;
data = sdk().getUserInfo();
return data;
};
})();
const orgId = Chat.getOrgId;
// const getMyinfo = (function () {
// let data;
// return async () => {
// if (data != null) return data;
// data = sdk().getUserInfo();
// return data;
// };
// })();
function uniqueMessages(
messages: NonNullable<ChatStore.STATE_CHAT_MSG_HISTORY>
) {
......@@ -49,23 +47,23 @@ const removeRegisterChatEvents: (() => void)[] = [];
async function preCacheImgs(msgs: any[]) {
await Promise.all(
msgs.map((k) => {
return new Promise((done: (p: void) => void) => {
return new Promise((resolve: (p: void) => void) => {
if (k.type === "image") {
const msg = JSON.parse(k.msg);
const url = msg.url;
if (!isAccessibleUrl(url)) {
done();
resolve();
}
if (url && isAccessibleUrl(url)) {
const preCache = new Image();
preCache.src = url;
preCache.onload = () => done();
setTimeout(done, 2000);
preCache.onload = () => resolve();
setTimeout(resolve, 2000);
} else {
done();
resolve();
}
} else {
done();
resolve();
}
});
})
......@@ -291,7 +289,7 @@ export default {
actions: {
async [ChatStore.ACTION_GET_MY_CHAT_LIST](
{ commit },
...params: Parameters<ChatStore.ACTION_GET_MY_CHAT_LIST>
// ...params: Parameters<ChatStore.ACTION_GET_MY_CHAT_LIST>
) {
const { pageData } = await model().list().query({
pageIndex: 1,
......@@ -316,12 +314,12 @@ export default {
total: pageData.record_count,
});
},
async [ChatStore.ACTION_JOIN_CHAT](
{ commit },
chatId: Parameters<ChatStore.ACTION_JOIN_CHAT>[0]
) {
// return await XimService.getInstance().joinChat(chatId)
},
// async [ChatStore.ACTION_JOIN_CHAT](
// { commit },
// chatId: Parameters<ChatStore.ACTION_JOIN_CHAT>[0]
// ) {
// // return await XimService.getInstance().joinChat(chatId)
// },
async [ChatStore.ACTION_GET_CHAT_MESSAGES]({ state, commit }) {
const chatId = state[ChatStore.STATE_CHAT_CURRENT_CHAT_ID];
if (chatId == null) return;
......@@ -332,6 +330,7 @@ export default {
commit(ChatStore.MUTATION_SCROLL_TO_BOTTOM);
return data;
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
}
},
......@@ -379,6 +378,7 @@ export default {
await dispatch(ChatStore.ACTION_GET_FRESH_MESSAGE);
return data;
} catch (error) {
// eslint-disable-next-line no-console
console.error("testing 信息发送失败", error);
}
},
......@@ -397,7 +397,7 @@ export default {
msgs[msgs.length - 1].id
);
}
const lastMsg = newMsgsArr[newMsgsArr.length - 1];
// const lastMsg = newMsgsArr[newMsgsArr.length - 1];
await preCacheImgs(newMsgsArr);
commit(ChatStore.MUTATION_SCROLL_TO_BOTTOM);
},
......@@ -432,7 +432,7 @@ export default {
detailManager.done();
const { id } = await action.dryExecute();
// 无法得到chat id
const data = await sdk()
await sdk()
.model(UniplatChatModelName)
.action("createXimChat")
.updateInitialParams({
......@@ -451,13 +451,13 @@ export default {
uniplatId: newChat.uniplatId,
});
},
async [ChatStore.ACTION_CREATE_NEW_CHAT_BY_CLIENT_SIDE](
{ commit, dispatch },
option: {
customerServiceId?: number | string;
customerServiceGroupId?: number;
}
) {},
// async [ChatStore.ACTION_CREATE_NEW_CHAT_BY_CLIENT_SIDE](
// { commit, dispatch },
// option: {
// customerServiceId?: number | string;
// customerServiceGroupId?: number;
// }
// ) {},
async [ChatStore.ACTION_REGISTER_EVENT]({ dispatch, commit, state }) {
const chatId = state[ChatStore.STATE_CHAT_CURRENT_CHAT_ID];
if (chatId == null) return;
......@@ -471,7 +471,6 @@ export default {
) {
return;
}
console.log("事件消息已读", e);
if (chatId !== e.chat_id) return;
const msgs = state[ChatStore.STATE_CHAT_MSG_HISTORY];
if (msgs == null) return;
......@@ -554,6 +553,7 @@ export default {
phone: info.row.last_name.value as string,
};
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
result = member;
}
......
......@@ -25,14 +25,14 @@ export class ImageCompresser {
maxWidth: number,
maxHeight: number
): Promise<File | null> {
return new Promise((resolve, reject) => {
return new Promise<File>((resolve, reject) => {
const img = new Image();
const reader = new FileReader();
reader.onload = (e) => {
if (e && e.target && e.target.result) {
img.src = e.target.result as string;
} else {
reject();
reject(new Error("file load failed"));
}
};
reader.readAsDataURL(file);
......@@ -49,7 +49,7 @@ export class ImageCompresser {
newFile.size <= file.size ? newFile : file
);
} else {
reject();
reject(new Error("file load failed"));
}
})
.catch(reject);
......@@ -77,7 +77,7 @@ export class ImageCompresser {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
if (!context) {
reject();
reject(new Error(" compress image failed"));
return;
}
const { width: originWidth, height: originHeight } = img; // 最大尺寸限制
......
......@@ -22,7 +22,7 @@ function base64_url_decode(str: string) {
output += "=";
break;
default:
throw "Illegal base64url string!";
throw new Error("Illegal base64url string!");
}
try {
......
......@@ -8,14 +8,14 @@ import tokenManager from "./token";
import xim from "./xim";
class Chat {
private _sdk?: () => UniplatSdk
private _orgId: () => string | number = () => "0"
private token!: TokenStringGetter
private _sdk?: () => UniplatSdk;
private _orgId: () => string | number = () => "0";
private token!: TokenStringGetter;
private userMapping: { [key: string]: { name: string; avatar: string } } =
{}
{};
private webHost = false
private webHost = false;
public async setup(option: ChatOption) {
if (!option) {
......@@ -46,11 +46,11 @@ class Chat {
public getSdk = () => {
if (this._sdk == null) return;
return this._sdk();
}
};
public getOrgId = () => {
return this._orgId();
}
};
public isWebHost() {
return this.webHost;
......
import { ChatServiceLogger } from "../model";
export class ChatLoggerService {
public static logger = console
......
......@@ -4,10 +4,11 @@ export enum UserType {
Customer, // 客户
}
export default interface User {
type User ={
uid: string;
oid: string;
eid: string;
jwt: string;
userType: UserType;
};;;;;;;;;;
};
export default User;
import { ChatOption, TokenStringGetter } from "./../model";
import { TokenStringGetter } from "./../model";
function Token() {
let _token: TokenStringGetter;
return {
......
......@@ -12,7 +12,7 @@ wampDebug(true);
const DefaultMsgPageSize = 20;
function emptyFunc() {
return null;
}
export type MsgListener = (msg: Message) => void
......@@ -58,7 +58,7 @@ export class Xim {
public async open(url: string, token: TokenStringGetter) {
this.connectionPending = true;
await new Promise((success: (p?: unknown) => void, failed) => {
await new Promise((resolve: (p?: unknown) => void, reject) => {
this.paramsForReconnection = { url, token };
this.close();
......@@ -67,15 +67,15 @@ export class Xim {
this.client = client;
client.onstatuschange = (status: any, details: any) => {
this.onStatusChange.call(this, status, details);
this.onStatusChange(status, details);
if (status === "DISCONNECTED" || status === "CLOSED") {
failed();
reject(status);
}
};
client.onconnected = () => {
this.onConnected.apply(this);
success();
resolve();
};
client.onmsg = this.handleMsg.bind(this);
......@@ -92,15 +92,16 @@ export class Xim {
* token过期或者切换用户登录时,需要设置新的token
*/
public async setToken(token: TokenStringGetter) {
const client = this.client!;
const client = this.client;
if (client == null) return;
client.close();
client.setToken(this.trimToken(await token()));
client.open();
}
public fetchMsgInBox(chatId: number, msgId: number) {
return this.client!.fetchMsgInBox(chatType, chatId, msgId);
if (this.client == null) return;
return this.client.fetchMsgInBox(chatType, chatId, msgId);
}
/**
......@@ -113,13 +114,14 @@ export class Xim {
msg: string
) {
this.checkConnected();
return this.client!.sendMsg(chatType, chatId, msgType, msg, "", {});
if (this.client == null) return;
return this.client.sendMsg(chatType, chatId, msgType, msg, "", {});
}
public inputing(chatId: number) {
this.checkConnected();
return this.client!.userInput(chatType, chatId);
if (this.client == null) return;
return this.client.userInput(chatType, chatId);
}
/*
......@@ -127,8 +129,8 @@ export class Xim {
*/
public fetchChatMembers(chat_id: number) {
this.checkConnected();
return this.client!.fetchChatMembers(chat_id);
if (this.client == null) return;
return this.client.fetchChatMembers(chat_id);
}
/**
......@@ -143,7 +145,8 @@ export class Xim {
desc = true
): Promise<Message[]> {
this.checkConnected();
const res = await this.client!.fetchChatMsgs(chatType, chatId, {
if (this.client == null) return;
const res = await this.client.fetchChatMsgs(chatType, chatId, {
lid,
rid,
limit,
......@@ -283,8 +286,9 @@ export class Xim {
}
private onConnected() {
if (this.client == null) return;
// 连接成功后,需要调用pubUserInfo, 否则服务端会认为此连接无效
this.client!.pubUserInfo("");
this.client.pubUserInfo("");
this.debug("xim connected");
}
......@@ -334,10 +338,12 @@ export class Xim {
}
private checkConnected() {
if (!this.client!.connected) {
if (this.client == null) return;
if (!this.client.connected) {
try {
this.client?.open();
} catch (e) {
// eslint-disable-next-line no-console
console.error("checkConnected", e);
this.reOpen();
}
......
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