Commit 84b48c2e by panjiangyi

format file

parent 31d2e1e4
import type { UniplatSdk } from "uniplat-sdk" import type { UniplatSdk } from "uniplat-sdk";
export interface Chat { export interface Chat {
chat_id: number chat_id: number;
title: string title: string;
service_id: number service_id: number;
create_time: number create_time: number;
update_time: number update_time: number;
start_time: number start_time: number;
end_time: number end_time: number;
is_finish: boolean is_finish: boolean;
msg_id: number msg_id: number;
last_cs_eid: string last_cs_eid: string;
first_cs_eid: string first_cs_eid: string;
last_msg_eid: string last_msg_eid: string;
last_msg_name: string last_msg_name: string;
last_msg_ts: number last_msg_ts: number;
last_online_time: number last_online_time: number;
msg_type: string msg_type: string;
msg: string msg: string;
customer_name: string customer_name: string;
customer_mobile: string customer_mobile: string;
customer_avatar_url: string customer_avatar_url: string;
customer_online: boolean customer_online: boolean;
customer_eid: string customer_eid: string;
origin: string origin: string;
unread_msg_count: number unread_msg_count: number;
} }
export type TokenStringGetter = () => Promise<string> export type TokenStringGetter = () => Promise<string>
...@@ -33,174 +33,174 @@ export interface ChatOption { ...@@ -33,174 +33,174 @@ export interface ChatOption {
/** /**
* 企业token [商户端使用,用户端和移动端不需要] * 企业token [商户端使用,用户端和移动端不需要]
*/ */
enterpriseTokenString?: TokenStringGetter enterpriseTokenString?: TokenStringGetter;
/** /**
* 个人token * 个人token
*/ */
userTokenString: TokenStringGetter userTokenString: TokenStringGetter;
/** /**
* 长链接chat sdk地址 * 长链接chat sdk地址
*/ */
webSocketUri: string webSocketUri: string;
sdk: () => UniplatSdk sdk: () => UniplatSdk;
orgId: () => string | number orgId: () => string | number;
logger?: ChatServiceLogger logger?: ChatServiceLogger;
} }
export interface ChatServiceLogger { export interface ChatServiceLogger {
enabled: boolean enabled: boolean;
debug(message?: any, ...optionalParams: any[]): void debug(message?: any, ...optionalParams: any[]): void;
info(message?: any, ...optionalParams: any[]): void info(message?: any, ...optionalParams: any[]): void;
error(message?: any, ...optionalParams: any[]): void error(message?: any, ...optionalParams: any[]): void;
} }
export type ChatListRequestList = { export type ChatListRequestList = {
list: Chat[] list: Chat[];
total: number total: number;
} }
export interface Message { export interface Message {
at_id: string at_id: string;
chat_id: number chat_id: number;
create_time: number create_time: number;
eid: string eid: string;
id: number id: number;
is_open: boolean is_open: boolean;
is_read: boolean is_read: boolean;
like: boolean like: boolean;
like_count: number like_count: number;
msg: string msg: string;
oid: string oid: string;
read_count: number read_count: number;
ref_id: number ref_id: number;
status: number status: number;
total_read_count: number total_read_count: number;
ts: number ts: number;
type: "text" | "image" | "file" | "video" | "voice" type: "text" | "image" | "file" | "video" | "voice";
update_time: number update_time: number;
url: string url: string;
} }
export type MessageRequestResult = readonly Message[] export type MessageRequestResult = readonly Message[]
export interface CreateChatByServicemanRequestResult { export interface CreateChatByServicemanRequestResult {
id: number id: number;
org_id: string org_id: string;
uid: string uid: string;
oid: string oid: string;
eid: string eid: string;
type: string type: string;
title: string title: string;
app_id: string app_id: string;
tag: string tag: string;
msg_id: number msg_id: number;
ext: string ext: string;
exit_msg_id: number exit_msg_id: number;
is_exited: boolean is_exited: boolean;
dnd: number dnd: number;
is_top: boolean is_top: boolean;
label: string label: string;
join_msg_id: number join_msg_id: number;
last_read_msg_id: number last_read_msg_id: number;
biz_id: string biz_id: string;
business_data: string business_data: string;
is_finish: boolean is_finish: boolean;
is_deleted: boolean is_deleted: boolean;
is_remove: boolean is_remove: boolean;
member_type: number member_type: number;
ref_id: number ref_id: number;
unread_msg_count: number unread_msg_count: number;
at_me: boolean at_me: boolean;
at_all: boolean at_all: boolean;
last_login_oid: string last_login_oid: string;
owner_oid: string owner_oid: string;
owner_eid: string owner_eid: string;
is_act: boolean is_act: boolean;
create_time: number create_time: number;
update_time: number update_time: number;
last_msg_ts: number last_msg_ts: number;
members_updated: number members_updated: number;
user_updated: number user_updated: number;
} }
export type ChatMemberExtraInfo = { export type ChatMemberExtraInfo = {
name?: string name?: string;
phone?: string phone?: string;
} }
export interface ChatMember { export interface ChatMember {
at_all: boolean at_all: boolean;
at_me: boolean at_me: boolean;
chat_id: number chat_id: number;
create_time: number create_time: number;
dnd: number dnd: number;
eid: string eid: string;
exit_msg_id: number exit_msg_id: number;
id: number id: number;
is_act: boolean is_act: boolean;
is_exited: boolean is_exited: boolean;
is_remove: boolean is_remove: boolean;
is_top: boolean is_top: boolean;
join_msg_id: number join_msg_id: number;
label: string label: string;
nickname: string nickname: string;
oid: string oid: string;
org_id: string org_id: string;
type: number type: number;
uid: string uid: string;
unread_msg_count: number unread_msg_count: number;
update_time: number update_time: number;
} }
export type ChatMembers = readonly ChatMember[] export type ChatMembers = readonly ChatMember[]
export interface ServiceMan { export interface ServiceMan {
id: number id: number;
oid: string oid: string;
eid: string eid: string;
is_deleted: boolean is_deleted: boolean;
delete_time: number delete_time: number;
delete_eid: string delete_eid: string;
service_id: number service_id: number;
type: number type: number;
name: string name: string;
mobile: string mobile: string;
email: string email: string;
description: string description: string;
avatar_url: string avatar_url: string;
create_time: number create_time: number;
update_time: number update_time: number;
chat_count: number chat_count: number;
status: number status: number;
} }
export type AllServiceMan = ServiceMan[] export type AllServiceMan = ServiceMan[]
export interface OneWhoReadMessage { export interface OneWhoReadMessage {
create_time: number create_time: number;
eid: string eid: string;
id: number id: number;
is_read: boolean is_read: boolean;
like: boolean like: boolean;
like_time: number like_time: number;
oid: string oid: string;
owner_id: number owner_id: number;
read_time: number read_time: number;
target_id: number target_id: number;
type: number type: number;
uid: string uid: string;
} }
export interface GetAllChatListParams { export interface GetAllChatListParams {
service_id: number service_id: number;
user_info?: string user_info?: string;
origin?: string origin?: string;
user_id?: string user_id?: string;
is_finish?: boolean | -1 | number is_finish?: boolean | -1 | number;
chat_update_time_start?: string chat_update_time_start?: string;
chat_update_time_end?: string chat_update_time_end?: string;
page?: number page?: number;
page_size?: number page_size?: number;
last_cs_eid?: string | number last_cs_eid?: string | number;
} }
import { TokenStringGetter } from "../model" import { TokenStringGetter } from "../model";
import { invokeGet } from "./request"
import { invokeGet } from "./request";
export class EmojiService { export class EmojiService {
private static ready = false private static ready = false
...@@ -11,39 +12,39 @@ export class EmojiService { ...@@ -11,39 +12,39 @@ export class EmojiService {
this.url = this.url =
process.env.NODE_ENV === "production" process.env.NODE_ENV === "production"
? "https://file.teammix.com" ? "https://file.teammix.com"
: "" : "";
} }
public async getEmoji() { public async getEmoji() {
const token = await EmojiService.token() const token = await EmojiService.token();
return invokeGet<{ return invokeGet<{
type: string type: string;
list: { list: {
code: string code: string;
name: string name: string;
emoji_chars: string emoji_chars: string;
}[] }[];
}>(`${this.url}/v1/emoji/list?type=chat`, token) }>(`${this.url}/v1/emoji/list?type=chat`, token);
} }
public static onReady(callback: () => void) { public static onReady(callback: () => void) {
if (EmojiService.ready) { if (EmojiService.ready) {
callback() callback();
} else { } else {
EmojiService.beforeReadyCacheAction.push(callback) EmojiService.beforeReadyCacheAction.push(callback);
} }
} }
private static fireBeforeReadyAction() { private static fireBeforeReadyAction() {
for (const item of EmojiService.beforeReadyCacheAction) { for (const item of EmojiService.beforeReadyCacheAction) {
item() item();
} }
EmojiService.beforeReadyCacheAction = [] EmojiService.beforeReadyCacheAction = [];
} }
public static raiseOnReady(token: TokenStringGetter) { public static raiseOnReady(token: TokenStringGetter) {
EmojiService.ready = true EmojiService.ready = true;
EmojiService.token = token EmojiService.token = token;
EmojiService.fireBeforeReadyAction() EmojiService.fireBeforeReadyAction();
} }
} }
import Axios from "axios" import Axios from "axios";
import qs from "qs" import qs from "qs";
export function buildConfig(token: string, url: string) { export function buildConfig(token: string, url: string) {
if (url && url.includes("/general")) { if (url && url.includes("/general")) {
return { headers: { Authorization: token, CurrentOrg: this.station } } return { headers: { Authorization: token, CurrentOrg: this.station } };
} }
return { headers: { Authorization: token } } return { headers: { Authorization: token } };
} }
export function invokeGet<T>(url: string, token: string) { export function invokeGet<T>(url: string, token: string) {
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
Axios.get(url, buildConfig(token, url)) Axios.get(url, buildConfig(token, url))
.then((r) => { .then((r) => {
if (r?.data?.data !== undefined) { if (r?.data?.data !== undefined) {
return resolve(r.data.data as T) return resolve(r.data.data as T);
} }
reject(r) reject(r);
}) })
.catch(reject) .catch(reject);
}) });
} }
export const enum DataType { export const enum DataType {
...@@ -32,21 +32,21 @@ export function invokePost<T>( ...@@ -32,21 +32,21 @@ export function invokePost<T>(
data: any, data: any,
dataType = DataType.Json dataType = DataType.Json
): Promise<T> { ): Promise<T> {
let postData: any = null let postData: any = null;
if (dataType === DataType.Qs) { if (dataType === DataType.Qs) {
postData = qs.stringify(data) postData = qs.stringify(data);
} else { } else {
postData = data postData = data;
} }
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
Axios.post(url, postData, buildConfig(token, url)) Axios.post(url, postData, buildConfig(token, url))
.then((r) => { .then((r) => {
if (r?.data?.data !== undefined) { if (r?.data?.data !== undefined) {
return resolve(r.data.data as T) return resolve(r.data.data as T);
} }
reject(r) reject(r);
}) })
.catch(reject) .catch(reject);
}) });
} }
export function isAccessibleUrl(url: string) { export function isAccessibleUrl(url: string) {
return url && (url.startsWith("blob") || url.startsWith("http")) return url && (url.startsWith("blob") || url.startsWith("http"));
} }
import Vue from "vue" import Axios from "axios";
import { invokePost } from "./request" import Vue from "vue";
import Axios from "axios"
import tokenManager from "../xim/token" import tokenManager from "../xim/token";
const orgId = () => Vue.prototype.global.org?.id ?? "0"
import { invokePost } from "./request";
const orgId = () => Vue.prototype.global.org?.id ?? "0";
export async function uploadFile( export async function uploadFile(
file: File, file: File,
chatId: number, chatId: number,
width?: number, width?: number,
height?: number height?: number
) { ) {
const splits = file.name.split(".") const splits = file.name.split(".");
const parameter = { const parameter = {
file_name: file.name, file_name: file.name,
size: file.size, size: file.size,
...@@ -18,30 +20,30 @@ export async function uploadFile( ...@@ -18,30 +20,30 @@ export async function uploadFile(
owner_id: chatId, owner_id: chatId,
org_id: orgId(), org_id: orgId(),
ext_type: splits[splits.length - 1], ext_type: splits[splits.length - 1],
} };
if (width && height) { if (width && height) {
Object.assign(parameter, { width, height }) Object.assign(parameter, { width, height });
} }
const token = await invokePost<{ const token = await invokePost<{
url_id: string url_id: string;
sign: string sign: string;
domain: string domain: string;
file_name: string file_name: string;
id: number id: number;
}>("/xchat/personal/upload_token", await tokenManager.getToken(), parameter) }>("/xchat/personal/upload_token", await tokenManager.getToken(), parameter);
const uri = `${token.domain}/gw/file/upload` const uri = `${token.domain}/gw/file/upload`;
const form = new FormData() const form = new FormData();
form.append("file", file) form.append("file", file);
form.append("fileId", token.url_id) form.append("fileId", token.url_id);
form.append("fileSize", file.size.toString()) form.append("fileSize", file.size.toString());
form.append("orgId", orgId()) form.append("orgId", orgId());
form.append("sign", token.sign) form.append("sign", token.sign);
const result = await Axios.post(uri, form, { const result = await Axios.post(uri, form, {
headers: { "Content-Type": "multipart/form-data" }, headers: { "Content-Type": "multipart/form-data" },
}) });
if (result && result.data && result.data.errcode === 0) { if (result && result.data && result.data.errcode === 0) {
return token.url_id return token.url_id;
} }
return "" return "";
} }
export class ImageCompresser { export class ImageCompresser {
public static dataURL2File(data: string, name: string) { public static dataURL2File(data: string, name: string) {
const arr = data.split(",") const arr = data.split(",");
if (arr) { if (arr) {
if (arr[0]) { if (arr[0]) {
const match = arr[0].match(/:(.*?);/) const match = arr[0].match(/:(.*?);/);
if (match) { if (match) {
const mime = match[1] const mime = match[1];
const bstr = atob(arr[1]) const bstr = atob(arr[1]);
let n = bstr.length let n = bstr.length;
const u8arr = new Uint8Array(n) const u8arr = new Uint8Array(n);
// eslint-disable-next-line no-plusplus // eslint-disable-next-line no-plusplus
while (n--) { while (n--) {
u8arr[n] = bstr.charCodeAt(n) u8arr[n] = bstr.charCodeAt(n);
} }
return new File([u8arr], name, { type: mime }) return new File([u8arr], name, { type: mime });
} }
} }
} }
return null return null;
} }
public static readFile2Image( public static readFile2Image(
...@@ -26,38 +26,38 @@ export class ImageCompresser { ...@@ -26,38 +26,38 @@ export class ImageCompresser {
maxHeight: number maxHeight: number
): Promise<File | null> { ): Promise<File | null> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const img = new Image() const img = new Image();
const reader = new FileReader() const reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => {
if (e && e.target && e.target.result) { if (e && e.target && e.target.result) {
img.src = e.target.result as string img.src = e.target.result as string;
} else { } else {
reject() reject();
} }
} };
reader.readAsDataURL(file) reader.readAsDataURL(file);
img.onload = () => { img.onload = () => {
const originWidth = img.naturalWidth const originWidth = img.naturalWidth;
const originHeight = img.naturalHeight const originHeight = img.naturalHeight;
if (originWidth > maxWidth || originHeight > maxHeight) { if (originWidth > maxWidth || originHeight > maxHeight) {
ImageCompresser.compressImg(img, maxWidth, maxHeight) ImageCompresser.compressImg(img, maxWidth, maxHeight)
.then((b) => { .then((b) => {
if (b) { if (b) {
const newFile = new File([b], file.name) const newFile = new File([b], file.name);
// 如果压缩完还不如原始图片size小,直接返回原始图片 // 如果压缩完还不如原始图片size小,直接返回原始图片
resolve( resolve(
newFile.size <= file.size ? newFile : file newFile.size <= file.size ? newFile : file
) );
} else { } else {
reject() reject();
} }
}) })
.catch(reject) .catch(reject);
} else { } else {
resolve(file) resolve(file);
} }
} };
}) });
} }
/** /**
...@@ -74,40 +74,40 @@ export class ImageCompresser { ...@@ -74,40 +74,40 @@ export class ImageCompresser {
type?: string type?: string
): Promise<Blob | null> { ): Promise<Blob | null> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const canvas = document.createElement("canvas") const canvas = document.createElement("canvas");
const context = canvas.getContext("2d") const context = canvas.getContext("2d");
if (!context) { if (!context) {
reject() reject();
return return;
} }
const { width: originWidth, height: originHeight } = img // 最大尺寸限制 const { width: originWidth, height: originHeight } = img; // 最大尺寸限制
const maxWidth = mx const maxWidth = mx;
const maxHeight = mh // 目标尺寸 const maxHeight = mh; // 目标尺寸
let targetWidth = originWidth let targetWidth = originWidth;
let targetHeight = originHeight let targetHeight = originHeight;
if (originWidth > maxWidth || originHeight > maxHeight) { if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > 1) { if (originWidth / originHeight > 1) {
// 宽图片 // 宽图片
targetWidth = maxWidth targetWidth = maxWidth;
targetHeight = Math.round( targetHeight = Math.round(
maxWidth * (originHeight / originWidth) maxWidth * (originHeight / originWidth)
) );
} else { } else {
// 高图片 // 高图片
targetHeight = maxHeight targetHeight = maxHeight;
targetWidth = Math.round( targetWidth = Math.round(
maxHeight * (originWidth / originHeight) maxHeight * (originWidth / originHeight)
) );
} }
} }
canvas.width = targetWidth canvas.width = targetWidth;
canvas.height = targetHeight canvas.height = targetHeight;
context.clearRect(0, 0, targetWidth, targetHeight) context.clearRect(0, 0, targetWidth, targetHeight);
context.drawImage(img, 0, 0, targetWidth, targetHeight) context.drawImage(img, 0, 0, targetWidth, targetHeight);
canvas.toBlob((blob) => { canvas.toBlob((blob) => {
resolve(blob) resolve(blob);
canvas.remove() canvas.remove();
}, type || "image/png") }, type || "image/png");
}) });
} }
} }
import { UserAgentHelper } from "../user-agent" import { UserAgentHelper } from "../user-agent";
export enum TransformTarget { export enum TransformTarget {
Mobile, Mobile,
...@@ -36,12 +36,12 @@ export interface PcMobileTransformerOption { ...@@ -36,12 +36,12 @@ export interface PcMobileTransformerOption {
/** /**
* 手机端根host,如 https://www.teammix.com/ms * 手机端根host,如 https://www.teammix.com/ms
*/ */
mobileHost?: string mobileHost?: string;
/** /**
* 桌面端根host,如 https://www.teammix.com/s * 桌面端根host,如 https://www.teammix.com/s
*/ */
desktopHost?: string desktopHost?: string;
} }
/** /**
...@@ -79,84 +79,84 @@ export class PcMobileTransformer { ...@@ -79,84 +79,84 @@ export class PcMobileTransformer {
public static setup(option: PcMobileTransformerOption) { public static setup(option: PcMobileTransformerOption) {
if (option.desktopHost) { if (option.desktopHost) {
PcMobileTransformer.target = TransformTarget.Desktop PcMobileTransformer.target = TransformTarget.Desktop;
PcMobileTransformer.host = PcMobileTransformer.trimEnd( PcMobileTransformer.host = PcMobileTransformer.trimEnd(
option.desktopHost option.desktopHost
) );
} }
if (option.mobileHost) { if (option.mobileHost) {
PcMobileTransformer.target = TransformTarget.Mobile PcMobileTransformer.target = TransformTarget.Mobile;
PcMobileTransformer.host = PcMobileTransformer.trimEnd( PcMobileTransformer.host = PcMobileTransformer.trimEnd(
option.mobileHost option.mobileHost
) );
} }
} }
public static isNeed2Redirect() { public static isNeed2Redirect() {
if (PcMobileTransformer.target === TransformTarget.Mobile) { if (PcMobileTransformer.target === TransformTarget.Mobile) {
return PcMobileTransformer.isMobileDevice() return PcMobileTransformer.isMobileDevice();
} }
return false return false;
} }
private static trimEnd(input: string) { private static trimEnd(input: string) {
if (input && input.endsWith("/")) { if (input && input.endsWith("/")) {
return input.substring(0, input.length - 1) return input.substring(0, input.length - 1);
} }
return input return input;
} }
private static isMobileDevice() { private static isMobileDevice() {
const ua = window.navigator.userAgent const ua = window.navigator.userAgent;
return UserAgentHelper.isMobile(ua) return UserAgentHelper.isMobile(ua);
} }
public static transform( public static transform(
parameters: (string | number)[], parameters: (string | number)[],
target: TransformDirection target: TransformDirection
) { ) {
let v = "" let v = "";
if (PcMobileTransformer.target === TransformTarget.Desktop) { if (PcMobileTransformer.target === TransformTarget.Desktop) {
v = PcMobileTransformer.transform2Desktop(parameters, target) v = PcMobileTransformer.transform2Desktop(parameters, target);
} }
if (PcMobileTransformer.target === TransformTarget.Mobile) { if (PcMobileTransformer.target === TransformTarget.Mobile) {
v = PcMobileTransformer.transform2Mobile(parameters, target) v = PcMobileTransformer.transform2Mobile(parameters, target);
} }
return v.replace(/\.html/gi, "") return v.replace(/\.html/gi, "");
} }
private static transform2Mobile( private static transform2Mobile(
parameters: (string | number)[], parameters: (string | number)[],
target: TransformDirection target: TransformDirection
) { ) {
const url = PcMobileTransformer.desktop2MobileMapping.get(target) const url = PcMobileTransformer.desktop2MobileMapping.get(target);
if (url) { if (url) {
let targetUrl = `${PcMobileTransformer.host}${url}` let targetUrl = `${PcMobileTransformer.host}${url}`;
for (let i = 0; i < parameters.length; i++) { for (let i = 0; i < parameters.length; i++) {
targetUrl = targetUrl.replace(`{${i}}`, parameters[i] + "") targetUrl = targetUrl.replace(`{${i}}`, parameters[i] + "");
} }
return targetUrl return targetUrl;
} }
const base = PcMobileTransformer.rebuildMapping.get(target) const base = PcMobileTransformer.rebuildMapping.get(target);
if (base) { if (base) {
let rebuildUrl = base let rebuildUrl = base;
for (let i = 0; i < parameters.length; i++) { for (let i = 0; i < parameters.length; i++) {
rebuildUrl = rebuildUrl.replace(`{${i}}`, parameters[i] + "") rebuildUrl = rebuildUrl.replace(`{${i}}`, parameters[i] + "");
} }
return `${PcMobileTransformer.host}${rebuildUrl}` return `${PcMobileTransformer.host}${rebuildUrl}`;
} }
return PcMobileTransformer.host return PcMobileTransformer.host;
} }
private static transform2Desktop( private static transform2Desktop(
parameters: (string | number)[], parameters: (string | number)[],
target: TransformDirection target: TransformDirection
) { ) {
return target + "" return target + "";
} }
} }
...@@ -4,24 +4,24 @@ export class SeoHelper { ...@@ -4,24 +4,24 @@ export class SeoHelper {
title && title &&
(title.indexOf("TeamMix") > -1 || title.indexOf("亲亲小站") > -1) (title.indexOf("TeamMix") > -1 || title.indexOf("亲亲小站") > -1)
) { ) {
return title return title;
} }
return `${title || ""}-亲亲小站` return `${title || ""}-亲亲小站`;
} }
public static updateFavicon(path: string) { public static updateFavicon(path: string) {
const link = document.querySelector( const link = document.querySelector(
"link[rel*='icon']" "link[rel*='icon']"
) as HTMLLinkElement ) as HTMLLinkElement;
if (link) { if (link) {
link.href = path link.href = path;
} else { } else {
const l = document.createElement("link") const l = document.createElement("link");
l.type = "image/x-icon" l.type = "image/x-icon";
l.rel = "shortcut icon" l.rel = "shortcut icon";
l.href = path l.href = path;
document.getElementsByTagName("head")[0].appendChild(l) document.getElementsByTagName("head")[0].appendChild(l);
} }
} }
} }
...@@ -39,79 +39,79 @@ export const enum UserAgentType { ...@@ -39,79 +39,79 @@ export const enum UserAgentType {
export class UserAgentHelper { export class UserAgentHelper {
private static contains(source: string, match: string) { private static contains(source: string, match: string) {
return source.indexOf(match) > -1 return source.indexOf(match) > -1;
} }
private static containsAll(source: string, matches: string[]) { private static containsAll(source: string, matches: string[]) {
for (const item of matches) { for (const item of matches) {
if (!UserAgentHelper.contains(source, item)) { if (!UserAgentHelper.contains(source, item)) {
return false return false;
} }
} }
return true return true;
} }
private static containsAny(source: string, matches: string[]) { private static containsAny(source: string, matches: string[]) {
for (const item of matches) { for (const item of matches) {
if (UserAgentHelper.contains(source, item)) { if (UserAgentHelper.contains(source, item)) {
return true return true;
} }
} }
return false return false;
} }
public static getType(ua: string) { public static getType(ua: string) {
const lower = ua.toLowerCase() const lower = ua.toLowerCase();
if (UserAgentHelper.contains(lower, "ipad")) { if (UserAgentHelper.contains(lower, "ipad")) {
return UserAgentType.IPad return UserAgentType.IPad;
} }
if (UserAgentHelper.contains(lower, "android_tablet")) { if (UserAgentHelper.contains(lower, "android_tablet")) {
return UserAgentType.Tablet return UserAgentType.Tablet;
} }
if (UserAgentHelper.contains(lower, "iphone")) { if (UserAgentHelper.contains(lower, "iphone")) {
return UserAgentType.IPhone return UserAgentType.IPhone;
} }
if (UserAgentHelper.contains(lower, "ipod")) { if (UserAgentHelper.contains(lower, "ipod")) {
return UserAgentType.IPhone return UserAgentType.IPhone;
} }
if (UserAgentHelper.containsAny(lower, ["android", "mobile"])) { if (UserAgentHelper.containsAny(lower, ["android", "mobile"])) {
return UserAgentType.Andriod return UserAgentType.Andriod;
} }
if (UserAgentHelper.contains(lower, "safari")) { if (UserAgentHelper.contains(lower, "safari")) {
return UserAgentType.DesktopSafari return UserAgentType.DesktopSafari;
} }
if (UserAgentHelper.containsAny(lower, ["edge", "edg"])) { if (UserAgentHelper.containsAny(lower, ["edge", "edg"])) {
return UserAgentType.DesktopEdge return UserAgentType.DesktopEdge;
} }
if (UserAgentHelper.contains(lower, "trident")) { if (UserAgentHelper.contains(lower, "trident")) {
return UserAgentType.DesktopIE return UserAgentType.DesktopIE;
} }
if (UserAgentHelper.contains(lower, "firefox")) { if (UserAgentHelper.contains(lower, "firefox")) {
return UserAgentType.DesktopFirefox return UserAgentType.DesktopFirefox;
} }
if (UserAgentHelper.contains(lower, "chrome")) { if (UserAgentHelper.contains(lower, "chrome")) {
return UserAgentType.DesktopChrome return UserAgentType.DesktopChrome;
} }
if (UserAgentHelper.containsAny(lower, ["360", "baidu", "qq"])) { if (UserAgentHelper.containsAny(lower, ["360", "baidu", "qq"])) {
return UserAgentType.DesktopOthers return UserAgentType.DesktopOthers;
} }
return UserAgentType.None return UserAgentType.None;
} }
public static isMobile(ua: string) { public static isMobile(ua: string) {
const type = UserAgentHelper.getType(ua) const type = UserAgentHelper.getType(ua);
return type === UserAgentType.Andriod || type === UserAgentType.IPhone return type === UserAgentType.Andriod || type === UserAgentType.IPhone;
} }
} }
function b64DecodeUnicode(str: string) { function b64DecodeUnicode(str: string) {
return decodeURIComponent( return decodeURIComponent(
atob(str).replace(/(.)/g, function (m, p) { atob(str).replace(/(.)/g, function (m, p) {
let code = p.charCodeAt(0).toString(16).toUpperCase() let code = p.charCodeAt(0).toString(16).toUpperCase();
if (code.length < 2) { if (code.length < 2) {
code = "0" + code code = "0" + code;
} }
return "%" + code return "%" + code;
}) })
) );
} }
function base64_url_decode(str: string) { function base64_url_decode(str: string) {
let output = str.replace(/-/g, "+").replace(/_/g, "/") let output = str.replace(/-/g, "+").replace(/_/g, "/");
switch (output.length % 4) { switch (output.length % 4) {
case 0: case 0:
break break;
case 2: case 2:
output += "==" output += "==";
break break;
case 3: case 3:
output += "=" output += "=";
break break;
default: default:
throw "Illegal base64url string!" throw "Illegal base64url string!";
} }
try { try {
return b64DecodeUnicode(output) return b64DecodeUnicode(output);
} catch { } catch {
return atob(output) return atob(output);
} }
} }
export function decode(token: string) { export function decode(token: string) {
return JSON.parse(base64_url_decode(token.split(".")[1])) return JSON.parse(base64_url_decode(token.split(".")[1]));
} }
const STANDARD = Math.pow(10, 12) const STANDARD = Math.pow(10, 12);
const ONE_DAY_TICKS = 86400000 const ONE_DAY_TICKS = 86400000;
const ONE_MINUTE_TICKS = 60 * 1000 const ONE_MINUTE_TICKS = 60 * 1000;
const ONE_HOUR_TICKS = 60 * 60 * 1000 const ONE_HOUR_TICKS = 60 * 60 * 1000;
export const enum TimeFormatRule { export const enum TimeFormatRule {
/** /**
...@@ -17,43 +17,43 @@ export const enum TimeFormatRule { ...@@ -17,43 +17,43 @@ export const enum TimeFormatRule {
function formatHour2Friendly(hour: number) { function formatHour2Friendly(hour: number) {
if (hour <= 1) { if (hour <= 1) {
return "凌晨" return "凌晨";
} }
if (hour < 12) { if (hour < 12) {
return "上午" return "上午";
} }
if (hour === 12) { if (hour === 12) {
return "中午" return "中午";
} }
if (hour < 20) { if (hour < 20) {
return "下午" return "下午";
} }
return "晚上" return "晚上";
} }
function formatHour12Unit(hour: number, rule: TimeFormatRule) { function formatHour12Unit(hour: number, rule: TimeFormatRule) {
if (rule === TimeFormatRule.Hour12) { if (rule === TimeFormatRule.Hour12) {
return hour > 12 ? hour - 12 : hour return hour > 12 ? hour - 12 : hour;
} }
return hour return hour;
} }
function format2DetailTime(hour: number, time: Date, rule: TimeFormatRule) { function format2DetailTime(hour: number, time: Date, rule: TimeFormatRule) {
let hourString = "" let hourString = "";
const h = formatHour12Unit(hour, rule) const h = formatHour12Unit(hour, rule);
if (h < 10) { if (h < 10) {
hourString = "0" + h hourString = "0" + h;
} else { } else {
hourString = h + "" hourString = h + "";
} }
let minuteString = "" let minuteString = "";
const m = time.getMinutes() const m = time.getMinutes();
if (m < 10) { if (m < 10) {
minuteString = "0" + m minuteString = "0" + m;
} else { } else {
minuteString = "" + m minuteString = "" + m;
} }
return `${formatHour2Friendly(hour)} ${hourString}:${minuteString}` return `${formatHour2Friendly(hour)} ${hourString}:${minuteString}`;
} }
function isSameDay(d1: Date, d2: Date) { function isSameDay(d1: Date, d2: Date) {
...@@ -61,43 +61,43 @@ function isSameDay(d1: Date, d2: Date) { ...@@ -61,43 +61,43 @@ function isSameDay(d1: Date, d2: Date) {
d1.getFullYear() === d2.getFullYear() && d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() && d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate() d1.getDate() === d2.getDate()
) );
} }
function isInMinute(d1: Date, d2: Date) { function isInMinute(d1: Date, d2: Date) {
return Math.abs(d1.valueOf() - d2.valueOf()) <= ONE_MINUTE_TICKS return Math.abs(d1.valueOf() - d2.valueOf()) <= ONE_MINUTE_TICKS;
} }
function isInHour(d1: Date, d2: Date) { function isInHour(d1: Date, d2: Date) {
return Math.abs(d1.valueOf() - d2.valueOf()) < ONE_HOUR_TICKS return Math.abs(d1.valueOf() - d2.valueOf()) < ONE_HOUR_TICKS;
} }
function isYesterday(date: Date) { function isYesterday(date: Date) {
const now = new Date() const now = new Date();
now.setHours(0) now.setHours(0);
now.setMinutes(0) now.setMinutes(0);
now.setSeconds(0) now.setSeconds(0);
now.setMilliseconds(0) now.setMilliseconds(0);
const ticks = now.valueOf() const ticks = now.valueOf();
const yesterday = ticks - ONE_DAY_TICKS const yesterday = ticks - ONE_DAY_TICKS;
const v = date.valueOf() const v = date.valueOf();
return v >= yesterday && v < ticks return v >= yesterday && v < ticks;
} }
function isIn6Days(date: Date) { function isIn6Days(date: Date) {
const now = new Date() const now = new Date();
now.setHours(0) now.setHours(0);
now.setMinutes(0) now.setMinutes(0);
now.setSeconds(0) now.setSeconds(0);
now.setMilliseconds(0) now.setMilliseconds(0);
const ticks = now.valueOf() const ticks = now.valueOf();
const sixDaysAgo = ticks - ONE_DAY_TICKS * 6 const sixDaysAgo = ticks - ONE_DAY_TICKS * 6;
const v = date.valueOf() const v = date.valueOf();
return v >= sixDaysAgo && v < ticks return v >= sixDaysAgo && v < ticks;
} }
function isSameYear(d1: Date, d2: Date) { function isSameYear(d1: Date, d2: Date) {
return d1.getFullYear() === d2.getFullYear() return d1.getFullYear() === d2.getFullYear();
} }
const DAY_MAPPING: { [key: number]: string } = { const DAY_MAPPING: { [key: number]: string } = {
...@@ -108,39 +108,39 @@ const DAY_MAPPING: { [key: number]: string } = { ...@@ -108,39 +108,39 @@ const DAY_MAPPING: { [key: number]: string } = {
4: "四", 4: "四",
5: "五", 5: "五",
6: "六", 6: "六",
} };
function getDayInWeek(time: Date) { function getDayInWeek(time: Date) {
const d = time.getDay() const d = time.getDay();
return DAY_MAPPING[d] return DAY_MAPPING[d];
} }
function formatWithTwoNumber(number: number) { function formatWithTwoNumber(number: number) {
return number < 10 ? `0${number}` : `${number}` return number < 10 ? `0${number}` : `${number}`;
} }
function formatTime2MonthDate(time: Date) { function formatTime2MonthDate(time: Date) {
return `${formatWithTwoNumber(time.getMonth() + 1)}${formatWithTwoNumber( return `${formatWithTwoNumber(time.getMonth() + 1)}${formatWithTwoNumber(
time.getDate() time.getDate()
)}日` )}日`;
} }
function formatTime2ShortMonthDate(time: Date) { function formatTime2ShortMonthDate(time: Date) {
return `${formatWithTwoNumber(time.getMonth() + 1)}/${formatWithTwoNumber( return `${formatWithTwoNumber(time.getMonth() + 1)}/${formatWithTwoNumber(
time.getDate() time.getDate()
)}` )}`;
} }
function formatTime2YearMonthDate(time: Date) { function formatTime2YearMonthDate(time: Date) {
return `${time.getFullYear()}${formatWithTwoNumber( return `${time.getFullYear()}${formatWithTwoNumber(
time.getMonth() + 1 time.getMonth() + 1
)}${formatWithTwoNumber(time.getDate())}日` )}${formatWithTwoNumber(time.getDate())}日`;
} }
function formatTime2ShortYearMonthDate(time: Date) { function formatTime2ShortYearMonthDate(time: Date) {
return `${time.getFullYear()}/${formatWithTwoNumber( return `${time.getFullYear()}/${formatWithTwoNumber(
time.getMonth() + 1 time.getMonth() + 1
)}/${formatWithTwoNumber(time.getDate())}` )}/${formatWithTwoNumber(time.getDate())}`;
} }
/** /**
...@@ -160,63 +160,63 @@ export function formatTime( ...@@ -160,63 +160,63 @@ export function formatTime(
option = { rule: TimeFormatRule.Hour12, short: false } option = { rule: TimeFormatRule.Hour12, short: false }
) { ) {
if (time < STANDARD) { if (time < STANDARD) {
time *= 1000 time *= 1000;
} }
const t = new Date(time) const t = new Date(time);
const now = new Date() const now = new Date();
if (!option.short) { if (!option.short) {
if (isInMinute(t, now)) { if (isInMinute(t, now)) {
return "刚刚" return "刚刚";
} }
if (isInHour(t, now)) { if (isInHour(t, now)) {
return `${Math.round( return `${Math.round(
Math.abs(t.valueOf() - now.valueOf()) / 1000 / 60 Math.abs(t.valueOf() - now.valueOf()) / 1000 / 60
)}分钟前` )}分钟前`;
} }
} }
const hour = t.getHours() const hour = t.getHours();
if (isSameDay(t, now)) { if (isSameDay(t, now)) {
return format2DetailTime(hour, t, option.rule) return format2DetailTime(hour, t, option.rule);
} }
if (isYesterday(t)) { if (isYesterday(t)) {
if (option.short) { if (option.short) {
return "昨天" return "昨天";
} }
return "昨天 " + format2DetailTime(hour, t, option.rule) return "昨天 " + format2DetailTime(hour, t, option.rule);
} }
if (isIn6Days(t)) { if (isIn6Days(t)) {
if (option.short) { if (option.short) {
return `星期${getDayInWeek(t)}` return `星期${getDayInWeek(t)}`;
} }
return ( return (
`星期${getDayInWeek(t)} ` + format2DetailTime(hour, t, option.rule) `星期${getDayInWeek(t)} ` + format2DetailTime(hour, t, option.rule)
) );
} }
if (isSameYear(t, now)) { if (isSameYear(t, now)) {
if (option.short) { if (option.short) {
return formatTime2ShortMonthDate(t) return formatTime2ShortMonthDate(t);
} }
return ( return (
formatTime2MonthDate(t) + formatTime2MonthDate(t) +
" " + " " +
format2DetailTime(hour, t, option.rule) format2DetailTime(hour, t, option.rule)
) );
} }
if (option.short) { if (option.short) {
return formatTime2ShortYearMonthDate(t) return formatTime2ShortYearMonthDate(t);
} }
return ( return (
formatTime2YearMonthDate(t) + formatTime2YearMonthDate(t) +
" " + " " +
format2DetailTime(hour, t, option.rule) format2DetailTime(hour, t, option.rule)
) );
} }
export default "group" export default "group";
import xim from "./xim" import type { UniplatSdk } from "uniplat-sdk";
import { ChatOption, TokenStringGetter } from "./../model"
import { ChatLoggerService } from "./logger" import { EmojiService } from "../service/emoji";
import { EmojiService } from "../service/emoji"
import tokenManager from "./token" import { ChatOption, TokenStringGetter } from "./../model";
import type { UniplatSdk } from "uniplat-sdk" import { ChatLoggerService } from "./logger";
import tokenManager from "./token";
import xim from "./xim";
class Chat { class Chat {
private _sdk?: () => UniplatSdk private _sdk?: () => UniplatSdk
private _orgId: () => string | number = () => "0" private _orgId: () => string | number = () => "0"
...@@ -11,11 +14,12 @@ class Chat { ...@@ -11,11 +14,12 @@ class Chat {
private userMapping: { [key: string]: { name: string; avatar: string } } = private userMapping: { [key: string]: { name: string; avatar: string } } =
{} {}
private webHost = false private webHost = false
public async setup(option: ChatOption) { public async setup(option: ChatOption) {
if (!option) { if (!option) {
throw new Error(`You must specify a chat option for chat service`) throw new Error(`You must specify a chat option for chat service`);
} }
// if (!option.userTokenString) { // if (!option.userTokenString) {
// throw new Error(`You must specify a user token for chat service`) // throw new Error(`You must specify a user token for chat service`)
...@@ -23,75 +27,75 @@ class Chat { ...@@ -23,75 +27,75 @@ class Chat {
if (!option.webSocketUri) { if (!option.webSocketUri) {
throw new Error( throw new Error(
`You must specify a web socket address for chat service` `You must specify a web socket address for chat service`
) );
} }
this._sdk = option.sdk this._sdk = option.sdk;
this._orgId = option.orgId this._orgId = option.orgId;
// if (option.enterpriseTokenString) { // if (option.enterpriseTokenString) {
// this.token = option.enterpriseTokenString // this.token = option.enterpriseTokenString
// } else { // } else {
this.token = option.userTokenString this.token = option.userTokenString;
tokenManager.save(this.token) tokenManager.save(this.token);
// } // }
EmojiService.raiseOnReady(this.token) EmojiService.raiseOnReady(this.token);
return this.initChatSdk(option.webSocketUri) return this.initChatSdk(option.webSocketUri);
} }
public getSdk = () => { public getSdk = () => {
if(this._sdk == null) return if (this._sdk == null) return;
return this._sdk() return this._sdk();
} }
public getOrgId = () => { public getOrgId = () => {
return this._orgId() return this._orgId();
} }
public isWebHost() { public isWebHost() {
return this.webHost return this.webHost;
} }
private trimToken(token: string) { private trimToken(token: string) {
return token.replace(/^Bearer\s/, "") return token.replace(/^Bearer\s/, "");
} }
public async getToken() { public async getToken() {
return this.trimToken(await this.token()) return this.trimToken(await this.token());
} }
private async initChatSdk(uri: string) { private async initChatSdk(uri: string) {
if (xim.isConnected()) { if (xim.isConnected()) {
return uri return uri;
} }
return new Promise((resolve: (p?: unknown) => void) => { return new Promise((resolve: (p?: unknown) => void) => {
xim.open(uri, this.token) xim.open(uri, this.token);
this.registerXimEvent(resolve) this.registerXimEvent(resolve);
}) });
} }
public registerXimEvent(onConnected?: () => void) { public registerXimEvent(onConnected?: () => void) {
xim.off("status", (e) => this.raiseOnStatusChanged(e, onConnected)) xim.off("status", (e) => this.raiseOnStatusChanged(e, onConnected));
xim.on("status", (e) => this.raiseOnStatusChanged(e, onConnected)) xim.on("status", (e) => this.raiseOnStatusChanged(e, onConnected));
} }
private raiseOnStatusChanged(e: any, onConnected?: () => void) { private raiseOnStatusChanged(e: any, onConnected?: () => void) {
if (e === "CONNECTED") { if (e === "CONNECTED") {
if (onConnected) { if (onConnected) {
onConnected() onConnected();
} }
} }
this.debug(`client status ${e}`) this.debug(`client status ${e}`);
} }
public getUserMapping() { public getUserMapping() {
return {} return {};
} }
private debug(message: string) { private debug(message: string) {
ChatLoggerService.logger?.debug(message) ChatLoggerService.logger?.debug(message);
} }
} }
export default new Chat() export default new Chat();
import { ChatServiceLogger } from "../model" import { ChatServiceLogger } from "../model";
export class ChatLoggerService { export class ChatLoggerService {
public static logger = console public static logger = console
......
export interface Chat { export interface Chat {
type: string type: string;
chat_id: number chat_id: number;
service_id: number service_id: number;
title: string title: string;
// tag: string; // tag: string;
// ext: string; // ext: string;
create_time: number create_time: number;
update_time: number update_time: number;
// exit_msg_id: number; // exit_msg_id: number;
// is_exited: boolean; // is_exited: boolean;
// dnd: number; // dnd: number;
is_top: boolean is_top: boolean;
// label: string; // label: string;
// join_msg_id: number; // join_msg_id: number;
// last_read_msg_id: number; // last_read_msg_id: number;
...@@ -22,62 +22,62 @@ export interface Chat { ...@@ -22,62 +22,62 @@ export interface Chat {
// is_remove: boolean; // is_remove: boolean;
// member_type: number; // member_type: number;
// ref_id: number; // ref_id: number;
unread_msg_count: number unread_msg_count: number;
// at_me: boolean; // at_me: boolean;
// at_all: boolean; // at_all: boolean;
// last_login_oid: string; // last_login_oid: string;
last_msg_eid: string last_msg_eid: string;
last_msg_name: string last_msg_name: string;
last_msg_ts: number last_msg_ts: number;
msg_id: number msg_id: number;
msg_type: string msg_type: string;
msg: string msg: string;
} }
export interface Message { export interface Message {
chat_id: number chat_id: number;
oid: string oid: string;
eid: string eid: string;
id: number id: number;
ts: number ts: number;
type: string type: string;
msg: string msg: string;
total_read_count: number total_read_count: number;
read_count: number read_count: number;
like_count: number like_count: number;
ref_id: number ref_id: number;
at_id: string at_id: string;
is_read: boolean is_read: boolean;
like: boolean like: boolean;
create_time: number create_time: number;
update_time: number update_time: number;
status: number status: number;
url: string url: string;
is_open: boolean is_open: boolean;
} }
export interface NotifyMessage { export interface NotifyMessage {
chat_type: string chat_type: string;
chat_id: number chat_id: number;
eid: string eid: string;
ts: number ts: number;
msg_type: string msg_type: string;
msg: string msg: string;
} }
export interface Member { export interface Member {
chat_id: number chat_id: number;
oid: string oid: string;
eid: string eid: string;
type: number type: number;
is_exited: boolean is_exited: boolean;
is_remove: boolean is_remove: boolean;
is_top: boolean is_top: boolean;
label: string label: string;
create_time: number create_time: number;
update_time: number update_time: number;
nick_name: string nick_name: string;
} }
/** /**
...@@ -119,102 +119,102 @@ export type ChatInputBoxData = { key: string } & ( ...@@ -119,102 +119,102 @@ export type ChatInputBoxData = { key: string } & (
) )
export type TextMessageBody = { export type TextMessageBody = {
text: string text: string;
} }
export type FileMessageBody = { export type FileMessageBody = {
name: string name: string;
url: string // 生消息是本地path,熟消息是文件url_id url: string; // 生消息是本地path,熟消息是文件url_id
size: number // number, 可选,文件大小:单位-字节 size: number; // number, 可选,文件大小:单位-字节
remark: string remark: string;
isNeedUploaded?: boolean // pc客户端自定义属性(只有生消息的消息体才有该属性, 值为false时不需要上传, true和undefined时需要上传) isNeedUploaded?: boolean; // pc客户端自定义属性(只有生消息的消息体才有该属性, 值为false时不需要上传, true和undefined时需要上传)
source?: { source?: {
source_type: number //来源类型(若为团队小站文件,则来源类型为团队小站文件) source_type: number; // 来源类型(若为团队小站文件,则来源类型为团队小站文件)
source_id: number //来源id(若为团队小站文件,此处为团队工作站id) source_id: number; // 来源id(若为团队小站文件,此处为团队工作站id)
source_name: string //来源名称(若为团队小站文件,此处传入团队小站名称) source_name: string; // 来源名称(若为团队小站文件,此处传入团队小站名称)
source_icon: string //来源图标(若为团队小站文件,此处传入团队icon的url) source_icon: string; // 来源图标(若为团队小站文件,此处传入团队icon的url)
extra?: { [prop: string]: any } //附加信息 extra?: { [prop: string]: any }; // 附加信息
} };
} }
export type ImageMessageBody = { export type ImageMessageBody = {
name: string name: string;
url: string url: string;
size: number size: number;
w: number w: number;
h: number h: number;
thumbnail?: string // 缩略图地址 thumbnail?: string; // 缩略图地址
preview?: string // 预览图地址 preview?: string; // 预览图地址
remark: string remark: string;
} }
export type VoiceMessageBody = { export type VoiceMessageBody = {
name: string name: string;
url: string url: string;
size: number size: number;
duration: number // 语音时间:单位-ms duration: number; // 语音时间:单位-ms
} }
//第一顺序 default_text 第二顺序 operator_text、receiver_text // 第一顺序 default_text 第二顺序 operator_text、receiver_text
export type NotifyMessageBody = { export type NotifyMessageBody = {
operator_id: string operator_id: string;
receiver_ids: string[] receiver_ids: string[];
default_text: string //默认文本 default_text: string; // 默认文本
operator_text: string //操作人文本 operator_text: string; // 操作人文本
receiver_text: string //处理人文本 receiver_text: string; // 处理人文本
} }
export type TextNoticeMessageBody = { export type TextNoticeMessageBody = {
title: string title: string;
text: string text: string;
is_at_all: boolean //是否@全部人 is_at_all: boolean; // 是否@全部人
} }
export type VideoMessageBody = { export type VideoMessageBody = {
name: string name: string;
url: string // 生消息是本地path,熟消息是文件url_id url: string; // 生消息是本地path,熟消息是文件url_id
size: number size: number;
cover?: string cover?: string;
duration: number duration: number;
w: number w: number;
h: number h: number;
isNeedUploaded?: boolean // pc客户端自定义属性(只有生消息的消息体才有该属性, 值为false时不需要上传, true和undefined时需要上传) isNeedUploaded?: boolean; // pc客户端自定义属性(只有生消息的消息体才有该属性, 值为false时不需要上传, true和undefined时需要上传)
} }
export type UrlMessageBody = { export type UrlMessageBody = {
title: string title: string;
icon: string icon: string;
url: string url: string;
desc: string desc: string;
source?: { source?: {
source_type: number //来源类型(若为团队小站文件,则来源类型为团队小站文件) source_type: number; // 来源类型(若为团队小站文件,则来源类型为团队小站文件)
source_id: number //来源id(若为团队小站文件,此处为团队工作站id) source_id: number; // 来源id(若为团队小站文件,此处为团队工作站id)
source_name: string //来源名称(若为团队小站文件,此处传入团队小站名称) source_name: string; // 来源名称(若为团队小站文件,此处传入团队小站名称)
source_icon: string //来源图标(若为团队小站文件,此处传入团队icon的url) source_icon: string; // 来源图标(若为团队小站文件,此处传入团队icon的url)
extra?: { [prop: string]: any } //附加信息 extra?: { [prop: string]: any }; // 附加信息
} };
} }
export type ForwardMessageBody = { export type ForwardMessageBody = {
snap: string snap: string;
chat_type: string //会话类型 chat_type: string; // 会话类型
chat_id: number // 会话id chat_id: number; // 会话id
msg_ids: number[] //消息id集合 msg_ids: number[]; // 消息id集合
} }
export type QuoteMessageBody = { export type QuoteMessageBody = {
text: string text: string;
quote_text: string // JSON字符串 quote_text: string; // JSON字符串
quote_msg_type: string quote_msg_type: string;
quote_eid: string quote_eid: string;
quote_msg_id: number //引用id quote_msg_id: number; // 引用id
} }
export type CommentForwardMessageBody = { export type CommentForwardMessageBody = {
snap: string snap: string;
channel_id: number //团队工作站id channel_id: number; // 团队工作站id
topic_id: number // 主题id topic_id: number; // 主题id
comment_ids: number[] //评论id集合 comment_ids: number[]; // 评论id集合
} }
// export type SpecifiedChatRecordMsg = SpecifiedChatRecord & { // export type SpecifiedChatRecordMsg = SpecifiedChatRecord & {
...@@ -229,21 +229,21 @@ export type CommentForwardMessageBody = { ...@@ -229,21 +229,21 @@ export type CommentForwardMessageBody = {
// 客服 // 客服
export interface CsUser { export interface CsUser {
id: number id: number;
oid: string oid: string;
eid: string eid: string;
is_deleted: boolean is_deleted: boolean;
delete_time: number delete_time: number;
delete_oid: string delete_oid: string;
delete_eid: string delete_eid: string;
service_id: number service_id: number;
type: number type: number;
name: string name: string;
mobile: string mobile: string;
email: string email: string;
description: string description: string;
create_time: number create_time: number;
update_time: number update_time: number;
chat_count: number chat_count: number;
status: number status: number;
} }
...@@ -5,9 +5,9 @@ export enum UserType { ...@@ -5,9 +5,9 @@ export enum UserType {
} }
export default interface User { export default interface User {
uid: string uid: string;
oid: string oid: string;
eid: string eid: string;
jwt: string jwt: string;
userType: UserType userType: UserType;
} };;;;;;;;;;
import { ChatOption, TokenStringGetter } from "./../model" import { ChatOption, TokenStringGetter } from "./../model";
function Token() { function Token() {
let _token: TokenStringGetter let _token: TokenStringGetter;
return { return {
save(token: TokenStringGetter) { save(token: TokenStringGetter) {
_token = token _token = token;
}, },
getToken() { getToken() {
return _token() return _token();
}, },
} };
} }
export default Token() export default Token();
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